Assembly 为什么';mov&x27;指令导致目标寄存器的高位中存在多余字节?
我试图在一个非常简单的for循环中调试崩溃。C++非常类似于:Assembly 为什么';mov&x27;指令导致目标寄存器的高位中存在多余字节?,assembly,x86-64,Assembly,X86 64,我试图在一个非常简单的for循环中调试崩溃。C++非常类似于: bool test(uint64_t value) { auto iter = std::find_if(..., ..., [value](const auto& element) { return element.proxy ? element.proxy->value == value : false; //element.proxy is a pointer
bool test(uint64_t value) {
auto iter = std::find_if(..., ..., [value](const auto& element) {
return element.proxy ? element.proxy->value == value : false; //element.proxy is a pointer
}
...
}
生成的程序集非常简单,基本上是一个展开的for循环
...
6b5b72: 4c 8b 6d 08 mov r13,QWORD PTR [rbp+0x8]
6b5b76: 4d 85 ed test r13,r13
6b5b79: 74 06 je 6b5b81
6b5b7b: 41 3b 55 00 cmp edx,DWORD PTR [r13+0x0]
6b5b7f: 74 7f je 6b5c00
6b5b81: 4c 8b 6d 48 mov r13,QWORD PTR [rbp+0x48]
6b5b85: 4d 85 ed test r13,r13
6b5b88: 74 0a je 6b5b94
6b5b8a: 41 3b 55 00 cmp edx,DWORD PTR [r13+0x0]
6b5b8e: 0f 84 bc 01 00 00 je 6b5d50
6b5b94: 4c 8b ad 88 00 00 00 mov r13,QWORD PTR [rbp+0x88]
6b5b9b: 4d 85 ed test r13,r13
6b5b9e: 74 0a je 6b5e10
6b5ba0: 41 3b 55 00 cmp edx,DWORD PTR [r13+0x0] ;We will crash here
6b5ba4: 0f 84 66 02 00 00 je 6b5e10
6b5baa: 4c 8b ad c8 00 00 00 mov r13,QWORD PTR [rbp+0xc8]
6b5bb1: 4d 85 ed test r13,r13
6b5bb4: 74 0a je 6b5bc0
6b5bb6: 41 3b 55 00 cmp edx,DWORD PTR [r13+0x0]
6b5bba: 0f 84 80 01 00 00 je 6b5d40
6b5bc0: 48 81 c5 00 01 00 00 add rbp,0x100
6b5bc7: 48 39 c5 cmp rbp,rax
...
(note: there might be slight transcription errors in the raw hex and je addresses which I am attempting to fix)
程序在第6b5ba0行崩溃。$r13的值远远超出了我预期的有效内存地址
(gdb) p/x $r13
$130 = 0x40007f7bd5b3fde8
但问题是,基于我期望$r13等于$rbp+0x88所指向的64位值的程序集。如果我们在gdb中查看该值,我们会得到:
(gdb) p *(uint64_t **)($rbp+0x88)
$132 = (uint64_t *) 0x7f7bd5b3fde8
这是$r13中的值,除非地址前面有0x4000。我还验证了0x7f7bd5b3fde8处的数据是否符合我的预期。看看输出,我不知道这是怎么可能的,特别是因为我必须假设前面对应于展开循环的指令没有触发这一点
这些额外的字节是如何到达那里的?您能发布足够的代码使您的示例可以重现吗?这是否能持续重现?您是否在6b5b94上中断,确保
[rbp+0x88]
符合您的预期,然后单步验证r13
是否错误?您确定这是正确的反汇编吗。我认为74 0a
和0f 84 66 02 00 00
具有相同的分支目标6b5e10
是毫无意义的,因为它们之间只有一条其他指令。您的反汇编肯定是错误的<代码>74 0aat6b5b9e
是je 6b5baa
,而不是je 6b5e10
。假设您没有手工编辑显示的内容,则会出现严重错误。事实上,0x40007f7bd5b3fde8
是非规范的(不是48或57位符号扩展),因此取消引用它肯定会出错。你的CPU是否超时了?或者你的RAM会出故障吗?这也许可以解释“加载”一个不在内存中的值。