2016-12-03 134 views
0

我有一個NASM文件和一個C文件。我的操作系統是Ubuntu 17.04 64位鏈接C與NASM在64位

我按照其他帖子的指示。 Linking C with NASM

這裏是我的代碼

的main.c:

#include <stdio.h> 

int doit(int a, int b); 

int main() 
{ 
    printf("%d\n", doit(2,4)); 
    return 0; 
} 

doit.asm:

global doit 

section .data 

section .text 

doit: 

    xor rax, rax   ;sets rax to 0 

    mov eax, [rsp+8]  ;sets **b** to eax(32bit = int size) 
    add eax, [rsp+16]  ;adds **a** to eax(32bit = int size) 

    ret 

編譯:

[email protected]:~/Desktop/TEST$ nasm -f elf64 doit.asm && gcc -Wall main.c doit.o 
[email protected]:~/Desktop/TEST$ ./a.out 318503633 
[email protected]:~/Desktop/TEST$ 

正如你所看到的,結果甚至不是接近預測的結果,這是6

請告訴我爲什麼是從32位彙編結果不同

+0

的問題調用約定。系統V 64位ABI可以[在這裏找到](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r252.pdf)。參數傳遞在_3.4.3_節中介紹。前6個整數類參數依次通過寄存器_RDI _,_ RSI _,_ RDX _,_ RCX _,_ R9_和_R8_傳入。整數類結果返回_RAX_。圖3.4還顯示了哪些寄存器需要通過函數來​​保存。添加2個參數就像'add rsi,rdi''mov rax,rsi'' ret'一樣簡單。添加2個寄存器並保存到第三個寄存器的技巧是''rax,[rdi + rsi]' –

回答

0

這是很簡單的,你用不同的調用約定 在x64參數由寄存器 因此通過你的彙編代碼正在尋找堆棧上的a,b參數(使用esp),你將會傳遞一個32位的數據,b通過堆棧 爲了解決這個問題,要麼研究x64上使用的調用約定,要學習哪些寄存器是用於傳遞參數以及如何確定在您的C代碼中 使用objdump -d並研究該代碼的反彙編以瞭解實際打開的內容 O r編譯gcc -m32並強制編譯器使用專有調用約定(在堆棧上)

+0

32位x86 System V ABI不是「專有」的。我認爲這是不好的自動更正或什麼,因爲缺乏段落和標點符號讓我覺得你在手機上寫了這個。 –

+0

是的,我現在沒有在我的電腦上,我會很樂意修復這一點,當它是可能的 – DrPrItay

1

您沒有使用正確的調用約定。 AMD64上的Linux使用System V AMD64 ABI

的main.c

#include <stdio.h> 

extern int sum (int a, int b); 

int main() 
{ 
    const int a = 2; 
    const int b = 3; 

    printf ("%d + %d = %d\n", a, b, sum (a, b)); 
    return 0; 
} 

sum.asm

 global sum 

     section .text 
sum: 
     mov eax, edi 
     add eax, esi 
     ret 

構建指令

nasm -f elf64 -o sum.o sum.asm 
gcc -o main.o -c main.c 
gcc -o main main.o sum.o 
+0

註冊參數調用約定允許更有效的代碼:'lea eax,[rdi + rsi]',它節省了MOV 。 (注意32位操作數,OP的原型使用'int'作爲args和返回值,所以在64位寄存器的高半部分對垃圾進行保存/操作是沒有意義的,尤其是因爲它耗費代碼 - REX前綴的大小。)(儘管在獨立函數中,下一個函數之前的填充實際上意味着它們都需要16B)。 –

+0

此外,x86-64.org [已死亡,似乎沒有回來](http://stackoverflow.com/questions/18133812/where-is-the-x86-64-abi-documented)。 :(請參閱[x86 tag wiki](http://stackoverflow.com/tags/x86/info)以獲取有關ABI文檔的鏈接。有些人喜歡在其他網站上鍊接某些最近的PDF副本 –

+0

我更改了操作數大小爲了與C簽名匹配,我保留了一個明確的'add'指令,以便清晰。 –