汇编.data段使用.int/.long初始化数据后取值异常咨询
问题原因解答
你观察到的高32位非预期值不是脏数据,核心原因是指令宽度和数据宽度不匹配,导致越界读取内存。
- 首先明确基础规则:GNU汇编器中
.int和.long伪指令都是定义32位(4字节)宽度的整数,对应读取应该使用32位传输指令movl。而你代码中用的movq是64位传输指令,执行movq 内存地址, %rcx时,CPU会从目标地址开始连续读取8个字节写入rcx寄存器,比你预期的多读了4个字节,这多出来的4字节就是相邻内存位置存储的真实值,不是随机脏数据。 - 你的结果是读错内存导致的,你还看错了十六进制数值的位:
你定义的数据在.data段从iary开始的内存布局是连续排列的:偏移0-3字节存1,4-7字节存2,8-11字节存3,12-15字节存4,16字节之后是段对齐填充或相邻段的内容。
对应你每条指令的实际读取结果:- 读
iary偏移0处的8字节:低4字节是1,高4字节是相邻的2,实际寄存器值为0x0000000200000001,你把高32位的0x2和后续的0连看,误判为0x20 - 读
iary偏移4处的8字节:低4字节是2,高4字节是相邻的3,实际寄存器值为0x0000000300000002,你误判高32位为0x30 - 读
lary偏移0处的8字节:低4字节是3,高4字节是相邻的4,实际寄存器值为0x0000000400000003,你误判高32位为0x40 - 读
lary偏移4处的8字节:低4字节是4,高4字节是16字节偏移处的填充值0x2c,实际寄存器值为0x0000002c00000004,你数错位数误写为0x2c00000004
- 读
- 正确写法:读取4字节宽度的
.int/.long数据时,使用movl指令操作32位寄存器即可,比如movl iary(, %rdi, 4), %ecx。x86-64架构规定,所有写入32位寄存器的操作,都会自动把对应64位寄存器的高32位零扩展,不会有残留值问题。
内容的提问来源于stack exchange,提问作者OnlyWick
相关产品推荐
相关产品推荐

