Базовые операции над целочисленными данными 


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



ЗНАЕТЕ ЛИ ВЫ?

Базовые операции над целочисленными данными



Команда XCHG позволяет совершить обмен значений двух операндов. В качестве операндов должны выступать регистры или ячейки памяти. Операнды должны быть одинаковой длины. Например, команда xchg eax,Z произведён обмен значений между регистром eax и двойным словом Z.

Команды INC и DEC (Increment и Decrement) прибавляют и вычитают единицу из указанного операнда. Например, команда inc X увеличивает на 1 значение переменной X, а команда dec ebx уменьшает на единицу содержимое регистра ebx.

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

Для получения полной информации по этим и другим командам процессора Intel достаточно заглянуть в Приложение Б или воспользоваться англоязычной справкой masm32 ® Help ® Opcodes Help.

Для умножения и деления 8-, 16- и 32-разрядных целых чисел в процессоре Intel предусмотрены четыре команды: MUL, DIV, IMUL, IDIV. Эти команды кроме объявленных действий изменяют флаги, однако суть этих изменений мы рассмотрим в следующем параграфе.

Команда MUL служит для умножения 8-, 16- и 32-разрядного беззнакового целого числа, находящегося в одном из регистров общего назначения или в памяти, с операндом, расположенным в аккумуляторе (AL, AX, EAX). Расположение множимого, множителя и произведения зависит от размера множимого:

Таблица 1.2.1. Расположение множимого, множителя

Множимое Множитель Произведение
AL reg / mem8 AX
AX reg / mem16 DX:AX
EAX reg / mem32 EDX:EAX

Чтобы в результате не возникло переполнения, размер памяти, отводимый под произведение, должен в два раза превышать размер множимого и множителя.

Синтаксис команды MUL предусматривает указание только одного операнда, являющегося множителем. Множимое указывать в команде не надо, т.к. оно всегда расположено в аккумуляторе – это особенность архитектуры процессоров Intel.

Пример 1.2.7. В приведённой ниже программе выполняется умножение 8-разрядных чисел без знака (5´10h = 50h), в результате чего получается 16-разрядное число 0050h, которое размещается в регистре AX:

.code

start:

mov al, 5h; al=5h

mov bl, 10h; bl=10h

mul bl; ax=0050h

PrintHex ax

ret

end start

Пример 1.2.8. В приведённой ниже программе выполняется умножение 16-разрядных чисел без знака (100h´2000h = 200000h), в результате чего получается 32-разрядное число 00200000h, которое размещается в регистровой паре DX:AX таким образом, что младшие 16 разрядов произведения записываются в регистр AX, а старшие 16 разрядов – в регистр DX:

.data

X word 2000h

.code

start:

mov ax,100h; ax=100h

mul X; dx:ax=00200000h

PrintHex ax; ax=0000h

PrintHex dx; dx=0020

ret

end start

Пример 1.2.9. В приведённой ниже программе выполняется умножение 32-разрядных чисел без знака (12345h´100000h = 1234500000h), в результате чего получается 64-разрядное число 0000001234500000h, которое размещается в регистровой паре EDX:EAX

.code

start:

mov eax,12345h; eax=12345h

mov ecx,100000h; ecx=100000h

mul ecx; edx:eax=0000001234500000h

PrintHex eax; eax=34500000h

PrintHex edx; edx 00000012h

ret

end start

Команда IMUL служит для умножения целых чисел со знаком. Результат умножения является знаковым. Формат команды IMUL отличается от команды MUL.

Один операнд:

IMUL reg8/mem8; ax = al * reg8/mem8

IMUL reg16/mem16; dx:ax = ax * reg16/mem16

IMUL reg32/mem32; edx:eax = eax * reg32/mem32

Два операнда:

IMUL reg16,reg16/mem16/imm; reg32=reg16*reg16/mem16/imm

IMUL reg32,reg32/mem32/imm; reg32=reg32*reg32/mem32/imm

Три операнда:

IMUL reg16,reg16/mem16,imm; reg16=reg16/mem16*imm

IMUL reg32,reg32/mem32,imm; reg32=reg32/mem32*imm

Пример 1.2.10. В приведённой ниже программе выполняется умножение 8-разрядных чисел со знаком (30h ´ 4 = С0h), в результате чего получается 16-разрядное число 00С0h, которое размещается в регистре AX:

.code

start:

mov al, 30h; al=30h

mov bl, 4h; bl=4h

imul bl; ax=00C0h

PrintHex ax

ret

end start

Пример 1.2.11. В приведённой ниже программе выполняется умножение 8-разрядных чисел со знаком (-4 ´ 4 = FFF0h), в результате чего получается 16-разрядное число FFF0h (-16), которое размещается в регистре AX:

.code

start:

mov al, -4h; al=-4h (в дополнительном коде FC)

mov bl, 4h; bl=4h

imul bl; ax=FFF0h

PrintHex ax

ret

end start

Команда DIV служит для деления на 8-, 16- и 32-разрядное беззнаковое целое число, находящееся в одном из регистров общего назначения или в памяти, операнда, расположенного в регистрах AX, DX:AX или EDX:EAX.

Расположение делимого, делителя, частного и остатка зависит от размера делителя:

Таблица 1.2.2. Расположение исходных данных и результатов деления

Делимое Делитель Частное Остаток
AX reg / mem8 AL AH
DX:AX reg / mem16 AX DX
EDX:EAX reg / mem32 EAX EDX

Пример 1.2.12. В приведённой ниже программе выполняется деление на 8-разрядное число без знака (25h / 2 = 12h), в результате чего получается 8-разрядное частное 12h и остаток 1, которые размещаются в регистрах AL и AH соответственно:

.code

start:

mov ax, 25h; ax=25h

mov bl, 2h; bl=2h

