您刚刚开始了我们学习汇编的课程,我们有一个问题是在16位处理器中添加2位32位数。这是我们的代码:
ORIG 8000h
Num1 STR 8091h, 1201h
Num2 STR 8061h, 4f01h
Soma TAB 2
ORIG 0000h
MOV R1, Num1
MOV R2, Num2
MOV R3, Soma
MOV R4, M[R1]
ADD R4, M[R2]
MOV M[R3], R4
INC R1
INC R2
INC R3
MOV R4, M[R1]
ADDC R4, M[R2]
MOV M[R3], R4
Fim: BR Fim
我们的问题是第一次添加的携带不会被添加到第二次,我们不知道为什么。
答案 0 :(得分:1)
Carry位在Flags寄存器中,受许多操作的影响,通常包括INC
。
您有几个选项可以保留ADD
:
在ADD
之后保存标志寄存器,并在ADDC
之前将其恢复。在英特尔上,这是通过pushf
和popf
说明完成的。
将Carry位存储在寄存器中。在英特尔,这是通过setc [8-bit-register]
完成的。或者,您可以使用条件跳转。 (在intel上,这将是jc
,跳上携带;这可能是你模拟器中的BRC
。第三种方式是MOV R4, 0; ADC R4, R4
。
重新排序或重写代码,以便ADD
和ADDC
之间没有改变标志的指令。这是首选解决方案,我将继续基于此选项。
首先,我将向您展示它在英特尔上的表现:
; add the low words
mov ax, [Num1]
add ax, [Num2]
mov [Soma], ax
; Add the high words and the Carry bit
mov ax, [Num1 + 2]
addc ax, [Num2 + 2]
mov [Soma +_2], ax
现在进行模拟器组装。
(我假设MOV R4, M[R1]
表示将值R1
中的值放入R4
)。
如果模拟器支持像M[R1 + 1]
那样的操作数语法,那么递增寄存器的需要就会消失:
MOV R1, Num1
MOV R2, Num2
MOV R3, Soma
MOV R4, M[R1]
ADD R4, M[R2]
MOV M[R3], R4
MOV R4, M[R1+2]
ADDC R4, M[R2+2]
MOV M[R3+2], R4
此外,如果模拟器支持R1, R3, R3
语法,您可以完全不使用M[Num1]
。
请注意,我添加了2
,而不是1
,因为您要添加长度为2个字节的字词。
您的INC
可能需要加倍(模拟CPU可以在字节偏移处访问内存,可以吗?)。例如,INC R1
将成为:
INC R1
INC R1
相当于
ADD R1, 2
这清楚地表明了Carry标志是如何被覆盖的。
如果模拟器不支持M[register + constant]
语法,我们可以使用R4
和MOV M[R3], R4
之间未使用的MOV R4, M[R1]
寄存器来解决这个问题:< / p>
MOV R1, Num1
MOV R2, Num2
MOV R3, Soma
MOV R4, M[R1]
ADD R4, M[R2]
MOV M[R3], R4
MOV R4, 0
ADC R4, R4 ; R4 now contains the carry flag.
INC R1 ; Note you probably need to change
INC R2 ; these to ADD R?, 2
INC R3
ADD R4, M[R1]
ADD R4, M[R2]
MOV M[R3], R4
干杯!
答案 1 :(得分:1)
您可以在递增值之前添加进位:
ORIG 8000h
Num1 STR 8091h, 1201h
Num2 STR 8061h, 4f01h
Soma TAB 2
ORIG 0000h
MOV R1, Num1
MOV R2, Num2
MOV R3, Soma
MOV R4, M[R1]
ADD R4, M[R2]
MOV M[R3], R4
MOV R4, R0
ADDC R4, R0
INC R1
INC R2
INC R3
ADD R4, M[R1]
ADD R4, M[R2]
MOV M[R3], R4
Fim: BR Fim