Assembly 火星MIPS模拟器';s内置汇编程序的对齐比要求的多?
我有以下数据段Assembly 火星MIPS模拟器';s内置汇编程序的对齐比要求的多?,assembly,mips,memory-alignment,mars-simulator,Assembly,Mips,Memory Alignment,Mars Simulator,我有以下数据段 .data a: .byte 0x11 .align 1 b: .word 0x22334455 假设地址“a”是0x10010000,那么b处的单词的预期地址是0x10010002,但是MARS将单词存储在0x10010004,忽略显式的“.align”指令。顺便说一下,我使用MARS MIPS模拟器(MacBook Pro上的4.5版)来汇编上述代码 因此,我的问题是:这是一个bug,还是MARS的行为与SGI 1992年针对MIPS汇编语言的文档有所
.data
a: .byte 0x11
.align 1
b: .word 0x22334455
假设地址“a”是0x10010000,那么b处的单词的预期地址是0x10010002,但是MARS将单词存储在0x10010004,忽略显式的“.align”指令。顺便说一下,我使用MARS MIPS模拟器(MacBook Pro上的4.5版)来汇编上述代码
因此,我的问题是:这是一个bug,还是MARS的行为与SGI 1992年针对MIPS汇编语言的文档有所不同
(MARS和非MARS MIPS asm文档都同意MIPS语法中的
.align
需要2个arg的幂,因此.align 1
与2^1=2字节的边界对齐。与GAS/Unix汇编程序语法不同的是,对于其他一些架构,.align
=byte align,其中1
的arg是冗余的。)TL:DR:MARS工具提示有误导性;您需要使用.align 0
禁用该节其余部分的自动对齐。不能将下一个单词对齐。
.align 1
以2对齐,这不是问题所在。e、 g.在.byte
或.ascii
伪指令之间尝试
e、 g.该源生成0x00110062作为.data部分的第一个字,就像一样。字节'b',0,0x11,0
会这样
.data
a: .ascii "b"
b:
.align 1
.byte 0x11
而b:
标签在对齐填充后有地址2
(为了简单起见,我将MARS设置为“紧凑”内存布局,数据部分从地址0
开始。)
到目前为止,我们看到的与您为其Unix汇编程序链接的Silicon Graphics文档相匹配。(这与GNU
as
(又称GAS)和clang等现代汇编程序的工作方式非常不同。)
SGI文件中说:
推进位置计数器以使表达式处于低位
计数器的位为零。通常情况下,.half
、.word
、.float
和
.double
指令自动适当地对齐其数据。对于
例如,.word
执行隐式.align 2(.double
执行.align 3)。
您可以使用.align 0
禁用自动对齐功能。这个
汇编程序在下一个.text
,.data
时恢复自动对齐,
.rdata
或.sdata
指令
自动对齐或显式对齐前的标签
它们也重新排列。例如,foo:.align 3。单词0
是相同的
如.align 3;foo:.word0
这并不是说要使用.align 1
来对齐下一个.word
。仅此而已,您可以使用.align 0
完全关闭作为数据指令一部分的隐式对齐。让.align 1
覆盖并在下一个下对齐.word
而不必禁用自动对齐是有意义的,也是一种有效的设计,但这不是他们选择实现的功能
(请注意,.align 0
非常特殊:按1字节对齐不需要插入任何填充;当前位置始终是字节边界。因为没有理由使用.align 0
来对齐单个位置,语法设计者可能会用不同的含义来重载它:禁用自动对齐。)
火星确实支持这一点。(然后.align 1
将执行您期望的操作,在不使用隐式的情况下对齐到2^1=2。align 2
作为的一部分。word
在这之后增加对齐。)
数据段输出:
0x44550001 0x66662233 0x00006666 as little-endian words
01 00 55 44 33 22 66 66 66 66 00 00 as bytes
是的,.align
(明确地或作为.word
的一部分)不只是在当前位置插入填充,而是在任何前面的标签之前插入,就在最后一段数据之后
当然,如果确实希望避免隐式对齐到4字节边界,而不禁用自动对齐,则可以使用.byte
或.half
指令发出所需的任何数据。通常情况下,您并不希望这样做,而且在大多数情况下,这将避免初学者遇到对齐问题。MIPS是一种高度面向单词的ISA,因此通常没有什么理由使用欠对齐的.word
我看到的唯一一个火星bug是可用性:一个非常误导人的工具提示。
它当前表示对齐指定字节边界上的下一个数据项:(0=字节,1=一半,2=字,3=双精度)。这似乎意味着您可以将.word
对齐。关于.align 0
,这是一个严重的误导,它实际上禁用了本节其余部分的自动对齐
这不是
.align
在使用GAS语法(GNUas
或clang)的汇编程序中的工作方式。(例如,请参阅)
在我的Linux桌面上,我使用clang-c-target mipsel mipsalign.s
(“mipsel”是小端mips,与MARS使用的一样)
然后,我使用llvm objdump转储.data部分(使用“反汇编”,因为这是最简单的方法,尽管我必须清除不以单词边界开头的b:标签的重叠部分)
注意,b
有地址2
,而不是4
。(这是一个未链接的.o
;当链接到可执行文件时,地址会更高。对于位置相关的可执行文件,静态地址会更高,对于饼图,仅在运行时地址会更高)
在GAS语法中,.align
只是在该位置插入填充,直到到达对齐边界。因此,您通常希望将这些指令放在标签之前,因此标签地址是对齐的,并且位于填充之后。作为其他指令的一部分,也没有隐式的.align
MARS(和老式的SGI)的行为对我来说听起来有点像“训练轮子”,但我想这在一个重单词导向的ISA上是有意义的
0x44550001 0x66662233 0x00006666 as little-endian words
01 00 55 44 33 22 66 66 66 66 00 00 as bytes
$ llvm-objdump -D mips-align-clang-output.o
00000000 a:
0: 11 00 # manually cleaned up this line
00000002 b:
2: 55 44 33 22 addi $19, $17, 17493