div bl; ax=0112h (остаток=01, частное = 12h)

PrintHex ax

ret

end start

Команда IDIV служит для деления целых чисел со знаком. Она имеет те же форматы операнда, что и команда DIV. При делении на 8‑разрядное число, перед выполнением команды IDIV при необходимости нужно расширить знак делимого в регистр AH с помощью команды CBW (Convert byte to word).

Пример 1.2.13. В приведённой ниже программе выполняется деление числа -48 на 5:

.data

X sbyte -48d

.code

start:

mov al,X; al=-48d

cbw; расширяем знак регистра AL в AH

mov bl,5; bl=5d

idiv bl

PrintDec al; al=-9d

PrintDec ah; ah=-3d

ret

end start

При делении на 16-разрядное число, необходимо вначале расширить знак делимого, находящегося в регистр AX, в регистр DX с помощью команды CWD (Convert word to Doubleword).

Пример 1.2.14. В приведённой ниже программе выполняется деление числа -48 на 5:

.data

X sword -5004d

.code

start:

mov ax,X; ax=-5004d

cwd; расширяем знак регистра AX в DX

mov bx,500d; bx=500d

idiv bx

PrintDec ax; ax=-10d

PrintDec dx; dx =-4d

ret

end start

При делении на 32-разрядное число, необходимо вначале расширить знак делимого, находящегося в регистр AX, в регистр DX с помощью команды CDQ (Convert Doubleword to Quardword).

Пример 1.2.15. В приведённой ниже программе выполняется деление числа -48 на 5:

.data

X sdword -50004d

.code

start:

mov eax,X; eax=-5004d

cdq; расширяем знак регистра EAX в EDX

mov ebx,5000d; ebx=500d

idiv ebx

PrintDec eax; eax=-10d

PrintDec edx; edx =-4d

ret

end start

Упражнения для закрепления материала

Упражнение 1.2.4. Напишите последовательность команд, в которой умножается число -5 на 3 и результат записывается в 16-разрядную переменную со знаком.

Упражнение 1.2.5. Напишите последовательность команд, в которой число -276 делится на 10 и результат записывается в 16-разрядную переменную со знаком.

Упражнение 1.2.6. Напишите программу для вычисления 5!=1×2×3×4×5. Результат сохраните в переменную без знака.

Упражнение 1.2.7. Объявите в программе массив десятичных чисел 1, -2, 3, -4, 5 и найдите сумму его элементов.

Упражнение 1.2.8. Объявите в программе массив чисел 1h, 123h, 12345h, 1234567h и найдите сумму его элементов.

Упражнение 1.2.9. Объявите в программе строку с Вашей фамилией и вычислите произведение ASCII-кодов первого и последнего символов фамилии.

Упражнение 1.2.10. Объявите в программе переменную 12345678h и вычислите произведение старшей и младшей половины числа. Результат сохраните в другой переменной.

Вопросы для самопроверки

1. В каком случае операторы SIZEOF и LENGTHOF вернут одинаковые значения?

2. Каково отличие между оператором offset и командой lea?

3. В чём отличие ближних и дальних указателей?

4. Для чего используются команды расширения целых чисел?

5. В чём отличие команды NEG и команды NOT?

6. В чём отличие формата команды IMUL от формата команды MUL?

6. Как работают трёхаргументные команды умножения целых чисел со знаком?

7. Почему размер произведения больше размера любого из множителей в два раза?

8. Для чего используются команды расширения знака делимого?

Управление вычислительным процессом

Использование стека

Команда push помещает в стек двухбайтовое число из регистра, памяти или непосредственно указанное в команде число, предварительно уменьшив содержимое указателя стека ESP на 4. Команда pop выталкивает из стека двухбайтовое число и размещает его в двухбайтовом регистре или памяти, после чего увеличивает регистр ESP на 4. Таким образом, стек растёт в сторону меньших адресов, а уменьшается в сторону б о льших адресов.

Важно соблюдать в программе баланс команд push и pop: сколько раз в программе была выполнена команда push, столько же раз должна быть выполнена команда pop. Если это правило не соблюдать, то при завершении программы будет потерян адрес возврата.

Пример 1.3.1. Ниже приведена программа, демонстрирующая различные способы работы со стеком.

.486

.model flat, stdcall

option casemap: none

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

include \masm32\include\masm32.inc

include \masm32\include\debug.inc

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\masm32.lib

includelib \masm32\lib\debug.lib

.data

Z dword 12345678h

.code

start:

mov ebx, 0AAAAAAAAh

PrintHex esp; esp=0012FFA4h

push ebx

PrintHex esp; esp=0012FFA0h

push Z

PrintHex esp; esp=0012FF9Ch

push 12345678h

PrintHex esp; esp=0012FF98h

pop Z

PrintHex esp; esp=0012FF9Ch

pop ebx

PrintHex esp; esp=0012FFA0h

pop ecx

PrintHex esp; esp=0012FFA4h

ret

end start

Упражнение 1.3.1. Определите содержимое переменной Z и используемых регистров после завершения работы программы из примера 1.3.1.

Дополнительные стековые команды:

· pushfd – помещает в стек содержимое регистра флагов EFLAGS.

· popfd – выталкивает из стека двухбайтовое число и помещает его в регистр EFLAGS.

· pushad – помещает в стек значения всех 32-разрядных регистров общего назначения в следующем порядке: EAX, ECX,EDX, EBX, ESP (то значение, которое было до выполнения команды), EBP, ESI, EDI.

· popad – выполняет обратную операцию, т.е. восстанавливает из стека значения указанных регистров в обратном порядке.

Упражнение 1.3.2. Разработайте программу вывода на печать содержимого регистра флагов в шестнадцатеричном представлении.



Поделиться:


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

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