Mai*_*ter 7 assembly mips disassembly binutils
因此,我们正在学校学习MIPS架构,我们正在实施MIPS32架构.我以为我会使用GNU cross-binutils作为汇编程序但是在处理jal,j和jr指令时我得到了奇怪的输出.汇编程序似乎将指令插入错误的位置.我不知道为什么会发生这种情况,我怀疑MIPS汇编程序会破坏,所以我认为这应该发生.
这是我的虚拟程序集文件:
.section .text
.globl __start
__start:
addi $a0, $0, 100
addi $a1, $0, 200
jal test
test:
add $v0, $a0, $a1
jr $ra
Run Code Online (Sandbox Code Playgroud)
但是,当我反汇编时,我得到这个输出:
Disassembly of section .text:
00000000 <__start>:
0: 20040064 addi a0,zero,100
4: 0c000003 jal c <test> <--- Why is jal coming before addi?
8: 200500c8 addi a1,zero,200
0000000c <test>:
c: 03e00008 jr ra <--- Why is jr coming before add?
10: 00851020 add v0,a0,a1
...
Run Code Online (Sandbox Code Playgroud)
这是一些建筑怪癖吗?如果是这样,这背后的理由是什么?
编辑:测试添加一些nop只是为了...
.section .text
.globl __start
__start:
addi $a0, $0, 100
addi $a1, $0, 200
nop
jal test
test:
add $v0, $a0, $a1
nop
jr $ra
Run Code Online (Sandbox Code Playgroud)
它给了我一些似乎有点正确的东西.
Disassembly of section .text:
00000000 <__start>:
0: 20040064 addi a0,zero,100
4: 200500c8 addi a1,zero,200
8: 0c000004 jal 10 <test>
c: 00000000 nop
00000010 <test>:
10: 00851020 add v0,a0,a1
14: 03e00008 jr ra
18: 00000000 nop
1c: 00000000 nop
Run Code Online (Sandbox Code Playgroud)
为什么jal和j交换位置的最后一条指令?
MIPS具有明确的管道危害; 紧接在分支或跳转指令之后的指令将始终被执行(该指令有时被称为"分支延迟槽").如果您的代码与您编写的代码完全一致:
__start:
addi $a0, $0, 100
addi $a1, $0, 200
jal test
test:
add $v0, $a0, $a1
jr $ra
Run Code Online (Sandbox Code Playgroud)
然后,add指令将在jal发生的时间周围执行两次:一次在延迟槽中,一次在下一个周期,当程序计数器更改实际生效时.
默认情况下,GNU汇编程序会为您重新排序指令:很明显第二个addi必须始终执行,因此可以与jal指令交换,以便addi进入延迟槽.(如果汇编程序无法推断出这样做是安全的,它会nop在延迟槽中插入一个.)
如果您不希望它为您重新排序,请添加该指令
.set noreorder
Run Code Online (Sandbox Code Playgroud)
在源文件的顶部.在这种情况下,您必须自己处理危险.如果你这样做,我建议注释延迟槽,以便它们脱颖而出 - 例如通过添加额外的空格(或两个)缩进.例如:
.set noreorder
__start:
addi $a0, $0, 100
jal test
addi $a1, $0, 200
test:
add $v0, $a0, $a1
jr $ra
nop
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3615 次 |
| 最近记录: |