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

Assembly 如何在裸模式下运行的MIPS中获取静态数据的地址(无la伪指令),assembly,mips,mips32,Assembly,Mips,Mips32,我只是试图从控制台的输入中读入一个字符串。我运行xspim是为了模拟,但需要在裸模式下运行,这意味着我不能使用伪指令,我在网上发现的很多东西都是使用伪指令来实现这一点的方法。在我阅读的所有文档中,都说使用“la”指令将字符串存储在$a0中,但是我们无法使用该指令。我读到这个指令的翻译,它实际上变成了一个“lui”,后面跟着一个“ori”。让我感到困惑的是,我们应该输入第一个数据位置(总是0x 1000 0000)和字符串中第一个字节的地址之间的字节数。我不确定字符串的第一个字节是什么。以下是我所

我只是试图从控制台的输入中读入一个字符串。我运行xspim是为了模拟,但需要在裸模式下运行,这意味着我不能使用伪指令,我在网上发现的很多东西都是使用伪指令来实现这一点的方法。在我阅读的所有文档中,都说使用“la”指令将字符串存储在$a0中,但是我们无法使用该指令。我读到这个指令的翻译,它实际上变成了一个“lui”,后面跟着一个“ori”。让我感到困惑的是,我们应该输入第一个数据位置(总是0x 1000 0000)和字符串中第一个字节的地址之间的字节数。我不确定字符串的第一个字节是什么。以下是我所拥有的:

.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

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

例如,如果查看(
gcc-O3-S
,而不是反汇编链接的二进制文件):

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


如果您知道两个地址位于同一64k块中,一个有用的优化方法是使用不同的
ori
低半常数重用相同的
lui
结果。 我想你的数据就是这样的;我认为SPIM是相同的


如果您必须手动执行此操作(没有链接器帮助),则是的,您必须知道数据的绝对地址

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

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

我没有使用SPIM,但希望它能让您编写
结果提示
输入提示

e、 g

main:
addi$v0,$0,4#打印输入数字的提示
lui$a0,0x1000#提示地址
系统调用#显示提示

#$a0仍然保存0x1000,您可以使用堆栈上的缓冲区(用于输入缓冲区)来解决此问题。
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
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.