编辑:出于某种原因,我完全忽略了在 ci20 机器上测试的这段代码。
那么这是linux吗?那么你就不能使用 MARS 系统调用,你必须找到 linux 系统调用。那么它可能会在第一次出现段错误syscall
指令,因为参数对于 Linux 无效。
要显示“提示”,请使用syscall
参数设置为v0 = 4, a0 = prompt
...要显示“消息”,您将系统调用的参数设置为v0 = 1, a0 = message
.
如果这是在MARS http://courses.missouristate.edu/KenVollmar/mars/Help/SyscallHelp.html, then v0
=1 是“打印整数”,所以a0
应该是整数,而不是“message”字符串的地址。 ..您可能想调用系统调用两次v0
=4 and v0
=1(参数a0
是“消息”和特定调用的用户整数)。
无论如何,这一切都不应该出现段错误。段错误可能发生在最后,您的代码以addiu $sp, $sp, +4
,不返回到ra
,或调用系统调用“退出”函数(从保存ra
在代码的开头,看起来您想要返回而不是退出,但这取决于您)。因此,执行会继续执行一些随机指令(未初始化的内存内容)。
无论如何 2,你应该弄清楚如何在调试器中加载此代码并逐条指令地跳过它,那么您将能够说出它到底在哪里出现了段错误,以及在发生段错误指令之前寄存器的内容是什么。如果你的代码出现了段错误,而你甚至不知道错误发生在哪里,这表明你缺乏努力。
(免责声明:我从未做过 MIPS 汇编,所以我主要猜测它是如何工作的,并且可能忽略了一些东西)
编辑关于syscall
,也许这个提示也会有帮助?
syscall
是不是有一些神奇的指令在 CPU 上完成所有这些漂亮的事情。它只是跳转到某个处理程序例程。
该处理程序代码由操作系统设置。 SO 上的大多数 MIPS 程序集列表都是针对 MARS 或 SPIM,它们具有与 Linux 完全不同的处理程序。
因此,您应该研究 MIPS 的 linux ABI,以及其中如何使用 syscall。然后找到linux系统调用表,你可能会发现大量的x86文档,所以你必须将其转换为v0/a0/... ABI。
您仍然可以遵循 MARS 示例,但任何操作系统交互都必须进行调整,并且不要指望为所有内容找到替代方案。例如,在 Linux 中输出数字是不可用的。您必须自己将数字值转换为 ASCII 字符串(对于单位数字添加“0”就足够了,对于 9 以上的数字,您必须计算 10 的每个幂的数字并将其转换为 ASCII 字符并将其存储到某个缓冲区中),然后用 sys_write/etc 输出字符串。 (或链接一些 libc 并调用sprintf
-类似 C 库中的函数)。