MIPS标签存储位置

问题描述 投票:1回答:3

在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.如果您认为没有足够的信息来生成代码说明。

assembly mips machine-language
3个回答
1
投票

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

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

这是重要的区别:

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

所以,这将是会发生的事情:

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

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

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


1
投票

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

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

加载可执行文件时的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地址除以四个0x0100000,因为每个指令必须启动在对齐的地址,因此编码两个最低有效位将是浪费,它们将始终是000x100000 * 4 = 0x00400000 ...我太懒了,无法检查MIPS是如何工作的,但我认为j定义位2-27,0-1是零,28-31是从当前的pc复制的可能吗?使CPU能够在完整的4GiB地址范围内工作,但是可能有一些特殊的方法如何在不同的“库”(pc的高4位)之间跳转。)我不确定,我从来没有为MIPS编写代码,所以我没有阅读CPU规格。

无论如何,如果你说again:0x10010020,所有这些都可以重新计算,以便生成功能代码准备在0x10010020执行(虽然j会很棘手,你必须知道,总地址如何组成,如果复制高4位或什么)。

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


0
投票

标签到其相应地址的转换是由您正在使用的代码汇编程序或MIPS模拟器完成的,例如,MARS是MIPS模拟器,因此MARS正在进行该转换。 MARS将为您找到标签的地址。

© www.soinside.com 2019 - 2024. All rights reserved.