c - 在推送/弹出其他寄存器时从堆栈访问相对于 EBP 的函数参数?

标签 c assembly x86 nasm calling-convention

我正在编写一个汇编程序和一个 C 程序; C 程序将调用一个用汇编编写的函数。环境为Ubuntu 18.04LTS x64。

它是为 32 位 x86 设计的,将由 NASM 编译,但它不能传递正确的参数。

为了简化问题,我只是更改了函数以获得ab 的总和。

extern int FindPattern(int a,int b);

int result;
result=FindPattern(1,1);
printf("%d\n",result);
global FindPattern
 section .text
FindPattern:
    push    ebp
    push    esi
    push    edi
    push    ebx
    push    edx
    push    ecx
    
    mov     ebp,esp
    mov     esi,[ebp+8]     ; a
    mov     edi,[ebp+12]    ; b
    mov     eax,0
    add     eax,esi
    add     eax,edi         ; return a+b
    
    pop     ecx
    pop     edx
    pop     ebx
    pop     edi               
    pop     esi
    pop     ebp
    ret          

该函数只是将ab 相加,并返回总和。总和应该是 2,但是我得到了一个随机数,如 1449041840。看来程序集没有得到正确的参数。

代码有什么问题,我该如何解决?

# Makefile
cc=gcc
ASMBIN=nasm

all : asm cc link
asm:
    $(ASMBIN) -o findpattern.o -f elf32 -l findpattern.lst findpattern.asm
cc :
    $(cc) -m32 -c -g -O0 -fpack-struct graph_io.c
link :
    $(cc) -m32 -o graph_io findpattern.o graph_io.o 
clean:
    rm *.o
    rm graph_io
    rm findpattern.lst

最佳答案

您的堆栈框架设置有误。 推 ebp; mov ebp, esp 必须在任何其他堆栈移动发生之前发出。

通过在设置 ebp 之前将其他内容压入堆栈,您已经将 ebp 设置为指向与平常不同的位置,从而导致所有偏移量不同。要解决这个问题,首先设置栈帧,然后压入剩余的寄存器:

global FindPattern
 section .text
FindPattern:
    push    ebp
    mov     ebp,esp

    push    esi
    push    edi
    push    ebx
    push    edx
    push    ecx
    
    mov     esi,[ebp+8]     ; a
    mov     edi,[ebp+12]    ; b
    mov     eax,0
    add     eax,esi
    add     eax,edi         ; return a+b
    
    pop     ecx
    pop     edx
    pop     ebx
    pop     edi               
    pop     esi
    pop     ebp
    ret 

关于c - 在推送/弹出其他寄存器时从堆栈访问相对于 EBP 的函数参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65905009/

相关文章:

c++ - 有没有办法检查变量是否在编译时声明?

c++ - 为什么我绕行的代码会因 NOP 而崩溃

c - STM8 ASM 安全执行 WFE

c - ARMv7 汇编函数中查找数组最大元素时出现总线错误

architecture - 用于培训嵌入式开发的 x86 模拟器

assembly - 以 1ms 为增量获取时间

performance - 英特尔性能监视器计数器可用于测量内存带宽吗?

c# - 画一个圆的边界?

c:使用动态数组访问冲突写入位置

c++ - 滚动一个非常大的 GtkDrawingArea