gpt4 book ai didi

assembly - 带有跳转(和链接)指令的奇怪的MIPS汇编器行为

转载 作者:行者123 更新时间:2023-12-04 11:31:03 24 4
gpt4 key购买 nike

因此,我们正在学校学习MIPS架构,并且正在实现MIPS32架构。我以为我会使用GNU cross-binutils作为汇编器,但是在处理指令jal,j和jr时却得到了奇怪的输出。汇编程序似乎将指令插入错误的位置。我不知道为什么会这样,而且我怀疑MIPS汇编程序是否会损坏,所以我认为这应该发生。

这是我的虚拟 assembly 文件:

.section .text
.globl __start

__start:
addi $a0, $0, 100
addi $a1, $0, 200
jal test

test:
add $v0, $a0, $a1
jr $ra

但是,当我反汇编时,会得到以下输出:
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
...

这是一些建筑怪癖吗?如果是这样,背后的理由是什么?

编辑:
测试添加一些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

它给了我一些似乎正确的东西。
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

为什么jal和j用最后一条指令交换位置?

最佳答案

MIPS具有明显的管道危害;紧接在跳转或跳转指令之后的指令将始终被执行(该指令有时称为“分支延迟槽”)。如果您的代码确实按照编写的方式正确地进行了汇编:

__start:
addi $a0, $0, 100
addi $a1, $0, 200
jal test

test:
add $v0, $a0, $a1
jr $ra

那么 add指令将在 jal发生的时间附近执行两次:一次在延迟时隙中,一次在程序计数器更改实际生效时的下一个周期执行。

默认情况下,GNU汇编器为您重新排序指令:很明显,第二个 addi必须始终执行,因此可以与 jal指令交换,以便 addi移入延迟槽。 (如果汇编程序无法推断出这样做是安全的,它将改为在延迟槽中插入 nop。)

如果您不希望它为您重新排序,请添加指令
.set noreorder

在您的源文件的顶部。在这种情况下,您必须自己处理危险。如果您这样做,建议您为延迟槽添加注释,以使它们脱颖而出-例如通过增加一个或多个缩进空间。例如:
.set noreorder

__start:
addi $a0, $0, 100
jal test
addi $a1, $0, 200

test:
add $v0, $a0, $a1
jr $ra
nop

关于assembly - 带有跳转(和链接)指令的奇怪的MIPS汇编器行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3807480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com