微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

汇编语言学习—— 第八章 数据处理的两个基本问题

计算机是进行数据处理、运算的机器,那么有两个基本的问题就包含在其中:

(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

 

个人总结: 本章的实验题是核心,也是过去所有章节的一个综合应用,必须熟练掌握。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