Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Сдвиг регистровой пары edx:eax

Поиск

Следующая подпрограмма может быть полезна для сдвига содержимого регистровой пары EDX:EAX вправо или влево. Можно придумать более эффективный метод, но данный пример представляет общий подход для любого числа циклов (и соответственно сдвигов) в регистре CX. Заметьте, что сдвиг единичного бита за разрядную сетку устанавливает флаг переноса.

Сдвиг влево на 4 бита

MOV ECX,04;4 цикла

С20: SHL EDX,1;EDX на 1 бит влево

SHL EAX,1;EAX на 1 бит влево

ADC EАX,00;Плюс перенос

LOOP С20;Повторить

Сдвиг вправо на 4 бита

MOV ECX,04;4 цикла

D20: SHR EAX,1;EAX на 1 бит вправо

SHR EDX,1;EDX на 1 бит вправо

JNC D30;Если есть перенос,

OR EАX,80000000H;то 1 в EAX

D30: LOOP 020;Повторить

Ниже приведен более эффективный способ для сдвига влево для пары AX:DX, не требующий организации цикла. В этом примере фактор сдвига записывается в регистр CL. Пример написан для сдвига на 4 бита, но может быть адаптирован для других значений сдвигов:

MOV CL,04;Установить фактор сдвига

SHL DX,CL;DX влево на 4 бита

MOV BL,АН;Сохранить АН в BL

SHL AX,CL;AX влево на 4 бита

SHL BL, CL;BL влево на 4 бита

OR DL,BL;4 бита из BL в DL

Деление

Операция деления для беззнаковых данных выполняется командой DIV, а для знаковых – IDIV. Ответственность за подбор подходящей команды лежит на программисте.

Существуют две основные операции деления:

Деление слова на байт. Делимое находится в регистре AX, а делитель - в байте памяти или в однобайтовом регистре. После деления остаток получается в регистре АН, а частное - в AL. Так как однобайтовое частное, очень мало - максимально + 255 (0FFH) для беззнакового деления и +127 (7FH) для знакового, то данная операция имеет ограниченное использование:

До AX После АН AL

деления: Делимое) деления: Остаток Частное

Деление четверного слова на двойное слово(Деление двойного слова на слово). Делимое находится в регистровой паре EDX:EAX, а делитель - в двойном слове памяти или в регистре. После деления остаток получается в регистре EDX, а частное - в регистре EAX. Частное в одном слове допускает максимальное значение + FFFFFFFF для беззнакового деления и 7FFFFFFF для знакового:

До EDX EAX После EDX | EAX

деления: Старшая Младшая деле-

часть часть ния: Остаток | частное

Делимое

 

В единственном операнде команд DIV и IDIV указывается делитель. Если делимое находится только в EAX, то его расширяют до EDX специальной командой CDQ. Рассмотрим следующую команду:

DIV DIVISOR

Если поле DIVISOR определено как байт (DB), то операция предполагает деление слова на байт. Если поле DIVISOR определено как слово (DW), то операция предполагает деление двойного слова на слово. Если поле DIVISOR определено как двойное слово (DD), то операция предполагает деление четверного слова на двойное слово.

При делении, например, 13 на 3 получается результат 4 1/3. Частное здесь 4, а остаток - 1. Заметим, что ручной калькулятор (или программа на языке БЕЙСИК) выдает в этом случае результат 4,333... Значение содержит целую часть (4) и дробную часть (,333). Значения 1/3 и,333... - дробные части, в то время как 1 -остаток от деления.

Беззнаковое деление: команда DIV

Команда DIV делит беззнаковые числа. На рис. 4.28 в процедуре D10DIV дано четыре примера деления:

1. слова на байт,

2. байта на байт,

3. двойного слова на слово и

4. слова на слово.

Первый пример команды DIV делит 2000Н (8092) 80H (128). В результате остаток 00 получается в регистре АН, а частное 40H (64) - в регистре AL.

Во втором примере команды DIV выполняется прежде расширение байта BYTE1 до размеров слова. Так как здесь предполагается беззнаковая величина, то в примере левый бит регистра АН равен нулю. В результате деления остаток - 12Н получается в регистре АН, а частное 05Н - в регистре AL.

