ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 11.04.2019
Просмотров: 5823
Скачиваний: 8
Выбор подходящей команды умножения и контроль за форматом обрабатываемых чисел лежит на самом программисте.
Деление чисел без знака выполняет команда DIV, а чисел со знаком — команда IDIV:
DIV операнд-источник
IDIV операнд-источник
Также как инструкции умножения, инструкции деления требуют указывать только один операнд. Операнд-источникявляется делителем, а в качестве делимого используется либо содержимое регистра AL при операциях над байтами, либо AX при операциях над словами, либо EAX при операциях над двойными словами. Результат деления помещается в AL, AX или EAX, а остаток – в AH, DX или EDX соответственно.
Также как в случае команд умножения выбор подходящей команды деления и контроль за форматом обрабатываемых чисел лежит на самом программисте.
5.2.3.4. Изменение знака числа
Команда NEG изменяет знак числа на противоположный:
NEG операнд
Физически команда просто вычитает операнд из нуля (операнд = 0 – операнд). При этом выполняются все правила представления чисел со знаком т. е. числа конвертируются в двоичный дополнительный код.
7.Переполнение. Виды переполнений, возникающих при математических операциях на Ассемблере. https://wasm.in/blogs/perenos-i-perepolnenie-chto-oni-predstavljajut-soboj-na-samom-dele.275/
http://precious-cpp.blogspot.com/2011/01/eflags-cf-of.html
Допустим, мы складываем два целых числа при работе с числами со знаком:
01101110
+
01101110
=
11011100
Или в десятичной системе 110 + 110 = 220. Но мы то работаем с числами со знаком. В этом случае максимальное значение для байта равно 127. А полученное нами двоичное число будет на самом деле отрицательным числом –36 (см. раздел Отрицательные числа). В случае переполнения устанавливается флаг OF в регистре флагов (см. следующий раздел).
Вернёмся к примеру сложения двух чисел: 01101110
+
10010010
=
1000
Мы складывали отрицательное число 110 с таким же положительным и в итоге получили ноль, что вполне справедливо. А вот если бы мы работали с числами без знака, то это были бы уже другие числа и другой результат (точнее, по сути тот же самый, но формально другой)
01101110b = 110
10010010b = 146
110 + 146 = 256
Если мы запишем в программе такой код (прибавим к числу в регистре AL число, указанное в команде ADD – сложение):
MOV AL, 110
ADD AL, 146
то в результате в регистре AL у нас будет не 256, а 0, потому что регистр AL может работать только с одним байтом информации, а максимальное беззнаковое число, которое можно «запихнуть» в байт – это число 255. Число 256 это
100000000
то есть число, которое для записи в двоичной форме требует 9 разрядов. То есть единица находится в старшем 8-м разряде, а все младшие 8 разрядов (с 0 по 7) заполнены нулями. Именно поэтому в 8-разрядном регистре AL после выполнения операции сложения чисел 110 и 146 будет 0. В таком случае будет установлен флаг CF в регистре флагов, так как результат не поместился в регистре-приёмнике и произошёл перенос единицы из старшего бита.
Ситуации, подобные описанным выше, называются переполнением. То есть переполнение – это когда результат какой-либо операции не помещается в предназначенный для этого результата регистр. Разумеется, при переполнении результатом может быть и не ноль, а другое число. Например, при сложении чисел 110 и 147 в регистре AL будет число 1 (а не 257, как нам хотелось бы).
Как вы понимаете, переполнение – это один из подводных камней на пути программиста. Ведь совершенно неожиданно при увеличении зарплаты с 200 до 256 вы можете получить ноль. И это будет справедливо, потому что неожиданно это будет только для плохого программиста. Хороший программист при работе с числами всегда помнит о вероятности переполнения/переноса и принимает соответствующие меры. Например, для описанного выше случая избежать переполнения можно так:
MOV AX, 110
ADD AX, 146
В результате в регистре AX у нас будет число 256, потому что регистр AX – это 16-разрядный регистр, в который при работе с беззнаковыми числами можно «впихнуть» число вплоть до значения 65 535.
1) Перенос происходит тогда, когда единица выносится за пределы разрядной сетки (при операции сложения) или занимается из этих пределов (при операции вычитания);
Переполнение происходит тогда, когда единица выносится в последний разряд числа (при операции сложения) или занимается из этого разряда (при операции вычитания)
Переполнение при сложение, вычитании, делении, умножении
Таким образом, если в результате выполнения операции сложения происходит перенос из знакового бита, то индикатор переноса устанавливается, если нет, то индикатор переноса (CF) сбрасывается, т.е. состояние индикатора переноса, сброшенное или установленное, показывает соответственно правильность или неправильность операции сложения без учета знака. Индикатор переполнения устанавливается, если два складываемых числа имеют один и тот же знак, а результат сложения получается с противоположным знаком; в противном случае он сбрасывается, т.е. индикатор переполнения уста навливается тогда и только тогда, когда происходит только один из переносов в знаковый бит или из него. Тем самым состояние инди катора переполнения (Флаг OF) может исполь зоваться для определения соответственно правильности или непра вильности сложения с учетом знака.
(перенос)Рассмотрим числа 8 и 6. Что будет если из 6 вычесть 8? В двоичном представлении 6 имеет вид 00000110, 8 - 00001000. При поразрядном вычитании в 4 бите произойдет заем, который породит заем из 5,6,7,8 битов. Т.е. в итоге происходит заем из старшего бита, а это значит что флаг переноса устанавливается.
clc
mov al, 6
mov bl, 8
sub al, bl ; теперь в al -2
Для чего в данном случае устанавливается флаг. Дело в том, что результат получается отрицательным, что логично, но это неверно для беззнаковых чисел, которые по определению не могут иметь отрицательного значения. Т.е. результат опять не входит в диапазон 0...255 Из этого можно сделать вывод - если происходит вычитание большего числа из меньшего, то флаг переноса будет установлен, т.к. в этом случае происходит заем из старшего бита.
Переполнение (Первый случай:
mov al, 117
mov bl, 92
add al, bl ;
В итоге имеем -47 вместо 209 из-за переноса в знаковый бит, т.е. число 209 выходит за допустимый диапазон сверху.
CF
(перенос) -
флаг контролирующий выход значения за
пределы разрядной сетки, может
устанавливатся/сбрасыватся/инвертироватся
программно.
OF
(переполнение) -
флаг контролирующий изменения знакового
разряда, т.е. если при сложении двух
отрицательных чисел, получился
положительный результат, т.е. ошибка.
Эти
флаги используются программистами, для
контроля результата при работе с
знаковыми числами.
-
Понятие безусловного перехода. Виды безусловных переходов. Применение условных и безусловных переходов для управления процессом на языке ассемблер.
В программах можно нарушать естественный (последовательный) порядок выполнения команд, для этого служат команды перехода. Переходы бывают условные и безусловные. Условный переход выполняется только тогда когда выполняется заранее заданное условие, безусловный переход выполняется всегда без каких-либоусловий. В ассемблере безусловный переход выполняет команда:
JMP метка
Эта команда является аналогом оператора goto в языках высокого уровня. После выполнения JMP управление передается на метку (точнее на команду помеченную меткой).
Например, в листинге 3.3 показана программа, в которой присутствуют две функции для вывода на экран сначала фразы "Hello, World!", а затем "Goodbye, World!". Однако реально будет выведена на экран только вторая фраза, потому что с помощью команды JMP выполняет безусловный переход сразу на выполнение второй функции, т. е. первая функция вывода будет пропущена.
Листинг 3.3. Пример выполнения безусловного перехода (jump1.asm)
.model tiny
.code
org 100h
start:
|
|
|
|
|
|
jmp |
Go_mess2 |
||
|
mov |
ah,9 |
; эта функция не будет выполнена |
|
|
mov |
dx,offset message1 ; |
||
|
int |
21h |
; |
|
|
Go_mess2: |
|
|
|
|
mov |
ah,9 |
|
|
|
mov |
dx,offset message2 |
||
|
int |
21h |
|
|
|
ret |
|
|
|
|
message1 |
db |
"Hello, World!",0Dh,0Ah,'$' |
|
|
message2 |
db |
"Goodbye, World!",0Dh,0Ah,'$' |
|
end start
Вкачестве домашнего задания: добавьте в листинг 3.3 дополнительные команды JMP, так чтобы программа сначала выводила на экран фразу "Goodbye, World!", а затем "Hello, World!". При этом удалять и переставлять существующие команды в программе не нужно. Сколько минимальное количество JMP для этого нужно добавить в программу?
Вассемблере символ $, используемый в качестве операнда в машинной команде, всегда соответствует текущему адресу.
Например, команда
jmp $
Создает вечный цикл, т. к. выполняет безусловный переход на саму себя.
Символ $ можно использовать для адресации. Например, в следующем примере команда JMP выполняет переход на команду MOV:
jmp $+4 ; безусловный переход на команду mov nop ; длина команды NOP составляет 1 байт nop ; длина команды NOP составляет 1 байт mov bx,10
Это происходит потому, что сама команда JMP занимает 2 байта и две команды NOP в сумме дают 2 байта, в итоге требуется всего 4 байта, для того чтобы перепрыгнуть на команду MOV. Команда NOP (ее машинный код 90h) это так называемая ничего не делающая команда, она только занимает место и время.
Вкоманде JMP может указываться тип перехода:
short (короткий переход) — если адрес перехода находится в пределах - 128…+127 байт от команды JMP. Команда короткого перехода занимает всего 2 байта: в первом байте записывается код операции (EBh), во втором – смещение к точке перехода.
near (ближний переход) — если адрес перехода находится в пределах того же сегмента, что и команда JMP. В команде ближнего перехода под смещение отводится целое слово (это дает возможность осуществить переход в любую точку64-кбайтногосегмента), поэтому она занимает 3 байта (в первом байте находится код операции – 0E9h). По умолчанию ассемблер транслирует команды JMP, именно в этой тип.
far (дальний переход) — если адрес перехода находится в другом сегменте. Команда дальнего перехода имеет длину 5 байт. В первом байте находится код операции (0EAh), а в следующих четырех байтах — адрес сегмента и смещение точки перехода внутри сегмента.
Типы far и near в программе должны обязательно указываться с описателем PTR. Примеры:
|
jmp Lab |
; ближний переход (near) (3 байта) |
|
jmp short Lab |
; короткий переход (2 байта) |
|
jmp near ptr Lab |
; ближний переход (3 байта) |
|
jmp far ptr Lab |
; дальний переход (5 байт) |
|
jmp short $+2 |
; это команда просто передает |
;управление на следующую команду.
-
Понятие условного перехода. Виды условных переходов. Применение условных и безусловных переходов для управления процессом на языке ассемблер.
Если переход осуществляется только при выполнении соответствующего условия, то такой переход называется условным. Команд условного перехода достаточно много в ассемблере, но все они имеют следующий общий вид:
Jcc метка
где операнд указывает метку той команды в программе, на которую нужно сделать переход в случае выполнения некоторого условия, а сс сокращение из одной или двух букв описывающее условие:
e — равно (equal), n — не (not),
g — больше (greater), l — меньше (less),
a — выше (above), b — ниже (below).
Условием для команд условного перехода служат отдельные флаги в регистре флагов EFLAGS/FLAGS. Например, команда JZ проверяет флаг нуля, поэтому если в какойлибо программе встретится команда JZ и при этом в регистре флагов будет установлен в 1 флаг нуля (ZF=1), то произойдет переход на указанную метку, если же флаг нуля будет установлен в нуль (ZF=0), то переход не осуществится. В табл. 3.1 перечислены все команды условных переходов и флаги, значения которых они проверяют.
Таблица 3.1. Команды условных переходов
|
Команда |
Условие для CMP |
Значения флагов |
|
|
|
|
|
ja |
Если выше |
CF=0 и ZF=0 |
|
jnbe |
Если не ниже и не равно |
|
|
|
|
|
|
jae |
Если выше или равно |
CF=0 |
|
jnb |
Если не ниже |
|
|
jnc |
Если перенос |
|
|
|
|
CF=1 |
|
jb |
Если ниже |
|
|
jnae |
Если не выше и не равно |
|
|
jc |
Если перенос |
|
|
|
|
|
|
jbe |
Если ниже или равно |
CF=1 и ZF=1 |
|
jna |
Если не выше |
|
|
|
|
|
|
jcxz |
Если CX=0 |
Не влияет на флаги |
|
jecxz |
Если ECX=0 |
|
|
|
|
|
|
je |
Если равно |
ZF=1 |
|
jz |
Если ноль |
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
Таблица 3.1. (окончание) |
||||
|
|
|
|
|
|
||||
|
|
jg |
|
Если больше |
ZF=0 и SF=OF |
||||
|
|
jnle |
|
Если не меньше и не равно |
|
|
|||
|
|
|
|
|
|
||||
|
|
jge |
|
Если больше или равно |
SF=OF |
||||
|
|
jnl |
|
Если не меньше |
|
|
|||
|
|
|
|
|
|
||||
|
|
jl |
|
Если меньше |
SF<>OF |
||||
|
|
jnge |
|
Если не больше и не равно |
|
|
|||
|
|
|
|
|
|
||||
|
|
jle |
|
Если меньше или равно |
ZF=1 или SF<>OF |
||||
|
|
jng |
|
Если не больше |
|
|
|||
|
|
|
|
|
|
||||
|
|
jne |
|
Если не равно |
ZF=0 |
||||
|
|
jnz |
|
Если не ноль |
|
|
|||
|
|
|
|
|
|
||||
|
|
jno |
|
Если нет переполнения |
OF=0 |
||||
|
|
|
|
|
|
||||
|
|
jnp |
|
Если нет четности |
PF=0 |
||||
|
|
jpo |
|
Если нечетное |
|
|
|||
|
|
|
|
|
|
||||
|
|
jns |
|
Если нет знака |
SF=0 |
||||
|
|
|
|
|
|
||||
|
|
jp |
|
Если есть четность |
PF=1 |
||||
|
|
jpe |
|
Если четное |
|
|
|||
|
|
|
|
|
|
||||
|
|
jo |
|
Если есть переполнение |
OF=1 |
||||
|
|
|
|
|
|
||||
|
|
js |
|
Если есть знак |
SF=1 |
||||
|
|
|
|
|
|
|
|||