非常大的地址被复制为负值
Posted
技术标签:
【中文标题】非常大的地址被复制为负值【英文标题】:Very large address copied as negative value 【发布时间】:2017-08-15 09:56:07 【问题描述】:我正在浏览一个对应于 C 程序的二进制文件。
我有一个非常大的地址存储在%eax
。
当尝试通过gdb
查看该值时,它会打印一个负值(原因here)。
现在当执行mov %eax, 0x4c(%esp)
时,0x4c(%esp)
中的结果值有时为正有时为负。此效果cmp $0, 0x4c(%esp)
声明如下!
有人可以解释一下这种行为吗?
如果这有帮助:core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style
【问题讨论】:
您实际上是如何在gdb
中显示这些值的?
您复制的位序列始终相同,但解释可能不同,可能 gdb 默认为二进制补码 32 位值
我使用print %eax
显示%eax
0x4c(%esp)
的内容如何显示?
FWIW,它不影响cmp
指令。它只是设置不同的标志,由您来解释它们,例如在条件跳转中使用ja
、jb
(用于无符号比较)或jg
、jl
(用于有符号比较),或使用seta
、setb
等。
【参考方案1】:
寄存器没有标志;他们持有比特。如何解释它们取决于您。堆栈也是如此:它保存位,如何解释它们取决于您。如果将值从寄存器移动到堆栈,则会复制这些位。如果你像解释寄存器中的位一样解释堆栈上的位,你会得到相同的值。
请注意,有 指令将这些位解释为值 - 乘法、比较等。但MOV
不是其中之一。
【讨论】:
加1用于解释数据之间的差异以及对此类数据的解释 但是,当0x4c(%esp)
用于cmp
时,我得到不同的结果。为什么会这样?
@JithinPavithran:我不知道这意味着什么。猜测:你的意思是紧接着,cmp %eax, 0x4c(%esp; jne ...
跳转?我不知道为什么这个序列会出现在编译的 C 代码中。
不,不是马上。在 mov 之后,有一个 jmp
(无条件),然后是 cmp
,然后是 jmp
,具体取决于结果。 (代码有一个heisenbug,我正在尝试深入理解)
@JithinPavithran:mov %eax,(...)
在内存中存储的值是32位值。您可以按照自己的意愿解释它,它仍然是相同的值(在位级别)。无论您对 "cmp
和代码流" 有什么困惑,一定有其他原因,cmp $0,...
针对地址有点荒谬,因为通常测试地址为零的唯一充分理由是捕获nullptr
值,因此符号位的值也无关紧要(然后使用jz(je)/jnz(jne)
之一)。很难说你在那里看到了什么,因为你没有发布它。【参考方案2】:
您复制的位序列始终相同,但解释可能不同,可能 gdb 默认为二进制补码 32 位值
如何更改 gdb 输出格式:
https://sourceware.org/gdb/onlinedocs/gdb/Output-Formats.html
【讨论】:
【参考方案3】:如果在 GDB 中使用以下命令:
print $esp-0x4c
您实际上显示的是 地址 -0x4c(%esp)
(即:寄存器 esp
的值加上偏移量 -0x4c
)并且 不是 位于此地址的内容。为了显示-0x4c(%esp)
的内容(即:查看此地址的实际内容),您可以使用x
命令:
x $esp-0x4c
【讨论】:
以上是关于非常大的地址被复制为负值的主要内容,如果未能解决你的问题,请参考以下文章