RISC-V汇编器中的大多数指令将目标操作数排序在源操作数之前,例如:
li t0, 22 # destination, source
li t1, 1 # destination, source
add t2, t0, t1 # destination, source
但商店的说明书却颠倒了顺序:
sb t0, (sp) # source, destination
lw t1, (a0) # destination, source
vlb.v v4, (a1) # destination, source
vsb.v v5, (a2) # source, destination
怎么会这样?
这种(可论证的)非对称汇编语法设计的动机是什么?
2条答案
按热度按时间iih3973s1#
当涉及到 * 目标 * 和 * 源操作数 * 时,我没有看到RISC-V汇编中真正的不一致:目标操作数(如果是指令编码的一部分)始终对应于汇编语言中的 * 第一个操作数 *。
下面是六种不同指令格式中四种的指令示例:
add t0, t1, t2
addi t0, t1, 1
1jal ra, off
lui t0, 0x12345
在上面的汇编指令中,* 目标操作数 * 是第一个操作数。显然,此目标操作数对应于指令编码中的
**destination register**
。现在,让我们关注存储指令(S型格式)。作为示例,考虑以下存储指令:
我认为上面的**
t0
是source operand
**是非常清楚的,因为存储指令将其内容存储在内存中。我们可能会认为
8(sp)
是一个 * 目标操作数 *。但是,通过仔细查看S类型指令格式:我们可以看出,上述汇编指令中的
8(sp)
部分实际上不是一个操作数,而是两个操作数,即立即数8
(即 * imm *)和 * 源寄存器 *sp
(即 * rs1 *)。如果该指令可以表示为(类似于addi
2):很明显,这条指令需要三个操作数,而不仅仅是两个。
寄存器
sp
未修改,仅读取;因此,它不能被视为 * 目标寄存器 。它也是 * 源寄存器 ,就像t0
一样-存储指令将其内容存储在内存中的寄存器。内存是destination operand
,因为它接收t0
的内容。S类型指令格式不编码目标操作数。此指令编码的是目标操作数上的
addressing information
**。对于sw t0, 8(sp)
,目标操作数是存储指令根据sp
与8
计算出的word in memory at the location specified by the **effective address**
。寄存器sp
包含有关该字在内存中的部分寻址信息(即目的操作数)。总结
RISC-V中编码目标操作数的汇编指令将此操作数作为第一个操作数。但是,存储指令不编码目标操作数。它的目标操作数是内存中的一个位置,此位置在内存中的地址是根据指令源操作数的内容计算出来的。
1我们可能会认为,上面的
jal ra, off
指令还有一个目标操作数,即pc
,因为pc
的更新方式如下:pc
←pc
+* 符号扩展名然而,执行任何其它指令也会导致修改pc
,例如,将pc
递增4(对于分支和jalr
可以不同)。无论如何,pc
没有被编码在任何指令中,程序员不能直接将其作为寄存器访问。因此,它不是我们讨论的重点。出于同样的原因,我也省略了B型格式。2或者反过来说:假设可以将
addi t0, t0, -1
表示为addi t0, -1(t0)
,那么addi
是否有两个操作数(例如t0
和-1(t0)
)?4uqofj5v2#
汇编语言是由汇编程序,即程序来定义的。它是由作者来选择语法的。汇编程序可以选择语法
并且这将是将一个寄存器存储到由另一个寄存器定义的地址中的完全有效的语法。在某些汇编语言语法中,甚至可能使用#define的等价物。
"为什么"这个问题实际上意味着您希望与可能不使用Stack Overflow的实际开发人员交谈,尽管您可能很幸运,因此这个问题没有实际的答案。
为了获得成功的机会,处理器开发者的最佳利益是创建或雇用某人来创建用于他们的新处理器的最初和后来的汇编程序工具链,这将包括某人坐下来检查机器代码并根据其创建语言。用于目标的第三方汇编程序的成功机会包括使用与原始指令相似的指令语法,但是如果你不想把它弄混,为什么还要费心去做一个新的呢?指令语法只是汇编程序定义的整个语言的一部分,你会发现mips,arm等有很大的变化,随着时间的推移risc-v也会有很大的变化,尽管在过去的几十年里,制造新工具的愿望已经急剧下降。
一个成功的汇编程序必须遵循的唯一规则是逻辑定义的规则,语法可以是他们选择的任何东西,无论他们选择的原因是什么。所以如果你想知道,你必须询问每个作者/团队,甚至不确定Bugzilla是否会让你到达那里。
一个相关的为什么问题是,既然我们在早期生活中花了那么多时间,目的地就在左边
而不是
哪个理智的人会设计一个指令部分在右边的汇编语言,即使是高级语言也不会这样做。
对于你的问题,一个可能的答案是,很久以前有人很懒,用同样的代码来加载/存储,或者剪切和粘贴它。
不仅仅是Intel,还有所有的主要/次要指令集,你会发现不同工具之间的语法不兼容,x86,arm,mips,msp430,avr,8051,6502,z80等,如果还没有的话,最终会发现risc-v。为gnu汇编添加目标的人必须为他们经常做的不兼容汇编语言感到自豪。
指令中的位置一般与汇编语言无关。作者一开始要么在目的地的第一营地,要么在目的地的最后营地。
然后寄存器的名称是自由形式的,有时会变化。ax,% ax.r0,$0
最近的一个(可怕的)时尚,我想是来自mips和它在v0,a0,t0等学校的使用......以及感染其他不相关的指令集。不同指令集习惯的混乱这些天经常发生。
他们选择如何指示间接@r1、(r1)、[r1]......
如何指示前/后增量/修改等,因为他们通过说明工作。
有些人选择4(r1),而另一些人则选择[r1,#4]
首先,汇编语言或大量使用的个人发挥作用,他们喜欢如何处理其他人,有些人只是必须使自己的工具,以避免学习另一种语言或处理他们不喜欢的另一种语言,因此AT & T的事情,可能是gnu汇编程序的选择。肯定的方式MIPS处理调用约定,以及如何的概念,功能?感染了其他的工具甚至教室。
特别是看一下x86汇编语言随时间的演变(AT & T与Intel的对比与我所说的无关)。
正如它应该的那样,你只需学习汇编程序使用的语言并继续前进,或者你编写自己的汇编程序来匹配你喜欢的语言,如果你发布它和其他喜欢它的人,那么它就可以进入规范,你正在看到这种情况的发生。
简短的回答,因为其他汇编语言也这样做。因为你可以在他们的设计中看到risc-v和MIPS之间的明确联系,毫无疑问文档的作者也遵循了他们已经习惯于导致risc-v的MIPS风格。规则的例外情况会发生,虽然总是把目的地留在一边会是一个更纯粹的解决方案。但更重要的是如你所指出的一致性。Don "不要有一种存储方式和另一种存储方式。看看典型ARM语法中的MRS/MSR,目标/源在中间,在同一个地方。
就gnu汇编程序而言,binutils是开源的,你可以完全自由地转换它,同样你也可以自由地创建你自己的汇编程序,按照你想要的顺序和语法。如果你想让它成为一个链的一部分,那么就像当前的工具链一样,你需要创建/修改编译器来匹配汇编程序和链接器。
如果这是一个严格意义上的“为什么”问题,那么它主要是基于观点的,应该关闭。文档的作者和汇编程序(后端)的作者可以自由选择,这就是选择。