Третий пример команды DIV генерирует остаток 1000Н в регистре DX и частное 0080Н в регистре AX.

В четвертом примере команды DIV сначала выполняется расширение слова WORD1 до двойного слова в регистровой паре DX:AX. После деления остаток 0000Н получится в регистре DX, а частное 0002Н - в регистре AX.

Знаковое деление: команда IDIV

Команда IDIV (Integer DIVide) выполняет деление знаковых чисел. На рис. 4.28 в процедуре E101DIV используются те же четыре примера деления, что и в процедуре D10DIV, но вместо команд DIV записаны команды IDIV. Первый пример команды IDIV делит 2000Н (положительное число) на 80H (отрицательное число). Остаток от деления 00Н получается в регистре АН, а частное -0С0Н (-64) - в регистре AL. Команда DIV, используя те же числа, генерирует частное + 64.

Шестнадцатиричные результаты трех остальных примеров деления приведены ниже:

Пример команды IDIV

Остаток Частное

2 ЕЕ (-18) FB (-5)

3 1000 (4096) 0080 (128)

4 0000 0002

Только в примере 4 вырабатывается такой же результат, как и для команды DIV.

Таким образом, если делимое и делитель имеют одинаковый знаковый бит, то команды DIV и IDIV генерируют одинаковый результат. Но если делимое и делитель имеют разные знаковые биты, то команда DIV генерирует положительное частное, а команда IDIV - отрицательное частное. Можно обнаружить это, используя трассировку этих примеров.

 

TITLE EXDIV (СОM) Пример операций DIV и IDIV

CODESG SEGMENT PARA 'Code'

ORG 100H

BEGIN: JMP SHORT MAIN

;

BYTE1 DB 80H;Элементы данных

BYTE2 DB 16H

WORD1 DW 2000Н

WORD2 DW 0010H

WORD3 DW 1000H

MAIN PROC NEAR;Основная процедура

CALL D10DIV;Вызов п/п DIV

CALL E101DIV;Вызов п/п IDIV

MAIN ENDP

; Примеры с командой DIV:

;

D10DIV PROC

MOV AX,WORD1;Слово / байт

DIV BYTE1;ост:частное в AH: AL

MOV AL,BYTE1;Байт / байт

SUB АН,АН;расшир.делимое в АН

DIV BYTE2;ост:частное в AH: AL

MOV DX, WORD2;Двойное слово / слово

MOV AX,WORD3;делимое в DX:AX

DIV WORD1;ост:частное в DX:AX

MOV AX,WORD1;Слово / слово

SUB DX, DX;расшир.делимое в DX

DIV WORD3;ост:частное в DX:AX

RET

D10DIV ENDP

; Примеры с командой IDIV:

E101DIV PROC

MOV AX, WORD1;Слово / байт

IDIV BYTE1;ост:частное в AH: AL

MOV AL,BYTE1;Байт / байт

CBW;расшир.делимое в АН

IDIV BYTE3;ост:чартное в AH: AL

MOV DX,WORD2;Двойное слово / слово

MOV AX, WORD3;делимое в DX:AX

IDIV WORD1;ост:частное в DX:AX

MOV AX,WORD1;Слово / слово

CWD;расшир.делимое в DX

IDIV WORD3;ост:частное в DX:AX RET

E10DIV ENDP

CODESG ENDS

END BEGIN

Рис. 4.28. Беззнаковое и знаковое деление

 

Повышение производительности.

При делении на степень числа 2 (2, 4 и т.д.) более эффективен сдвиг вправо на требуемое количество битов. В следующих примерах предположим, что делимое находится в регистре AX:

Деление на 2:

SHR AX,1

Деление на 8:

MOV CL.3

SHR AX,CL

Переполнения и прерывания

Используя команды DIV и особенно IDIV, очень просто вызвать переполнение. Прерывания приводят (по крайней мере в системе, используемой при тестировании этих программ) к непредсказуемым результатам. В операциях деления предполагается, что частное значительно меньше, чем делимое. Деление на нуль всегда вызывает прерывание. Но деление на 1 генерирует частное, которое равно делимому, что может также легко вызвать прерывание.

