学习参考:汇编语言(第2版)王爽
- bx、si、di 和 bp
- 机器指令处理的数据在什么地方
- 汇编语言中数据位置的表达
- 寻址方式
- 指令要处理的数据有多长
- div 指令
- 伪指令 dd
- dup
计算机作为进行数据处理、运算的机器,那么有两个基本问题:
- 处理的数据在什么地方
- 要处理的数据有多长
我们使用 reg 来表示一个寄存器,sreg 表示一个段寄存器
- reg 的集合包括:ax、bx、cx、dx、ah、al、bh、bl、ch、cl、dh、dl、sp、bp、si、di
- sreg的集合包括:ds、ss、cs、es
bx、si、di 和 bp
- 只有这四个寄存器可以用在 “[…]” 中来进行内存单元的寻址
- 这四个寄存器可以单个出席那,或只能以四种组合出现:
- bx 和 si
- bx 和 di
- bp 和 si
- bp 和 di
- 只要在 “[…]” 中使用寄存器 bp,而指令中没有显性地给出段地址,段地址就默认在 ss 中
机器指令处理的数据在什么地方
进行数据处理的指令分为三类:
- 读取
- 写入
- 运算
在机器指令这一层来讲,并不关心数据的值是多少?而关心指令执行前一刻,它将要处理的数据所在的位置。
在指令执行之前,所要处理的数据可以在 3 个地方:
- CPU 内部
- 内存
- 端口
指令举例
汇编指令 | 指令执行前数据的位置 |
---|---|
mov bx,[0] | 内存,ds:0 单元 |
mov bx,ax | CPU 内部,ax 寄存器 |
mov bx,1 | CPU 内部,指令缓冲器 |
汇编语言中数据位置的表达
用 3 个概念表达数据的位置
- 立即数(idata):对于直接包含在机器指令中的数据(执行前在 CPU 的指令缓冲器中)
1
2
3
4mov ax,1
add bx,2000h
or bx,00010000b
mov al,'a' - 寄存器:指令要处理的数据在寄存器中
1
2
3
4mov ax,bx
mov ds,ax
push bx
mov ds:[0],bx - 段地址(SA)和偏移地址(EA):指令要处理的数据在内存中,在汇编指令中可用[x]的格式给出 EA,SA 在某个段寄存器中
1
2
3mov ax,[0]
mov ax,[di]
mov ax,[bx+di+8]
寻址方式
指令要处理的数据有多长
8086CPU 的指令,可以处理两种尺寸的数据,byte 和 word。所以在机器指令中要指名,指令进行的是字操作还是字节操作。对于这个问题,用一下方法处理
- 通过寄存器指明要处理的数据的尺寸 下面进行的是字操作 下面进行的是字节操作
1
2
3
4
5
6mov ax,1
mov bx,ds:[0]
mov ds,ax
mov ds:[0],ax
inc ax
add ax,10001
2
3
4
5
6mov al,1
mov al,bl
mov al,ds:[0]
mov ds:[0],al
inc al
add al,100 - 在没有寄存器名称存在的情况下,用操作符 X ptr 指明内存单元的长度,X 在汇编指令中可以为 word 或 byte 下面的指令中,用 word ptr 指明了指令访问的内存单元是一个字单元 下面的指令中,用 byte ptr 指明了指令访问的内存单元是一个字节单元
1
2
3
4mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],21
2
3
4mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2 - 其他方法 有些指令默认了访问的字单元还是字节单元,比如,push 指令只进行字操作
div 指令
div 是除法指令,使用 div 做除法的时候应注意一下问题
- 除数:有 8 位和 16位两种,在一个 reg 或内存单元中
- 被除数:默认凡在 AX 或 DX 和 AX 中,如果除数为 8 位,被除数则为 16 位,默认在 AX 中存放;如果除数为 16 位,被除数则为 32 位,在 DX 和 AX 中存放,DX 存放高 16 位,AX 存放低 16 位
- 结果:如果除数为 8 位,则 AL 存储除法操作的商,AH 存储除法操作的余数;如果除数为 16 位,则 AX 存储除法操作的商,DX 存储除法操作的余数
格式如下
1 | div reg |
现在可以有多种方法来表示一个内存单元了,比如下面的例子:
1 | div byte ptr ds:[0] |
dx*10000H
相当于将 dx 左移了 16 位
编程 利用除法指令计算 100001/100
分析:被除数大于 65535(2^16),不能用 ax 寄存器存放,所以只能使用 dx 和 ax 两个寄存器联合存放 100001,也就是说要进行 16 位的除法。除数 100 小于 255,可以在一个 8 位寄存器存放,但是,因为被除数是 32 位的,除数应为 16 位,所以要用一个 16 位寄存器来存放被除数 100
因为要分别为 dx 和 ax 赋 10001 的高 16 位值和低 16 位值,所以应先将 100001 表示为 16 进制形式:186A1H,程序如下:
1 | mov dx,1 |
程序执行后,(ax)=03E8H(即 1000),(dx)=1(余数为 1)
编程 利用除法指令计算 1001/100
分析:被除数 1001 小于 65535 ,所以可以用 ax 寄存器存储,除数 100 小于 255,可以用 8 位寄存器存储,也就是说要进行 8 位的除法。程序如下:
1 | mov ax,1001 |
程序执行后,(al)=0AH(即 10),(dh)=1(余数为 1)
伪指令 dd
dd 是用来定义 dword(double word,双字)型数据的。比如:
1 | data segment |
在 data 段中定义了 3 个数据
第一个数据为 01H,在 data:0 处,占 1 个字节
第二个数据为 0001H,在 data:1 处,占 1 个字
第三个数据为 00000001H,在 data:3 处,占 2 个字
用 div 计算data段中第一个数据除以第二个数据后的结果,商存在第三个数据的存储单元中。
1 | data segment |
分析:data 段中的第一个数据是被除数,为 dword(双字)型,32 位,所以在做除法之前,用 dx 和ax 存储。应将 data:0 字单元中的低 16 位存储在ax中,data:2 字单元中的高16位存
储在 dx 中。程序如下。
1 | mov ax,data |
dup
和 db、dw、dd 等数据定义伪指令配合使用,用来表示数据的重复
格式如下
1 | db 重复次数 dup (重复的字节型数据) |