首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何获取以裸模式运行的MIPS中静态数据的地址(无la伪指令)

如何获取以裸模式运行的MIPS中静态数据的地址(无la伪指令)
EN

Stack Overflow用户
提问于 2017-10-09 21:07:40
回答 1查看 1.1K关注 0票数 2

我只是试图从控制台的输入中读取一个字符串。我运行xspim来模拟,但需要在裸模式下运行,这意味着我不能使用伪指令,而且我在网上发现的很多东西都是用伪指令来实现的。在我正在阅读的所有文档中,它都说使用"la“指令将字符串存储在$a0中,但是该指令对我们来说是不可用的。我读到了这个指令的翻译,它实际上变成了一个"lui“,后面跟着一个"ori”。抛给我的部分是,我们应该输入第一个数据位置(总是0x10000000)和字符串中第一个字节的地址之间的字节数。我不知道我的字符串的第一个字节是什么。我现在拥有的是:

代码语言:javascript
复制
.globl main
.globl done
.globl convert

.data
prompt:  .asciiz   "Enter a decimal number, to quit type 'quit':" #45
result:  .asciiz   "The number you entered is " #72
input:   .space    64

.text
convert:


main:       addi $v0, $0, 4         #Print prompt to enter number
            lui $a0, 0x1000         #Address of prompt
            syscall                 #Display prompt

            addi $v0, $0, 8         #Setting up syscall to read in string
            lui $at, 4097
            ori $a0, $at, input     #Where I want my string to be stored
            addi $a1, $0, 64        #How long my string will be
            syscall                 #Syscall to read in string
EN

回答 1

Stack Overflow用户

发布于 2017-10-09 22:18:33

通常,用于RISC机器的汇编程序+链接器支持将地址分成两部分,因此您可以编写lui $reg, upper(input)ori $reg, $reg, lower(input),因此地址只需要是链接时间常数,而不是组装时间。

例如,如果您查看MIPS gcc在戈德螺栓上的装配输出 (gcc -O3 -S,而不是解压缩链接的二进制文件):

代码语言:javascript
复制
int my_global;
int *foo() { return &my_global; }
    lui     $2,%hi(my_global)
    j       $31
    addiu   $2,$2,%lo(my_global)    # branch-delay slot (SPIM doesn't have a branch-delay slot, but real MIPS does)

int bar() { return my_global; }
    lui     $2,%hi(my_global)
    lw      $2,%lo(my_global)($2)
    j       $31
    nop

    .section        .bss,"aw",@nobits
    .align  2
    .type   my_global, @object
    .size   my_global, 4
my_global:
    .space  4

注意,bar使用地址的lo一半作为lw中的偏移量,而不是在寄存器中生成完整地址,然后在加载指令中使用0偏移量。

如果您知道两个地址位于同一个64k块中,那么一个有用的优化就是使用不同的lui下半常量来重用相同的ori结果。我想你的数据就是这样的。保存除结果外的所有寄存器。;我假设SPIM是相同的。

如果您必须手动执行(没有链接器来帮助您),那么是的,您必须知道数据的绝对地址。

在您的示例中,没有CRT启动代码或其他任何将其数据放入.data部分的代码。.data部分中的内容位于可执行文件数据段的开头,因此prompt:将有地址0x1000 0000

你没有要求任何填充或对齐,所以你不会得到任何。您的数据将被组装到输出打包在一起。(与C不同,在C中,char prompt[45], result[];不能保证是连续的。)

我还没有使用SPIM,但希望它可以让您编写result-promptinput-prompt

例如:

代码语言:javascript
复制
main:
        addi $v0, $0, 4         #Print prompt to enter number
        lui $a0, 0x1000         #Address of prompt
        syscall                 #Display prompt

       # $a0 still holds 0x1000 << 16
        addui $a0, $a0, input-prompt      #buffer address
        addi $a1, $0, 64                  # length

        addi $v0, $0, 8         #syscall 8 = read string
        syscall                 #read_string(input, 64)

        addui $t0, $a0, 0       # copy pointer to input
        addui $a0, $a0, result - input   # offset pointer again to point to the output message.

或者,您可以通过将input-result添加到用于访问input[]的每个lb / sb中的偏移量来优化,而不是将指针复制到另一个寄存器。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46655006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档