2017-10-09 41 views
0

我只是试图从控制台的输入中读取字符串。我正在运行xspim来模拟,但是需要这个在裸模式下运行,这意味着我不能使用伪指令,并且我在网上找到的很多东西都是用伪指令来完成的。在我正在阅读的所有文档中,它说使用“​​la”指令将字符串存储在$ a0中,但是该指令不适用于我们。我读到了那条指令的意思,并且有效地变成了一个“lui”,然后是一个“ori”。抛出我的部分是我们应该输入第一个数据位置(始终为0x 1000 0000)和字符串中第一个字节的地址之间的字节数。我不确定我的字符串的第一个字节是什么。下面是我有:对于RISC机器如何获取在裸机模式下运行的MIPS中的静态数据的地址(不是伪指令)

.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 
+0

您可以通过使用堆栈上的缓冲区(用于输入缓冲区)来解决该问题。 –

回答

0

通常汇编+链接器支持分裂地址分为两半,所以你可以写lui $reg, upper(input)ori $reg, $reg, lower(input),所以地址只能是链接时间常数,不装配时间。

例如,如果你看一下MIPS gcc's assembly output on Godboltgcc -O3 -S,不拆卸链接的二进制):

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的偏移量。


有用的优化,如果你知道2个地址是在同一个64K块是重复使用相同的lui结果不同ori低一半常量。 我认为这是您的数据的情况。 Mars guarantees that syscall preserves all registers except the result;我认为SPIM是一样的。


如果你必须这样做手工(没有接头,以帮助你),然后是,你必须知道你的数据的绝对地址。

就你而言,没有CRT启动代码或任何其他数据将其数据放入.data部分。您的.data部分中的内容在您的可执行文件数据段的最开始处为,因此prompt:将具有地址0x1000 0000

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

我没有使用SPIM,但希望它能让你编写result-promptinput-prompt

例如

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在您使用的每个lb/sb偏移访问input[]优化。