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