【问题标题】:why did not fill with zeros为什么没有用零填充
【发布时间】:2017-01-18 22:39:04
【问题描述】:

为 10000 位分配的数组 = 1250 字节(10000/8):

mov edi, 1250
call malloc

测试过指针:

cmp rax, 0
jz .error ; error handling at label down the code

内存已分配:

(gdb) p/x $rax
$3 = 0x6030c0

尝试用零填充分配的内存:

mov rdi, rax
xor esi, esi
mov edx, 1250 ; 10000 bits
call memset

检查第一个字节:

(gdb) p/x $rax
$2 = 0x6030c0
(gdb) x/xg $rax + 0
0x6030c0: 0x0000000000000000

检查最后一个字节(0 - 第一个字节,1249 - 最后一个字节)

(gdb) p/x $rax + 1249
$3 = 0x6035a1
(gdb) x/xg $rax + 1249
0x6035a1: 0x6100000000000000

已解决的问题 应该输入x/1c $rax + 1249

【问题讨论】:

  • 最后一个字节为零:0x6100000000000000。当您读取 8 字节值时,您会在最后一个字节之后获得 7 个字节,并且您不需要将它们归零。
  • 我正在使用带有小端序的 intel x64(i3)。所以看起来最重要的字节(0x61)应该在缓冲区的最后?或者我犯了错误,请纠正。
  • 您需要使用$rax + 1242 来读取缓冲区的最后 8 个字节。现在您只读取缓冲区的最后一个字节加上缓冲区后的 7 个字节。这 7 个字节不需要为零。
  • Little-endian 表示最低有效字节在前(地址较小):0x($rax + 1256)61($rax +1255)00($rax +1254)00($rax +1253 )00($rax +1252)00($rax +1251)00($rax +1250)00($rax +1249)00.
  • 现在我明白了,命令应该是x/1c $rax + 1249,并且会准确显示最后一个字节。

标签: x86-64 memset yasm fencepost


【解决方案1】:

您将内存解释为 64 位整数,但您忘记了 intel 的字节序是小字节序。所以字节被颠倒了。

0x6100000000000000是CPU在反序列化该地址的内存时读取的值。由于是小端,0x61 字节在内存中是最后一个(以这种格式转储内存不是很方便,除非你有大端架构)

使用x /10bx $rax + 1249,您会看到它在正确的位置为零。剩下的都是垃圾(碰巧一会为零,然后是垃圾)

0x00    0x00    0x00    0x00    0x00    0x00    0x61

【讨论】:

  • 我得到0x6035a1: 0 '\000' 0 '\000' 0 '\000' '\000' 0 '\'000' 0 '\'000' 0 '\'000' 97 'a',很奇怪
  • 此调试格式发出值 + 字符表示。所以这是正常的。使用这种格式,您可以获得内存中的内容,而不是 CPU 在将数据加载到整数寄存器时所解释的内容。
猜你喜欢
  • 2020-04-28
  • 1970-01-01
  • 2013-03-14
  • 2015-04-28
  • 2011-12-28
  • 2017-01-21
  • 2014-10-03
  • 2010-12-29
  • 1970-01-01
相关资源
最近更新 更多