首页 > 解决方案 > 我如何将其转换为十六进制?

问题描述

slt $t2, $t0, $t1
beq $t2, $0, ELSE
j DONE
ELSE: addi $t2, $0, 3
DONE:

我需要将 beq $t2, $0, ELSE 转换为十六进制的机器语言,我真的不知道该怎么做?我知道你应该遵循格式 beq rs, rt, label 但问题是那里有一个 ELSE 那么我该怎么做呢?另外,为什么在定义之前使用 ELSE?为什么允许这样做?

标签: assemblymipsmachine-language

解决方案


BEQ是一个相对于 pc 的分支(相对于它之后的下一条指令完成)。它是一个带有立即数的 I-Type 指令,其值被添加到 pc (pc-next) 以形成分支目标。当立即数的值为 0 时,这与说分支到下一条指令相同(不要向前或向后跳过)。当立即数的值为 (+)1 时,表示向前跳过 1 条指令,而 -1 表示返回并再次重新运行该指令。-2 表示从分支本身返回一条指令,等等。(显然 0 和 -1 的值在实际代码中没有帮助,但最好知道它们(将)意味着什么。)

j指令不同;虽然它也有一个立即数,但它更大,而且它使用部分绝对寻址而不是 pc 相对寻址进行编码。由于这种行为,您必须知道此目标标签的地址DONE:才能创建立即值以使其跳转到那里。(而使用beq,只需要知道区别。)您没有显示代码地址,但是如果您更仔细地阅读问题陈述,它可能会告诉您第一条指令的地址,并且您可以从中得出标签的地址,DONE:因为它只是从一开始的 4 条指令。

分支和跳转都保持 PC 4 字节对齐。因此,立即数的低 2 位将始终为零,因此不会在指令中编码——这允许立即数比其他情况具有更大的范围。这些低 2 位均为零,由处理器在使用期间通过将立即数(左移 2)重新生成。(出于这个原因,相对于 pc 的分支使用指令计数而不是字节地址;对于跳转也是如此)。


另外,为什么在定义之前使用 ELSE?为什么允许这样做?

正如迈克尔所说,如果没有它,代码将很难编写。这称为前向引用,解析此类引用是汇编器的主要工作之一。

前向引用用于控制结构,如 if-then-else(如您所介绍的情况)和 while 循环(例如,退出它们);

if-then-else 语句通常有 2 个前向引用——一个在 if 条件为假时向前跳过(绕过/超过 then 部分)到 else 部分,一个用于 then 部分向前跳过/ 在 else 部分(以及 if-then-else 之后的下一条语句)。

while 循环通常具有至少一个用于退出循环的前向引用,通过跳过/跳过整个循环以便继续执行循环之后的下一条语句。

当被调用函数在汇编文件中物理位置位于调用函数之后时,前向引用也用于函数调用。

引用(向前和向后)是编写汇编而不是机器代码的主要价值之一,即汇编器计算立即数而不是人类必须这样做,尤其是在编辑代码时,例如,立即数需要更改这将是非常繁琐的手工操作。


推荐阅读