如何强制 GAS 生成与输入相同的输出?
How do I force GAS to generate output identical to input?
我想编写具有 public C 接口的代码,但在其他方面完全在 MIPS 中实现,主要作为学习练习。但是,我一直在与 GAS 作斗争,因为它似乎认为它比我更了解。
为了说明,假设我想在 MIPS 中实现以下内容:
int bar(void)
{
return (4 / 2);
}
如上所述,我希望能够从 C 调用 ASM 例程,因此我们需要一个 C 代码文件,bar.c,以及 bar.S 中的 MIPS 程序集.
bar.c:
extern int bar(void);
void _start()
{
int foo = bar();
}
bar.S:
.global bar .text
bar:
addi , [=12=], 4
addi , [=12=], 2
div ,
mflo
jr
addu , [=12=], [=12=]
mipsel-none-elf-gcc bar.c bar.S -o bar.elf -ffreestanding -nostdinc -nostdlib
成功编译了这个,但是 mipsel-none-elf-objdump -d bar.elf
显示 GAS 弄乱了我的 bar() 代码:
00400050 <bar>:
400050: 20020004 addi v0,zero,4
400054: 20030002 addi v1,zero,2
400058: 14600002 bnez v1,400064 <bar+0x14>
40005c: 0043001a div zero,v0,v1
400060: 0007000d break 0x7
400064: 2401ffff li at,-1
400068: 14610004 bne v1,at,40007c <bar+0x2c>
40006c: 3c018000 lui at,0x8000
400070: 14410002 bne v0,at,40007c <bar+0x2c>
400074: 00000000 nop
400078: 0006000d break 0x6
40007c: 00001012 mflo v0
400080: 00001012 mflo v0
400084: 03e00008 jr ra
400088: 00000000 nop
40008c: 00001821 move v1,zero
我不想在此处以任何方式进行除法检查、延迟槽修正或汇编程序 "helpful":如果需要,我完全有能力自己处理这些事情。我如何告诉 GAS 只是一个愚蠢的汇编程序?
这个在评论里解决了。 GAS 接受 div
的 3 操作数版本,如果第一个操作数是 [=13=]
,除法检查将被禁用。至于延迟槽,.set noreorder
指令可防止指令重新排序(duh)。将程序集更改为:
.set noreorder
.global bar .text
bar:
addi , [=10=], 4
addi , [=10=], 2
div [=10=], ,
mflo
jr
addu , [=10=], [=10=]
产生正确的输出:
00400050 <bar>:
400050: 20020004 addi v0,zero,4
400054: 20030002 addi v1,zero,2
400058: 0043001a div zero,v0,v1
40005c: 00001012 mflo v0
400060: 03e00008 jr ra
400064: 00001821 move v1,zero
我想编写具有 public C 接口的代码,但在其他方面完全在 MIPS 中实现,主要作为学习练习。但是,我一直在与 GAS 作斗争,因为它似乎认为它比我更了解。
为了说明,假设我想在 MIPS 中实现以下内容:
int bar(void)
{
return (4 / 2);
}
如上所述,我希望能够从 C 调用 ASM 例程,因此我们需要一个 C 代码文件,bar.c,以及 bar.S 中的 MIPS 程序集.
bar.c:
extern int bar(void);
void _start()
{
int foo = bar();
}
bar.S:
.global bar .text
bar:
addi , [=12=], 4
addi , [=12=], 2
div ,
mflo
jr
addu , [=12=], [=12=]
mipsel-none-elf-gcc bar.c bar.S -o bar.elf -ffreestanding -nostdinc -nostdlib
成功编译了这个,但是 mipsel-none-elf-objdump -d bar.elf
显示 GAS 弄乱了我的 bar() 代码:
00400050 <bar>:
400050: 20020004 addi v0,zero,4
400054: 20030002 addi v1,zero,2
400058: 14600002 bnez v1,400064 <bar+0x14>
40005c: 0043001a div zero,v0,v1
400060: 0007000d break 0x7
400064: 2401ffff li at,-1
400068: 14610004 bne v1,at,40007c <bar+0x2c>
40006c: 3c018000 lui at,0x8000
400070: 14410002 bne v0,at,40007c <bar+0x2c>
400074: 00000000 nop
400078: 0006000d break 0x6
40007c: 00001012 mflo v0
400080: 00001012 mflo v0
400084: 03e00008 jr ra
400088: 00000000 nop
40008c: 00001821 move v1,zero
我不想在此处以任何方式进行除法检查、延迟槽修正或汇编程序 "helpful":如果需要,我完全有能力自己处理这些事情。我如何告诉 GAS 只是一个愚蠢的汇编程序?
这个在评论里解决了。 GAS 接受 div
的 3 操作数版本,如果第一个操作数是 [=13=]
,除法检查将被禁用。至于延迟槽,.set noreorder
指令可防止指令重新排序(duh)。将程序集更改为:
.set noreorder
.global bar .text
bar:
addi , [=10=], 4
addi , [=10=], 2
div [=10=], ,
mflo
jr
addu , [=10=], [=10=]
产生正确的输出:
00400050 <bar>:
400050: 20020004 addi v0,zero,4
400054: 20030002 addi v1,zero,2
400058: 0043001a div zero,v0,v1
40005c: 00001012 mflo v0
400060: 03e00008 jr ra
400064: 00001821 move v1,zero