assembly 为什么程序在LC3中没有达到“RET”或“HALT”?

j2cgzkjk  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(168)

当用户按下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还是被发送到其他地方。

6ju8rftf

6ju8rftf1#

JSR指令执行调用。调用有两个作用:将控制权转移到指定的标签,并将要返回的位置(此处为main,代码地址)放在R7中。为了使GETSTR成功返回到main,它必须具有main通过JSR指令放入R7的相同返回地址。
然而,它并没有这样做,因为陷阱调用指令(这里是GETC)将R7重新用于陷阱的返回地址。因此,在某种意义上,使用GETC会删除一个R7值,这样GETC就可以使用R7返回到GETSTR。因此,当GETSTR试图通过RET使用R7时,它返回的不是应该去的地方,而是R7中的返回地址,该地址位于GETSTR内,正好在GETC之后,因为这是R7最后一次使用的方式-因此出现了奇怪的循环。
只需要保存和恢复R7的方式相同的一些其他寄存器已经完成。

相关问题