我目前正在研究ci20机器上的一个小程序,它提示用户输入一个整数值,然后将值打印到屏幕上。
我当前的代码
.data
prompt:
.asciiz "Please enter an integer: "
message:
.asciiz "\nValue entered: "
.text
.global main
main:
addiu $sp, $sp, -4 # push stack
sw $ra, ($sp) # save return address
addi $v0, $0, 4
la $a0, prompt
syscall # printing prompt
addi $v0, $0, 5
syscall # get user input
move $t0, $v0 # save input in $t0
move $a0, $v0
addi $v0, $0, 1 # Not sure if this is right to print message
la $a0, message # Not sure if this is right to print message
syscall
lw $ra, ($sp) # restoring $sp
addiu $sp, $sp, +4 # release the stack space used for $sp
当我尝试运行程序时,我遇到了一个seg错误而不确定原因。任何帮助或建议将不胜感激。
答案 0 :(得分:3)
编辑:由于某种原因,我完全忽略了这个代码在ci20机器上测试过。
这是linux吗?那么你不能使用MARS系统调用,你必须找到linux系统调用。然后可能会在第一条syscall
指令上进行分区,因为参数对Linux无效。
显示"提示"您使用syscall
并将参数设置为v0 = 4, a0 = prompt
...来显示" message"您将syscall的参数设置为v0 = 1, a0 = message
。
如果这是MARS,那么v0
= 1是"打印整数",所以a0
应该是整数,而不是"消息& #34;串。 ..你可能想要两次调用系统调用,v0
= 4和v0
= 1(参数a0
是"消息"和特定呼叫的用户整数)。
无论如何,这一切都不应该是段错误。段错误可能发生在最后,您的代码以addiu $sp, $sp, +4
结束,不返回ra
,或调用系统调用"退出"功能(在代码开头保存ra
看起来你想要返回而不是退出,但它取决于你)。因此,执行会继续执行一些随机指令(未初始化的内存内容)。
无论如何2,你应该弄清楚如何在调试器中加载这段代码并按指令逐步执行,然后你就可以说出段落的确切位置,以及它的内容是什么在segfaulting指令之前注册。如果你的代码是段错误的,而你甚至不知道在哪里,那就表明你没有那么努力了。
(免责声明:我从未做过MIPS组装,所以我大多猜测它是如何工作的,可能忽略了一些东西)
编辑syscall
,或许这个提示也有帮助吗?
syscall
不是一些魔术指令在CPU上做所有那些漂亮的东西。它只是跳转到一些处理程序例程。
该处理程序代码由OS设置。 SO上的大多数MIPS汇编列表都针对MARS或SPIM,它们的处理程序与Linux完全不同。
所以你应该研究Linux ABI for MIPS,以及如何在那里使用系统调用。然后找到linux系统调用表,你可能会找到大量的x86文档,所以你必须把它转换成v0 / a0 / ... ABI。
您仍然可以关注MARS示例,但必须调整任何操作系统互动,并且不要期望找到所有内容的替代方案。例如,输出数字在linux中不可用。您必须自己将数字值转换为ASCII字符串(对于单个数字的数字,添加' 0'就足够了,对于9以上的数字,您必须为每个10的幂计算数字并将其转换为ASCII字符和将它存储到某个缓冲区中,然后输出带有sys_write / etc的字符串。 (或链接一些libc并调用sprintf
- 类似C库中的函数)。