2016-12-03 70 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'指令,以便清晰。 –