ГЛАВА 10
АРИФМЕТИЧЕСКИЕ КОМАНДЫ
(часть 7/7)
Изменение размера числа Пусть к числу из регистра BX надо прибавить число из регистра AL (BX+AL  BX). Здесь требуется сложить слово с байтом, но команды для сложения слова с байтом не существует, поэтому сперва требуется сделать равными размеры этих чисел, а именно расширить байт, содержащийся в AL, до слова, записав его, скажем, в регистр AX, и только затем сложить числа из регистров AX и BX. Если число в регистре AL трактуется как беззнаковое, то для расширения байта до слова требуется записать 0 в регистр AH – это беззнаковое расширение. Для чисел со знаком, если число отрицательное – слева требуется дописать двоичные единички, а если положительное – нули. Для осуществления расширения чисел со знаком в систему команд введены специальные команды. Команды CBW, CWD, CWDE, CDQ, CQO Команды с фиксированым месторасположением операнда и результата.
CBW – Convert Byte to Word – Знаковое расширение содержимого регистра AL до слова в AX
 при
 при 
По команде CBW операнд всегда берется из AL, а результат всегда записывается в AX. Команда CBW пишет в регистр AH число 00h или 0FFh в зависимости от знака числа из регистра AL.
CWD – Convert Word to Double word – Знаковое расширение содержимого регистра AX до двойного слова в регистрах AX: DX
 при
 при 
Для CWD операнд всегда берется из AX, а результат всегда записывается в DX:AX. Команда CWD записывает в регистр DX число 0 или 0FFFFh в зависимости от знака числа из регистра AX.
CWDE – Convert Word to Double Extend word – Знаковое расширение содержимого регистра AX до двойного расширенного слова в EAX
Старшая часть  при 
Старшая часть  при 
Команда CWDE преобразует слово со знаком, находящееся в регистре AX, в двойное слово со знаком, помещаемое в регистр EAX, распространением старшего бита регистра AX в два старших байта регистра EAX:
CDQ – Convert Double word to Quadruple word – Знаковое расширение содержимого регистра EAX до учетверенного слова в регистрах EAX:EDX
 при
 при 
