循环批量传送和条件转移

循环批量传送和条件转移

串传送指令

movsb 和 movsw

传送前的准备工作:

设置元数据和目标数据位置

DS:SI:原始数据串的段地址:偏移地址

ES:DI: 目标位置的短地址:偏移地址

设置传送方向:

通过设置flags寄存器第10位DF(direction flag)标志位,可以通过cld指令将DF标志位置为0,此时传送方向是从低地址到高地址(正向)。std指令将DF标志位置为1此时传送方向是从高地址到低地址(逆向)

在设置完方向后,每次执行movsb或movsw后对于的si di会指向下一待处理位置

设置重复次数:

1
rep 指令    ;rep=repeat重复

重复对应的指令,重复的次数位于寄存器cx中,每次执行检测cx中的值,只有在cx不为0时才执行这条指令

$ 和 $$

$:当前指令的汇编地址

$$:当前所在段的起始的汇编地址

loop指令

1
loop 标号

loop指令的机器码:E2 8位相对偏移量

在8086中,loop指令的执行过程

将寄存器 cx 的内容减一

如果 cx 的内容不为零,转移到指定的位置处执行,否则按顺序执行后面的指令

基址寻址

  • 寄存器BX在设计之初的作用之一就是用来提供数据访问的基地址,所以又叫基址寄存器(Base Address Register)
  • 在设计8086cpu时,每个寄存器都有自己的太特殊用途,比如AX时累加器(Accumulator),与它有关的指令还会做指令长度的优化;CX是计数寄存器(count);DX是数据(Date)寄存器,除了作为通用寄存器使用外还专门用于和外设之间进行数据传送;SI是原索引寄存器(Source Index);DI是目标索引(Destination Index)寄存器,用于数据传送操作

inc dec指令

inc = incream 递增

1
2
inc 寄存器/内存
dec 寄存器/内存

inc 用于将寄存器或内存地址中的值加一

dec 用于将寄存器或内存地址中的值减一

在8086中如果要用寄存器来提供偏移地址,只能使用 bx si di bp,不能采用其他寄存器

mov [ax] , dl ;非法

mov [dx] , bl ;非法

mov word [bx] , 0x10 ;合法

基址变址寻址

基址寄存器bx bp

变址寄存器si di

在8086中只允许几种基址变址的组合

1
2
3
4
bx + si
bx + di
bp + si
bp + di

jns指令

当SF标志位为0时跳转,为1时不跳转继续执行下面指令

SF位为符号位,当运算结果最高位为0时SF为0,当运算结果最高位为1时SF为1

用合理的方法显示数字

使用循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    jmp start

mytest db 'L' , 0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,' ',0x07,'o',0x07,
db 'f' , 0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07

start:
;---------------------------显示Labe offset:
mov ax , 0x7c0
mov ds , ax

mov ax , 0xb800
mov es , ax

cld ;将DF标志位清0表示方向为从低字节到高字节
mov si , mytest
mov di , 0

mov cx , (start - mytest)/2 ;设置循环次数
rep movsw ;执行movsw cx内数据的次数

;-----------------------------------------------
mov ax , number ;得到标号的汇编地址

;分解各个数位
mov bx , ax
mov cx , 5 ;循环次数
mov si , 10 ;除数

dight:
xor dx , dx ;与ax一起形成被除数
div si
mov [bx] , dl ; 保存数位
inc bx
loop dight

mov cx , 5
;显示各个数位
show:
dec bx ;取到对于的字符数字
mov al , [bx]
add al , 0x30 ;转换为对应的字符
mov ah , 04 ;对应的字符属性
mov [es:di] , ax ;es是显存对应的段地址,di是rep movsw后的di
add di , 2 ;找到写下一个字符的位置
loop show

jmp $

number db 0,0,0,0,0

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

使用跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    jmp start

mytest db 'L' , 0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,' ',0x07,'o',0x07, ; \是续行符编译器将其合并位一行
db 'f' , 0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07

start:
;---------------------------显示Labe offset:
mov ax , 0x7c0
mov ds , ax

mov ax , 0xb800
mov es , ax

cld ;将DF标志位清0表示方向为从低字节到高字节
mov si , mytest
mov di , 0

mov cx , (start - mytest)/2 ;设置循环次数
rep movsw ;执行movsw cx内数据的次数

;-----------------------------------------------
mov ax , number ;得到标号的汇编地址

;分解各个数位
mov bx , ax
mov cx , 5 ;循环次数
mov si , 10 ;除数

dight:
xor dx , dx ;与ax一起形成被除数
div si
mov [bx] , dl ; 保存数位
inc bx
loop dight

mov bx , number
mov si , 4

show:
mov al , [bx + si] ;基址和变址的组合
add al , 0x30
mov ah , 0x04
mov [es:di] , ax
add di , 2
dec si
jns show

jmp $

number db 0,0,0,0,0

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