Клуб програмістів - - матеріали по delphi і з - blog archive - assembler - win32

основи Ассемблера

Коли ви пишете програму на асемблері, ви просто пишете команди процесора. Команди процесора - це просто коди або коди операцій або опкоди. Опкоди - фактично «читається текст» - версії шістнадцятирічних кодів. Через це, асемблер вважається самим низькорівневим мовою програмування, все в асемблері безпосередньо перетворюється в шістнадцяткові коди. Іншими словами, у вас немає компілятора, який перетворює мову високого рівня в мову низького рівня, асемблер тільки перетворює коди асемблера в дані.

У цьому уроці ми обговоримо кілька опкодов, які мають відношення до обчислення, порозрядним операціями, і т.д. Інші опкоди: команди переходу, порівняння і т.д, будуть обговорені пізніше.

Найперша команда буде добре всім відома MOV. Ця команда використовується для копіювання (не звертайте уваги на ім'я команди) значення з одного місця в інше. Це 'місце' може бути регістр, елемент пам'яті або безпосереднє значення (тільки як початкове значення). Синтаксис команди:

mov приймач, джерело

Ви можете копіювати значення з одного регістра в інший.

mov al, ecx; неправильно

Цей опкод намагається помістити DWORD (32-бітове) значення в байт (8 бітів). Це не може бути зроблено mov командою (для цього є інші команди).

А ці команди правильні, тому що у них джерело і приймач не відрізняються за розміром:

mov al, bl
mov cl, dl
mov cx, dx
mov ecx, ebx

Ви також можете отримати значення з пам'яті і помістити его в регістр. Для прикладу візьмемо таку схему пам'яті:

(Кожен блок являє байт)

Значення зміщення позначено тут як байт, але насправді це це - 32-розрядне значення. Візьмемо для прикладу 3A, це також - 32-розрядне значення: 0000003Ah. Тільки, щоб з економити простір, деякі використовують маленькі зміщення.

Подивіться на зміщення 3A в таблиці вище. Дані на цьому зміщенні - 25, 7A, 5E, 72, EF, і т.д. Щоб помістити значення з зміщення 3A, наприклад, в регістр, ви також використовуєте команду mov:

mov eax, dword ptr [0000003Ah]

Чи означає: помістити значення з розміром DWORD (32-біт) з пам'яті зі зміщенням 3Ah в регістр eax. Після виконання цієї команди, eax буде містити значення 725E7A25h. Можливо ви помітили, що це - інверсія того що знаходиться в пам'яті: 25 7A 5E 72. Це тому, що значення зберігаються в пам'яті, використовуючи формат little endian. Це означає, що наймолодший байт зберігається в найбільш значущу байті: порядок байтів задом на перед. Я думаю, що ці приклади покажуть це:

dword (32-біт) значення 10203040 шестнадцатиричное зберігається в пам'яті як: 40, 30, 20, 10
word (16-біт) значення 4050 шестнадцатиричное зберігається в пам'яті як: 50, 40

Повернемося до прикладу вище. Ви також можете це робити і з іншими розмірами:

mov cl, byte ptr [34h]; cl отримає значення 0Dh
mov dx, word ptr [3Eh]; dx отримає значення 7DEFh

Ви, напевно, вже зрозуміли, що префікс ptr позначає, що треба брати з пам'яті деякий розмір. А префікс перед ptr позначає розмір даних:
Byte - 1 байт
Word - 2 байта
Dword - 4 байта

Іноді розмір можна не вказувати:

mov eax, [00403045h]

Так як eax - 32-розрядний регістр, асемблер розуміє, що йому також потрібно 32-розрядне значення, в даному випадку з пам'яті зі зміщенням 403045h.

Можна також безпосередні значення:

Ця команда просто запише в регістр edx, значення 5006. Дужки, [і], використовуються, для отримання значення з пам'яті (в дужках знаходиться зміщення), без дужок, це просто безпосереднє значення.

Можна також використовувати регістр як осередок пам'яті (він повинен бути 32-розрядних в 32-розрядних програмах):

mov eax, 403045h; пише в eax значення 403045
mov cx, [eax]; поміщає в регістр CX значення (розміру word) з пам'яті
; зазначеної в EAX (403045)

В mov cx, [eax], процесор спочатку дивиться, яке значення (= комірці пам'яті) містить eax, потім яке значення знаходиться в тій комірці пам'яті, і поміщає це значення (word, 16 біт, тому що приймач, cx, є 16- розрядних регістром) в CX.

(1) mov ecx, 100
(2) mov eax, 200
(3) push ecx; збереження ecx
(4) push eax
(5) xor ecx, eax
(6) add ecx, 400
(7) mov edx, ecx
(8) pop ebx
(9) pop ecx

аналіз:
1: помістити 100 в ecx
2: помістити 200 в eax
3: розмістити значення з ecx (= 100) в стеку (розміщується першим)
4: розмістити значення з eax (= 200) в стеку (розміщується останнім)
5/6/7: виконання операцій над ecx, значення в ecx змінюється
8: витяг значення з стека в ebx: ebx стане 200 (останнє розміщення, перше витяг)
9: витяг значення з стека в ecx: ecx знову стане 100 (перше розміщення, останнім витяг)

Щоб дізнатися, що відбувається в пам'яті, при розміщенні та витягу значень в стеку, см. На малюнок нижче:

edx тепер 4560FFFFh.

push значення_1
push значення_2
call procedure

Одне важливе зауваження:
регістр eax майже завжди використовується для зберігання результату процедури.
Це також може бути застосовано до функцій windows. Звичайно, ви можете використовувати будь-який інший регістр в ваших власних процедурах, але це стандарт.

випадкові статті