我只是试图从控制台的输入中读取一个字符串。我正在运行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
答案 0 :(得分:0)
通常,RISC机器的汇编程序+链接器支持将地址分成两半,因此您可以编写lui $reg, upper(input)
和ori $reg, $reg, lower(input)
,因此地址只需要是链接时常量,而不是汇编时间。 / p>
例如,如果您查看MIPS gcc's assembly output on Godbolt(gcc -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
使用地址的一半作为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-prompt
和input-prompt
。
e.g。
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[]
中的偏移量进行优化。 / p>