assembly 如何使用VVM程序编辑器将负数相乘?

jtw3ybtb  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(94)

如何仅使用vvm中的某些函数(如INPSTOLDABRBRPSUBADDOUT)乘以负数?
我的代码可以乘以正数,但如果第二个输入是负数或零,它就不能正常工作:

in
sto 99
in
sto 98
lda 97
add 99
sto 97 
lda 98 
sub 90
sto 98
lda 98
brz 13
br 04
lda 97
out
hlt
*90
dat 001

字符串
当第二个输入为零或更小时,程序会继续循环,并最终在add 99处遇到“Data value out of range(1000)”错误,这意味着结果超过了999。
我被卡住了,我不知道如何解决这个问题。我觉得我需要将输入的负输入转换为正输入,然后像这样将它们相乘,但我不知道如何做到这一点,以及它是否能解决问题。
我如何使它对第二个输入的非正值起作用?

lh80um4z

lh80um4z1#

实际上,当第二个输入为负或零时,代码无法正常工作。
对于零的情况:你的代码只检查第二个输入(用作倒计数)是否在循环的一次迭代后变为零。这个检查最好在循环的开始时进行,所以它也在开始时执行。
对于负值的情况:在这种情况下,您应该“翻转”两个输入的符号,因为(-a)*(-b) == a*b。要“翻转”符号,您可以从0减去原始值,因为0-a == -a
遗憾的是VVM不支持标签,所以你必须在操作数中使用正确的数字地址。当程序还在构建中,这些地址可能会随着你添加更多的代码而改变时,这可能是一个痛苦。出于这个原因,我建议在代码块之间留一些间隙,这样当你编辑代码时,这些跳转到的地址可以保持稳定。
代码:

in
sto 99
in
brp 20     Normal case: start loop
// Remove sign from the second input (98)
sto 98
lda 91     Zero
sub 98
sto 98
// Toggle sign of the first input (99) to compensate
lda 91     Zero
sub 99
sto 99
lda 98     Prepare for loop
br  20     Start the loop
///////////////////// LOOP ////////////
*20
brz 40     Check immediately for 0
sto 98
lda 97
add 99
sto 97   
lda 98    
sub 90     Subtract one
br  20     Repeat
///////////////////// OUTPUT //////////
*40
lda 97
out
hlt
///////////////////// DATA ////////////
*90
dat 001
dat 000

字符串

备注:

最后一个dat 000只是为了强调这个内存地址(91)是由程序使用的,并且应该有值0。这是默认值,所以没有必要严格包含它。
在程序开始时,结果的初始值(地址97)也被假定为0。这是一个稍微不同的情况,因为这个结果将被程序更新。但是当程序重新加载时,所有内存首先被清除到000,这样我们就可以假定结果在每次运行时都以0开始。
但是,在VVM中的执行菜单中有一个名为 * 重新启动的选项?*.默认情况下它是开着的。如果你关闭它,并在程序运行至少一次后重新启动程序,那么就不会重新加载,所以内存将保持在前一次运行后的状态。这意味着地址97处的结果在大多数情况下不会为0。因此,新的运行将把新的产品添加到结果中,可能会给出一个令人惊讶的结果--这取决于您在这种情况下期望发生什么。
如果你希望每次运行都以结果的值零开始,即使上面提到的选项被关闭,那么在程序开始时显式地初始化结果,在最顶部插入这两条指令:

lda 91    Zero
sto 97    Initialise the result to 0

相关问题