MIPS标签存储位置

时间:2017-03-05 17:14:03

标签: assembly mips machine-language

在MIPS中,在使用跳转指令时,我们使用标签。

again: nop
    $j again

因此,当我们到达跳转指令时,我们使用标签again来显示去哪里以及使用的实际地址的值。我想知道再次标签的存储位置。意思是,nop表示存储在0x00400000,跳转指令位于0x00400004。那么,again保存在哪里,MIPS如何知道again指向0x00400000?它存储在存储器映射的动态数据区域中吗? This is the memory map I've been provided for MIPS

我还在下面列出了导致这种混淆的问题,供参考。

为以下分支(be,bne)和jump(j)指令提供十六进制的目标代码。

... # some other instructions
again:  add ... # there is an instruction here and meaning is insignificant
    add ... # likewise for the other similar cases
    beq    $t0, $t1, next
    bne  $t0, $t1, again
    add ...
    add ...
    add ...
next:   j   again

假设标签再次位于内存位置0x10 01 00 20.如果您认为没有足够的信息来生成代码解释。

3 个答案:

答案 0 :(得分:1)

标签本身不存储在任何地方。它只是汇编器/链接器的符号地址。跳转j again指令操作码确实存储了实际结果地址,如数字。

链接器将所有目标文件粘合在一起,合并目标文件中的所有符号并填充正确的相对地址+为OS加载程序创建重定位表,生成可执行文件。

加载可执行文件时的操作系统还会加载重定位表,根据加载二进制文件的实际地址修改/填充使用绝对地址的指令,然后抛出重定位表,并执行代码

因此标签只是程序员的“源代码”,是特定固定内存地址的别名,可以节省程序员计算实际指令操作码大小,计算磁头或内存变量地址中的跳转偏移量。

您可能需要检查汇编程序中的“列表文件”(通常是/l开关),同时编译一些汇编源代码,以查看生成的实际machine code个字节(标签中没有)。

0x00400000编译时,您的“任务”代码如下所示(我将add设置为执行t1 = t1 + t1以获得任何内容):

 Address    Code        Basic                     Source

0x00400000  0x01294820  add $9,$9,$9          4     add  $t1,$t1,$t1
0x00400004  0x01294820  add $9,$9,$9          5     add  $t1,$t1,$t1
0x00400008  0x11090004  beq $8,$9,0x00000004  6     beq  $t0, $t1, next
0x0040000c  0x1509fffc  bne $8,$9,0xfffffffc  7         bne  $t0, $t1, again
0x00400010  0x01294820  add $9,$9,$9          8     add  $t1,$t1,$t1
0x00400014  0x01294820  add $9,$9,$9          9     add  $t1,$t1,$t1
0x00400018  0x01294820  add $9,$9,$9          10    add  $t1,$t1,$t1
0x0040001c  0x08100000  j 0x00400000          11   next:   j   again

正如您所看到的,每条实际指令都产生32位值,有时称为“操作码”(操作码),该值在“代码”列中可见。 “Address”列表示,此值存储在内存中,当加载可执行文件并准备执行时。 “Basic”列显示从操作码反汇编的指令,最后一个位置有“Source”列。

现在看看条件跳转如何将相对跳转值编码为16位(beq $8, $9操作码为0x1109,其他16位0x0004为16位符号扩展值“多少跳“)。该值表示远离“当前位置”的指令数,其中当前是后续指令的地址,即

0x0040000c + 0x0004 * 4 = 0x0040001c = target address

* 4,因为在MIPS上,每条指令都是4字节长,每个字节的内存寻址工作,而不是每条指令。

下一个bne也是如此,操作码本身为0x1509,偏移为0xfffc,即-4。 =>

0x00400010 + (-4) * 4 = 0x00400000

绝对跳转使用不同的编码,它是6位操作码0b000010xx(xx是存储在第一个字节中的两位地址以及j操作码,在本例中它们是零)然后是26b地址除以4 0x0100000,因为每条指令必须从对齐的地址开始,因此编码两个最低有效位将是浪费,它们总是000x100000 * 4 = 0x00400000 ...我太懒了,无法检查MIPS是如何工作的,但我认为j定义位2-27,0-1是零,28-31是从当前复制的可能pc?使CPU能够在完整的4GiB地址范围内工作,但是可能有一些特殊的方法如何在不同的“库”之间跳转(pc的高4位))..我不确定,我从来没有做过代码对于MIPS,所以我没有阅读CPU规格。

无论如何,如果您说again:位于0x10010020,则可以重新计算所有这些内容,以便生成准备好在0x10010020执行的生产函数代码(尽管j pc 1}}会很棘手,你必须确定如何组成总地址,如果复制了高4位或者是什么)。

BTW,真正的MIPS CPU确实延迟了分支(即,总是执行分支跳转后的下一条指令,同时评估条件,并在下一条指令之后跳转),我认为beq用于计算目标地址也是1个指令“稍后”一个,因此真正的MIPS的正确代码将在add之前具有0x0004,但相对偏移仍然是{{1}} }。 :)简单呃?如果它对您没有意义,请检查MARS设置(默认情况下,延迟分支的模拟已关闭,以免混淆学生),并搜索谷歌以获得更好的解释。很好的小搞笑CPU,那是MIPS。 :)

答案 1 :(得分:1)

每个标签对应于内存中的唯一地址。因此,在您的示例中,并且与您所声明的内容一致,如果nop指令存在于0x00400000,那么again将对应于(不是点 - 在一秒钟内更多)指向同一地址。 / p>

标签可以存在于文本和数据段中。但是,在您的示例中,标签显示在.text:细分中。因此,它表示指令的地址而不是变量。

以下是重要的区别:

标签是大多数ISA的一部分,使人们更轻松地编写程序集。但是,重要的是要记住汇编是最终的代码形式。换句话说,在二进制表示中,您的标签将不再是标签。

所以,这将会发生:

汇编程序将识别与每个标签指令关联的内存地址。让我们保持运行的0x00400000示例。然后,在每个跳转指令中,它将获取该地址并使用它来替换操作码中的标签。 Poof ,没有更多的标签,绝对没有指针(这意味着我们会在内存中存储另一个存储内存地址的位置)。

当然,内存地址本身对应于示例中文本段中的一个点,因为它与指令匹配。

简单地说,标签的存在是为了让我们的生活更轻松。但是,一旦它们组装好,它们就会转换为它们标记的指令/变量的实际内存地址。

答案 2 :(得分:0)

标签到其对应地址的转换是由您使用的代码汇编器或MIPS模拟器完成的,例如,MARS是MIPS模拟器,因此MARS进行了转换。 MARS会为您找到标签的地址。