本文是Mooc <Linxu操作系統(tǒng)分析>課程第一次作業(yè).
姓名:石維康
轉(zhuǎn)載請注明出處.
經(jīng)過簡單的數(shù)字修改,需要編譯的C語言代碼如下:
int g(int x)
{
return x + 2;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(5) + 4;
}
編譯后生成的匯編代碼如下所示:
生成的完整匯編代碼如下:
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $2, %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 $5, (%esp)
call f
addl $4, %eax
leave
ret
完整截圖(對應(yīng)匯編代碼函數(shù)):
與視頻中采用相同約定,假設(shè)初始esp= ebp =0.
先進(jìn)入main函數(shù)執(zhí)行到call f后,esp=3,ebp=1,堆棧目前的情況
編號 內(nèi)容
| --- | --- |
ebp | 1 | 0 |
| --- | --- |
| --- | --- |
| 2 | 5 |
| --- | --- |
| --- | --- |
esp | 3 | 23 |
| --- | --- |
| --- | --- |
| 4 | |
| --- | --- |
進(jìn)入f函數(shù),執(zhí)行到call g后,堆棧如下
ebp=4
| --- | --- |
| 1 | 0 |
| --- | --- |
| --- | --- |
| 2 | 5 |
| --- | --- |
| --- | --- |
| 3 | 23 |
| --- | --- |
| --- | --- |
ebp-> | 4 | 1 |
| --- | --- |
| --- | --- |
| 5 | 5 |
| --- | --- |
| --- | --- |
esp-> | 6 | 14 |
| --- | --- |
進(jìn)入g函數(shù)執(zhí)行運(yùn)算,執(zhí)行到addl $2, %eax 這句. eax=5+2=7
| --- | --- |
| 1 | 0 |
| --- | --- |
| --- | --- |
| 2 | 5 |
| --- | --- |
| --- | --- |
| 3 | 23 |
| --- | --- |
| --- | --- |
| 4 | 1 |
| --- | --- |
| --- | --- |
| 5 | 5 |
| --- | --- |
| --- | --- |
| 6 | 15 |
| --- | --- |
| --- | --- |
esp,ebp-> | 7 | 4 |
| --- | --- |
在g函數(shù)值中,在eip指向ret語句時(即執(zhí)行完popl %ebp),堆棧如下:
| --- | --- |
| 1 | 0 |
| --- | --- |
| --- | --- |
| 2 | 5 |
| --- | --- |
| --- | --- |
| 3 | 23 |
| --- | --- |
| --- | --- |
ebp-> | 4 | 1 |
| --- | --- |
| --- | --- |
| 5 | 5 |
| --- | --- |
| --- | --- |
esp-> | 6 | 15 |
| --- | --- |
ret 后 eip=15,堆棧變成如下:
| --- | --- |
| 1 | 0 |
| --- | --- |
| --- | --- |
| 2 | 5 |
| --- | --- |
| --- | --- |
| 3 | 23 |
| --- | --- |
| --- | --- |
ebp-> | 4 | 1 |
| --- | --- |
| --- | --- |
esp-> | 5 | 5 |
| --- | --- |
f中的leave執(zhí)行完之后:
| --- | --- |
ebp-> | 1 | 0 |
| --- | --- |
| --- | --- |
| 2 | 5 |
| --- | --- |
| --- | --- |
esp-> | 3 | 23 |
| --- | --- |
執(zhí)行f中的ret后,eip=23,eax=7:
| --- | --- |
ebp-> | 1 | 0 |
| --- | --- |
| --- | --- |
esp-> | 2 | 5 |
| --- | --- |
執(zhí)行main中的leave后,堆棧如下,eax=11,esp=ebp=0:
ebp,esp-> | --- | --- |
| 1 | 0 |
| --- | --- |
回到初始態(tài).
我對計算機(jī)執(zhí)行程序的理解:
計算機(jī)只是機(jī)械的從PC指針指向的位置取指令并解析執(zhí)行.而數(shù)據(jù)與指令都是以二進(jìn)制形式進(jìn)行存儲.
在C語言層面上的函數(shù)調(diào)用與返回的語義,在x86層面上是通過call指令與ret指令來完成.