所以我正在编写一个包含许多常量整数值的汇编程序。
我知道在.data部分我可以分配一个带有.word数据类型的标签并输入我的号码。使用这种方法,我仍然需要在main中加载一个地址。
但在主要方面,我可以简单地使用
li $ t1,some_number
这些方法中的任何一种方法都比其他方法更好吗?为什么?
答案 0 :(得分:0)
一般来说,我说使用li
是更好的方法。您在.data
部分中避免添加一堆混乱,并且在某些情况下您还可以获得更高效的代码。
让我们看看一些例子:
.data
ten: .word 10
million: .word 1000000
.text
main:
lw $t0,ten
li $t1,10
lw $t2,million
li $t3,1000000
在此理解这一点非常重要,lw
和li
都是伪指令,它们会被翻译成一个或多个实际指令。 lw
存在于MIPS指令集中,但它的这个特定变体并不存在。 MIPS指令集中不存在li
。
如果我们看一下SPIM为前两条指令生成的内容,我们会看到:
[0x00400024] 0x3c011001 lui $1, 4097 ; 9: lw $t0,ten
[0x00400028] 0x8c280000 lw $8, 0($1)
[0x0040002c] 0x3409000a ori $9, $0, 10 ; 10: li $t1,10
这是lw
变体的另一条附加指令,因为首先必须将地址加载到寄存器中,然后从该地址加载该值。这也意味着一个额外的(可能很慢的)内存访问(如果计算取指令数,则为两个)。
现在让我们看看另外两条指令,其中要加载的值太大而无法在单条指令中编码:
[0x00400030] 0x3c011001 lui $1, 4097 ; 11: lw $t2,million
[0x00400034] 0x8c2a0004 lw $10, 4($1)
[0x00400038] 0x3c01000f lui $1, 15 ; 12: li $t3,1000000
[0x0040003c] 0x342b4240 ori $11, $1, 16960
这里使用两个指令(15 << 16) | 16960
加载即时1000000。因此,这两种变体都需要两条指令,但li
变体不需要从内存中读取。
如果您想为常量指定一个有意义的名称,以避免在代码中包含幻数,您可以使用=
执行此操作:
TEN = 10
li $t0, TEN # Expands to li $t0, 10
你可以通过lw
- 相对寻址来避免一直加载$gp
的地址,但我觉得这超出了这个范围问题子>