简体   繁体   English

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

[英]Wrong return value when calling NASM on x86-64 from C

I'm studying NASM on Linux 64-bit and have been trying to implement some examples of code.我正在 Linux 64 位上学习 NASM,并且一直在尝试实现一些代码示例。 However I got a problem in the following example.但是,我在以下示例中遇到了问题。 The function donothing is implemented in NASM and is supposed to be called in a program implemented in C:函数 donothing 是在 NASM 中实现的,应该在一个用 C 实现的程序中调用:

File main.c:文件 main.c:

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

int donothing(int, int);

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

File first.asm文件优先.asm

global donothing

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

What donothing does is nothing more than returning the value of the first parameter. donothing 所做的无非是返回第一个参数的值。 But when donothing is called the value 0 is printed instead of 1. I tried rbp+0x4, but it doesn't work too.但是当调用 donothing 时,打印的值是 0 而不是 1。我试过 rbp+0x4,但它也不起作用。 I compile the files using the following command:我使用以下命令编译文件:

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

Compiling the function 'test' in C by using gcc -s the assembly code generated to get the parameters looks similar to the donothing:使用 gcc -s 在 C 中编译函数 'test' 为获取参数而生成的汇编代码看起来类似于 donothing:

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

Assembly generated by gcc for the function 'test' above: 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

So, what's wrong with donothing?那么,什么都不做有什么错呢?

In x86-64 calling conventions the first few parameters are passed in registers rather than on the stack.x86-64 调用约定中,前几个参数在寄存器中而不是在堆栈中传递。 In your case you should find the 1 and 2 in RDI and RSI .在您的情况下,您应该在RDIRSI找到12

As you can see in the compiled C code, it takes a from edi and b from esi (although it goes through an unnecessary intermediate step by placing them in memory)正如您在编译后的 C 代码中所见,它从edi获取a并从esi获取b (尽管它通过将它们放入内存而经历了一个不必要的中间步骤)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM