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

0 c x86 assembly 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
Run Code Online (Sandbox Code Playgroud)

Mat*_*lia 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
Run Code Online (Sandbox Code Playgroud)

(很抱歉将其更改为英特尔表示法,但AT&T语法对我来说看起来像是一个难以理解的混乱,尤其是解除引用和偏移的可怕符号1)

要理解这一点,请在函数prolog之后的x86上的cdecl函数调用中保留这个堆栈通常看起来的方便图表:

x86堆栈帧方案

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

从本质上讲,这是一个(非常天真)的翻译

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
}
Run Code Online (Sandbox Code Playgroud)

(使用cdecl调用约定,调用者有责任从堆栈中清除参数)

可能这是由禁用了优化的编译器生成的.更紧凑的版本是:

mov eax, [esp+4]
imul eax, [esp+8]
ret
Run Code Online (Sandbox Code Playgroud)

(因为一切都可以在没有局部变量的情况下完成,甚至不需要设置堆栈帧)


编辑

刚刚检查过,你的代码与gcc产生的代码完全匹配-O0,而我的代码几乎与生成的代码相同-O3.


笔记

  1. 记录:当你看到

    displacement(%register, %offset_register, multiplier)
    
    Run Code Online (Sandbox Code Playgroud)

    (其他每个组件%register都是可选的)它实际上意味着AT&T语法

    [register + displacement + offset_register*multiplier]
    
    Run Code Online (Sandbox Code Playgroud)

    括号的意思是"取值存储在这里".

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

  • AT&T语法恕我直言并不可怕.我发现自己很可读.阅读英特尔或AT&T语法需要花费相同的努力才能阅读.在你的注释中,你错过了``register + offset_register*multiplier]中的`offset`或位移.通常为了更有意义,我会说`offset [base_register + index_register*multiplier]`.`offset`也可以描述为`displacement`(术语可以互换).`multiplier`也可以描述为`标量`常数. (2认同)