ASM: Лекция
Програмні регістри|реєстри|
Регістри - ділянки високошвидкісної пам'яті, розташовані в ЦПУ.
Регістри|реєстри| загального|спільного| призначення
Використовуються для виконання арифметичних операцій і пересилки даних. До кожного регістру| можна звернутися|обертатися| як до 32-розрядного або як до 16-розрядного регістра,|реєстру| або як до двох 8-розрядних регістрів|. Наприклад, регістр|реєстр| ЕАХ, АХ, АН або AL|.
Частина|частку| регістрів|реєстрів| мають особливе значення.
ЕАХ - акумулятор (accumulator). Автоматично використовується при виконанні команд множення і ділення.
ЕСХ - лічильник циклу.
Регістр покажчика команд EIP - зберігається адреса наступної виконуваної команди.
Регістр|реєстр| ознак (прапорів) EFLAGS| - Кожен біт цього регістра відображає|відбиває| результат виконання арифметичної чи логічної команди ЦПУ або деяку іншу інформацію . |реєстру|
Якщо прапор встановлений, то значення відповідного йому біта дорівнює 1, а коли скинутий - 0.
Наприклад, ZF - прапор нуля (Zero flag)- встановлюється, якщо при виконанні операції виходить число, рівне нулю. SF - прапор знаку (Sign flag) - встановлюється, якщо при виконанні операції виходить відємне число.
Основні команди цілочисельної арифметики.
Команда MOV|
Mov приймач, джерело
Приклад: скопіювати значення з|із| однієї області пам'яті в іншу
include| irvine32|.inc
.data
n1 DWORD 15
n2 DWORD ?
.code
main PROC
mov eax,n1
mov n2,eax
mov ebx, eax
mov n1,3
exit
main endp
end main
Неправильні записи команд:
mov n1,n2 ; Обидва операнди не можуть бути комірками пам’яті.
mov ах, bl ; Обидва операнди мають бути одного розміру:
Приклад. Скопіювати значення BL| в регістр|реєстр| АХ.
...
main PROC
mov ah,0
mov al,bl
...
Якщо довжина операндів різна, можна використовувати директиву PTR|:
Тип ptr| [вираз|вираження|]
Приклад.
Include| irvine32|.Inc
.data
n1 DWORD 12345678h ; в пам’яті - 00404000 : 78 56 34 12
.code
main PROC
mov ah, BYTE PTR n1 ; eax – 00 00 78 00
exit
main endp
end main
Команди додавання.
add операнд_1,операнд_2
операнд_1 = операнд_1 + операнд_2
Приклади:
mov| ах, 8 ;заносим у АХ число 8
mov| сх|, 6 ;заносим у СХ число 6
mov| dx|, сх| ;копируем СХ в DX|, DX| = 6
add| dx|, ах ;DX = DX| + АХ
Команда інкремента.
inc операнд
операнд = операнд + 1
Команди віднімання.
sub операнд_1,операнд_2
операнд_1 = операнд_1 - операнд_2
Команда декремента .
dec операнд
операнд = операнд - 1
Целочисельне множення і ділення.|поділ|
В результаті|унаслідок| множення двох чисел можна отримати|одержувати| число, діапазон якого в два рази перевищуватиме діапазон операндів.
Ці команди спроектовані так, що один з операндів і результат знаходяться|перебувають| у фіксованому регістрі|реєстрі|, а другий операнд указується|вказує| програмістом.
Команди множення.
MUL (беззнакові операнди) і IMUL (знакові)
Мнемокод_команди операнд_1
Другий операнд - співмножник заданий неявно в залежності від розміру першого операнда.
-
Операнд 1
Операнд 2
(за умовчанням)
Результат
Байт
AL|
AL| - молодша частина|частка| результату;
АН - старша частина результату
Слово
АХ
AX - молодша частина результату; DX - старша частина результату
Подвійне слово
ЕАХ
ЕАХ - молодша частина|частка| результату
EDX - старша частина результату
Приклад 1. Помножити значення, збережені в регістрах|реєстрах| ВН і CL|:
Include| irvine32|.Inc
.code
main PROC
mov BH,2
MOV CL,3
mov al,bh ; AL = ВН - заносимо в AL другий операнд
mul CL ; АХ = AL * CL - множимо його на CL
exit
main endp
end main
Вміст регістрів|реєстрів| до виконання команди множення :
BX |
|||||||||||||||
BH=2 |
BL |
||||||||||||||
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
|
|
|
|
|
|
|
|
0 |
2 |
|
|
-
CX
CH
CL=3
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
3
Оскільки операнди команди множення по умові задачі - однобайтові, то для виконання команди множення необхідно|треба| підготувати регістр|реєстр| AL : mov AL, BH
-
AX
AH
AL=2
0
0
0
0
0
0
1
0
0
2
Вміст регістра|реєстру| AX після виконання команди множення :
-
AX=6
AH
AL
0
0
0
0
0
1
0
1
0
0
0
6
Приклад 2. Перемножити беззнакові цілі числа 155 і 140 , збережені в регістрах|реєстрах| ВН і CL|:
Результат множення чисел 155*140=21700 не вміщається в один байт, тому результат буде розміщуватися в двох регістрах: AL – молодша частина числа, AH – старша.
Вміст регістрів|реєстрів| до виконання команди множення :
BX |
|||||||||||||||
BH=155 |
BL |
||||||||||||||
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
|
|
|
|
|
|
|
|
9 |
B |
|
|
-
CX
CH
CL=140
0
0
0
0
0
0
0
0
1
0
0
0
1
1
0
0
8
С
Вміст регістра|реєстру| AX до виконання команди множення :
-
AX
AH
AL=BH=155
1
0
0
1
1
0
1
1
9
В
Вміст регістра|реєстру| AX після виконання команди множення :
-
AX=21700
AH
AL
0
1
0
1
0
1
0
0
1
1
0
0
0
1
0
0
5
4
С
4
Для розв’язання наступного прикладу введемо декілька понять.
Є можливість|спроможність| створити одне довге ціле число на основі двох коротких цілих чисел.
Приклад|зразок|. Завантажити 32-розрядне значення, що складається з|із| чотирьох 8-розрядних змінних, в регістр|реєстр| ЕАХ.
include irvine32.inc
.data
LongValue LABEL DWORD
vall BYTE 78h
val2 BYTE 56h
val3 BYTE 34h
val4 BYTE 12h
.code
main PROC
mov eax,LongValue ; EAX = 12345678h
exit
main endp
end main
Тут директива LABEL дозволяє визначити в програмі мітку і|та| призначити їй потрібний атрибут довжини (DWORD), не розподіляючи при цьому фізично пам'ять під змінну.
Можна помітити|зауважити|, що число 12345678h розміщується в пам'яті в перевернутому вигляді: спочатку молодша частина|частка| числа, потім - старша.
У процесорах Intel при вибірці і|та| зберіганні даних в пам'яті використовується прямий порядок|лад| наступністі байтів (little endian order) - молодший байт змінної зберігається в пам'яті за меншою адресою.
Тому подвійне слово 12345678h в памяті:
-
Значення
78
56
34
12
Зміщення
0000:
0001:
0002:
0003:
У регістрах|реєстрах| дані розташовуються в звичному вигляді.
Приклад|зразок|. Завантажити 32-розрядне значення, що складається з двох 16-розрядних змінних, в регістр|реєстр| ЕАХ.
include irvine32.inc
.data
LongValue LABEL DWORD
vall word 5678h
val2 word 1234h
.code
main PROC
mov eax,LongValue ; EAX = 12345678h
exit
main endp
end main
Приклад. Використання директиви LABEL для визначення в програмі додаткових імен розмірів для змінних, розміщених в сегменті даних.
include irvine32.inc
.data
vall6 LABEL WORD
val32 DWORD 12345678h
.code
main PROC
mov ax,vall6 ; AX = 5678h
mov dx,vall6+2 ; DX = 1234h
mov ecx,val32
exit
main endp
end main
Перед змінною val32 ми оголосили мітку vall6 і|та| присвоїли|привласнили| їй атрибут довжини WORD.
-
Значення
78
56
34
12
Зміщення
0000
0001
0002
0003
vall6+0
vall6+1
vall6+2
vall6+3
val32
Приклад 3. обчислити 4862
Розробка алгоритму рішення|розв'язання|.
Алгоритм розв’язання задачі – лінійний.
Визначення змінних програми.
Для розв’язання завдання нам знадобиться змінна для представлення цілого беззнакового числа 486. Мінімальна комірка пам’яті, в якої може розміститися число 486 – 2 байти. Для представлення результату, нам знадобиться комірка пам’яті розміром 4 байта (486*486=236196).
За допомогою директив визначення даних в сегменті даних зарезервуємо область пам'яті відповідної довжини для розміщення значень змінних:
digit word 486,0
Додаткове подвійне слово резервуємо для наглядності.
Оскільки|тому що| після виконання команди множення, результат буде збережений в двох регістрах|реєстрах| (AX - молодша частина|частка| числа, в DX - старша частина|частка| числа), для збереження результата в ОП необхідно|треба| виділити комірку розміром 4 байти. Причому, необхідно|треба| потурбуватися|поклопотатися| про доступ до старшої і|та| молодшої частинам|часткам| числа.
Причина того, що результат 16-розрядного множення зберігається в парі DX:AX|, а не в 32-розрядному регістрі, заключається в забезпечені сумісністі з|із| попередніми 16-розрядними процесорами, у|біля| яких не було 32-розрядних регістрів|реєстрів|.
include irvine32.inc
.data
digit word 486,0
result label dword
result_l word ?
result_h word ?
.code
main PROC
mov eax,0
mov ax,digit ; AX = 486
mul ax ; AX * AX -> DX:AX
mov result_l,ax
mov result_h,dx
mov ecx,result
exit
main endp
end main
Вміст регістра|реєстру| AX після виконання команди mov ax,digit
-
AX=486
0
0
0
0
0
0
0
1
1
1
1
0
0
1
1
0
0
1
Е
6
Вміст регістра|реєстру| AX , DX і ECX після виконання команди множення :
-
AX
1
0
0
1
1
0
1
0
1
0
1
0
0
1
0
0
9
А
А
4
-
DX
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0
0
0
3
ECX=236196 |
|||||||||||||||||||||||||||||||
|
CX |
||||||||||||||||||||||||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
3 |
9 |
А |
А |
4 |
Приклад 4. Обчислити|обчисляти| діаметр по радіусу, збереженому в 8-бітовій змінній.
include irvine32.inc
.data
radius byte 25,0
diameter word ?
.code
main PROC
mov al,2 ; AL = 2
mul radius ; AX = radius * 2
mov diameterl,ax ; diameter <- AX
exit
main endp
end main
Множення двійкових чисел із|із| знаком