有人可以解释反汇编代码中的这些步骤会做什么。我有一个大概,但我仍然感到困惑。我知道前两个指令设置堆栈,而eax将是一个返回值但是关于它。
我正在寻找的是以下步骤的目的:
push %ebp - base stack frame pointer
mov %esp, %ebp - stack pointer
sub $0x10, %esp - subtracts 16 from ?
mov 0x8(%ebp), %eax - ?
imul 0xc(%ebp), %eax - multiply 12 and ?
mov %eax, -0x4(%ebp) - ?
mov -0x4(%ebp), %eax - puts -0x4(%ebp) not sure what that would be , into eax making it the return value?
leave
ret
答案 0 :(得分:5)
; Standard prolog: stack frame setup
push ebp ; save the old frame pointer
mov ebp, esp ; set the frame pointer to the current top of the stack
sub esp, 0x10 ; make space for 16 bytes of local variables
; Do the stuff
mov eax, [ebp+8] ; copy the first parameter in eax
imul eax, [ebp+0xc] ; multiply eax with the second parameter
mov [ebp-4], eax ; move the result to the first local variable
mov eax, [ebp-4] ; move it back to eax (?) => set it as return value
; Standard cdecl epilog - clean up locals & return
leave ; restore the old frame pointer
; same as: mov esp, ebp
; pop ebp
ret ; return
(很抱歉将其更改为英特尔符号,但AT& T语法对我来说看起来是一个难以理解的混乱,尤其是解除引用和抵消 1 的可怕符号)
要理解这一点,请在函数prolog之后的x86上的 cdecl 函数调用中,了解堆栈通常如何显示的方便图:
并记住括号中的表达式是指针解除引用操作。
基本上,这是
的(非常天真)翻译int multiply(int a, int b) {
// \ \ &b == ebp+12
// \ &a == ebp+8
int c = a*b;
// \ \ multiplication performed in eax
// \ &c == ebp-4
return c;
// \ return value left in eax
}
(使用cdecl调用约定,调用者有责任从堆栈中清除参数)
可能这是由禁用了优化的编译器生成的。更紧凑的版本是:
mov eax, [esp+4]
imul eax, [esp+8]
ret
(因为一切都可以在没有局部变量的情况下完成,甚至不需要设置堆栈框架)
修改的
刚刚检查过,您的代码与gcc在-O0
生成的内容完全匹配,而我的代码几乎与-O3
生成的内容相同。
记录:当你看到
displacement(%register, %offset_register, multiplier)
(除了%register
之外的每个组件都是可选的)在AT& T语法中它实际上意味着
[register + displacement + offset_register*multiplier]
其中括号表示“取值存储在此处”。
此外,几乎所有参数都以AT& T语法交换(在Intel语法中,目标操作数位于左侧,即mov
读取类似于赋值 - mov ebp, esp
=> {{1 }})。