ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.04.2019

Просмотров: 5815

Скачиваний: 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 (переполнение) - флаг контролирующий изменения знакового разряда, т.е. если при сложении двух отрицательных чисел, получился положительный результат, т.е. ошибка.
Эти флаги используются программистами, для контроля результата при работе с знаковыми числами.

  1. Понятие безусловного перехода. Виды безусловных переходов. Применение условных и безусловных переходов для управления процессом на языке ассемблер.

В программах можно нарушать естественный (последовательный) порядок выполнения команд, для этого служат команды перехода. Переходы бывают условные и безусловные. Условный переход выполняется только тогда когда выполняется заранее заданное условие, безусловный переход выполняется всегда без каких-либоусловий. В ассемблере безусловный переход выполняет команда:


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

; это команда просто передает

;управление на следующую команду.

  1. Понятие условного перехода. Виды условных переходов. Применение условных и безусловных переходов для управления процессом на языке ассемблер.

Если переход осуществляется только при выполнении соответствующего условия, то такой переход называется условным. Команд условного перехода достаточно много в ассемблере, но все они имеют следующий общий вид:

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