从C调用x86-64上的NASM时返回值错误

时间:2013-06-19 14:22:19

标签: c assembly nasm

我在Linux 64位上学习NASM,并且一直在尝试实现一些代码示例。但是我在下面的示例中遇到了问题。函数donothing在NASM中实现,应该在用C:

实现的程序中调用

文件main.c:

#include <stdio.h>
#include <stdlib.h>

int donothing(int, int);

int main() {
    printf(" == %d\n", donothing(1, 2));
    return 0;
}

档案first.asm

global donothing

section .text
    donothing:
    push rbp
    mov rbp, rsp
    mov eax, [rbp-0x4]
    pop rbp
    ret

所做的只不过是返回第一个参数的值。但是当调用donothing时,将打印值0而不是1.我尝试了rpb + 0x4,但它也不起作用。 我使用以下命令编译文件:

  nasm -f elf64 first.asm && gcc first.o main.c

使用gcc -s在C中编译函数'test',生成的汇编代码看起来类似于donothing:

int test(int a, int b) {
    return a > b;
}

gcc为上面的函数'test'生成的程序集:

test:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -4(%rbp), %eax
    cmpl    -8(%rbp), %eax
    setg    %al
    movzbl  %al, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

那么,什么是不好的?

1 个答案:

答案 0 :(得分:4)

x86-64 calling conventions中,前几个参数在寄存器中而不是在堆栈中传递。在您的情况下,您应该在12中找到RDIRSI

正如您在编译的C代码中看到的那样,来自a的{​​{1}}和来自edi的{​​{1}}(尽管通过放置它们会经历一个不必要的中间步骤)在记忆中)