【问题标题】:MIPS Assembly - Storing user input into a stackMIPS 程序集 - 将用户输入存储到堆栈中
【发布时间】:2017-10-09 18:02:25
【问题描述】:

我正在尝试将用户输入存储到堆栈中,当用户输入 0 时,程序将停止接收输入并打印出用户添加的所有数字,不包括零。我不确定如何正确解决这个问题。到目前为止,这是我的代码。

.data
prompt: .ascii "Please enter numbers, enter (0) to exit: "

.text

main:
li $v0, 4
la $a0, prompt
syscall


do:
li $v0, 5
syscall
addi $sp, $sp, -4 # Move stack four bytes down -- MAYBE MAKE SOME OF COUNTER TO KEEP TRACK OF HOW MUCH DATA NEEDS TO BE STORED IN STACK??
sw $v0, 0($sp) # Places contents of $t0 into first spot into the stack -- THINK I NEED TO CHANGE THIS TO ACCOMADATE CHANGE IN MEMORY??
#while
bne $t0, 0, do # Branch to print section if input = 0

print:
lw $t0, 0($sp)
addi $sp, $sp, 4
# Do printing instructions here from stack

end:
li $v0, 10
syscall

非常感谢任何建议或帮助!

【问题讨论】:

  • 您似乎走在了正确的轨道上。由于您需要以相同的顺序打印,我建议您将$sp 的原始值存储在某处。然后使用该副本遍历数字,直到达到$sp 的当前值。 PS:您想将do 标签向上移动,以便重新加载$v0,这当然会被输入破坏。
  • 好吧,这似乎是有道理的,所以存储堆栈的初始值开始的位置,即 0($sp),然后减 4 存储新值等,直到值等于 0,移动堆栈指向初始值的指针,并将用户输入的次数减 4。

标签: assembly mips mars-simulator


【解决方案1】:

这可能应该被关闭为“不清楚你在问什么”(你的问题不适合stackoverflow类型的问题......说得好),但我个人对这些广泛的问题没有意见风格有偏见的问题,只是答案对其他人来说不是很有用,所以最好至少为自己付出一些努力。

...
li $v0, 5

do:

v0 中的内容是什么(即 MARS 询问了哪些服务)?五?在第二次循环迭代时?

syscall
move $t0, $v0 # Places input in $t0

为什么? (*)

addi $sp, $sp, -4 # Move stack four bytes down MAYBE MAKE SOME OF COUNTER TO KEEP TRACK OF HOW MUCH DATA NEEDS TO BE STORED IN STACK??

您新编辑的评论解决了最大的缺陷。是的,您是在盲目地从sp 中减去,而以后没有任何方法可以恢复它。保留计数器是一种可能的方法,另一种是将原始sp 存储在某处($sX 寄存器很方便),然后是stored_bytes = original_sp - sp;(和count = stored_bytes>>2;,但如果你愿意,你甚至可能不需要直接计数只是将值打印回来,然后使用 original_sp 值就足够了)。

sw $t0, 0($sp) # Places contents of $t0 into first spot into the stack -- THINK I NEED TO CHANGE THIS TO ACCOMADATE CHANGE IN MEMORY??

是的,它将t0 中的值存储到地址sp 的内存中。我不确定你编辑的评论是什么意思,你担心什么。

while:

未使用的标签,不如把它变成评论,因为你不需要它。

beq $t0, $zero, print # Branch to print section if input = 0
j do

这可能会变成非零时的分支(bne 是 MIPS 指令 IIRC?),那么您在任何地方都不需要j,而print: 代码将随之而来。

(更多高级提示/信息,请随意跳过)还要确保您的 MARS 模拟器在选项中延迟分支关闭(默认情况下,使 MIPS 的模拟不真实,但更易于理解和学习编码) .在真正的 MIPS CPU 上,您必须将分支代码 1 指令放在分支实际有效的位置之前(或者通过在每个分支之后使用 nop 来避免这种情况,这在极少数情况下是有效的解决方案,而在其他情况下则是蹩脚的)。

print:

# Do printing instructions here from stack

所以,试试吧。

您还应该在调试器中尝试您的代码,使用单步指令,观察寄存器和内存内容,以更好地掌握 CPU 的工作原理。

* - 我小时候学习编程时最大的个人心理“突破”(基本上我是在汇编中学习编程,之前做了一些 BASIC,但很早就转向了汇编,因为我想要所有的那个 3.5MHz Z80 CPU 的性能(那个速度不是打字错误))是,当我终于意识到,一旦你有足够清晰的计算理论公式,你可以简单地将其 1:1 写入计算机指令。无需四处乱跳并添加额外的代码,使其看起来与其他东西相似,等等。您所需要的只是非常清晰和深刻的理解,您想要实际计算的是什么。

在您的情况下,您希望将输入的值存储到堆栈内存中。输入的值是/在v0。为什么要额外注册t0?只需存储它sw $v0, 0($sp)(当然是在spaddi 调整之后)。

您的其余代码和工作可能也是如此。拿一张纸和铅笔,先试着写下你真正想要达到的目标。一旦您尝试创建打印代码,丢失的计数器/sp 恢复就会变得很明显(您会注意到打印的基端没有任何价值)。

请记住,数周的编码可以节省数小时的计划时间。

【讨论】:

  • 非常感谢您的意见,我会检查我正在做的所有事情,让您知道发生了什么。我最大的问题是只是存储到堆栈中而不知道用户将输入多少输入。这就是为什么我在考虑某种计数器。
  • 嗯,这就是 stack 实际上是一个很好的选择,你可以动态地向下进入它,因为用户输入的项目数(除非用户真的是恶意的,并且填满了所有可用的堆栈空间) ,那么您可能会遇到堆栈溢出情况 - 双关语)。但是一旦你在堆栈中拥有所有这些值,并且sp 修改了很多次,你必须有一些机制来恢复它,首先将值打印回来,其次它需要任何体面的子程序来恢复堆栈退出时正确(您的代码不是子程序,而是整个应用程序,仍然熟能生巧)。
  • 如果您将原始堆栈指针存储在某处,它既可以作为打印的起点(只需要-4),也可以在打印后将sp直接设置回原始值,有效从堆栈中“释放”所有输入的值。 (这些值当然会一直写入内存,直到下面的代码将堆栈空间用于自己的值)。
  • For This Code: sw $v0, 0($sp) # 将 $t0 的内容放入堆栈的第一个位置,每次用户输入一个数字时,它不会只是替换数字栈顶?
  • 对不起,我不明白那个评论。堆栈是普通内存。 sw 是“将单词存入内存”。使用sp寄存器来跟踪特定的内存区域作为“stack”更像是汇编程序和程序员的方便,CPU不这么看,对于CPU来说它是通过寻址的普通内存寄存器 $30 中的地址(或别名为sp)。 “堆栈”没有什么神奇之处。同样,您有 MARS,使用调试器,单步执行指令,在堆栈 16 的地址处打开带有内存的窗口,等等……首先观察并尝试理解会发生什么(+read inst. docs)。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
相关资源
最近更新 更多