关于.short数组奇数偏移处movw至AX与movb至AL加载指令的差异及代码运行结果异常的技术问询
解释x86汇编中movb与movw从.short数组奇数偏移加载的差异
咱们先从你的.short数组在内存里的实际布局说起——x86默认是小端模式,也就是每个多字节数据的低字节存在低地址,高字节存在高地址。你的数组定义是:
arr: .short 1, 0xEA, 0x2, 0x3, 0b1010
转换成内存中的字节序列(按地址从低到高排列)就是:
地址偏移 | 字节值 0x00 | 0x01 ; 第一个.short元素1的低字节 0x01 | 0x00 ; 第一个.short元素1的高字节 0x02 | 0xEA ; 第二个.short元素0xEA的低字节 0x03 | 0x00 ; 第二个.short元素0xEA的高字节 0x04 | 0x02 ; 第三个.short元素0x2的低字节 0x05 | 0x00 ; 第三个.short元素0x2的高字节 ...(后面元素同理)
现在逐个拆解你的指令:
1. movb 3(%rbx),%al
%rbx指向arr的起始地址,3(%rbx)就是从起始地址偏移3字节的位置——对应上面的0x03偏移,字节值是0x00。movb是单字节加载指令,只读取这个位置的1个字节,然后存入8位寄存器%al,所以%al的值自然是0x0。
2. movw arr+3, %ax
arr+3同样是偏移3字节的位置,但movw是16位(字)加载指令,会从这个位置开始连续读取2个字节:偏移3的0x00和偏移4的0x02。
因为x86是小端模式,加载16位值时,低地址的字节会存在寄存器的低8位(%al),高地址的字节存在寄存器的高8位(%ah)。所以这两个字节组合起来就是0x02(高字节) + 0x00(低字节) = 0x200,也就是你看到的%ax的值。
两条指令的核心区别(针对奇数偏移加载.short数组场景)
movb 目标地址, %al:只读取目标偏移处的单个字节,完全不关心这个位置是否在.short元素的边界上,直接取这1个字节到8位寄存器。movw 目标地址, %ax:从目标偏移处开始读取连续2个字节(大概率跨了两个.short元素的部分字节),然后按小端规则把这两个字节拼接成16位值存入%ax。简单说就是,它不会校验起始地址是否对齐,只要是16位加载就取连续2字节再组合。
内容的提问来源于stack exchange,提问作者Raea6789
相关产品推荐
相关产品推荐

