X86汇编的加减法和循环

加法:add

减法:substract

寄存器:register (8/16)

内存:memory (8/16)

立即数:immediate (8/16)

加减法

CPU内部有一个标志寄存器(eflags),它的第0位就是CF位,用来保存进位和借位,当计算结果出现进位和借位时,CF会被置一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
; 不产生进位的加法
mov ax, 0x0001
mov bx, 0x0002
add ax, bx
; 产生进位的加法
mov ax, 0xf000
mov bx, 0x1000
add ax, bx
; 不产生进位的减法
mov cx, 0x0003
mov dx, 0x0002
sub cx,dx
; 产生进位的减法
mov cx, 0x0001
mov dx, 0x0002
sub cx,dx

xuanmai: jmp xuanmai
times 510-($-$$) db 0
db 0x55,0xaa

第一次加法时cf小写为,所以值位0,不产生进位

Screenshot_20220109_215906.png

第二次加法CF大写,产生进位

Screenshot_20220109_220003.png

减法同理

循环

loop循环

每次执行到loop时,会判断CX寄存器是否为0,不为0则跳到标号处继续执行,并自动将CX-1。直到CX为0

1
2
3
4
5
标号
...
循环体 CX=0
...
loop 标号

计算1+2+…+100

1
2
3
4
5
6
7
8
9
10
11
12
; 设定循环次数
mov cx, 100
; 初始化ax
mov ax, 0x0000
;循环部分
sum:
add ax, cx
loop sum

jmp $
times 510-($-$$) db 0
db 0x55, 0xaa

自增和自减

自增:incease = add ax, 1

自减:decease

inc和dec虽然也是加减法,但是它们并不影响CF标志位

16位寄存器处理32位加减法

解决思路时两个相加或者相减的数,都用2个寄存器来保存,然后分别把高位和高位相加减,低位和低位相加减,但是低位相加可能会产生进位,相减可能会产生借位,此时add/sub指令就不能满足要求了,此时需要两个指令

adc = add with carry = 被加数+加数+CF

sbb = sub with carry = 被减数-减数-CF

1
2
3
4
5
6
7
8
9
10
11
12
13
; bx:ax = 0x0001f000
mov bx, 0x0001
mox ax, 0xf000
; dx:cx = 0x00101000
mov dx, 0x0010
mov cx, 0x1000
;低位相加
add ax, cx
;高位相加
adc bx, dx
jmp $
times 510-($-$$) db 0
db 0x55, 0xaa