C語言與匯編語言相互調用原理以及實例
C語言與匯編語言相互調用原理以及實例
1.原理
其實不管是C語言還是匯編語言想要執行都是最終編譯鏈接成為二進制文件。
這裏一定要明確編譯和鏈接是兩個步驟,生成的文件格式也是不一樣的。
編譯生成的文件是一定格式的,裏面包括函數符號表、參數表...等信息,這些信息主要是提供給鏈接階段使用,函數調用是怎麽調用的?是不是指定利用的函數的符號?所以鏈接階段就是將函數調用的符號變成相對地址(要特別註意這個階段,因為這個過程使得C語言和匯編語言相互調用成為可能)。
2.下面兩個分別是一個hello.asm(匯編語言文件),main.c(c語言文件)
;hello.asm extern print_helloworld [section .text] global print_two_hello_world print_two_hello_world: call print_helloworld call print_helloworld /* main.c */ #include "stdio.h" extern void print_two_hello_world(); char *strhello = "Hello,world!\n"; void print_helloworld () { printf ("%s",strhello); } int main () { print_two_hello_world(); return 0; }
首先看NASM代碼,先導入一個外部函數print_helloworld(),此函數是C語言定義的一個函數。接下來是定義了一個函數print_two_hello_world,用global關鍵字導出使其可以在C中調用,函數的內容是調用了兩次print_helloword()。
在來看C代碼,代碼很簡單就具體講了,這裏主要數一下我們將主函數放在了C代碼中寫,這時因為我們要使用C代碼的函數庫中的printf()函數,如果C代碼中沒有什麽庫的依賴可以將主函數放在匯編代碼中
3.NASM和C互相調用對方的變量
Nasm代碼
global string extern strhello [section .data] string: db ‘I am Chinese.‘,0x0A,0x0 [section .text] global print_hello global cpy_mem print_hello: mov edx, 13 mov ecx,[strhello] mov ebx,1 mov eax,4 int 0x80
C代碼
#include "stdio.h" #include "string.h" extern char *string; extern void print_hello(); extern cpy_mem (void *dest, int len); char *strhello = "Hello,world!\n"; char *str = NULL; int main () { printf ("%x\n",&string); str = &string; printf ("%s", str); print_hello (); return 0; }
Make後的執行結果如下:
I am Chinese.
Hello,world!
具體的代碼內容就部分析了,這裏主要將兩個關鍵的地方。
1.在C語言中定義了一個strhello的字符串變量,在C語言中strhello表示的是字符串的首地址,比如字符串的地址是0xa00001,而strhello是個指針即4字節其地址為0xb00001, 在C語言中strhello表示的值是 0xa00001 字符串的首地址,但到了NASM中則表示的 strhello變量的首地址了 0xb00001,所以
Nasm代碼
mov ecx,[strhello]
代碼中加了中括號表示是內容,這一點一定要註意,否則會出錯!!
2.第二點要註意的是,在NASM中定義了一個字符串string , 在C語言中導入的話,就是表示字符串的首地址,因此要引用該字符串一定要取其地址,不要直接轉為(char*)類型直接用,否則出錯,這是因為直接轉的話,就將字符串的前4個字節轉成了字符串指針,但該指針是不確定會出現段錯誤!
C語言與匯編語言相互調用原理以及實例