为啥没有用零填充
Posted
技术标签:
【中文标题】为啥没有用零填充【英文标题】: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
,并且会准确显示最后一个字节。
【参考方案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 在将数据加载到整数寄存器时所解释的内容。以上是关于为啥没有用零填充的主要内容,如果未能解决你的问题,请参考以下文章
为啥 toLocaleTimeString(),总是零填充分钟和秒