assembly 斐波那契序列汇编代码进行无意义操作[重复]

yyyllmsg  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(182)

此问题在此处已有答案

x86-64 assembly order of operands(1个答案)
上个月关门了。
下面的代码是如何编写的:

#include <stdio.h>
#include <stdint.h>

uint32_t fibonacci(uint32_t pos) {
    long next = 1, current = 0, tmp;
    for (long n = 1; n <= pos; n++) {
        tmp = current;
        current = next;
        next += tmp;
    }
    return current;
}

int main() {
    uint32_t target_pos, result;
    
    scanf("%u", &target_pos);
    result = fibonacci(target_pos);
    printf("%u\n", result);
    return 0;
}

这将产生以下汇编代码:

0000000000001189 <fibonacci>:
    1189: endbr64
    118d: push   %rbp
    118e: mov    %rsp,%rbp
    1191: mov    %edi,-0x24(%rbp)
    1194: movq   $0x1,-0x20(%rbp)
    119c: movq   $0x0,-0x18(%rbp)
    11a4: movq   $0x1,-0x10(%rbp)
    11ac: jmp    11cb <fibonacci+0x42>
    11ae: mov    -0x18(%rbp),%rax
    11b2: mov    %rax,-0x8(%rbp)
    11b6: mov    -0x20(%rbp),%rax
    11ba: mov    %rax,-0x18(%rbp)
    11be: mov    -0x8(%rbp),%rax
    11c2: add    %rax,-0x20(%rbp)
    11c6: addq   $0x1,-0x10(%rbp)
    11cb: mov    -0x24(%rbp),%eax
    11ce: cmp    %rax,-0x10(%rbp)
    11d2: jle    11ae <fibonacci+0x25>
    11d4: mov    -0x18(%rbp),%rax
    11d8: pop    %rbp
    11d9: retq

我做了一些调查,这是我的发现:
1.第一条指令(endbr 64)与安全性相关[ref],在我的例子中,它将是一个NOP
1.指令0x 118 d、0x 118 e、0x 11 d8和0x 11 d9与返回[ref]相关

  1. %rbp是堆栈的基底
    有了这些信息,我们就有了这个图表:

我试着去理解它,但有些操作完全是无稽之谈:

  • %eax(我发现它用于返回数据)被保存(而不是加载),未更改
  • %edi在开始时加载,并且从该点起不会更改/查询
  • asm在-0x10(%rbp)上执行“变量++”;所以你期望在-0x10(%rbp)中存储n,这是唯一一个加1的变量。但是在一条指令中,%rax-0x10(%rbp)进行了“小于或等于”的比较(查看原始C代码,我假设asm正在执行pos <= n,而实际上应该是相反的)。

就像这样越来越多...
有人能解释一下这到底是怎么回事吗?我用一个没有优化的AMD 3950X编译了C代码。

9q78igpj

9q78igpj1#

由于这显然是原来的问题,我会继续下去,并张贴它作为一个答案,所以这个问题可以得到关闭。

%edi is loaded at the start, and it doesn't change/get queried from that point

我相信你把它弄反了,在at&t语法中,mov %edi,-0x24(%rbp)意味着把edi移到rbp之前的内存地址0x24,这是有意义的,因为在x64调用约定中(对于linux),edi包含第一个参数。
如果你更喜欢阅读intel语法(哪个逻辑人不喜欢呢?),告诉你的反汇编器这就是你想要的输出格式。如果你使用objdump来产生你的输出,那就使用-M intel
虽然我还没有回顾你的其他问题,但这可能是所有问题的原因。
至于为什么intel语法不是默认的,我只想说 * 有些人 * 更喜欢at&t语法(可能就是那些认为制表符应该是2个空格的人),我希望大多数linux工具默认使用这种格式,至少现在你知道要注意它了。

相关问题