【发布时间】:2021-11-22 18:03:29
【问题描述】:
无论优化级别如何,在程序集级别加载立即值的指针都会加载一个稍微不同的值,在取消引用时使用固定偏移量进行更正。
例如
int test(){
int *tmp = (int*)0x30000004;
tmp[0]++;
return tmp[1];
}
使用mips-linux-gnu-gcc-8 -O3 -nostdlib test.c -c 编译生成以下程序集:
Disassembly of section .text:
00000000 <test>:
0: 3c033000 lui v1,0x3000
4: 8c640004 lw a0,4(v1)
8: 8c620008 lw v0,8(v1)
c: 24840001 addiu a0,a0,1
10: 03e00008 jr ra
14: ac640004 sw a0,4(v1)
如您所见,$v1 寄存器加载了0x30000000,然后偏移量全部移动了+4。
为什么 GCC 会这样做?
可以停用吗?
最终目标是得到这样的东西:
Disassembly of section .text:
00000000 <test>:
li v1,0x30000004
lw a0,0(v1)
lw v0,4(v1)
addiu a0,a0,1
jr ra
sw a0,0(v1)
【问题讨论】:
-
您不能仅在 1 条指令中加载任意 32 位数字。
lui接受 16 位立即数。您可以加载任意 32 位数字,发出lui来加载上半部分,然后发出ori来加载下半部分。您显示的代码使用lw的立即字段来偏移到所需的地址 -
一条 MIPS 指令是 32 位长的,那么如何在为操作码和寄存器号留出空间的同时将 32 位立即数挤入其中? How to load 32 bit constant to a register without using LUI, Load 32-bit constant to register in MIPS
-
@gusbro @phuclv 你说得对,我们不能在一条指令中做到这一点。我已经用正确的伪指令
li替换了“最终目标”,该伪指令扩展为lui/ori组合。我的问题与为什么 gcc 更喜欢使用lw的直接字段有关,旧版本没有这样做。
标签: gcc optimization mips