x86架構彙編指令一般有兩種格式:Intel彙編和AT&T彙編,DOS、Windows使用Intel彙編,而Unix、Linux、MacOS使用AT&T彙編。
1.彙編組成
彙編程序是由定義好的段組成的,每個段的意義都不一樣。最常用的由以下幾個段:
- data段:存放大部分的數據
- bss段:存放未初始化的數據
- rodata段:存放只讀的數據
- text段:存放代碼
對於最簡單一個程序而言,text段是必須的,其他都是可選的。
操作碼:但是操作碼都是一堆16進制字符,不太人性化,所以就就產生了助記符來方便程序員來編寫彙編代碼。
寄存器:x86_64 平臺16個通用寄存器和6個16位段寄存器
立即數:x86_64 平臺規定立即數的最大值不能超過32位。
大小寫:指令不區分大小寫,但是Intel格式的指令習慣上使用大寫字母,而AT&T格式習慣上使用小寫字母。
2.數據格式
GAS中每個操作都是有一個字符的後綴,表明操作數的大小。"b"表示 byte(一個字節) ;"w"表示 word(2 個字節) ;"l"表示 long(4 個字節) 。INTEL 中處理內存操作數時也有類似的語法如:BYTE PTR、WORD PTR、DWORD PTR。
C聲明 | GAS後綴 | 大小(字節) |
---|---|---|
char | b | 1 |
short | w | 2 |
long | l | 4 |
注意:GAL使用後綴"l"同時表示4字節整數和8字節雙精度浮點數,這不會產生歧義因爲浮點數使用的是完全不同的指令和寄存器。
3.彙編指令格式
- 數據傳送
movl %ebx,%eax #寄存器前加% movl $1,%eax #立即數前加$
傳送方向與Intel格式相反,如:把EAX值存入EBX
intel格式:MOV EBA, EAX at&t格式:movl %eax, %ebx
2.跳轉指令
lcall $secion:$offset
ljmp $secion:$offset
lret $stack_adjust
4.尋址方式
-
直接尋址
movl 0x8000, %eax # 把地址0x8000上的值放到eax中
-
寄存器尋址
movl $2, %ebx # 立即數尋址
-
立即數尋址
movl $2, %ebx # 把2放到寄存器ebx中
-
間接尋址
movl $0x8000, %ebx # 立即數尋址 movl %ebx, %eax # 間址尋址, 把地址0x8000(放在寄存器ebx中)上的值放到eax
-
基址尋址
movl $0x8000, %eax # 立即數尋址 movl 4(%eax), %ebx #基址尋址, 把地址0x8004(0x8000+4)上的值放到eax中
-
變址尋址
movl $0x8000, %eax # 立即數尋址 movl $0x4, %ebx # 立即數尋址 movl (%eax,%ebx), %ecx #變址尋址, 把地址0x8004(0x8000+4)上的值放到ecx中 movl 4(%eax,%ebx), %ecx #變址尋址, 把地址0x8008(0x8000+4+4)上的值放到ecx中
- 比例變址尋址
movl $0x2000, %eax # 立即數尋址 movl $0x2, %ebx # 立即數尋址 movl (,%eax,4), %ecx #比例變址尋址, 把地址0x8000(0x2000 *4)上的值放到ecx中 movl 6(,%eax,4), %ecx #比例變址尋址, 把地址0x8006(0x2000 *4+6)上的值放到ecx中 movl (%ebx,%eax,4), %ecx #變址尋址, 把地址0x8002(0x2000*4+2)上的值放到ecx中 movl 6(%ebx,%eax,4), %ecx #變址尋址, 把地址0x8008(0x2000*4+2+6)上的值放到ecx中