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语法(GNU
as
或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