我正在用LC3写一个程序,它读入一个整数文件,对每个元素进行平方运算,然后将它们的平方相加。我需要一个函数中的“平方”部分,但在我的while循环中,对函数的调用完全跳过了。所以我得到的只是文件中的数字求和,而不是先平方。感谢您的帮助,谢谢!
; Program to calculate Euclidian sum of numbers stored at location x4000
;
.ORIG x3000
LD R1,a ;first element address
LD R2,zero ;ans -> R2 initialized to 0
;while (R1 isn't zero)
LOOP: LDR R4,R1,#0 ;element -> R4
ADD R4,R4,-1
BRn DONE ;if R1 < 0, condition fails
;loop body
LDR R4,R1,#0 ;element ->R4
LDR R5,R1,#0 ;counter
JSR SQUARE
ADD R2,R2,R4 ;ans = ans + element
ADD R1,R1,#1 ;prepare for next element
BR LOOP ;another iteration
ST R2,ans ;result to ans
;
TRAP x25 ;exit
SQUARE
ADD R4,R5,#0 ;R4 <- multiplier
AND R6,R6,#0 ;R3 <- 0, sq
;inner loop
AGAIN
ADD R6,R6,R4
ADD R5,R5,#-1 ;decerement counter
BRp AGAIN ;check end of calculation
RET
;
zero .FILL 0
a .FILL x4000 ;a has the address of first location
ans .BLKW 1 ;reserve location for ans
DONE HALT ;halt
.END发布于 2020-01-30 12:05:04
你的程序中有两个错误。
返回后从错误的寄存器读取
让我们看一下这个SQUARE子例程:
SQUARE
ADD R4,R5,#0 ;R4 <- multiplier
AND R6,R6,#0 ;R3 <- 0, sq
;inner loop
AGAIN
ADD R6,R6,R4
ADD R5,R5,#-1 ;decerement counter
BRp AGAIN ;check end of calculation
RET您在这里没有任何关于应该如何调用子例程,或者它返回什么的注释。这使得我们很难看清哪里出了问题。下面是您应该在该子例程上编写的内容:
; SQUARE subroutine
; Squares an integer value
;
; Parameters:
; R5: Value to be squared
; Return value:
; R6: Squared value
; Notes:
; This subroutine tramples R4为什么?如果您正在尝试调试调用代码,那么如果您知道应该如何调用子例程,以及在编写它时所做的假设,就会容易得多。例如,您可能对外部循环进行了更改,以使用R4作为临时变量,并对该值被覆盖的原因感到困惑。(如果您真的想走得更远,还要记录该子例程是否支持零值或负值作为参数。)
现在我们有了这个注释,主代码中的问题很明显:
LDR R4,R1,#0 ;element ->R4
LDR R5,R1,#0 ;counter
JSR SQUARE
ADD R2,R2,R4 ;ans = ans + element我们将要平方的值加载到R5中,并调用SQUARE。然后,SQUARE将平方的值写入R6,然后我们...从R4加载值。这是不正确的。应该从R6加载,而不是从R4加载。
(作为次要问题,这里不需要LDR R4,R1,#0,因为SQUARE子例程忽略了R4中的值。注释代码的另一个好处!)
因此,我们可以将此代码更正为:
LDR R5,R1,#0 ;counter
JSR SQUARE
ADD R2,R2,R6 ;ans = ans + elementDONE不会存储到ans
让我们看一下外部循环的情况:
LOOP LDR R4,R1,#0 ;element -> R4
ADD R4,R4,-1
BRn DONE ;if R1 < 0, condition fails因此,我们从R1指向的地址加载,并检查该值是否小于或等于零。(顺便说一句,评论是不正确的。)
那么在做了什么呢?
DONE HALT ;halt它会立即停止,而不会将R2存储到结果中!
因此,修复方法是将存储的行移动到R2,这样它就可以在分支完成后运行。
DONE
ST R2, ans
HALT ;halt下面是修复后的程序的完整代码清单:
; Program to calculate Euclidian sum of numbers stored at location x4000
;
.ORIG x3000
LD R1,a ;first element address
LD R2,zero ;ans -> R2 initialized to 0
;while (R1 isn't zero)
LOOP
LDR R4,R1,#0 ;element -> R4
ADD R4,R4,-1
BRn DONE ;if R1 < 0, condition fails
;loop body
LDR R5,R1,#0 ;counter
JSR SQUARE
ADD R2,R2,R6 ;ans = ans + element
ADD R1,R1,#1 ;prepare for next element
BR LOOP ;another iteration
; SQUARE subroutine
; Squares an integer value
;
; Parameters:
; R5: Value to be squared
; Return value:
; R6: Squared value
; Notes:
; This subroutine tramples R4
SQUARE
ADD R4,R5,#0 ;R4 <- multiplier
AND R6,R6,#0 ;R3 <- 0, sq
;inner loop
AGAIN
ADD R6,R6,R4
ADD R5,R5,#-1 ;decerement counter
BRp AGAIN ;check end of calculation
RET
;
zero .FILL 0
a .FILL x4000 ;a has the address of first location
ans .BLKW 1 ;reserve location for ans
DONE
ST R2, ans
HALT ;halt
.END下面是我测试修复后的程序的方法:
$ lc3sim -quiet prog_fixed.obj
x0289 x0FFB BRNZP TRAP_LOOP
Loaded "prog_fixed.obj" and set PC to x3000
(lc3sim) memory x4000 3
Wrote x0003 to address x4000.
(lc3sim) continue
x0289 x0FFB BRNZP TRAP_LOOP
(lc3sim) translate ans
Address ans has value x0009.https://stackoverflow.com/questions/59817320
复制相似问题