assembly - x86 汇编语言中的函数调用

标签 assembly x86 att

我很难理解 gcc 创建的简单 C 程序的汇编语言输出。

这是该程序的 C 代码:

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

int sum1=1;
int sum2=1;

int add(int s1, int s2){
    return s1+s2;
}

int main(int argc,char** agrv){
    int res=sum1+sum2;
    return 0;
}

这是 gcc 创建的汇编代码:

    .file   "main.c"
    .globl  sum1
    .data
    .align 4
sum1:
    .long   1
    .globl  sum2
    .align 4
sum2:
    .long   1
    .text
    .globl  add
    .def    add;    .scl    2;  .type   32; .endef
    .seh_proc   add
add:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    .seh_endprologue
    movl    %ecx, 16(%rbp)
    movl    %edx, 24(%rbp)
    movl    16(%rbp), %edx
    movl    24(%rbp), %eax
    addl    %edx, %eax
    popq    %rbp
    ret
    .seh_endproc
    .def    __main; .scl    2;  .type   32; .endef
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $48, %rsp
    .seh_stackalloc 48
    .seh_endprologue
    movl    %ecx, 16(%rbp)
    movq    %rdx, 24(%rbp)
    call    __main
    movl    sum1(%rip), %edx
    movl    sum2(%rip), %eax
    addl    %edx, %eax
    movl    %eax, -4(%rbp)
    movl    $0, %eax
    addq    $48, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev2, Built by MinGW-W64 project) 7.1.0"

我很难理解汇编代码中某些指令的操作数顺序(另请参阅内存布局图片以供引用 Memory Layout )。首先是说明

    pushq   %rbp

它将调用者的基指针压入堆栈。在此指令之后是以下指令:

    movq    %rsp, %rbp

该指令应将被调用者的基指针设置为当前堆栈指针的值。但是,两个操作数的顺序不应该相反吗(例如 movq %rbp, %rsp)?

指令中出现类似的“问题”:

    addl    %edx, %eax

这里,运算结果存储在寄存器%edx中,而不是%eax(用于返回函数参数)中。

到目前为止,我在互联网上查阅的几乎所有来源都声称指令的结果存储在指令的第一个参数中?

最佳答案

GNU 编译器以“AT&T 语法”而不是 Intel 语法生成汇编,如所解释的 here :

The GNU Assembler, gas, uses a different syntax from what you will likely find in any x86 reference manual, and the two-operand instructions have the source and destinations in the opposite order. Here are the types of the gas instructions:

opcode                    (e.g., pushal)
opcode operand            (e.g., pushl %edx)
opcode source,dest        (e.g., movl %edx,%eax) (e.g., addl %edx,%eax)

Where there are two operands, the rightmost one is the destination. The leftmost one is the source.

关于assembly - x86 汇编语言中的函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52238553/

相关文章:

c - 获取栈的起始地址

assembly - 如何在保持一个值不变的情况下翻转 SSE 中的范围?

assembly - 请验证 AT&T Assembly line 的含义

c++ - 我可以控制特定的VC++编译器优化吗?

gcc - 有没有办法在 gnu 汇编常量中使用数学表达式?

linux - 如何在禁用 SMP 支持的情况下运行 "invd"指令?

assembly - 设计 AT&T 汇编语法的最初原因是什么?

assembly - 为什么 AT&T jmp *bar 汇编为带有 SIB 字节的机器代码?指令中没有使用寄存器

c++ - 移位操作后使用进位标志

assembly - 为什么 GCC 选择 dword movl 将长移位计数复制到 CL?