Команда CDQ преобразует двойное слово со знаком, находящееся в регистре EAX, в 64-битовое целое со знаком, помещаемое в регистры EDX:EAX, распространением старшего бита регистра EAX по всем битам регистра EDX.
CDQE – Convert Double word to Quadruple Extend word – Знаковое расширение содержимого регистра EAX до учетверенного расширенного слова в RAX
CQO – Convert Quadruple to Octal word – Знаковое расширение содержимого регистра RAX до восьми слов в регистрах RAX:RDX
Псевдокод команды: IF OperandSize = 16 ;CBW
THEN AX  SignExtend(AL)
ELSE IF OperandSize = 32 ;CWDE
THEN EAX  SignExtend(AX);
ELSE IF 64-Bit Mode and OperandSize = 64 ;CDQE
THEN RAX  SignExtend(EAX);
ENDIF;
IF OperandSize = 16 ;CWD
THEN DX  SignExtend(AX)
ELSE IF OperandSize = 32 ;CDQ
EDX  SignExtend(EAX);
ELSE IF 64-Bit Mode and OperandSize = 64 ;CQO
RDX  SignExtend(RAX);
ENDIF;
Применение: перед командой IDIV для расширения AL/AX/EAX на AH/DX/EDX перед делением с 8/16/32-битным операндом. Если в AL/AX/EAX беззнаковое число менее 80h/8000h/80000000h, инструкцию CBW/CWD/CDQ можно использовать для обнуления AH/DX/EDX (длина команды CBW/CWD/CDQ 1 байт в отличие от двухбайтовых команд
sub или xor).
| Команда | Эквивалент |
|---|
| cbw | movsx ax, al | | cwde | movsx eax, ax | | movsx eax,al | cbw cwde | | cdq | mov edx,eax sar edx,31 | | cdq | mov edx,80000000h cmp edx,eax sbb edx,edx | | cdq | xor edx,edx cmp eax,edx setge dl dec edx | | cdq | xor edx,edx or ebx,-1cmp eax,edx cmovl edx,ebx |
Фиксированное местонахождение операнда и результата делают команды CBW, CWD, CWDE, CDQ, CDQE и CQO не очень удобными. Поэтому для процессора i80386 и выше созданы команды знакового расширения MOVSX и беззнакового расширения MOVZX, читающие содержимое по указанному адресу (из регистра или памяти) и записывающие расширенный результат в указанную ячейку памяти или любой регистр.
Кодировка CBW/CWD/CWDE/CDQ/CDQE/CQO
| команда | опкод | описание | | CBW | 66h 98h | AX SignExtend(AL) | | CWDE | 98h | EAX SignExtend(AX) | | CDQE | REX.W+98h | RAX SignExtend(EAX) | | CWD | 66h 99h | DX:AX SignExtend(AX) | | CDQ | 99h | EDX:EAX SignExtend(EAX) | | CQO | REX.W+99h | RDX:RAX SignExtend(RAX) |
Видно, что коды инструкций CBW/CWDE/CDQE и коды CWD/CDQ/CQO совпадают, но в 32-разрядном режиме перед CBW и CWD стоит префикс размера операнда 66h, а в 64-разрядном режиме – перед CDQE и CQO.
Команда MOVZX
(Пересылка с нулевым расширением =”MOVE and Zero EXTENSION”) Синтаксис команды: MOVZX <DEST>,<SRC> Возможные варианты команды:
movzx reg,reg/mem
Семантика команды: преобразование элементов без знака меньшей размерности в эквивалентные им элементы без знака большей размерности.
Псевдокод команды: DEST  ZeroExtend(SRC) Алгоритм работы: - считать содержимое операнда SRC;
- записать содержимое операнда SRC в операнд DEST, начиная с его младших разрядов;
- распространить двоичный нуль на свободные старшие разряды операнда DEST.
Применение: команду MOVZX обычно используют для получения эквивалентного, но большего по размеру операнда без учета знака. Она может быть использована для согласования операндов различной размерности. Но не следует думать, что все эти разнотипные пересылки делает одна машинная команда. На самом деле существует несколько машинных команд, каждая из которых работает со своими размерами операндов. Генерацию нужной команды обеспечивает транслятор на основе анализа исходного текста программы: | Assembler | 1
2
3
4
5
| mov al,0FFh
movzx bx,al ;bx=00FFh
;или из памяти
sl db ?
movzx eax,byte ptr sl |
|
| команда | эквивалент | эквивалент | команда | эквивалент | эквивалент |
|---|
| movzx ebx,al | xor ebx,ebx mov bl,al | mov bl,al and ebx,0FFh | movzx eax,si | lea eax,[si] | movzx eax,al | Команда MOVSX
(Пересылка со знаковым расширением ” MOVE and Sign E XTENSION”) Синтаксис команды:
MOVSX < DEST>,< SRC>
Возможные варианты команды:
movsx reg,reg/mem
Семантика команды: преобразование элементов со знаком меньшей размерности в эквивалентные им элементы со знаком большей размерности.
Псевдокод команды:
DEST  SignExtend(SRC)
Алгоритм работы: - считать содержимое операнда SRC;
- записать содержимое операнда SRC в операнд DEST, начиная с младших разрядов операнда DEST;
- распространить значение знакового разряда на свободные старшие разряды операнда DEST.
Применение: команду MOVSX обычно используют для получения эквивалентного, но большего по размеру операнда со знаком. Это может понадобиться для приведения размера операнда к нужному значению с целью обеспечения работы следующих команд программы: | Assembler | 1
2
| MOV AL,0FFh
MOVSX BX,AL ;BX=0FFFFh |
|
Команда PMOVMSKB
( =”Packed MOVE Byte Mask to integer”) Синтаксис команды:
PMOVMSKB <DEST>,<SRC>
Возможные варианты команды:
pmovmask reg32/64,mmx
pmovmask reg32/64,xmm
Семантика команды: формирование байта, содержащего знаковые биты восьми байтов, содержащихся в операнде SRC, в качестве которого может выступать один из MMX-регистров. Операндом DEST является 32-/64-разрядный регистр общего назначения, младший байт которого будет содержать результат. Если в качестве операнда SRC использован один из XMM-регистров, то будет сформировано два байта, содержащие знаковые биты шестнадцати упакованных байтов.
Псевдокод команды: r32[0]  SRC[07];
r32[1]  SRC[15];
r32[2]  SRC[23];
r32[3]  SRC[31];
r32[4]  SRC[39];
r32[5]  SRC[47];
r32[6]  SRC[55];
r32[7]  SRC[63];
r32[31:8]  ZERO_FILL;
Применение: команда PMOVMSKB удобна для формирования условных ветвлений по таблице. Контрольные вопросы и упражнения - Имеются следующие данные:
| Assembler | 1
2
3
4
| DATAX DW 0148h
DW 2316h
DATAY DW 0237h
DW 4D52h |
|
Напишите программы для сложения:- переменной DATAX, размером в слово, с переменной DATAY, размером в слово;
- переменной DATAX, размером в двойное слово, с переменной DATAY, размером в двойное слово.
- Объясните к чему приведет действие следующих команд:
| Assembler | 1
2
3
| STC
MOV EBX,DATAX
ADC EBX,DATAY |
|
- Составьте программу:
- сложения переменных из ячеек памяти OP1 и OP2, передачи суммы в ячейку OP2 и перехода к метке ADDOVF в случае переполнения;
- вычитания переменных из ячеек памяти OP2 и OP1, передачи разности в OP2 и перехода к метке SUBVF в случае переполнения.
- Напишите программы для умножения, используя только команды для микропроцессора i286:
- переменной DATAX, размером в слово на переменную DATAY, размером в слово;
- переменной DATAX, размером в двойное слово на переменную DATAY, размером в двойное слово (подсказка: необходимо представить произведение
как и использовать команды MUL, ADD и ADC).
- Напишите программы для деления:
- переменной DATAX, размером в слово, на 23;
- переменной DATAX, размером в двойное слово, на переменную DATAY, размером в слово.
- Запишите команду увеличения на единицу значения переменной DATAX.
- Какой делитель, кроме нуля, вызывает ошибку переполнения?
- Запишите последовательность команд вычитания из переменной DATAX переменной DATAY.
- Пусть регистр AL=0B4h и регистр BL=11h. Почему после команды IMUL BL в регистре AX число 0FAF4h, а после команды MUL BL в регистре AX число 0BF4h?
- Предположим, что значение переменной DATAX увеличено на единицу с помощью команды ADD. Как это повлияет на содержимое флагов CF, OF, PF и SF?
- Пусть регистр AX=0400h и регистр BL=0B4h. Почему после команды IDIV BL в регистре AX число 24F3h, а после команды DIV BL в регистре AX число 7C05h?
- Напишите программу для беззнакового деления переменной, размером в 6 байтов, на переменную, размером в слово, используя только команды для микропроцессора i286. Подсказка: необходимо представить делимое как
, а делитель как ; первое деление на даст частное и остаток ; второе деление на – частное и остаток ; третье деление на – частное и остаток ; результатом будет частное и остаток .
- Напишите программу для беззнакового деления переменной, размером в n слов, на переменную, размером в слово.
- Алгоритм беззнакового деления с двойной точностью числа
на число заключается в следующем. Вычислить такие и , что ( частное от деления на , а остаток). Но равенство означает, что . Число считается остатком первоначального деления; если оно отрицательно, следует производить повторяющийся декремент до тех пор, пока оно не станет положительным. Напишите программу, реализующую данный алгоритм.
- Напишите программу, которая определит какое умножение более быстрое: умножение командой MUL, умножение из сдвигов и сложений или умножение по алгоритму Бутса.
- Напишите программу, которая определит какое деление более быстрое:
деление командой DIV, умножение из сдвигов и вычитаний или по алгоритму деления без восстановления.
- Напишите программы, которые выполняют следующие действия:
;
;
остаток;
.
- Ассемблерный PUZZLE:
- в регистре AL число –63, поставьте в правильном порядке операции
NEG AL;
INC AL;
SAR AL,1;
SUB AL,32,
чтобы после выполнения всех операций AL стал равным 0;
- в регистре AL число –70, поставьте в правильном порядке следующие операции:
ADD AL,19;
SAL AL,1;
DEC AL;
DEC AL;
SUB AL,–123,
чтобы после выполнения всех операций AL стал равным 0;
- в регистре AL число –83, поставьте в правильном порядке следующие операции:
NEG AL;
ADD AL,93;
NEG AL;
SAL AL,1;
NEG AL;
SUB AL,–1,
чтобы после выполнения всех операций AL стал равным 0;
- в регистре AL число –31, поставьте в правильном порядке следующие операции
ADD AL,–78;
SUB AL,82;
SAR AL,1;
ADD AL,79;
ADD AL,–125;
SUB AL,–53,
чтобы после выполнения всех операций AL стал равным 0;
- Оформите приведённую ниже последовательность команд в виде программы, зафиксировав в комментариях для каждой команды причину изменения того или иного флага и указав содержимое регистра, изменившего своё значение:
| Assembler | 1
2
3
4
| mov ax,7FF0h
add al,10h
add ah,1
add ax,2 |
|
| Assembler | 1
2
3
4
5
6
| mov ax,0
mov cx,0
mov al,0F0h
mov cl,78h
add al,cl
adc ah,ch |
|
| Assembler | 1
2
3
| mov ax,0
sub al,1
mov al,–128 |
|
| Assembler | 1
2
3
4
5
6
| mov ax,0
mov bx,0
mov al,22
mov bl,26
sub al,bl
sbb ah,0 |
|
| Assembler | 1
2
| mov ax,30000
shl ax,1 |
|
| Assembler | 1
2
3
4
| mov ax,0
mov al,0
mov bl,255
mul bl |
|
| Assembler | 1
2
3
4
| mov dx,0
mov ax,2
mov bx,3
div bx |
|
| Assembler | 1
2
3
| mov ax,23
mov bl,–5
idiv bl |
|
- Напишите программу, демонстрирующую последовательную установку флагов ZF, SF, CF, OF в единицу, используя только арифметические команды: ADD, SUB, INC, DEC и NEG.
- Запишите последовательность из двух команд, при выполнении которых одновременно устанавливаются флаги CF и OF. Объясните причину изменения состояния указанных флагов.
- Преобразовать приведённые ниже адреса, используемые процессором в реальном режиме и заданные в форме «сегмент-смещение» (в шестнадцатеричной системе счисления), в линейные:
- 0950:0100;
- 0CD1:02E0.
Результат вывести на экран.
- Напишите программу сложения трёх целых чисел, введённых с клавиатуры в регистры процессора, отображая изменения значений регистров на экране дисплея.
- Напишите программу вычитания трёх целых чисел, введённых с клавиатуры в регистры процессора, отображая изменения значений регистров на экране дисплея.
- Напишите программу перемножения трёх целых чисел, введённых с клавиатуры в регистры процессора, отображая изменения значений регистров на экране дисплея.
- Напишите программу получения остатка от деления целого числа
(однобайтного или двухбайтного) на целое однобайтное число . Ввод чисел в регистры процессора осуществите с клавиатуры. Результаты изменения значений регистров отобразите на экране дисплея.
- Действительно ли, что операция целочисленного умножения выполняется быстрее операции целочисленного деления?
- Напишите программу получения суммы остатков от деления целых двухбайтных чисел
, и на целое однобайтовое число . Ввод чисел в регистры процессора осуществите с клавиатуры. Результат поместите в регистр AX с отображением его значения на экране.
- Напишите программу, вычисляющую площадь квадрата по данной его диагонали, введённой с клавиатуры.
- Напишите программу, вычисляющую площадь трапеции по данным её основаниям и высоте, введённым с клавиатуры.
- Напишите программу, вычисляющую площадь треугольника по данным его основанию и высоте, введённым с клавиатуры.
- Напишите программу, вычисляющую площадь ромба по данным его диагоналям, введённым с клавиатуры.
- Напишите программу, вычисляющую квадрат диагонали прямоугольника по данным его двум сторонам, введённым с клавиатуры.
- Напишите программу, вычисляющую периметр и площадь прямоугольника по данным его сторонам, введённым с клавиатуры.
- Напишите программу, вычисляющую объём прямоугольного параллелепипеда по заданным длинам его рёбер, введённым с клавиатуры.
- Напишите программу, вычисляющую площадь боковой поверхности куба по заданной длине его ребра.
- Напишите программу, вычисляющую полную поверхность прямоугольного параллелепипеда по заданным длинам его рёбер.
- Напишите программу, определяющую координаты вершины параболы
по данным коэффициентам , , , введённым с клавиатуры.
- Напишите программу по вычислению значения выражения при различных значениях
, вводимых с клавиатуры: . В комментариях программы поясните, при каких значениях программа выдаёт ошибку или неправильный результат и почему.
- По фрагменту программы восстановите функцию
:| Assembler | 1
2
3
4
5
6
7
8
9
10
11
| mov bx,[x]
mov ax,bx
imul al
dec ax
xchg ax,bx
imul al
shl ax,1
mov cx,8
sub cx,ax
mov ax,cx
idiv bl |
|
- По фрагменту программы восстановите арифметическое выражение с переменными
, :| Assembler | 1
2
3
4
| mov ax,[a]
mov bx,[b]
add ax,bx
shl ax,1 |
|
- По фрагменту программы восстановите арифметическое выражение с переменными
, , :| Assembler | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| mov ax,[a]
mov bx,[b]
mov cx,[z]
add bx,cx
add ax,bx
shr ax,1
mov bx,ax
mov cx,[a]
sub ax,cx
mul bx
mov cx,[b]
sub bx,cx
mul bx
add bx,cx
mov cx,[z]
sub bx,cx
mul bx |
|
- Пусть в регистре MM0 находится число 000180007F380001h, а в регистре MM2 – число 00020001E8E9FFFFh. Что окажется в MM0 в результате следующих вычитаний?
- psubw MM0,MM2;
- psubusw MM0,MM2;
- psubsw MM0,MM2.
0
|