深入瞭解C語言(函數的參數傳遞和函數使用參數的方法)

來源:互聯網
上載者:User
 深入瞭解C語言(函數的參數傳遞和函數使用參數的方法)

深入瞭解C語言(函數的參數傳遞和函數使用參數的方法)
tangl_99(原作)

C語言產生的程式碼在執行效率上比其它進階語言都高.現在讓我們來看看C語言產生的程式碼具體是什麼樣子的.當你看完本文對於C語言的瞭解一定會更深一步了.
本文通過一個個實際案常式序來講解C語言.

研究案例一

工具: Turboc C v2.0,Debug,MASM v5.0,NASM
執行個體C程式:
/* example1.c */
char ch;
int e_main()
{

e_putchar(ch);

}

目標內容:C語言調用函數的方法與細節

我們使用的C編譯器是16位的Turboc C v2.0,它產生的是16位的代碼,比較簡單,方便我們來研究.同時我們也需要用到DOS下的DEBUG來進行反組譯碼.由於我們很多案例中的程式並不是完整的C程式,所以Turboc下的Tlink並不能為我們產生目標程式,所以我將使用MASM中的link.exe,同時裡面的exe2bin.com也可以為我們把exe檔案轉換成bin檔案.

這個程式沒有main函數,我們用e_main來代替main函數.這樣我們能避開C語言對main函數進行一系列處理的代碼.同樣,我們也用e_putchar()來代替我們平常使用的putchar().這裡"e"的意思就是"example".

沒有了main函數,我們的C程式就沒有了入口,所以在開始編譯這段C代碼之前,我還得寫幾行簡單的彙編代碼,通過它來作為我們程式的入口.

; C程式的入口 start.asm
[BITS 16]
[global start]
[extern _e_main]
start:
call _e_main

按照C語言的習慣,所以C總的名詞都要自動在前面加一個"_"底線.所以,我們在C中的e_main函數,如果要在彙編中調用,就變成了_e_main函數.這段彙編代碼只有一句:call _e_main,就是調用我們在C中的e_main函數

這段代碼我將用nasm來進行編譯.產生start.obj
nasmw -f obj -o start.obj start.asm

下面我們用Turboc C來編譯這段C代碼:
TCC -mt -oexample1.obj -c example1.c
link start.obj example1.obj,example1.exe,,,
exe2bin example1.exe
這樣,我們就得到了這段C代碼編譯出來的機器代碼檔案(example1.bin)了.
下面我們用DEBUG這個老DOS的工具來對example1.bin進行反組譯碼.

DEBUG
-n example1.bin
-l 0
-u 0
xxxx:0000   CALL 0003
xxxx:0003   MOV  AX,000B
xxxx:0006   PUSH AX
xxxx:0007   CALL 0020
xxxx:000A   POP  CX

這裡看到藍色的代碼就是我們整個C程式的所產生的程式碼了.
最開始的第一句CALL 0003是我們用nasm編譯的start.asm所產生的程式碼.
我們主要目標是研究藍色的C語言的代碼,第一句start.asm所產生的程式碼太簡單,就是調用e_main函數.而我們的e_main函數就是藍色代碼部分.

從C來源程式中我們看到,我們在e_main做的就是一件事情:調用e_putchar(ch);其中ch是傳給出e_putchar的參數.

MOV AX,000B
000B就是我們的全域變數ch所在記憶體的地址.C語言會把所有的全域變數在另一塊記憶體區.C代碼先把ch的地址傳給AX,然後通過
PUSH AX
把AX的值,也就是ch的地址壓入堆棧.然後再
CALL 0020
而0020就是e_putchar代碼的地址.通過這跳語句,電腦就跳到e_putchar的代碼部分去執行了.我在這裡並不給出e_putchar的代碼,因為我們這個案例只是研究C語言中如何傳遞參數給其它函數的,並不管e_putchar如何取參數.下在一個案例中,我們將研究函數如何取參數.

