0

我目前正在 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

当我尝试运行该程序时,我得到一个段错误,不知道为什么。任何帮助或建议将不胜感激。

4

1 回答 1

3

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

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


要显示“提示”,请使用syscall设置为v0 = 4, a0 = prompt... 的参数来显示“消息”,您将系统调用的参数设置为v0 = 1, a0 = message.

如果这是在MARS中,那么v0=1 是“打印整数”,所以a0应该是整数,而不是“消息”字符串的地址。..您可能想要调用 syscall 两次,使用v0=4 和v0=1 (参数a0是“消息”和特定调用的用户整数)。

无论如何,这些都不应该出现段错误。段错误可能发生在最后,您的代码以 结尾addiu $sp, $sp, +4,不返回ra,或调用系统调用“退出”函数(从ra代码开头的保存来看,看起来您想要返回而不是退出,但它是由你决定)。因此,执行会继续执行一些随机指令(未初始化的内存内容)。

无论如何 2,您应该弄清楚如何在调试器中加载此代码并逐条指令对其进行单步执行,然后您将能够说出它的确切位置,以及在 segfaulting 指令之前寄存器的内容是什么。如果您的代码段错误并且您甚至不知道在哪里,这表明您缺乏努力。

(免责声明:我从未做过 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 输出字符串。sprintf(或与C 库中的一些 libc 和 call类似的函数链接)。

于 2016-10-14T10:23:02.553 回答