1.为了描述上的简洁,在以后的课程中,将使用两个描述性的符号reg来表示一个寄存器,用sreg表示一个段寄存器。
reg的集合包括:ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di;
sreg的集合包括:ds,ss,cs,es.
8086CPU处理数据的两个基本问题:处理的数据存放在哪个地方? 要处理的数据有多长?
2. bx, si, di, bp:这四个寄存器,都可以放在"[...]"来进行内存单元的寻址,其他寄存器都不可以,就是这么规定的,例如:
mov ax, [bx]; mov ax, [si]; mov ax, [di+bp]; mov ax, [bp]; 都是合法的;但是:
mov ax, [dx]; mov ax, [ax]; mov ax, [ds]; 等等都不是合法的操作;
第二点要注意的,上面这4个寄存器都可以单个出现,或者以组合形式出现的。但是,组合形式只能四种形式,分别是:
bx和si, bx和di, bp和si, bp和di;其他形式统统都不是合法的,例如:mov ax, [bx+bp] 是不合法的。
第三点要注意的,只要在[..]中使用寄存器bp,而指令中并没有给出明确的段地址,那么段地址就默认为ss。例如:
mov ax, [bp] 相当于 mov ax, ss:[bp]。
3.处理的数据放在什么地方:有三个地方存放:CPU内部、内存和端口;例如:
mov bx, [0] ; 内存中,ds:[0]
mov bx, ax ; CPU内部,寄存器ax
mov bx, 1 ; CPU内部,指令缓冲器
4. 数据位置的表达:分为三种:
1)立即数(idata):举例:mov ax, 1
2)段寄存器:举例:mov ax, bx
3)段地址加偏移地址:举例:mov ax, [0] ; mov ax, [bx+si]
5. 寻址方式:分为以下几种:
1) 直接寻址:[idata] 2)寄存器间接寻址:[bx] 3) 寄存器相对寻址:[bx+idata]
4) 基址变址寻址:[bx+si] 5)相对基址变址寻址:[bx+si+idata]
6. 指令要处理的数据长度:在8086CPU中,可以处理两种长度的数据:byte, word;所以要指明,指令进行的是字操作还是字节操作。实现这点可以通过以下几种方法:
1)通过寄存器指明:
mov ax, 1 ; mov bx, ds:[0] ;ax, bx 寄存器占用16个字节,是字寄存器,所以传送的是字;
mov al, 1 ; mov bl, ds:[0] ; al, bl 寄存器占用8个字节,是字节寄存器,所以传送的是字节;
2)通过指明内存单元长度来实现:
mov word ptr ds:[0], 1 ; word ptr 就是指明是按照字大小来传送数据
mov byte ptr ds:[0], 1 ; byte ptr 就是指明是按照字节大小来传送数据
归根结底,就是通过:X ptr 的方式来指明是按照字还是字节大小来传送数据。
3)其他方法:例如,栈操作都是按照字大小来传递的:push [bx]
7. div指令:div是除法指令,除法运算规则如下:
1)除数:8位或者16位,放在一个寄存器或者内存单元中;
2)被除数:默认放在AX或者DX和AX中。如果是16位,则放在AX中;如果是32位,则DX存放高16位,AX存放低16位;
3)结果:如果除数是8位,AL存放商,AH存放余数;如果是16位,AX存放商,DX存放余数;
按照上面的说法,除法指令格式为:
div reg / div 内存单元
举例:
div byte ptr ds:[0]
===> al = ax / (ds * 16 + 0) 的商 ; ah = ax / (ds * 16 + 0) 的余数
8. 伪指令DD: 跟db, dw一样道理,dd是定义double word,即双字型数据32位:
dd 1 ; 数值1是占了两个字宽度
9. dup:操作符,主要用来定义重复的数据,比如:
db 3 dup (0) ;定义了3个字节的0
db 3 dup (1, 2, 3) ; 定义了9个字节,1, 2, 3, 1, 2, 3, 1, 2, 3
可见,dup的格式为:
db/dw/dd 重复次数 dup (重复数据)
dup是一个非常有用的操作符,如果我们经常要定义大一点的数据,比如300个字节的0,简单一句:db 300 dup (0)
10.一般用[bx+idata+si]来访问结构体中的数据,用bx定位整个结构体,用idata定位结构体中的某一个数据项,用si定位数组项的每个元素。
数据处理的两个基本问题(学习汇编)