C 汇编语言 ATT 演练?

C assembly language ATT walkthrough?

我有一个简单的 C 程序,可以对三个变量进行乘法和加法运算,并 returns 结果。我已经在 32 位机器上将代码编译成汇编语言(ATT 格式)。我正在尝试学习汇编代码,虽然我可以理解其中的一些行,但我需要帮助来理解为什么例如 leal (%edx, %edx, 2), %edx,会在下面的代码中完成,比如结果会是什么,会是什么它完成了吗?

汇编代码

.file   "calc.c"
        .text
.globl calc
        .type   calc, @function
calc:
        pushl   %ebp                   #prolog
        movl    %esp, %ebp             #prolog
        movl    8(%ebp), %edx          #move %ebp +8 into %edx 
        movl    16(%ebp), %ecx         #move %ebp +16 into %ecx
        leal    (%edx,%edx,2), %edx
        movl    12(%ebp), %eax
        leal    (%edx,%eax,2), %eax
        movl    %ecx, %edx
        sall    , %edx
        subl    %ecx, %edx
        addl    %edx, %eax
        popl    %ebp
        ret
        .size   calc, .-calc
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits

C程序

#include <stdio.h>
int calc(int x, int y, int z){
    return 3*x + 2*y + 15*z;
}
int main(void) {
    int x = 2;
    int y = 6;
    int z = 11;

    int result = calc(x,y,z);

    printf("x=%d, y=%d, z=%d, result=%d\n", x,y,z,result);
    return 0;
}

谁能帮我从序言开始追查问题。

我建议您从不优化代码开始。您的优化器正在玩弄您。如果您的系统以相反的顺序推送参数

8(%ebp) = x = edx
12(%ebp) = y = eax
16(%ebp) = z = ecx

使用汇编游戏:

(%edx,%edx,2) = edx + 2 x edx = 3 x edx  (3 x X)
(%edx,%eax,2)  = edx + 2 x eax = (3 x X + 2 * y)

  movl    %ecx, %edx
  sall    , %edx = (16 x Z)
  subl    %ecx, %edx = 15 x Z

也许最好用 C 函数代码来解释:

int calc(int x, int y, int z){
    return 3*x + 2*y + 15*z;
}

查看参数 x。它乘以 3,因此在汇编代码中很容易识别:

movl    8(%ebp), %edx

.....

leal    (%edx,%edx,2), %edx
movl    12(%ebp), %eax
leal    (%edx,%eax,2), %eax

它将参数 x 的值移动到 edx 中。堆栈帧中参数 x 的地址是 ebp+8。然后稍后使用 leal 将 edx 添加到 2*edx 并将值存储在 edx 中。那等于 3*x.
然后将参数 y 加载到 eax 中,你可以很容易地识别它,因为 y 是一个 32 位 int,所以它比 x 的起始地址高 4 个字节。
接下来 leal 将 edx(即 3*x)与 2*eax(即 2*y)相加并将结果存储在 eax 中,因此在 eax 中你有 3*x + 2*y。
等等...