寄存器
早期的 x86 CPU
只有 8 個(gè)寄存器(eax
、ebx
区宇、ecx
娃殖、edx
、esi
议谷、edi
炉爆、ebp
、esp
),而且每個(gè)都有不同的用途芬首。
寄存器名稱 | 含義 | 用途 | 包含寄存器 |
---|---|---|---|
eax |
累加(Accumulator )寄存器 |
常用于乘除法和函數(shù)返回值 |
ax (ah 鲫凶、al ) |
ebx |
基址(Base )寄存器 |
常以它為基址來訪問內(nèi)存 |
bx (bh 、bl ) |
ecx |
計(jì)數(shù)器(Counter )寄存器 |
常做字符串和循環(huán)操作中的計(jì)數(shù)器 |
cx (ch 衩辟、cl ) |
edx |
數(shù)據(jù)(Data )寄存器 |
常用于乘除法和 I/O 指針 |
dx (dh 、dl ) |
esi |
來源索引(Source Index )寄存器 |
常用于內(nèi)存數(shù)據(jù)指針和源字符串指針 | si |
edi |
目的索引(Destination Index )寄存器 |
常用于內(nèi)存數(shù)據(jù)指針和源字符串指針 | di |
ebp |
基址指針(Base Pointer )寄存器 |
只做堆棧指針波附,可以訪問堆棧內(nèi)任意地址艺晴,經(jīng)常用于中轉(zhuǎn) ESP 中的數(shù)據(jù),也常以它為基址來訪問堆棧掸屡;不能用于算術(shù)運(yùn)算與數(shù)據(jù)傳送 |
bp |
esp |
堆棧指針(Stack Pointer )寄存器 |
只做堆棧的棧頂指針封寞,不能用于算術(shù)運(yùn)算與數(shù)據(jù)傳送 | sp |
棧幀中,最重要的是幀指針
ebp
和棧指針esp
仅财,有了這兩個(gè)指針狈究,我們就可以刻畫一個(gè)完整的棧幀。
x86-64
中盏求,所有寄存器都是 64 位抖锥,相對(duì) 32 位的 x86
來說,標(biāo)識(shí)符發(fā)生了變化碎罚,比如:從原來的 eax
變成了 rax
磅废。為了向后兼容性,eax
依然可以使用荆烈,不過指向了 rax
的低 32 位。
比如在 64 位 CPU 上:
-
rax
是 64 位的寄存器 -
rax
是rax
的低 32 位 -
ax
是rax
的低 16 位 -
ah
是ax
的高 8 位。 -
al
是ax
的低 8 位宿接。
它們的對(duì)照關(guān)系如下:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|=================================RAX=================================|---8個(gè)字節(jié)
|===============EAX===============|---4個(gè)字節(jié)
|======AX=======|---2個(gè)字節(jié)
|==AH===|-----------1個(gè)字節(jié)
|===AL==|---1個(gè)字節(jié)
通過 gdb 的 p /x $reg
命令打印寄存器的值德绿。
(gdb) p /x $rax
$16 = 0x555555554870
(gdb) p /x $eax
$12 = 0x55554870
(gdb) p /x $ax
$13 = 0x4870
(gdb) p /x $ah
$14 = 0x48
(gdb) p /x $al
$15 = 0x70
匯編指令
1. 數(shù)據(jù)傳送指令
指令 | 名稱 | 語法 | 描述 |
---|---|---|---|
mov |
數(shù)據(jù)傳送指令 | mov dest, src |
將數(shù)據(jù)從 src 移動(dòng)到 dest
|
push |
入棧指令 | push src |
將源操作數(shù) src 壓入堆棧 |
pop |
入棧指令 | pop dest |
從棧頂彈出數(shù)據(jù)到 dest
|
1.1 mov
指令
mov
指令是最常見的數(shù)據(jù)傳送指令,類似于高級(jí)語言中的賦值語句玫鸟。
mov
指令可以實(shí)現(xiàn)寄存器與寄存器之間导绷、寄存器與內(nèi)存之間、寄存器與立即數(shù)屎飘、內(nèi)存與立即數(shù)的數(shù)據(jù)傳遞诵次。
需要注意的是,內(nèi)存與內(nèi)存無法直接傳遞數(shù)據(jù)枚碗,目的操作數(shù)不能為立即數(shù)逾一。
mov
指令的用法示例如下:
mov eax, 12345678h
mov eax, [00401000h]
mov eax, ebx
mov [00401000h], 12345678h
mov [00401000h], eax
1.2 push
和 pop
指令
push
指令和 pop
指令互為相反的操作指令。
-
push
指令的功能是將操作數(shù)壓入堆棧肮雨。 -
pop
指令的功能是將棧頂?shù)牟僮鲾?shù)彈出遵堵。
push
指令把一個(gè) 32 位的操作數(shù)送入堆棧,該操作致使 esp
寄存器的值減 4。
esp
寄存器始終指向棧頂陌宿。堆棧的方向是由高地址向低地址進(jìn)行延伸锡足,也就是執(zhí)行的 push
次數(shù)越多,esp
寄存器指向的地址越小壳坪。
在 32 位平臺(tái)上舶得,每執(zhí)行一次 push
指令,esp
指向的地址都減小 4 字節(jié)爽蝴。
pop
指令把 esp
指向地址(棧頂)中的值送入寄存器或內(nèi)存中沐批,然后 esp
指向的地址加 4 字節(jié)。
執(zhí)行的 pop
指令越多蝎亚,esp
寄存器指向的地址越大九孩。
(2)算術(shù)運(yùn)算指令
指令 | 名稱 | 語法 | 描述 |
---|---|---|---|
add |
加法指令 | add dest, src |
在 dest 基礎(chǔ)上加 src
|
sub |
減法指令 | sub dest, src |
在 dest 基礎(chǔ)上減 src
|
inc |
加 1 指令 | inc dest |
在 dest 基礎(chǔ)上加 1 |
dec |
減 1 指令 | dec dest |
在 dest 基礎(chǔ)上減 1 |
(3)邏輯運(yùn)算指令
指令 | 名稱 | 語法 | 描述 |
---|---|---|---|
not |
取反運(yùn)算指令 | not dest |
把操作數(shù) dest 按位取反 |
and |
與運(yùn)算指令 | and dest, src |
把 dest 和 src 進(jìn)行與預(yù)算之后送回 dest
|
or |
與運(yùn)算指令 | or dest, src |
把 dest 和 src 進(jìn)行或預(yù)算之后送回 dest
|
xor |
與運(yùn)算指令 | xor dest, src |
把 dest 和 src 進(jìn)行異或預(yù)算之后送回 dest
|
(4)循環(huán)控制指令
指令 | 名稱 | 語法 | 描述 |
---|---|---|---|
loop |
計(jì)數(shù)循環(huán)指令 | loop label |
使 ecx 寄存器的值減 1,當(dāng) ecx 寄存器的值不為 0 的時(shí)候跳轉(zhuǎn)至 lable 发框,否則執(zhí)行 loop 之后的語句 |
(5)轉(zhuǎn)移指令
指令 | 名稱 | 語法 | 描述 |
---|---|---|---|
jmp |
無條件轉(zhuǎn)移指令 | jmp label |
無條件跳轉(zhuǎn)至標(biāo)號(hào)為 lable 的位置 |
call |
過程調(diào)用指令 | call label |
直接調(diào)用 lable
|
je |
條件轉(zhuǎn)移指令 | je label |
zf = 1 時(shí)跳轉(zhuǎn)至標(biāo)號(hào)為 lable 的位置 |
jne |
條件轉(zhuǎn)移指令 | jne label |
zf = 0 時(shí)跳轉(zhuǎn)至標(biāo)號(hào)為 lable 的位置 |