GCC 和 NASM 聯合編譯,彙編函數前要有引到下劃線 _

   爲了學習的順利進行,今天嘗試複習 C 語言和彙編語言的聯合編譯。代碼很簡單:函數

/* main.c */

#include <stdio.h>

extern int Caculate(int nX, int nY);


char strFormat[] = " %d + %d = %d\n";

int MyAdd(int nX, int nY);


int main()
{
	int nX = 3, nY = 2, nResult = 0;

	nResult = Caculate(nX, nY);
	printf(strFormat, nX, nY, nResult);

	return 0;
}

int MyAdd(int nX, int nY)
{
	return nX + nY;
}
; proc.nas

extern strFormat

extern MyAdd           ; int MyAdd(int nX, int nY);
extern printf


global Caculate        ; int Caculate(int nX, int nY);


[SECTION .data]
	nResult dw 0

[SECTION .text]
Caculate:
	push ebp            ; 保存父函數的棧基址
	mov ebp, esp        ; 設置本函數的棧基址,即父函數的棧頂
	sub esp, 0F0h       ; 給子函數開闢棧空間

	; 取入口參數
	mov ebx, [ebp + 12] ; 取參數2
	mov eax, [ebp + 8]  ; 取參數1

	push ebx            ; 參數入棧
	push eax
	call MyAdd          ; 函數的返回值保存在 eax 寄存器中
	mov [nResult], eax  ; 保存 _MyAdd 的返回值
	add esp, 2 * 4      ; 兩個參數出棧

	push eax
	mov ebx, [ebp + 12]
	mov eax, [ebp + 8]
	push ebx
	push eax
	push strFormat
	call printf
	add esp, 4 * 4

	mov eax, [nResult]  ; 設置本函數的返回值
	leave               ; 至關於下面兩條指令的效果
;   mov esp, ebp        ; 恢復父函數的棧頂指針(= 本函數的棧基址)
;   pop ebp             ; 恢復父函數的棧基址
	ret
#MakeFile

ALL:
    nasm -felf32 proc.nas
    gcc -m32 -o main main.c proc.o

    依然採用 GCC + NASM,能夠經過編譯,但是連接成執行文件怎麼都通不過,一直報錯「未定義函數」!
學習

    嘗試各類操做系統(WinXP 32位、Win7 64位)、各類編譯器版本(MinGW 32 位、64 位)、各類編譯參數,搞了大半天,死活不讓我過!spa

    就在快絕望的時候,忽然想起之前瀏覽的 C 語言庫函數,依稀記得函數名前面都帶有個下劃線 「_」!是否是就是這個緣由呢?試試,只需修改彙編代碼,涉及聯合編譯的變量和函數都加個下劃線前綴「_」。。。。。。操作系統

; proc.nas

extern _strFormat

extern _MyAdd           ; int MyAdd(int nX, int nY);
extern _printf


global _Caculate        ; int Caculate(int nX, int nY);


[SECTION .data]
	nResult dw 0

[SECTION .text]
_Caculate:
	push ebp            ; 保存父函數的棧基址
	mov ebp, esp        ; 設置本函數的棧基址,即父函數的棧頂
	                    ; 若是本函數有棧入口參數,則[bp + (n - 1) * 4]是第 n 個參數
	sub esp, 0F0h       ; 爲本函數的局部變量和調用中斷、子函數時保存現場數據的棧開闢空間

	; 取入口參數
	mov ebx, [ebp + 12] ; 取參數2
	mov eax, [ebp + 8]  ; 取參數1

	push ebx            ; 參數入棧
	push eax
	call _MyAdd         ; 函數的返回值保存在 eax 寄存器中
	mov [nResult], eax  ; 保存 _MyAdd 的返回值
	add esp, 2 * 4      ; 兩個參數出棧

	push eax
	mov ebx, [ebp + 12]
	mov eax, [ebp + 8]
	push ebx
	push eax
	push _strFormat
	call _printf
	add esp, 4 * 4

	mov eax, [nResult]  ; 設置本函數的返回值
	leave               ; 至關於下面兩條指令的效果
;   mov esp, ebp        ; 恢復父函數的棧頂指針(= 本函數的棧基址)
;   pop ebp             ; 恢復父函數的棧基址
	ret

    居然真是的,編譯經過了!指針

    總結,彙編語言(NASM)和 C 語言(GCC)聯合編譯的時候(在 Windows 系統下),彙編代碼中和 C 語言產生混編關係的變量和函數,前面都要加一個下劃線「_」!C 語言代碼中不加。code

相關文章
相關標籤/搜索