在這裡我得把CALL指令解釋清楚,因為在下個研究函數如何取參數的部分中大家可能會迷惑.CALL XXXX 指令簡單地或就是
PUSH IP
JMP XXXX
它首先把當前的執行地址IP壓入堆棧,然後跳轉到要CALL的地址去.CALL和RET指令是配套的.RET指令等同於
POP IP
也就是回複CALL前的執行地址IP.
正因為這樣,所以你一旦使用了CALL指令,你的堆棧指標SP就會自動減2.

POP CX
是每個函數調用完畢後都有的必備操作.在這裡它不起任何作用.可能唯一的作用就是與CALL 0020前的PUSH AX像對應.這樣堆棧指標SP才能回原.

好了,簡單的第一個案例研究結束了.雖然就這4跳指令,但是我們已經可以看出C語言傳遞參數方法了.總結起來就是
通過"MOV AX,參數地址"把參數的地址傳到AX,然後"PUSH AX"把參數的地址壓入堆棧.最後"CALL 函數地址"轉向執行要調用的函數.最後調用完後,"POP CX",恢複堆棧指標SP.

研究案例二

工具: Turboc C v2.0,Debug,MASM v5.0,NASM,TASM
執行個體C程式:
/* example1.c */
char ch;
extern void e_putchar(char c);
int e_main()
{

ch=0x44;
e_putchar(ch);

}
執行個體組譯工具:
; eio.asm
_TEXT segment byte public 'CODE'
DGROUP group _TEXT
assume cs:_TEXT,ds:DGROUP,ss:DGROUP
public _k_putchar
_k_putchar proc  near
push  bp
mov  bp,sp
mov  ah,0eh
mov  bx,7h
mov  al,byte ptr [bp+4]
int  10h
pop  bp
ret
_k_putchar endp

目標內容:C語言中函數使用參數的方法

這一節我們將使用TASM用彙編來寫個標準的C函數.這一節的內容大家可能在很多彙編的書籍上都看到過.講的是C語言和組合語言的串連方法.可能你會奇怪,我們這裡已經有了MASM,NASM兩個彙編編譯器了,為什麼還要使用TASM另外一個彙編編譯器.我不知道MASM是否可以和我們的Turboc C配合,但是TASM是肯定可以和Turboc C完全配合的.畢竟它們都是Borland公司的產品,而且Turboc C中用-S產生的彙編代碼是完全按照TASM中的文法而定的.這足以見Turboc C和TASM之間"親密的"關係了.

這個案例中我們主要並不研究C代碼了.而是研究那個用彙編寫的C函數.
push  bp
mov  bp,sp
mov  ah,0eh
mov  bx,7h
mov  al,byte ptr [bp+4]
int  10h
pop  bp
ret
其中byte ptr[bp+4]就是我們傳給e_putchar()的參數值.
前一個案例中我們一直知道了C語言是把參數的地址壓入堆棧的方式傳給函數.所以在標準的C函數中,都是通過取堆棧裡的值來讀參數.
標準的C函數前兩行都是
push  bp
mov  bp,sp
首先儲存BP的值,然後把當前的堆棧指標傳遞給BP,我們訪問傳遞給該函數的參數就是通過BP.而第一個參數值就放在BP+4的地址中,第二個參數值就放在BP+6,...,這樣依此對應每個參數的地址.BP就是CALL調用前的IP的值.因為CALL執行的時候,系統會自動把當前的IP壓入堆棧.關於這個前面一個案例中已經給出介紹.

別看這個C函數是用組合語言寫的,它可是個完完整整的C函數.
好了,讓我們編譯出來看看.

TASM eio.asm eio.obj
TCC -mt -oexample1.obj -c example1.c
link start.obj eio.obj example1.obj,example1.exe,,,
exe2bin example1.exe

好了,該是我們總結的時候了.
C語言中函數訪問參數的方法就是先通過"PUSH BP"儲存BP,"MOV BP,SP"把當前的堆棧指標傳遞給BP.第一個參數的地址就在BP+4,第二個參數的地址就在BP+6,...比如"MOV AX,WORD PTR[BP+4]"就可以把第一個參數值傳給AX 寄存器.而需要留意的是C/C++傳遞參數的順序是和其它語言相反的.C語言是把參數的地址從右至左壓入堆棧,所以越後面的參數,在堆棧中的地址越靠前.
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.