计算机是进行数据处理、运算的机器,那么有两个基本的问题就包含在其中:
(1)处理的数据在什么地方? (2)要处理的数据有多长?
这两个问题,在机器指令中必须给以明确或隐含的说明,否则计算机就无法工作。
一: 处理的数据在什么地方?
1、关于偏移地址[...]
(1)在8086cpu 中,只有这4个寄存器(bx、bp、si、di)可以用在“[…]” 中来进行内存单元的寻址。
(2)在“[…]” 中,这4个寄存器(bx、bp、si、di)可以单个出现,或只能以四种组合出现:
[bx+si]、[bx+di]、[bp+si]、[bp+di]
(3)只要在[…]中使用寄存器bp,而指令中没有显性的给出段地址,段地址就默认在ss中。
2、数据的位置表示
在机器指令这一层来讲,并不关心数据的值是多少,而关心指令执行前一刻,它将要处理的数据所在的位置。
指令在执行前,所要处理的数据可以在三个地方: cpu内部、内存、端口
汇编语言中用三个概念来表达数据的位置。
1)、立即数(idata)
2)、寄存器
3)、段地址(SA)和偏移地址(EA)
1)、立即数(idata)
对于直接包含在机器指令中的数据(执行前在cpu 的指令缓冲器中),
在汇编语言中称为:立即数(idata ) ,在汇编指令中直接给出。例如:
mov ax,1
2)、寄存器
指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名。例如:
mov ax,bx
3)、段地址(SA)和偏移地址(EA)
指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出EA,SA在某个段寄存器中。
存放段地址的寄存器可以是默认的,也可以显性的给出。(使用段前缀)
bx,si,di,默认的段地址在ds中,bp默认的段地址在ss中。
二、指令要处理的数据有多长?
8086cpu的指令,可以处理两种尺寸的数据,byte和word。
所以在机器指令中要指明,指令进行的是字操作还是字节操作。
有以下的方式:
(1)通过寄存器名指明要处理的数据的尺寸。
(2)在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以为word或byte。
下面的指令中,寄存器指明了指令进行的是字操作:
mov ax,1
mov bx,ds:[0]
mov ds,ax
mov ds:[0],ax
inc ax
add ax,1000
下面的指令中,寄存器指明了指令进行的是字节操作:
mov al,1
mov al,bl
mov al,ds:[0]
mov ds:[0],al
inc al
add al,100
下面的指令中,用word ptr指明了指令访问的内存单元是一个字单元:
mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],2
下面的指令中,用byte ptr指明了指令访问的内存单元是一个字节单元:
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2
在没有寄存器参与的内存单元访问指令中,用word ptr或byte ptr显性地指明所要访问的内存单元的长度是很必要的。
否则,cpu无法得知所要访问的单元是字单元,还是字节单元。
有些指令默认了访问的是字单元还是字节单元
比如:push [1000H]就不用指明访问的是字单元还是字节单元,因为push指令只进行字操作。
三、 寻址方式的综合应用
可以用bx定位整个结构体,用idata定位结构体中的某一个数据项,用 si 定位数组项中的每个元素 。
书本例题:
;关于dec公司的记录 ASSUME CS:CODESG,DS:DATASG DATASG SEGMENT DB 'DECKen Olsen',137,40,'PDP' DATASG ENDS CODESG SEGMENT START: MOV AX,DATASG MOV DS,AX MOV BX,0CH MOV BYTE PTR [BX],38 ADD BYTE PTR [BX+1],70 ADD BX,2 MOV BYTE PTR [BX],'V' MOV BYTE PTR [BX+1],'A' MOV BYTE PTR [BX+2],'X' MOV AX,4C00H INT 21H CODESG ENDS END START
四、 DIV指令
div是除法指令(division),使用div作除法的时候:
除数:8位或16位,在寄存器或内存单元中
被除数:(默认)放在AX 或 DX和AX中(高16位在DX中,低16位在AX中)
除数 被除数
8位 16位(AX)
16位 32位(DX+AX)
结果: 8位 16位
商 AL AX
余数 AH DX
div指令示例
div byte ptr ds:[0]
含义为:
(al) = (ax) / ((ds)*16+0)的商;
(ah) = (ax) / ((ds)*16+0)的余数
div word ptr es:[0]
含义为:
(ax) = [(dx)*10000H+(ax)]/((ds)*16+0)的商;
(dx) = [(dx)*10000H+(ax)]/((ds)*16+0)的余数
编程: 利用除法指令计算100001/100。
代码:
;DIV指令,利用那个除法计算100001/100 100001的十六进制 186A1 ASSUME CS:CODESG CODESG SEGMENT START: MOV DX,1 MOV AX,86A1H MOV BX,100 DIV BX MOV AX,4C00H INT 21H CODESG ENDS END START
分析:被除数 100001 大于65535,不能用ax寄存器存放,要用dx和ax两个寄存器联合存放100001,也就是说要进行16位的除法。
除数100小于255,可以在一个 8位寄存器中存放,
但是,因为被除数是32位的,除数应为16位,所以要用一个16位寄存器来存放除数100。
因为要分别为dx和ax赋100001的高16位值和低16位值,所以应先将100001表示为十六进制形式:186A1H。
编程实现2: 利用除法指令计算1001/100。
代码:
; 编程计算1001/100 ASSUME CS:CODESG CODESG SEGMENT START: MOV AX,1001 MOV BL,100 DIV BL MOV AX,4C00H INT 21H CODESG ENDS END START
分析:被除数1001可用 ax寄存器存放,除数100可用 8位寄存器存放,也就是说,要进行8位的除法。程序如下:
五、伪指令 DD
前面我们用db和dw定义字节型数据和字型数据。
dd是用来定义dword (double word双字)型数据的。
问题8.1
用div 计算data段中第一个数据除以第二个数据后的结果,商存放在第3个数据的存储单元中。
; 问题 8.1 ASSUME CS:CODESG,DS:DATASG DATASG SEGMENT DD 100001 DW 100 DW 0 DATASG ENDS CODESG SEGMENT START: MOV AX,AX MOV BX,0 MOV DX,[BX+2] MOV AX,[BX] DIV WORD PTR [BX+4] MOV AX,4C00H INT 21H CODESG ENDS END START
六、dup指令
dup是一个操作符,在汇编语言中同db、dw、dd 等一样,也是由编译器识别处理的符号。
它是和db、dw、dd 等数据定义伪指令配合使用的,用来进行数据的重复。
db 3 dup (0) 定义了3个字节,它们的值都是0, 相当于 db 0,0
db 3 dup (0,1,2) 定义了9个字节,它们是 0、1、2、0、1、2、0、1、2, 相当于 db 0,2,2
可见,dup的使用格式如下:
db 重复的次数 dup (重复的字节型数据)
dw 重复的次数 dup (重复的字型数据)
dd 重复的次数 dup (重复的双字数据)
七、上机->实验七(重点)
; 实验七 data segment db '1975','1976','1977','1978','1979','1980','1981','1982','1983' db '1984','1985','1986','1987','1988','1989','1990','1991','1992' db '1993','1994','1995' ;以上是表示21年的21个字符串 dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000 ;以上是表示21年公司总收的21个dword型数据 21*4 = 84 dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226 dw 11542,14430,45257,17800 ;以上是表示21年公司雇员人数的21个word型数据 ; 168起始地址 data ends table segment db 21 dup('year summ ne ?? ') table ends ASSUME CS: CODESG CODESG SEGMENT START: MOV AX,DATA MOV DS,AX MOV AX,TABLE MOV ES,AX MOV BX,0 MOV CX,21 MOV SI,0 MOV DI,0 S: MOV AX,0[SI] MOV ES:[BX],0[SI+2] MOV ES:[BX+2],AX ; 年份的复制 MOV AX,84[SI] MOV ES:[BX+5],84[SI+2] MOV ES:[BX+7],AX ; 总收入的复制 MOV AX,168[DI] MOV ES:[BX+10],AX ; 人数的复制 MOV AX,84[SI] MOV DX,84[SI+2] DIV WORD PTR 168[DI] ;因为人数的类型是word 所以每次只能加2 MOV ES:[BX+13],AX ; 人均收入 ; 循环变量的设置 ADD BX,16 ADD SI,4 ADD DI,2 LOOP S MOV AX,4C00H INT 21H CODESG ENDS END START
个人总结: 本章的实验题是核心,也是过去所有章节的一个综合应用,必须熟练掌握。