一個最基本的匯編程序如下所示:
.section .data .section .text .globl _start _start: movl $1, %eax # the number 1 is the number of the exit system call movl $0, %ebx int $0x80
1、.globl表示匯編器不能在匯編之后就丟棄該標識,因為接下來的連接器還會使用它。_start是一個特殊的標識,它必須用.globl修飾,因為它代表了程序開始的入口
否則在鏈接的時候會報“ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078”的錯誤
2、幾個通用寄存器如下所示:(但事實上,對每個通用寄存器,都至少在一條指令中它們是用於特殊用途的)
- %eax
- %ebx
- %ecx
- %edx
- %edi
- %esi
另外幾個用於特殊目的的寄存器如下所示:
- %ebp
- %esp
- %eip
- %eflags
3、在每次系統調用過程中,%eax總是用於存放系統調用的編號,而對於其他寄存器,在不同的系統調用中有不同的用途。例如在上述例子中,%ebx就用於存儲返回值
4、"int $0x80"中的int代表interrupt,而interrupt表示中斷當前正常的程序執行流,並且將控制權轉交給內核,讓它能執行系統調用
5、幾種尋址模型:
- direct addressing mode:
- movl ADDRESS, %eax ----- 將地址ADDRESS中的內容放到%eax中
- indexed addressing mode:
- movl string_start(, %ecx, 1), %eax ---- 將地址string_start + %ecx * 1地址中的內容放到%eax中
- indirect addressing mode:
- movl (%eax), %ebx ----- 將地址%eax中的內容放到%ebx中
- base pointer addressing mode:
- movl 4(%eax), %ebx ----- 將地址%eax + 4中的內容放到%ebx中
- immediate mode:
- movl $12, %eax ----- 將立即數12放到%eax中,若沒有$符號,則意為將地址12中的值放到%eax內
6、匯編函數調用規則
在調用一個函數之前,首先將所有參數以相反的聲明順序入棧,之后再調用call指令
call主要做兩件事:1、它將下一條指令的地址入棧 2、將%eip設置為函數的初始地址、
接着進入函數內部,首先要做的就是將%ebp入棧,並將當前%esp的值賦值給%ebp。事實上,我們就是利用%ebp作為基准來獲取函數的參數和局部變量
Parameter #N <--- N*4+4(%ebp)
...
Parameter 2 <--- 12(%ebp)
Parameter 1 <--- 8(%ebp)
Return Address <--- 4(%ebp)
Old %ebp <--- (%esp) and (%ebp)
最后在函數返回時,應該讓%ebp恢復到上一個函數的狀態,並調用ret返回,ret的作用是將上圖的Return Address裝入%eip中,恢復上一個函數的執行。具體的指令如下:
movl %ebp, %esp
popl %ebp
ret
7、mov指令不能用於內存和內存之間或者段寄存器和段寄存器之間的數據轉移。不過其實內存和內存之間的數據轉移是可以的,通過字符串的轉移指令movs
8、pusha將8個通用寄存器入棧,入棧的順序為:eax, ecx, edx, ebx, esp, ebp, esi, edi
9、inc/dec指令並不影響CF標志位
10、cr0中包含了系統控制的flag,包括標志位PE置位,則系統處於保護模式,標志位PG置位,則處理器利用頁表將線性地址轉換為物理地址
cr2用於保存導致缺頁異常的線性地址,cr3用於保存頁目錄的地址
