【发布时间】:2018-06-06 12:40:51
【问题描述】:
我注意到 NASM 汇编代码中 scanf 的一些特殊行为。我有两个电话给 scanf:
mov rdi, fmt
mov rsi, r14
call _scanf
和
mov rdi, fmt
mov rsi, r15
call _scanf
其中fmt 在data 部分中声明为:
section .data
fmt: db "%d", 0
在第一个scanf之前,r14和r15中的地址是:
r14 = 0x0000000000002104
r15 = 0x0000000000002105
在 LLDB 中,对这些地址中的任何一个执行 me read -fd -c1 都会输出 0。
在第一个 scanf 输入“2”后,0x0000000000002104 中的值是 2。
第二个scanf输入“2”后,0x0000000000002105中的值为2。而现在0x0000000000002104中的值为514。
在其他地方调用scanf 后,我在内存中遇到了类似的变化,如果需要,我会重现它们,但想知道是否有人遇到过这种情况。
【问题讨论】:
-
这些地址 2104 和 2105 相隔一个字节,但您使用的是“%d”,它将填充一个 4 字节整数,可能会破坏您尝试读取的位置之后的字节。您缺少一个最小的完整可验证示例。您应该只发布您的代码,我们可以更好地理解它。这是在 MacOS 上吗?在 scanf 调用之前,您是否将 AL 寄存器设置为零?
-
514为0x0202,即2105和2104中字节值的dword组合。
-
@MichaelPetch:您可以在 cmets 中使用
[mcve]:它扩展为 minimal reproducible example。这几乎太小了,但我认为这个具体问题可以基于此来回答。我猜你想检查 OP 在 scanf 之后读取整数值的宽度,以确保它是 dword,与%d存储的int的宽度匹配? -
换言之,0x2014 和 0x2015,如果用作 32 位整数的地址,重叠。如果 scanf 向 0x2014 写入“2”,它会将 2 写入 0x2014,0 写入 0x2015,0 写入 0x2016 和 0 写入 0x2017。写入 0x2015 将分别写入 2 到 0x2015 和 0 到 0x2016..0x2018。现在,如果您从 0x2014 读取,在 0x2014 将有一个 2,在 0x2015 有一个 2,在 0x2016 有一个 0,在 ox2017 有一个 0。这意味着你得到 0x00000202,即 514。
-
请将答案作为答案发布,而不是对您的问题进行编辑。
标签: assembly x86 scanf nasm lldb