x86 汇编语言中的函数调用
Function call in x86 Assembly Language
我很难理解 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 , %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 [=11=], %eax
addq , %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)?
类似的"problem"出现在指令处:
addl %edx, %eax
这里,操作的结果存储在寄存器 %edx 而不是 %eax(用于 return 函数参数)。
到目前为止,我在 Internet 上查阅的几乎所有资料都声称指令的结果存储在指令的第一个参数中?
GNU 编译器以 "AT&T syntax" 而非 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.
我很难理解 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 , %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 [=11=], %eax
addq , %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)?
类似的"problem"出现在指令处:
addl %edx, %eax
这里,操作的结果存储在寄存器 %edx 而不是 %eax(用于 return 函数参数)。
到目前为止,我在 Internet 上查阅的几乎所有资料都声称指令的结果存储在指令的第一个参数中?
GNU 编译器以 "AT&T syntax" 而非 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.