了解汇编代码中的减法和乘法

时间:2015-11-12 20:50:23

标签: c assembly x86 disassembly

有人可以解释反汇编代码中的这些步骤会做什么。我有一个大概,但我仍然感到困惑。我知道前两个指令设置堆栈,而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

1 个答案:

答案 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 函数调用中,了解堆栈通常如何显示的方便图:

x86 stack frame scheme

并记住括号中的表达式是指针解除引用操作。

基本上,这是

的(非常天真)翻译
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生成的内容相同。

注释

  1. 记录:当你看到

    displacement(%register, %offset_register, multiplier)
    

    (除了%register之外的每个组件都是可选的)在AT& T语法中它实际上意味着

    [register + displacement + offset_register*multiplier]
    

    其中括号表示“取值存储在此处”。

    此外,几乎所有参数都以AT& T语法交换(在Intel语法中,目标操作数位于左侧,即mov读取类似于赋值 - mov ebp, esp => {{1 }})。