持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
前言
点赞再看,养成习惯!
该系列博文基于王爽老师 <汇编语言 第四版> 一书,需要的同学链接自取:
链接:pan.baidu.com/s/1NAgD1Z15… 提取码:xlzb
另外书中提到的DosBox软件不想去官网下载的小伙伴也可以自取:
链接:pan.baidu.com/s/1O6PnLb_h… 提取码:xlzb
一、寄存器小结
首先我们看一下8086CPU都有哪些寄存器:
上述的这些寄存器我们基本上都已经在前序的学习中接触过了,现在我们要做的是总结一下这些寄存器的功能和使用场景:
# 数据寄存器类
1. AX寄存器(Accumulator):累加寄存器,也成为累加器,在目前的学习中常被用做中间数据存储。
2. BX寄存器(Base): 基地址寄存器,常用来存储偏移地址基地址。
3. CX寄存器(Count):计数器寄存器,常用来进行计数,如配合loop指令进行循环计数等。
4. DX寄存器(Data):数据寄存器,主要用在乘除法中作为数据累加器,在输入输出操作中存放端口的地址。
#指针寄存器
5. SP(Stack Pointer): 堆栈指针寄存器,用来存放栈顶的偏移地址信息。
6. BP(Base Pointer):基址指针寄存器,用来存放堆栈内出数据的基地址。其默认段地址寄存器为SS寄存器。
# 变址寄存器
7. SI(Source Index): 源变址寄存器,通常用来存放数据源偏移地址变址信息。
8. DI(Destination Index):目标变址寄存器,通常用来存放数据的目标偏移地址信息。
# 控制寄存器
9. IP(Instruction Pointer): 指令指针寄存器,用力存放指令偏移地址信息。
10. FLAG:标志寄存器
# 段寄存器
11. CS(Code Segment):代码段寄存器,常配合IP寄存器使用指向指令地址。
12. DS(Data Segment):数据段寄存器,常用来保存数据段的基地址信息。
13. SS(Stack Segment):堆栈段基地址寄存器,用来保存堆栈段地址信息。
14. ES(Extra Segment):附加段地址寄存器。使用方法同DS寄存器。
通常我们在描述这些寄存器时会做一个简单的分类: 用sreg来表示段地址寄存器,其中包括:CS,DS,SS,ES。 用reg来表示其他寄存器,其中包括: AX,BX,CX,DX,SP,BO,SI,DI
1. BX,SI,DI,BP
首先我们要来看一下这四个寄存器,在8086CPU中这四个寄存器都是可以通过[...]的方式进行寻址。比如下面的这些指令都是可以使用的:
1. mov ax,[bx]
2. mov ax,[bx+si]
3. mov ax,[bx+di]
4. mov ax,[bp]
5. mov ax,[bp+si]
6. mov ax,[bp+di]
当然这四个寄存器也都可以单独出现.,或者可以以四种组合出现:
1. bx和si
2. bx和di
3. bp和si
4. bp和di
这里强调一下,如果没有显性的为bp寄存器提供段地址,则其默认段地址就在SS中。同理如果没有显性的为bx寄存器提供段地址,其默认段地址在DS中。
二、数据处理
计算机的指令主要可以分为三大类:数据的读取,数据的运算及数据的写入。大多数情况下我们并不关注数据的值是多少,而是关心指令执行前的那一刻,我们将要处理的数据存放在哪里。而存放数据和读取数据都绕不开一个话题,我们该如何来表达我们数据的位置。
1. 立即数(idata)
对于直接包含在机器指令中的数据(执行前在CPU的指令缓冲器中),在汇编语言中称为立即数(idata),在汇编指令中直接给出。
# 其实俺是最不喜欢将概念的,咱们直接写个代码演示不香吗
mov ax,1
add bx,2000h
or bx,00010000b
mov al,'a'
#上述代码中直接给出的数据值就叫做立即数(idata)
2. 寄存器
指令需要的数据也可以存放在寄存器中。我们只需要在使用的时候给出寄存器的名称即可。
mov ax,1
mov bx,ax
# 这里面ax寄存器中就存放了我们需要使用的数据
3. 段地址(SA)+偏移地址(EA)
我们也可以通过段地址+ 偏移地址直接指定数据存放的内存单元,如;
mov ax,[0]
# 这里的偏移地址为0,段地址存放在ds寄存器中
三、寻址方式小结
当数据被存放在内存单元时,我们可以通过多种方式来指定对应的内存单元的地址,我们给出单元地址的方法一般被称为寻址方式。我们之前已经学习过很多种寻址方式,简单的可以参考下图:
四、数据长度
之前我们提到过,8086CPU有两种数据长度,分别是byte和word。所以我们在声明数据时需要指明是byte还是word。当然,指名数据类型的方式有很多种,比如:
1. 通过寄存器指明
由于寄存器分为16位寄存器及8位寄存器,因此我们可以通过不同的寄存器来指明我们使用的数据长度:
# 下面的数据是byte
mov al,1
# 下面的数据是word
mov ax,1
2. 通过X ptr指明
这里面的X是一个代指符号,并不能直接的用在指令中,使用时需要替换成具体的byte或者word,如下:
# 下面的数据为word
mov word ptr ds:[0],1
# 下面的数据为byte
mov byte ptr ds:[0],1
3. 通过指令判断
有一些指令是强制要求某一种数据类型的,比如push [1000H]就不需要指明,因为它强制要求只允许进行字(word)操作。
五、新的指令
我们还要接触一些新的指令。
1. div指令
div指令是除法指令,是我们做数据运算时需要用到的,在使用div指令时要注意:
- 除数:可以用8位或者16位两种,需要存放在一个reg或者内存单元中。
- 被除数:默认存放在AX或者DX和AX中,如果除数为8位则被除数需要为16位。如果除数为16位则被除数需要是32位,在DX和AX中存放,DX存放高16位,AX存放低16位。
- 结果:如果除数位8位,则AL存储除法操作的商,AH存放余数。如果除数位16位则AX存放商,DX存放余数。
格式如下:
div reg
div 内存单元
# 如:
div byte prt ds:[0]
#含义:
#(al) = (ax) / ((ds)*16 + 0) 的商
#(aH) = (ax) / ((ds)*16 + 0) 的余数
#例子: 100001/100
mov dx,1
mov ax,86A1H
mov bx,100
div bx
2. 伪指令dd
dd是用来定义double word的就是两个字长度的数据。
data segment
db 1 # 数据定义为01H,在data:0处,占一个byte
dw 1 # 数据定义为0001H,在data:1处,占一个word
dd 1 # 数据定义为00000001H,在data:3处,占两个word
3. dup
dup是一个操作符,其含义位进行数据重复,常配合db,dw,dd等数据定义伪指令使用。比如:
db 3 dup(0)# 定义了三个长度为byte的数据,其值为0,相当于 db 0,0,0
结语
今天的内容就到此结束了,有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。 Spring通用架构及工具已上传到gitee仓库,需要的小伙伴们可以自取: gitee.com/xiaolong-ob…
码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~ 如果大家有什么意见和建议请评论区留言或私聊博主,博主会第一时间反馈的哦。