作者 云青
原創(chuàng)作品轉(zhuǎn)載請(qǐng)注明出處
基本的匯編知識(shí):
movl辛臊,subl涂炎,pushl,topl宝磨,ret疮绷,addl翰舌,leave,enter
參考資料下載地址冬骚。http://pan.baidu.com/s/1cdISDC
課程地址:《Linux內(nèi)核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000
一椅贱、準(zhǔn)備
創(chuàng)建文件,并進(jìn)行編譯
int g(int x)
{
return x + 3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8) + 1;
}
編譯命令:
gcc -S -o demo1.s demo1.c -m32
運(yùn)行完畢后生成如下文件:
.file "demo1.c"
.text
.globl g
.type g, @function
g:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
addl $3, %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size g, .-g
.globl f
.type f, @function
f:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call g
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE1:
.size f, .-f
.globl main
.type main, @function
main:
.LFB2:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $4, %esp
movl $8, (%esp)
call f
addl $1, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",@progbits
我們將命令簡(jiǎn)化得到如下匯編指令:
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $3, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call g
leave
ret
main:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $8, (%esp)
call f
addl $1, %eax
leave
ret
備注:
%開(kāi)頭表示寄存器
$開(kāi)頭表示立即數(shù)
()表示間接尋址只冻,樣例(GAS = C語(yǔ)言):(%eax)= *eax [2]
Imm(Ea) 庇麦,變址尋址,樣例(GAS = C語(yǔ)言):4(%eax) = *(4+eax)
二喜德、匯編指令執(zhí)行流程分析
我們以簡(jiǎn)化版為例:
C語(yǔ)言的都是從mian函數(shù)開(kāi)始運(yùn)行的山橄,同理,匯編也是從main函數(shù)開(kāi)始運(yùn)行的舍悯,下面我們來(lái)從main函數(shù)入手驾胆。
首先執(zhí)行的是18行pushl指令涣澡,
先畫(huà)出內(nèi)存的棧此時(shí)的情況:esp和ebp此時(shí)都指向棧底。
pushl %ebx ,即將數(shù)據(jù)壓棧丧诺,指令相當(dāng)于
subl $4, %esp
movl %ebx,(%esp)
- 執(zhí)行pushl %ebp之后入桂,eip指向下一條指令,變?yōu)椋?/li>
2驳阎、執(zhí)行movl %esp抗愁,%ebp,之后eip指向下一條指令呵晚,變?yōu)?/p>
3蜘腌、執(zhí)行 subl $4, %esp
4、執(zhí)行movl $8, (%esp)
5 饵隙、call f
call f等價(jià)于
pushl %eip
movl f %eip
6 撮珠、pushl %ebp
7、movl %esp, %ebp
8金矛、 subl $4, %esp
9芯急、movl 8(%ebp), %eax
10、movl %eax, (%esp)
11驶俊、call g
12娶耍、
pushl %ebp
movl %esp,%ebp
每進(jìn)入一個(gè)函數(shù)都會(huì)執(zhí)行這兩個(gè)匯編指令
這兩步操作是個(gè)規(guī)范化步驟, 叫做前序(prologue) [1]。
13饼酿、 movl 8(%ebp), %eax
14榕酒、addl $3,%eax
15、popl %ebp
popl %ebp 相當(dāng)于
movl (%esp)故俐,%ebp
addl $4想鹰,%esb
16、ret
等價(jià)于 popl %eip
17药版、leave 等價(jià)于
movl %ebp,%esp
popl %ebp
18杖挣、ret
19、addl $1,%eax
20 leave
21刚陡、ret
main函數(shù)運(yùn)行結(jié)束惩妇,將%eax的值返回,即12
參考文章:
[1] X86匯編調(diào)用框架淺析與CFI簡(jiǎn)介
[2] http://www.cnblogs.com/lxgeek/archive/2011/01/01/1923738.html