8051模拟器汇编入门(2)算术与逻辑

由于算术逻辑单元(ALU),8051能够执行各种算术和逻辑运算。大多数操作都使用一个特殊的寄存器,称为累加器(accumulator),通常表示为ACC或A。例如,可以使用ADD指令将两个数字相加。

MOV A, #2
ADD A, #3

第一个操作数是累加器A,第二个操作数是立即值3。请注意,要将两个数字相加,A必须已经包含要相加的第一个数字。这可以通过使用MOV指令将立即值2移动到A来完成。加法的结果存储在A中,这意味着A的原始值不会被保留。ADD指令还会影响程序状态字(PSW)的进位位CY和辅助进位位AC。

图片

PSW第一位为CY,第二位为AC

练习2:

  1. 将数字63和37相加。
  2. 将数字250和20相加。
  3. 这些操作如何影响CY和AC标志?
  1. 63+37=100(64H)
图片

PSW(程序状态字)中的 AC(辅助进位)标志设置为 1,表示在上一次算术运算期间,位 3 和位 4 之间发生了进位。这对于 BCD(二进制编码的十进制)算术尤其重要。

让我们分析一下:

MOV A, #63      ; Load 63 (0011 1111 in binary)
ADD A, #1       ; Add 1  (0000 0001 in binary)
                ; Result: (0100 0000 in binary = 64)

查看二进制加法:

0011 1111  (63)
+ 0000 0001  (1)
-----------
  0100 0000  (64)

设置 AC 标志的原因是将两个数字相加时,从位 3 到位 4 发生了进位(低半字节和高半字节之间)在这个例子中:1111 + 0001 = 0000 带有进位。

可以这样想:

  • 字节被分成两个 4 位半字节(半字节)
  • AC = 1 表示这两个半字节之间发生了进位
  • 这主要用于执行 BCD 算术
  • 在常规二进制算术中,通常可以忽略 AC 标志
  • 主进位标志 (CY) 更常用于一般算术

2. 250+20=270(10EH)

图片

留意到PSW中的CY变为1。这是因为250 + 20 = 270,270 对于 8 位寄存器来说太大(最大值为 255 或 0xFF),溢出设置进位标志,实际结果回绕为 14(ACC 中显示的 0x0E)。

1111 1010  (250)
+ 0001 0100  (20)
--------------
1 0000 1110  (14 with carry)

前导 1 代表进位 (CY=1),底部 8 位 (0000 1110) 保留在累加器中。

ADDC指令与ADD指令非常相似,唯一的区别是ADDC还将进位标志加到结果中。例如,

MOV A, #255
ADD A, #1 ; CY设置为1,A重置为0。
ADDC A, #1 ; A设置为2而不是1。

ADDC的目的是允许更大整数的链式乘法。这使得在仅进行8位加法的系统上进行32位数字的加法成为可能。

练习3:

使用ADD和ADDC指令将两个2字节数字384和408相加,并将结果的低字节存储在寄存器R2中,高字节存储在R3中。

首先,让我们将数字转换为十六进制:

384 = 0180H(高字节:01H,低字节:80H)

408 = 0198H(高字节:01H,低字节:98H)

将低字节80H和98H相加存入寄存器R2,然后将高字节连同低字节相加时产生的进位存入寄存器R3。

; Load low bytes first
MOV A, #80H    ; Low byte of 384
ADD A, #98H    ; Add low byte of 408
MOV R2, A      ; Store low byte result in R2

; Now handle high bytes with carry
MOV A, #01H    ; High byte of 384
ADDC A, #01H   ; Add high byte of 408 with carry
MOV R3, A      ; Store high byte result in R3

让我们了解一下发生了什么:

添加低字节:80H + 98H = 118H(进位=1,ACC=18H)

添加带进位的高字节:01H + 01H + 进位 = 03H

最终结果:

R2 将包含 18H(低字节),R3 将包含 03H(高字节),它们一起形成 0318H(十进制为 792)

要点:

ADD 用于第一个(低)字节,ADDC 用于后续字节,因为它包含进位,低字节加法的进位自动包含在 ADDC 指令中

图片

一个类似的指令是SUBB,它执行减法。SUBB总是会减去两个给定的数字,但也会减去进位位。例如,

;假设CY已设置。
MOV A, #5
SUBB A, #1 ; A设置为3而不是4。

没有与简单ADD指令相对应的减法指令。其他类似的指令包括INC(增加)和DEC(减少)。然而,请注意,与ADD、ADDC和SUBB不同,INC和DEC指令不会影响进位标志。

8051还可以进行乘法和除法运算,这两个是唯一使用B寄存器的指令。关于乘法的第一件事是,在乘以两个n位数字时,结果将是一个2 × n位数字。8051通过将低字节和高字节存储在两个单独的寄存器中来处理这一点。表示如下。

MUL AB

这两个数字必须存储在A和B寄存器中。输出的低字节将放入A寄存器,高字节放入B寄存器。然后可以单独检索字节,或者如果不需要,可以丢弃。同样,两个n位数字的除法将产生两个输出:一个n位商和一个n位余数。表示如下。

DIV AB

这两个数字必须存储在A和B寄存器中。商(quotient)放入A寄存器,余数(remainder)放入B寄存器。请注意,如果结果太大,MUL将设置溢出标志OV,如果除数为0,DIV将设置溢出标志。

练习4:

执行6 * 9 / 5的计算。

A和B中的值是多少?

MOV A, #06H    ; Load 6 into A
MOV B, #09H    ; Load 9 into B
MUL AB         ; Multiply A * B
               ; Result: 6 * 9 = 54 (36H)
               ; 54 fits in one byte, so high byte in B will be 0

; At this point:
; A contains 36H (54 decimal)
; B contains 00H

; Now divide by 5
MOV B, #05H    ; Load 5 into B
DIV AB         ; Divide A by B (54 ÷ 5)

; Final result:
; A contains 0AH (10 decimal) - quotient
; B contains 04H (4 decimal) - remainder