在汇编中添加 2 个数字
Adding 2 numbers in assembly
您好,我们刚开始学习汇编的课程,我们有一个问题是在 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
我们的问题是第一次加法的进位没有加到第二次加法中,我们不知道为什么。
Carry位在Flags寄存器中,受很多操作影响,通常包括INC
。
您有多种选择来保留由 ADD
:
产生的进位标志
保存ADD
之后的Flags寄存器,恢复ADDC
之前的Flags寄存器。在 Intel 上,这是通过 pushf
和 popf
指令完成的。
将进位存储到寄存器中。在 Intel 上,这是用 setc [8-bit-register]
完成的。或者,您可以使用条件跳转。 (在英特尔上,这将是 jc
,进位跳跃;在您的模拟器中,这可能是 BRC
)。第三种方式是 MOV R4, 0; ADC R4, R4
.
重新排序或重写代码,以便 ADD
和 ADDC
之间没有标志更改指令。这是首选解决方案,我将根据此选项继续。
首先,我将向您展示它是如何在 Intel 上完成的:
; 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
此外,如果模拟器支持 M[Num1]
语法,您可能可以完全摆脱使用 R1, R3, R3
。
请注意,我添加的是 2
,而不是 1
,因为您添加的是 2 个字节长的单词。
您的 INC
可能需要加倍(模拟的 CPU 可以访问字节偏移量的内存,不是吗?)。例如 INC R1
会变成:
INC R1
INC R1
相当于
ADD R1, 2
这清楚地显示了进位标志是如何被覆盖的。
如果模拟器不支持 M[register + constant]
语法,我们可以通过使用 R4
寄存器来解决这个问题,MOV M[R3], R4
和 MOV R4, M[R1]
之间未使用该寄存器:
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
干杯!
您可以在递增值之前简单地添加进位:
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
您好,我们刚开始学习汇编的课程,我们有一个问题是在 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
我们的问题是第一次加法的进位没有加到第二次加法中,我们不知道为什么。
Carry位在Flags寄存器中,受很多操作影响,通常包括INC
。
您有多种选择来保留由 ADD
:
保存
ADD
之后的Flags寄存器,恢复ADDC
之前的Flags寄存器。在 Intel 上,这是通过pushf
和popf
指令完成的。将进位存储到寄存器中。在 Intel 上,这是用
setc [8-bit-register]
完成的。或者,您可以使用条件跳转。 (在英特尔上,这将是jc
,进位跳跃;在您的模拟器中,这可能是BRC
)。第三种方式是MOV R4, 0; ADC R4, R4
.重新排序或重写代码,以便
ADD
和ADDC
之间没有标志更改指令。这是首选解决方案,我将根据此选项继续。
首先,我将向您展示它是如何在 Intel 上完成的:
; 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
此外,如果模拟器支持 M[Num1]
语法,您可能可以完全摆脱使用 R1, R3, R3
。
请注意,我添加的是 2
,而不是 1
,因为您添加的是 2 个字节长的单词。
您的 INC
可能需要加倍(模拟的 CPU 可以访问字节偏移量的内存,不是吗?)。例如 INC R1
会变成:
INC R1
INC R1
相当于
ADD R1, 2
这清楚地显示了进位标志是如何被覆盖的。
如果模拟器不支持 M[register + constant]
语法,我们可以通过使用 R4
寄存器来解决这个问题,MOV M[R3], R4
和 MOV R4, M[R1]
之间未使用该寄存器:
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
干杯!
您可以在递增值之前简单地添加进位:
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