LMC 程序不输出正确的总和
LMC program do not output the correct sum
loop inp
sta numa
sub validate
endthis brp loop
bra label1
label1 lda numa
sub validate1
brp label2
brz label2
endthis bra loop
label2 lda num
loop sta num
add total
sta total
sta num
sub one
brp loop
lda total
out
validate dat 11
validate1 dat 5
numa dat
num dat
total dat
one dat 1
这个程序会让用户输入5到10之间的数字,并计算从1到用户指定输入的数字的总和,并在输出显示中打印结果。例如,如果用户输入 5,则总和将为 15。
代码存在以下问题:
有些标签不是唯一的,例如 loop
。所以这意味着不清楚执行应该用 brp loop
指令跳转到哪里。根据您使用的模拟器,您可以获得不同的行为。您应该为标签使用唯一的名称。
代码的第二部分——计算完成的地方——开始于:
label2 lda num
loop sta num
...但这只是读取和写入 num
中的内容,这是无用的。你真的想复制输入到num
,所以这应该是:
label2 lda num2
loop sta num
再往下看你有这个代码:
sta total
sta num
sub one
...但这会用总数覆盖 num
,然后从总数中减去 1。然而,您想要从输入数字的倒计时值中减去 1,而不是从总数中减去 1。所以你真正需要的是得到那个倒计时值然后减去:
sta total
lda num # corrected
sub one
您的程序没有 hlt
指令,这意味着执行将进入您程序的“数据部分”。所以在这里添加hlt
:
lda total
out
hlt # stop execution
还有以下几点需要改进:
从未引用 endthis
标签:不需要它。
在此代码中:
brp label2
brz label2
... brz
指令永远不会跳转到 label2
,因为零已经被 brp
捕获。这可能会造成混淆,但 brp
的意思是:“非负时分支”,因此当累加器为零时它也会分支。因此,您可以删除 brz label2
;不需要。
以下bra
指令:
bra label1
label1 lda numa
... 将跳转到 label1
否则也只继续该行。所以这是一个无用的跳跃。您可以只删除 bra label1
行,并删除标签。
一个LMC可以从顶部重新设置为运行。在这种情况下,您必须考虑到数据是 而不是 重置的,因此最好在程序开始时使用代码将数据初始化为初始值。在这种特殊情况下,您需要将总数重置为 0,否则您将添加到之前 运行.
的总数中
我建议使用更有意义的名称。例如,label1
和 numa
并没有真正阐明它们的用途。
建议的解决方案:
lda zero # added: initialise total
sta total
getinput inp
sta input
sub toogreat
brp getinput
lda input
sub minimum
brp inputok
bra getinput
inputok lda input # corrected
loop sta countdown
add total
sta total
lda countdown # corrected
sub one
brp loop
lda total
out
hlt # added
toogreat dat 11
minimum dat 5
input dat 4
countdown dat
total dat 0
zero dat 0
one dat 1
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.816/lmc.js"></script>
loop inp
sta numa
sub validate
endthis brp loop
bra label1
label1 lda numa
sub validate1
brp label2
brz label2
endthis bra loop
label2 lda num
loop sta num
add total
sta total
sta num
sub one
brp loop
lda total
out
validate dat 11
validate1 dat 5
numa dat
num dat
total dat
one dat 1
这个程序会让用户输入5到10之间的数字,并计算从1到用户指定输入的数字的总和,并在输出显示中打印结果。例如,如果用户输入 5,则总和将为 15。
代码存在以下问题:
有些标签不是唯一的,例如
loop
。所以这意味着不清楚执行应该用brp loop
指令跳转到哪里。根据您使用的模拟器,您可以获得不同的行为。您应该为标签使用唯一的名称。代码的第二部分——计算完成的地方——开始于:
label2 lda num loop sta num
...但这只是读取和写入
num
中的内容,这是无用的。你真的想复制输入到num
,所以这应该是:label2 lda num2 loop sta num
再往下看你有这个代码:
sta total sta num sub one
...但这会用总数覆盖
num
,然后从总数中减去 1。然而,您想要从输入数字的倒计时值中减去 1,而不是从总数中减去 1。所以你真正需要的是得到那个倒计时值然后减去:sta total lda num # corrected sub one
您的程序没有
hlt
指令,这意味着执行将进入您程序的“数据部分”。所以在这里添加hlt
:lda total out hlt # stop execution
还有以下几点需要改进:
从未引用
endthis
标签:不需要它。在此代码中:
brp label2 brz label2
...
brz
指令永远不会跳转到label2
,因为零已经被brp
捕获。这可能会造成混淆,但brp
的意思是:“非负时分支”,因此当累加器为零时它也会分支。因此,您可以删除brz label2
;不需要。以下
bra
指令:bra label1 label1 lda numa
... 将跳转到
label1
否则也只继续该行。所以这是一个无用的跳跃。您可以只删除bra label1
行,并删除标签。一个LMC可以从顶部重新设置为运行。在这种情况下,您必须考虑到数据是 而不是 重置的,因此最好在程序开始时使用代码将数据初始化为初始值。在这种特殊情况下,您需要将总数重置为 0,否则您将添加到之前 运行.
的总数中我建议使用更有意义的名称。例如,
label1
和numa
并没有真正阐明它们的用途。
建议的解决方案:
lda zero # added: initialise total
sta total
getinput inp
sta input
sub toogreat
brp getinput
lda input
sub minimum
brp inputok
bra getinput
inputok lda input # corrected
loop sta countdown
add total
sta total
lda countdown # corrected
sub one
brp loop
lda total
out
hlt # added
toogreat dat 11
minimum dat 5
input dat 4
countdown dat
total dat 0
zero dat 0
one dat 1
<script src="https://cdn.jsdelivr.net/gh/trincot/lmc@v0.816/lmc.js"></script>