在程序集ci20 seg故障中提示用户输入 [英] Prompting for user input in assembly ci20 seg fault

查看:80
本文介绍了在程序集ci20 seg故障中提示用户输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在ci20机器上的一个小程序上工作,该程序会提示用户输入整数值,然后将该值打印到屏幕上.

I am currently working on a small program on a ci20 machine that prompt the user for a integer value then print the value to the screen.

我当前的代码

.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

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

When I try to run the program I get a seg fault and not sure why. Any help or suggestion would be greatly appreciated.

推荐答案

由于某些原因,我完全忽略了此代码在ci20机器上进行的测试.

edit: for some reason I completely ignored this code was tested on ci20 machine.

那么这是Linux吗?然后,您将无法使用MARS syscall,而必须找到linux syscall.然后,它可能会在第一个syscall指令上进行段错误处理,因为参数对于Linux无效.

So is this linux? Then you can't use MARS syscalls, you have to find linux syscalls instead. It is then probably segfaulting on the very first syscall instruction, as the arguments are invalid for Linux.

要显示提示",请使用syscall,并将参数设置为v0 = 4, a0 = prompt ...以显示消息",请将syscall的参数设置为v0 = 1, a0 = message.

To display "prompt" you use syscall with arguments set as v0 = 4, a0 = prompt ... to display "message" you set arguments for syscall as v0 = 1, a0 = message.

如果它在 MARS 中,则v0 = 1是打印整数",因此a0应该是整数,而不是消息"字符串的地址. ..您可能想两次调用syscall,用v0 = 4和v0 = 1(参数a0是消息",并且用户为特定的调用整数).

If this is in MARS, then v0=1 is "print integer", so a0 should be integer, not address of "message" string. .. you probably want to call syscall twice, with v0=4 and v0=1 (argument a0 being "message" and users integer for particular call).

无论如何,这些都不应该是段错误. segfault可能发生在末尾,您的代码以addiu $sp, $sp, +4结尾,而不是返回到ra,或调用syscall"exit"函数(从在代码开始时保存ra看起来像您希望返回而不是退出,但这取决于您).因此,执行将继续执行一些随机指令(未初始化的内存内容).

Anyway, none of this should segfault. The segfault happens probably at the end, where your code ends with addiu $sp, $sp, +4, not returning to the ra, or calling syscall "exit" function (from the saving of ra at the start of your code it looks like you want rather to return than exit, but it's up to you). So the execution continues over some random instructions (uninitialized memory content).

无论如何,您应该弄清楚如何在调试器中加载此代码并逐条说明进行操作,然后您将能够说出它究竟在哪里出现段错误,以及其中的内容是什么在segfaulting指令之前注册.如果您的代码出现段错误,甚至不知道在哪里,则表明您的工作不足.

Anyway 2, you should figure out how to load this code in debugger and step over it instruction by instruction, then you will be capable to say where exactly it segfaults, and what was the content of registers before segfaulting instruction. If your code segfaults and you don't even know where, it shows lack of effort on your side.

(免责声明:我从未进行过MIPS组装,所以我主要猜测它是如何工作的,并且可能忽略了某些东西)

(disclaimer: I never did MIPS assembly, so I'm mostly guessing how it works and may have overlooked something)

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

edit about syscall, maybe this hint will help too?

syscall并不是在CPU上完成所有这些漂亮工作的魔术指令.它只是跳到了一些处理程序例程.

syscall isn't some magic instruction doing all that nifty stuff on the CPU. It just jumps to some handler routine.

该处理程序代码由操作系统设置. SO上大多数MIPS程序集清单都针对MARS或SPIM,它们的处理程序与Linux完全不同.

That handler code is set up by the OS. Most of the MIPS assembly listings on SO are targetted at MARS or SPIM, which have completely different handler than Linux.

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

So you should study linux ABI for MIPS, and how syscall is used there. And then find linux system calls table, you will probably find ton of x86 docs, so you have to convert that into v0/a0/... ABI.

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

You can still follow MARS examples, but any OS interaction has to be adjusted, and don't expect to find alternative for everything. For example outputting the number is not available in linux. You have to convert the number value into ASCII string by yourself (for single digit numbers adding '0' is enough, for numbers above 9 you have to calculate digit for each power of 10 and convert it into ASCII character and store it into some buffer), and output then the string with sys_write/etc. (or link with some libc and call sprintf-like function from C library).

这篇关于在程序集ci20 seg故障中提示用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