使用SPARC指令集

时间:2018-03-15 20:46:00

标签: assembly io sparc

我需要帮助使用SPARC指令集了解汇编语言中hello world程序的基本实现。我有完整功能的代码,我只需要帮助了解它是如何工作的。我无法弄清楚如何使用行号发布我的代码,所以我为有关引用特定代码行的任何混淆道歉。非常感谢任何帮助。

首先,使用cout .equ ...控制台数据端口 以及costat .equ ...控制台状态端口的行。不确定这意味着什么。看起来他们分别将术语“cout”和“costat”分配给内存地址0x0和0x4,但是什么是控制台数据端口和控制台状态端口,这行代码的重要性是什么?

接下来,带有“sethi”命令的行确实让我感到困惑。我知道这与将最重要的22位设置为某些东西有关但我不明白这个程序的重要性是什么,我们用这个命令完成了什么我根本不理解它。

接下来,循环子例程。看起来我们正在加载寄存器2的内容加上hello world字符串(由一系列ASCII字符定义)并将它放在寄存器3中。我不熟悉0xnn形式的HEX表示法,其中n表示整数。这是标准十六进制表示法的缩写形式吗?

循环的下一行看起来我们正在添加寄存器3的内容加零,并将结果存储在寄存器3中。这有什么意义,为什么要加零?

循环的最后一行是'结束'。我相信这意味着“分支如果相等并且分支到子程序称为”结束“但分支如果等于什么?注释说分支如果为空,但是再次,如果什么是空?我不确定这是指什么。

接下来,我们有'Wait'子程序,它以一个命令开始,在寄存器4加上costat(我们的控制台状态端口)的地址加载一个无符号字节,并将结果存储在寄存器1中。再次,这是什么意思,这个指令在程序中做了什么?顺便说一句,当一个术语在'[]'之类的大括号中时指的是内存地址的内容对吗?或者它是指内存地址本身。我一直对此感到困惑。

下一行我们正在使用“和”寄存器1和另一个ASCII字符并将结果放回寄存器1.也许这是某种标点符号,也许是“hello,world!”中的逗号。这个命令又是做什么的?

下一行是“等待”,看起来像“分支如果等于子程序'等'”再次,分支如果等于什么?为什么从子程序中调用子程序'wait',这是一个递归调用吗?这里发生了什么?

下一行我认为是将寄存器3中的字节存入寄存器4加cout(我们的控制台数据端口)的内容中。这必须与将字符输出到控制台有关,但这是如何工作的,这行代码中发生了什么,为什么要将寄存器4添加到cout?

下一行似乎是将寄存器2递增到下一个机器字,可能与hello world字符串中的下一个字符有关。

最后,“分支总是”回调循环。这有什么意义,请尽可能解释。谢谢

存储一个字节
    !在msgarea中打印“Hello,world!\ n”。     ! SRCTools版本:vph 6/29/00,更新rez 4/16/02     ! ARCTools版本:mww转换为6/17/05

.begin
BASE    .equ 0x3fffc0       !Starting point of the memory mapped region
COUT    .equ 0x0            !0xffff0000 Console Data Port
COSTAT  .equ 0x4            !0xffff0004 Console Status Port.

         .org 2048
         add %r0, %r0, %r2
         add %r0, %r0, %r4
         sethi BASE, %r4

Loop:    ld [%r2 + String], %r3 !Load next char into r3
         addcc %r3,%r0,%r3
         be End                 ! stop if null.

Wait:    ldub [%r4+COSTAT], %r1
         andcc %r1, 0x80, %r1
         be Wait
         stb %r3, [%r4+COUT]    !Print to console
         add %r2, 4, %r2        !increment String offset (r2)
         ba Loop
End:     halt

        .org 3000

! The "Hellow, world!" string

String: 0x48, 0x65, 0x6c, 0x6c, 0x6f
0x2c, 0x20, 0x77, 0x6f, 0x72 
0x6c, 0x64, 0x21, 0x0a, 0

.end

2 个答案:

答案 0 :(得分:2)

  

什么是控制台数据端口和控制台状态端口

这取决于你的硬件。显然,您的控制台是内存映射的,并使用这些地址进行通信。

  

接下来,带有“sethi”命令的行确实让我感到困惑。

它用于加载r4 0xffff0000sethi是内存映射范围的基地址。正如您所说,3fffc0仅使用22位,因此您需要将该地址右移10位,然后提供BASEcc的值)。

  

我不熟悉0xnn形式的HEX表示法,其中n表示整数。这是标准十六进制表示法的缩写形式吗?

你知道可以忽略前导零,对吗?如果我给你$ 00000100,你将不会成为百万富翁。

  

这有什么意义,为什么要加零?

重要的部分是be。该添加用于设置标志,以便您可以使用以下Wait检查零。

  

下一行是“等待”,看起来像“分支如果等于子程序'等''

be不是子程序,它只是一个标签。 cout只是查看零标志,先前设置,查看上一点和指令集引用。

  

为什么将寄存器4添加到cout

