在 64 位上返回 C 代码 x86 编译中的汇编函数 linux

returning Assembly Function In C Code x86 Compilation on 64 bit linux

C代码

#include <stdio.h>

int fibonacci(int);

int main()

{

    int x = fibonacci(3);

    printf("Fibonacci is : %d",x);

    return 0;
}

程序集

section .text

global fibonacci

fibonacci:

    push ebp;
    mov ebp, esp;
    ; initialize
    mov dword [prev], 0x00000000;
    mov dword [cur], 0x00000001;
    mov byte [it], 0x01; 
    mov eax, dword [ebp + 8]; // n = 3
    mov byte [n], al;

getfib:

    xor edx,edx;
    mov dl, byte [n];
    cmp byte [it] , dl;
    jg loopend; 
    mov eax,dword [prev];
    add eax, dword [cur];
    mov ebx, dword [cur];
    mov dword [prev], ebx;
    mov dword [cur] , eax;
    inc byte [it];
    jmp getfib;

loopend:

    mov eax, dword [cur];

    pop ebp;

    ret;

section .bss

    it resb 1

    prev resd 1

    cur resd 1

    n resb 1

我试图 运行 在 C 代码和调试中使用这个汇编函数,我看到 C 代码中变量 x 的值是正确的,但是当我使用 printf 函数时出现一些错误

需要帮助

编译命令:

nasm -f elf32 asmcode.asm -o a.o

gcc -ggdb -no-pie -m32 a.o ccode.c -o a.out

如果图片看起来模糊,请单击下面的图片

以下是printf执行前的调试

下面是printf执行后

您的代码不保留 ebx 寄存器,这是一个被调用者保留的寄存器。 main 函数显然试图做一些 rip 相对寻址,以使用 ebx 作为基址寄存器来获取 printf 的格式字符串的地址。这失败了,因为您的代码覆盖了 ebx.

要解决此问题,请确保在使用之前保存所有被调用者保存的寄存器,然后在 return 上恢复它们​​的值。例如,你可以做

fibonacci:

    push ebp
    mov ebp, esp
    push ebx ; <---

    ...

    pop ebx ; <---
    pop ebp
    ret