计算机是进行数据处理、运算的机器,那么就有两个基本的问题:
对于这两个问题,在机器指令中必须给出明确或者隐含的说明,否则计算机将无法工作
本章中我们就要针对8086CPU进行这两个问题的讨论。
为了使得描述更加的简洁,我们定义的描述性符号:reg(寄存器)和sreg(段寄存器)
reg的集合包括:ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di
sreg的集合包括:ds,ss,cs,es(扩展段)
1> 在8086CPU中只有这四个寄存器(bx、si、di、bp)可以用在[…]中进行内存地址的寻址
正确的表示形式:
错误的表示形式:
2> 在[…]中,这四个寄存器可以单独出现,或者只能以四种组合形式出现
错误的用法:
3> 只要在[…]中使用寄存器bp,而指令中没有显性的给出段地址,段地址就默认在ss中
绝大多数的机器指令都是进行数据的处理的指令,处理大致分为三类:读取,写入,运算
机器指令并不关心数据的值是多少,而关心指令执行前一刻,它将要处理的数据在什么位置
指令执行前,所要处理的内存可以在三个地方:CPU内部,内存,端口
在汇编语言中如何表示数据的位置?
定位内存地址的方法一般被称为寻址方式
8086CPU的指令可以处理为两中尺寸的数据,byte和word,所以在机器指令中要指明,指令进行的是字操作还是字节操作
确定指令要处理的数据有多长的方法:
通过寄存器名指明要处理的数据的尺寸
在没有寄存器名存在的时候,用操作符X ptr 指明内存单元的长度,X在汇编指令中可以为word或者byte
其他方法
通过例子来进一步的探讨各种寻址的作用
mov ax,seg
mov ds,ax
mov bx,60h ;确定记录地址ds:bx
mov word ptr [bx+0ch],38 ;排名字段改为38
add word ptr [bx+0eh],70 ;收入字段增加70
mov si,0 ;用si来定位产品字符串中的字符
mov byte ptr [bx+10h+si],'v'
inc si
mov byte ptr [bx+10h+si],'A'
inc si
mov byte ptr [bx+10h+si],'x'
我们可以看出,8086CPU提供的如[bx+si+idata]的寻址方法为结构化的处理提供了方便
从上面可以看到,一个结构化的数据包含了多个数据项,而数据项的类型又不相同,有的是字型数据,有的是字节型数据,有的是数组(字符串)。
一般来说,我们用[bx+si+idata]的方式来访问结构体中的数据,用bx定位整个结构体,用idata定位结构体中的某一个数据项,用si定位数组项中的每个元素。为此,汇编语言提供了更为贴切的书写方式,如:[bx].idata、[bx].idata[si]。
div是除法指令,使用div做除法的时候:
除数和被除数的关系
除数 被除数
8位 16位(AX)
16位 32位(DX和AX)
结果存放:
运算 8位 16位
商 AL AX
余数 AH DX
div reg(寄存器)
div 内存单元
div byte ptr ds:[0] 含义如下
div word ptr ds:[0] 含义如下
div byte ptr [bx+si+8]
div word ptr [bx+si+8 ]
分析:被除数100001的值大于了65535,所以不能用ax存放,只能用ax和dx联合起来存放
除数100小于255,可以在一个8位的寄存器中存放,但是由于被除数是32位则此时除数应该为16位,所以用一个16位的寄存器存放除数100
因为要分别将dx和ax赋100001的高16位和低16位,所以应该先将100001表示为16进制形式:186A1H
mov bx,1
mov ax,86A1H
mov bx,100
div bx
分析:被除数1001小于65535,因此可以用ax进行存放,除数可以用8位的寄存器存放
mov ax,1001
mov bl,100
div bl
之前学过的db定义的字节型数据,dw定义的字型数据
dd是用来定义dword(double word双字)型数据的
示例:datasg segment
db 1
dw 1
dd 1
datasg ends
在datasg段中定义的三个数据:
第一个数据:01H 在datasg:0处,占一个字节空间
第二个数据:0001H 在datasg:1处,占一个字型空间
第三个数据:00000001H 在datasg:3处,占一个双字型空间
问题8.1:用div计算 data段中第一个数据除以第二个数据后的结果,商存在第三个数据的存储单元中。
data segment
dd 100001
dw 100
dw 0
data ends
分析:data 段中的第一个数据是被除数,为 dword(双字)型,32位,所以在做除法之前,用dx 和 ax存储。应将data:0字单元中的低16位存储在ax 中,data:2字单元中的高16位存储在dx中。程序如下。
mov ax,data
mov ds,ax
mov ax,ds:[0] ;ds:0字单元中的低16位存储在ax中
mov dx,ds:[2] ;ds :2字单元中的高16位存储在dx中
div word ptr ds:[4] ;用dx :ax中的32位数据除以ds :4字单元中的数据
mov ds:[6],ax ;将商存储在ds:6字单元中
dup是一个操作符,由编译语言中同db,dw,dd等一样,也是由编译器进行识别处理的符号
它是和db,dw,dd等数据定义的伪指令配合使用,用来进行数据的重复
db 3 dup(0) 定义了三个字节,它们的值都是0 相当于db 0,0,0
db 3 dup(0,1,2) 定义了九个字节,它们是0,1,2,0,1,2,0,1,2
db 3 dup(‘abc’,'ABC) 定义了18个字节 它们是a,b,c,A,B,C,a,b,c,A,B,C,a,b,c,A,B,C
dup是一个非常有用的操作符
例如定义一个容量为200个字节的栈段时,不使用dup
stack segment
db 200 dup(0)
stack ends