我对汇编语言非常陌生,我正在尝试解码从二进制文件(使用 gdb)生成的汇编文件。我无法理解以下代码(这是新函数的开始)。我在 x64 机器上,%rdi
包含 6 位数字(我的输入)。所以我们就说这是 0 1 2 3 4 5
)
400e79: 55 push %rbp
400e7a: 48 89 e5 mov %rsp,%rbp
400e7d: 48 83 ec 30 sub $0x30,%rsp
400e81: 48 89 7d d8 mov %rdi,-0x28(%rbp)
400e85: 48 8d 75 e0 lea -0x20(%rbp),%rsi
400e89: 48 8b 7d d8 mov -0x28(%rbp),%rdi
如果可以的话,我想向您展示我认为正在发生的事情:
400e79
:所以当我们启动一个函数时,我们将旧的基指针压入堆栈。所以堆栈看起来像:
RETURN ADDRESS
old %rbp value <--- %rsp
400e7a
:堆栈看起来像:
RETURN ADDRESS
old %rbp value <---- %rsp, %rbp
400e7d
:堆栈看起来像:
RETURN ADDRESS
old %rbp value <----%rbp
----empty----
----empty----
----empty----
----empty----
----empty----
----empty---- <---%rsp
400e81
:这里的内容真正让我困惑。我们将 %rdi
(0 1 2 3 4 5
) 中的内容移至 -0x28(%rbp)
中。所以堆栈看起来像:
RETURN ADDRESS
old %rbp value <----%rbp
----empty----
----empty----
----empty----
----empty----
0 1 2 3 4 5
----empty---- <---%rsp
但是,当我尝试通过在 gdb 上运行 x/s $rbp-0x28
来查看 -0x28(%rbp)
中的内容时,我没有得到 0 1 2 3 4 5
正如我所期望的,但我得到“\020C”
。我运行正确吗?
400e85:
堆栈:
RETURN ADDRESS
old %rbp value <----%rbp
----empty----
----empty----
----empty----
----empty---- <--- %rsi
0 1 2 3 4 5
----empty---- <---%rsp
400e89:
我根本不明白这一点。我们之前刚刚执行了 mov %rdi,-0x28(%rbp)
,为什么现在要执行 mov -0x28(%rbp),%rdi
?这不是重复了吗?
非常感谢!我知道这真的很长,感谢您花时间帮助我!
最佳答案
你的分析是正确的。
运行 x/s $rbp-0x28
时得到奇怪结果的原因是您无法将字符串放入寄存器中。寄存器包含的值很可能是指向该字符串的指针,这意味着您需要另一级间接读取它。我相信这会起作用:
p/x *(char**)($rbp-0x28)
x/s $
至于无用负载,这对于未经优化编译的代码来说很常见。编译器盲目地将每一行转换为汇编代码,而不考虑当前的寄存器值。我见过代码通过多个寄存器将单个值传递回它原来所在的寄存器。
关于assembly - 初学者 : Can't decode this assembly code,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13080647/