我是汇编语言的新手,我正在尝试解码从二进制文件生成的汇编文件(使用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上运行-0x28(%rbp)
来查看x/s $rbp-0x28
中的内容时,我没有像我期望的那样得到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
?这不重复吗?
非常感谢!我知道这真的很长,感谢你抽出时间帮助我!
答案 0 :(得分:2)
您的分析是正确的。
运行x/s $rbp-0x28
时得到奇怪结果的原因是你不能将字符串放在寄存器中。寄存器包含的值很可能是指向该字符串的指针,这意味着您需要另一级别的间接读取它。我相信这会奏效:
p/x *(char**)($rbp-0x28)
x/s $
对于无用的负载,这对于没有优化编译的代码来说很常见。编译器盲目地将每一行转换为汇编而不考虑当前寄存器值。我见过代码,它通过几个寄存器将一个值传递回原来的寄存器。