因为r4只是0xffff0000指向的内存映射区域的起始偏移量。您真的想写信给0xffff0000+0,并且计算为COUT。当然知道window.onload = function() { let bodyContent = document.getElementById("appBody"); let jsonRequest = { "loggedStatus":"check" }; let jsonRequestString = JSON.stringify(jsonRequest); let request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState == 4 && request.status == 200) { let jsonResponse = JSON.parse(request.responseText); if (jsonResponse.loggedStatus.localeCompare("true") == 0) { document.getElementById("appBody").innerHTML = '<object type="text/html" data="HTML/calendar.html"></object>'; } else { document.getElementById("appBody").innerHTML = '<object type="text/html" data="HTML/login.html"></object>'; } } } request.open("POST", "PHP/Main.php", true); request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); request.send("request=" + jsonRequestString); } 为零,你可以省略添加。

  

最后,“分支总是”回调循环。这有什么意义,请尽可能解释。

你应该自己理解这部分内容。显然它会回去打印下一个角色。

答案 1 :(得分:1)

  

但是什么是控制台数据端口和控制台状态端口,这行代码的重要性是什么?

它可以帮助您了解旧式串行端口的工作原理。通常有一个硬件寄存器,您可以写入以输出字符,并且您有一个状态寄存器,您可以查看何时可以安全地写入另一个输出字符。这样做的原因是,数据字节需要一段时间才能在串行线路上发送出来,如果在前一个字符后过快地写入字符,输出将会出现乱码。

  

我不熟悉0xnn形式的HEX表示法,其中n表示整数。这是标准十六进制表示法的缩写形式吗?

它不是十六进制表示法的缩写形式,它只是十六进制表示法。所有十六进制数字的形式为0xnn,并且&#39; nn&#39;可以是任意数量的十六进制数字。所以0x48表示十六进制48,十进制为4 * 16 + 8 = 72,如果你查看任何ascii字符图表,你会看到这是字母&#39; H&#39;。< / p>

  

循环的下一行看起来我们正在添加寄存器3的内容加零,并将结果存储在寄存器3中。这有什么意义,为什么要加零?

addcc指令执行添加操作,但也将其与测试操作组合在一起。因此,根据添加的结果设置机器的条件代码。在这种情况下,我们并不真正关心添加任何内容,我们只是想执行测试,因此添加了零。

  

循环的最后一行是“结束”。我相信这意味着&#34;分支如果相等并且分支到子程序,称为&#34;结束&#34;但分支如果等于什么?注释如果为null则表示分支,但是如果为null则表示分支?我不确定这是指什么。

它指的是上次测试操作的结果。由于汇编语言没有&#34; if-then&#34;说明,这就是它的完成方式。您测试一些东西,然后根据测试结果进行分支。所以读取这两行代码的方法是&#34;如果r3等于零,则分支到End。&#34;

  

接下来,我们有“等待”等等。子程序以一个命令开始,在寄存器4的地址加上一个无符号字节加上costat(我们的控制台状态端口)并将结果存储在寄存器1中。再次,这意味着什么,这个指令在程序中做了什么?顺便说一句,当一个术语出现在诸如&#39; []&#39;那指的是内存地址的内容吧?或者它是指内存地址本身。我一直对此感到困惑。

方括号总是指存储在内存中的东西,方括号内的表达式给出了内存地址。因此,该指令意味着&#34;添加r4和COSTAT并将此结果用作存储器地址,然后将该存储器地址的(字节)内容加载到r1中。&#34;

  

下一行我们正在使用&#34;和&#34;使用寄存器1和另一个ASCII字符并将结果放回寄存器1.也许这是某种标点符号,也许是#34; hello,world中的逗号!&#34;这个命令又是做什么的?

&#39;&#39;&#39;指令执行按位&#34;和&#34;两个数字之间的操作,在这种情况下是r1的内容和十六进制值0x80。结果存储在r1中,&#39; cc&#39;指定要测试结果(r1)并设置条件代码。 0x80不是ascii字符,而是表示状态字节中某个状态标志的单个位。将字符写入串行输出寄存器后,该状态位将设置为零,直到可以安全地写入另一个字符。

  

下一行是&#34;等待&#34;看起来像#34;分支如果等于子程序&#39;等等&#39;&#34;再次,分支如果等于什么?也为什么要调用子程序等待&#39;从子程序中,它是递归调用吗?这是怎么回事?

等待&#34;等待&#34;使用先前测试的结果来确定是否采取分支。因此,您可以将这两条指令读作&#34;如果是r1&amp; 0x80然后转到等待#34;。这些指令实现了一个循环,它一直持续测试这个位,直到可以安全地写另一个字符。该位由硬件更改,一旦发生这种情况,循环将终止,控制将继续执行下一条指令。

  

下一行我认为是将寄存器3中的字节存入寄存器4加cout(我们的控制台数据端口)的内容中。这必须与将字符输出到控制台有关,但这是如何工作的,这行代码中发生了什么,为什么要将寄存器4添加到cout?

r4代表&#34;基地址&#34;串行端口注册的位置,cout和costat是该区域的偏移量。所以这里你只是在输出寄存器中写一个字符。

  

下一行似乎是将寄存器2递增到下一个机器字,可能与hello world字符串中的下一个字符有关。

这显然是意图,但是向r2添加4是没有意义的,因为它会超过3个字符。这看起来像一个bug,应该只是添加1。