在程序集 ci20 段错误中提示用户输入

Prompting for user input in assembly ci20 seg fault

我目前正在 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, [=10=], 4
    la $a0, prompt
    syscall            # printing prompt

    addi $v0, [=10=], 5
    syscall            # get user input

    move $t0, $v0      # save input in $t0
    move $a0, $v0
    addi $v0, [=10=], 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

当我尝试 运行 程序时出现段错误,但不确定原因。任何帮助或建议将不胜感激。

编辑:出于某种原因我完全忽略了这段代码是在 ci20 机器上测试过的。

这是linux吗?那么你不能使用 MARS 系统调用,你必须找到 linux 系统调用。然后它可能在第一个 syscall 指令上出现段错误,因为参数对 Linux.

无效

要显示 "prompt",您使用 syscall 并将参数设置为 v0 = 4, a0 = prompt ... 要显示 "message",您将系统调用的参数设置为 v0 = 1, a0 = message

如果这是在MARS,那么v0=1就是"print integer",所以a0应该是整数,而不是"message"字符串的地址。 .. 你可能想调用系统调用两次, v0=4 和 v0=1 (参数 a0 是 "message" 和特定调用的用户整数)。

无论如何,none 这应该是段错误。段错误可能发生在最后,您的代码以 addiu $sp, $sp, +4 结尾,而不是 returning 到 ra,或调用系统调用 "exit" 函数(来自 ra 在你的代码的开头看起来你想要 return 而不是退出,但这取决于你)。因此执行会继续执行一些随机指令(未初始化的内存内容)。

无论如何 2,你应该弄清楚如何在调试器中加载这段代码并逐条指令,然后你将能够说出它到底在哪里出现段错误,并且段错误指令之前寄存器的内容是什么。如果您的代码出现段错误,而您甚至都不知道发生在何处,则表明您缺乏努力。

(免责声明:我从未做过 MIPS 汇编,所以我主要是在猜测它是如何工作的,可能忽略了一些东西)


编辑 syscall,也许这个提示也有帮助?

syscall 并不是在 CPU 上做所有这些漂亮事情的魔法指令。它只是跳转到某个处理程序例程。

该处理程序代码由 OS 设置。 SO 上的大多数 MIPS 程序集列表都针对 MARS 或 SPIM,它们具有与 Linux.

完全不同的处理程序

所以你应该研究 linux MIPS 的 ABI,以及那里如何使用系统调用。然后找到 linux 系统调用 table,您可能会找到大量 x86 文档,因此您必须将其转换为 v0/a0/... ABI。

您仍然可以按照 MARS 示例进行操作,但是任何 OS 交互都必须进行调整,并且不要指望为所有事情找到替代方案。例如,输出数字在 linux 中不可用。您必须自己将数字值转换为 ASCII 字符串(对于单个数字,添加 '0' 就足够了,对于大于 9 的数字,您必须计算 10 的每个幂的数字并将其转换为 ASCII 字符并将其存储到某个缓冲区中), 然后输出带sys_write/etc的字符串。 (或 link 使用一些 libc 并从 C 库中调用类似 sprintf 的函数)。