当用户按下ENTER(ASCII 10)时,代码应该减去10,然后分支到GSEND并停止,但它正在执行一些奇怪的循环。代码如下:
.orig x3000
MAIN
LEA R0, STR1 ;R0 points to STR1, which is the memory where we store the string.
JSR GETSTR ;Get a string from the user
PUTS ;Print the string
HALT
;Data – Change these for testing
.blkw 50 ;Change this value when testing between 50 and 150.
;Save space for string storage. Note that this effectively limits your string
;size to 50 which is the number of zs below.
STR1 .stringz "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
GETSTR
;save registers
ST R2, GS_SR2
ST R3, GS_SR3
ST R4, GS_SR4
LD R4, GS_LR4
ADD R2, R0, #0
GSTOP
GETC ;get character
ADD R3, R0, R4 ;if newline skip to end
BRZ GSEND
STR R0, R2, #0 ;store letter in STR1
OUT
ADD R2, R2, #1 ;increment R2
BRNZP GSTOP
GSEND
ADD R0, R2, #0
;reset registers
LD R2, GS_SR2
LD R3, GS_SR3
RET
GS_SR0 .fill 0
GS_SR2 .fill 0
GS_SR3 .fill 0
GS_SR4 .fill 0
GS_LR4 .fill -10
.end
代码应该重新打印整个字符串并停止。我不知道它是从来没有到达RET还是被发送到其他地方。
1条答案
按热度按时间6ju8rftf1#
JSR
指令执行调用。调用有两个作用:将控制权转移到指定的标签,并将要返回的位置(此处为main
,代码地址)放在R7
中。为了使GETSTR
成功返回到main
,它必须具有main
通过JSR
指令放入R7
的相同返回地址。然而,它并没有这样做,因为陷阱调用指令(这里是
GETC
)将R7
重新用于陷阱的返回地址。因此,在某种意义上,使用GETC
会删除一个R7
值,这样GETC
就可以使用R7
返回到GETSTR
。因此,当GETSTR
试图通过RET
使用R7
时,它返回的不是应该去的地方,而是R7
中的返回地址,该地址位于GETSTR
内,正好在GETC
之后,因为这是R7
最后一次使用的方式-因此出现了奇怪的循环。只需要保存和恢复
R7
的方式相同的一些其他寄存器已经完成。