2013-04-27 176 views
9

是否可以使用GCC從C函數生成彙編語言函數,以便可以從彙編語言程序中調用它們?我知道gcc將C編譯爲機器代碼(可以很容易地將其拆分成彙編語言),並且我已經知道可以對inline assembly language functions in C進行編譯,但是我還沒有找到從彙編語言程序調用C函數的方法,它是基本上與此相反。從x86彙編語言中調用C函數

在這裏,我試圖在x86彙編程序中內聯C函數。如果內聯不可行,那麼是否有其他方法可以從彙編語言程序中調用C函數?

.686p 
.model flat,stdcall 
.stack 2048 

.data 

.code 
start: 

invoke ExitProcess, 0 

printSomething PROC ;now I'm attempting to inline a C function here 
    void printSomething(thingToPrint){ 
     printf("This is a C function that I want to invoke from an assembly language program."); 
     printf("There must be some way to do this - is it possible somehow?"); 
    } 
printSomething ENDP 

end start 
+0

我不記得所有的細節,但你只需要編譯目標文件並將它們鏈接在一起。您只需要知道調用該函數時使用的調用約定。 – 2013-04-27 18:44:54

+1

您可以添加顯示您嘗試過的彙編代碼,並告訴它如何編譯失敗或其行爲錯誤。答案指出它有什麼問題會容易得多。 – hyde 2013-04-27 18:47:53

+3

你可以通過編寫一個C函數來學習如何做到這一點,C函數調用你想調用的函數,將其編譯爲彙編語言('-S'),並研究結果。我也會將您指向「psABI」,但我再也找不到副本了。 – zwol 2013-04-27 18:59:49

回答

17

我從這裏回憶,所以我可能會在一兩個細節上稍微偏離。不過,我希望這足以讓你朝着正確的方向前進。

您將需要告訴GCC彙編程序,您的例程printSomething()沒有在您的程序集文件中定義。在'C'中,您可以使用extern關鍵字。對於裝配,您需要使用.globl

.globl printSomething 

如果使用與GCC不同的彙編器,關鍵字可能會有所不同。

下一個大問題是'我該如何傳遞參數'?這非常依賴於你的處理器和操作系統。由於問題的標題指示x86,因此我將假設您正在使用16位或32位模式以及標準x86 ABI(與Windows和Linux之間的x86-64不同)。 C參數通過將它們推入堆棧傳遞給被調用的例程。他們從右到左推入堆棧。

因此,

printSomething (arg1, arg2, arg3, arg4); 

轉換爲...

pushl arg4 
pushl arg3 
pushl arg2 
pushl arg1 
call printSomething 
addl $0x10, %esp 

您可能會問自己,這是什麼

addl $0x10, %esp 

?我們將四個32位參數傳遞(也就是推送)到例程(到堆棧中)。儘管該例程知道期望這些參數,但它不負責將它們從堆棧彈出。來電者對此負責。所以,當我們從例程中返回後,我們調整堆棧指針,放棄先前推入堆棧的四個32位參數。

在上面的例子中,我假設我們在32位模式下運行。如果是16位模式,這將是...

pushw arg4 
pushw arg3 
pushw arg2 
pushw arg1 
call printSomething 
addw $0x8, %sp 

我意識到,在你的榜樣,printSomething()只需要一(1)的說法,在我的例子中,我使用了四個(4) 。根據需要調整我的示例。

對於最後的步驟,您需要將C和彙編文件編譯爲目標文件,鏈接目標文件然後執行。

我希望這會有所幫助。

+0

現在我想知道是否可以使用GCC從C函數實際生成x86彙編程序。是否有可能將C程序中的每個函數轉換爲等效的彙編語言函數,使用GCC或其他C編譯器? – 2013-05-09 23:24:04

+1

@AndersonGreen - 您可以隨時嘗試使用-S選項。 「gcc -S file.c」會將「file.c」轉換爲程序集(將其命名爲file.s)。或者,如果您已經擁有可執行文件,則可以使用「objdump -d exe_file> exe_file.asm」反彙編「exe_file」並將結果轉儲爲「exe_file.asm」。 – Sparky 2013-05-10 02:06:51

+0

@Sparky在x86程序約定中,每個函數在返回給調用者之前都有'leave'或等價指令。我認爲在你的例子中'addl $ 0x10,%esp'是多餘的。 – StrikeW 2015-08-22 06:35:52