認識組合語言 - 暫存器
常規使用的暫存器
RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, R8, R9, R10, R11, R12, R12, R13, R14, R15
其中RSP始終指向stack頂部的位址,在C編譯風格的程式RBP指向區域變數頂部的位置
還有一個特殊的暫存器RIP始終指向下一條要執行的指令,也就是我們學過的程式計數器
RIP在使用者端不可寫(read only)
64 32 16 8 8RAX, EAX, AX, AH, ALAL是最右邊8位,AH是接著8位,AH和AL合起來是AX
在nasm語法中,取用暫存器大小直接依照上述寫法即可
後面的暫存器如下:
rsi, esi, si, silrdi, edi, di, dilrsp, esp, sp, splr8, r8d, r8w, r8b列舉了一些通用暫存器的常見用途
- rax: 存放函數的返回值
- rcx: 迴圈的疊代變數
(while i--)的i - rdx: 當兩個暫存器合併使用成16位時,左邊8位的內容
- rsi: 來源內容
- rdi: 目的內容
- rbp: 區域變數頂部
- rsp: stack頂部 (規定)
函數呼叫規範
Section titled “函數呼叫規範”呼叫函數時需要將參數內容放入對應的暫存器
linux使用的順序為:
rdi, rsi, rdx, rcx, r8, r9, rsp(堆疊)
windows使用的順序為:
rcx, rdx, r8, r9, rsp(堆疊)
rdi rsi rdxf(arg1, arg2, arg3)假設要呼叫一個函數f,參數需要先放入對應的地方,函數進入後會當作已經將參數放好了直接使用
超過的長度則全部放入堆疊中
SIMD暫存器
Section titled “SIMD暫存器”用於平行處理的暫存器(可處理浮點與整數)
XMM0 ~ XMM15 128 bitsYMM0 ~ YMM15 256 bitsZMM0 ~ ZMM31 512 bits包含特定的狀態旗標,有些指令執行過程會使用並依照情況亮燈
比如常用的ZF,當ZF亮了表示值為0,像是加減法和cmp都會觸發
舉個例子:
while(n--) {}我們只要一直執行dec遞減1,使用jz 當ZF觸發則跳轉到另一個地方
但不是所有指令出現0都會ZF,常用的xor就不會觸發,這部份請查找網路資料和Intel x86_64指令集文檔
還有CF(進位)、SF(符號)、OF(溢位)、DF(方向)等
CS、DS、SS、ES、FS、GS
現在只剩FS和GS在多線程使用到,平時不會出現
以下是補充說明:
記憶體位址可以用 [segment:offset] 來描述,segment 就是這幾個暫存器
比如bootloader以及早期的16 bits環境中,常用 [ds:si] 和 [es:di] 來表示記憶體位址
實際位址是 es × 16 + di,比如 es = 0x1000, di = 0x20,表示 0x10020 這個位址
當今x86_64使用的 fs 和 gs 是一般加法 [fs:0x12] 是 fs + 0x12