由于算术逻辑单元(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:
- 将数字63和37相加。
- 将数字250和20相加。
- 这些操作如何影响CY和AC标志?
- 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
