【问题标题】:x86 NASM changes value at address not passed as parameterx86 NASM 更改地址处的值未作为参数传递
【发布时间】: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

其中fmtdata 部分中声明为:

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


【解决方案1】:

以前,我使用%d 作为 scanf 的格式,它读取 4 个字节。但是 r14 和 r15 中的地址在 bss 部分中仅保留 1 个字节。我对此进行了更改,以便它们现在保留 4 个字节并且程序按预期运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多