在程序集 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
的函数)。
我目前正在 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
的函数)。