Рекомендуется использовать следующее правило: если делитель - байт, то его значение должно быть меньше, чем левый байт (АН) делимого; если делитель - слово, то его значение должно быть меньше, чем левое слово (DX) делимого.

Проиллюстрируем данное правило для делителя, равного 1:

Операция деления:

Делимое Делитель Частное

Слово на байт: 0123 01 (1)23

Двойное слово на слово: 0001 4026 0001 (1)4026

В обоих случаях частное превышает возможный размер. Для того чтобы избежать подобных ситуаций, полезно вставлять перед командами DIV и IDIV соответствующую проверку. В первом из следующих примеров предположим, что DIVBYTE - однобайтовый делитель, а делимое находится уже в регистре AX. Во втором примере предположим, что DIVWORD - двухбайтовый делитель, а делимое находится в регистровой паре DX:AX.

Слово на байт Двойное слово на байт

CMP AH,DIVBYTE CMP DX,DIVWORD

JNB;переполнение JNB;переполнение

DIV DIVBYTE DIV DIVWORD

 

Для команды IDIV данная логика должна учитывать тот факт, что либо делимое, либо делитель могут быть отрицательными, а так как сравниваются абсолютные значения, то необходимо использовать команду NEG для временного перевода отрицательного значения в положительное.

Деление вычитанием

Если частное велико, а делитель маленький, то деление можно выполнить с помощью циклического вычитания. Метод заключается в том, что делитель вычитается из делимого и в этом же цикле частное увеличивается на 1. Вычитание продолжается до тех пор, пока делимое остается больше делителя. В следующем примере делитель находится в регистре AX, а делимое - в EBX, частное вырабатывается в CX:

SUB CX,CX;Очистка частного

С20: CMP AX,BX;Если делимое < делителя,

JB СЗ0;то выйти

SUB AX,BX;Вычит. делит. из делимого

INC CX;Инкремент частного

JMP С20;Повторить цикл

СЗ0: RET;Частное в CX, остаток в AX

В конце подпрограммы регистр CX будет содержать частное, а AX - остаток. Пример умышленно примитивен, цель его -продемонстрировать данный способ деления. Если частное получается в регистровой паре DX:AX, то необходимо сделать два дополнения:

1. В метке С20 сравнивать AX и BX только при нулевом DX.

2. После команды SUB вставить команду SBB DX,00 (Вычитание с заимствованием).

Примечание: очень большое частное и малый делитель могут вызвать тысячи циклов.

4.13.4 Преобразование знака

Команда NEG обеспечивает преобразование знака двоичных чисел из положительного в отрицательное и наоборот. Практически команда NEG устанавливает противоположные значения битов и прибавляет 1. Примеры:

NEG AX

NEG BL

NEG BINAMT;(байт или слово в памяти)

Преобразование знака для 64-битового (или большего) числа включает большее количество шагов. Предположим, что регистровая пара EDX:EAX содержит 64-битовое двоичное число. Так как команда NEG не может обрабатывать два регистра

одновременно, то ее использование приведет к неправильному результату. Ниже показано применение команды NOT:

NOT EDX Инвертирование битов

NOT EAX Инвертирование битов

ADD EAX,1 Прибавление 1 к EAX

ADC EDX, 0 Прибавление переноса к EDX

Остается одна незначительная проблема: над числами, представленными в двоичном формате, удобно выполнять арифметические операции, если сами числа определены в программе. Данные, вводимые в программу с дискового файла, могут также иметь двоичный формат. Но данные, вводимые с клавиатуры, представлены в ASCII-формате. Хотя ASCII-коды удобны для отображения и печати, они требуют специальных преобразований в двоичный формат для арифметических вычислений.

Выводы

В настоящем разделе были рассмотрены системы команд процессоров Intel IA-32. Так как эта система команд IA-32 основана на архитектуре CISC, то в ней реализован широчайший набор команд для выполнения самых разных операций над различными типами данных.

 

 



Поделиться:


Последнее изменение этой страницы: 2016-09-13; просмотров: 471; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.137.189.236 (0.007 с.)