【问题标题】:What is %rax initialized to? [duplicate]%rax 初始化为什么? [复制]
【发布时间】:2021-06-17 14:59:42
【问题描述】:

hybrid.s

.section .text   # specifices the beginning of the 'text' or code section
.global collatz  # makes the name 'collatz' visible to the linker

collatz:   # int collatz(long long n) {      
     ret   # return

hybrid.c

#include <stdio.h>    
#include <stdlib.h>    
     
 
extern int collatz(long long n);    

int main(int argc, char *argv[]){    
    if (argc < 2) {    
        printf("Parameter \"n\" is missing. \n");    
        return -1;    
    }     
    int output=0;    
    long long n = atoll(argv[1]);    
    for (long long i=1 ; i<n ; i++) {    
        output = collatz(i);    
        printf("collatz(%lld) is %d\n", i,output);    
    }    
}   

我正在测试 %rax 的初始化方式

>> gcc -o hybrid hybrid.c hybrid.s

>> ./hybrid 5

产量:

collatz(1) is 1
collatz(2) is 2
collatz(3) is 3
collatz(4) is 4

我希望 hybrid.s 总是返回 0,因为我的猜测是 %rax 被初始化为 0;但如您所见,情况并非如此。通过观察输出,我的假设是 %rax 默认等于 %rdi?

这会提示问题:%rax 初始化为什么?


编辑:

在下面每当我说“运行 hybrid.s 隔离”时,我的意思是“运行 hybrid.s 隔离所有出现的 collat​​z 替换为 '_start'” ,当然。

根据@ErikEidt 的评论,不应该运行 hybrid.s 如下隔离导致只返回之前的任何 %rax (最后设置为),因为它没有初始化?为什么我会收到Segmentation fault (core dumped)

>> as hybrid.s -o hybrid.o
>> ld hybrid.o hybrid
>> ./hybrid 5

产量

Segmentation fault (core dumped)

我的意思是 %rax 在任何给定时刻都必须包含 some 值.. 对吗?那么为什么会出现分段错误而不是仅仅返回 that 值呢?

【问题讨论】:

  • 因为collatz 有一个定义的原型并且不接受可变数量的参数,所以raxcollatz 的开头是未定义的。 It happens that it holds the cycle counter by chance.。您可以看到,当使用-O3 编译时,它包含atoll 的结果。重点是:rax 没有初始化,也没有初始化为零,也没有任何稳定值。
  • 寄存器保持其旧值,直到它们被重新利用。初始化是work;如果要完成,则必须执行一些机器代码。如果没有理由初始化某些东西,它通常不会完成。您的 C 代码和汇编代码在函数 collatz 上存在分歧,因此您应该期待随机行为。 (如果您反汇编您的 C main,您可能会看到使用 rax 的代码(可能在 for 循环中),如果是这种情况,那么这就是它获得价值的地方。)
  • 这与 GCC -O0 如何始终评估 EAX/RAX 中的表达式有关,包括 i 参数。就像在Return value in unused parameter 中一样,但这发生在调用者身上。我想我写了一个关于这个的答案(一个非 void C 函数从末尾掉下来,所以它没有修改 RAX 就返回了),但现在找不到那个重复的 Q&A。
  • @MargaretBloom, ErikEidt, PeterCordes ,你会如何解释我的编辑? (运行 hybrid.s 隔离会导致分段错误)
  • 如果你想了解你正在尝试的疯狂,那么在调试器中只需一步,一切都会被揭示出来。使用汇编模式单步执行,因此您可以观看它执行每条指令并查看寄存器从何处获取值以及崩溃的原因。

标签: c assembly x86 att


【解决方案1】:

使用调试信息编译并在 gdb 中打开运行它。 Gdb 可以设置断点,你可以列出你的寄存器的内容 :) 有趣的人的行业我是对的 8)))))))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-16
    • 2017-12-21
    • 1970-01-01
    • 2012-02-10
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    相关资源
    最近更新 更多