资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,汇编语言,课件,第,8,章 数据处理的两个基本问题,8.1 bx,、,si,、,di,、,bp,8.2,机器指令处理的数据所在位置,8.3,汇编语言中数据位置的表达,8.4,寻址方式,8.5,指令要处理的数据有多长?,8.6,寻址方式的综合应用,8.7 div,指令,8.8,伪指令,dd,8.9 dup,引言,本章对前面的所有内容是具有总结性的。我们知道,计算机是进行数据处理、运算的机器,那么有两个基本的问题就包含在其中:(,1,)处理的数据在,什么地方?,(,2,)要处理的数据有,多长,?这两个问题,在机器指令中必须给以明确或隐含的说明,否则计算机就无法工作。,引言,为了描述上的简洁,在以后的课程中,我们将使用两个描述性的符号,reg,来表示一个寄存器,用,sreg,表示一个段寄存器。,reg,的集合包括:,ax,、,bx,、,cx,、,dx,、,ah,、,al,、,bh,、,bl,、,ch,、,cl,、,dh,、,dl,、,sp,、,bp,、,si,、,di,;,sreg,的集合包括:,ds,、,ss,、,cs,、,es,。,8.1 bx,、,si,、,di,、,bp,前三个寄存器我们己经用过了,现在我们进行一下总结。,(,1,)在,8086CPU,中,只有这,4,个寄存器(,bx,、,bp,、,si,、,di,)可以用在,“,”,中来进行内存单元的寻址。,正确的指令,错误的指令,8.1 bx,、,si,、,di,、,bp,正确的指令,mov ax,bx,mov ax,bx+si,mov ax,bx+di,mov ax,bp,mov ax,bp+si,mov ax,bp+di,8.1 bx,、,si,、,di,、,bp,错误的指令,mov ax,cx,mov ax,ax,mov ax,dx,mov ax,ds,8.1 bx,、,si,、,di,、,bp,正确的指令,mov ax,bx,mov ax,si,mov ax,di,mov ax,bp,mov ax,bx+si,mov ax,bx+di,mov ax,bp+si,mov ax,bp+di,mov ax,bx+si+idata,mov ax,bx+di+idata,mov ax,bp+si+idata,mov ax,bp+di+idata,8.1 bx,、,si,、,di,、,bp,(,3,)只要在,中使用寄存器,bp,,而指令中没有显性的给出段地址,段地址就默认在,ss,中。比如:,mov ax,bp,含义,:,(ax)=(ss)*16+(bp),mov ax,bp+idata,含义,:,(ax)=(ss)*16+(bp)+idata),mov ax,bp+si,含义,:,(ax)=(ss)*16+(bp)+(si),mov ax,bp+si+idata,含义,:,(ax)=(ss)*16+(bp)+(si)+idata),8.2,机器指令处理的数据所在位置,指令在执行前,所要处理的数据可以在三个地方:,CPU,内部、内存、端口,(端口我们将在后面的课程中进行讨论),指令举例,8.2,机器指令处理的数据所在位置,指令举例:,8.3,汇编语言中数据位置的表达,在汇编语言中如何表达数据的位置?,汇编语言中用三个概念来表达数据的位置。,1,、立即数(,idata,),2,、寄存器,3,、段地址(,SA,)和偏移地址(,EA,),8.3,汇编语言中数据位置的表达,1,、立即数(,idata,),对于直接包含在机器指令中的数据(执行前在,CPU,的指令缓冲器中),在汇编语言中称为:立即数(,idata),,在汇编指令中直接给出。例如:,mov ax,1,add bx,2000h,or bx,00010000b,mov al,a,8.3,汇编语言中数据位置的表达,1,、立即数(,idata,),mov ax,1,对应机器码:,B80100,执行结果:,(ax)=1,8.3,汇编语言中数据位置的表达,2,、寄存器,mov ax,bx,对应机器码:,89D8,执行结果,:,(ax)=(,bx,),8.3,汇编语言中数据位置的表达,3,、段地址(,SA,)和偏移地址(,EA,),指令要处理的数据在内存中,在汇编指令中可用,X,的格式给出,EA,,,SA,在某个段寄存器中。,存放段地址的寄存器可以是默认的。,示例,存放段地址的寄存器也可以显性的给出。,示例,8.3,汇编语言中数据位置的表达,存放段地址的寄存器是默认的,示例(续):,mov ax,bp,mov ax,bp+8,mov ax,bp+si,mov ax,bp+si+8,段地址默认在,ss,中,8.3,汇编语言中数据位置的表达,显性的给出存放段地址的寄存器,示例,mov ax,ds:bp,含义,:,(ax)=(ds)*16+(bp),mov ax,es:bx,含义,:,(ax)=(es)*16+(bx),mov ax,ss:bx+si,含义,:,(ax)=(ss)*16+(bx)+(si),mov ax,cs:bx+si+8,含义,:,(ax)=(cs)*16+(bx)+(si)+8),8.4,寻址方式,当数据存放在内存中的时候,我们可以用多种方式来给定这个内存单元的偏移地址,这种定位内存单元的方法一般被称为,寻址方式,。,8086CPU,有多种寻址方式,我们在前面的课程中都已经用到了,这里我们进行一下总结。,8.4,寻址方式,8.4,寻址方式,寻址方式,演示,1,、,直接寻址,演示,2,、,寄存器间接寻址,演示,3,、,寄存器相对寻址,演示,4,、,基址变址寻址,演示,5,、,相对基址变址寻址,8.5,指令要处理的数据有多长?,8086CPU,的指令,可以处理两种尺寸的数据,,byte,和,word,。所以在机器指令中要指明,指令进行的是字操作还是字节操作。,8.5,指令要处理的数据有多长?,对于这个问题,汇编语言中用以下方法处理。,(,1,),通过寄存器名指明要处理的数据的尺寸,。,(,2,),在没有寄存器名存在的情况下,用操作符,X ptr,指明内存单元的长度,,X,在汇编指令中可以为,word,或,byte,。,(,3,),其他方法,8.5,指令要处理的数据有多长?,下面的指令中,寄存器指明了指令进行的是字操作:,mov ax,1,mov bx,ds:0,mov ds,ax,mov ds:0,ax,inc ax,add ax,1000,8.5,指令要处理的数据有多长?,下面的指令中,寄存器指明了指令进行的是字节操作:,mov al,1,mov al,bl,mov al,ds:0,mov ds:0,al,inc al,add al,100,8.5,指令要处理的数据有多长?,下面的指令中,用,word ptr,指明了指令访问的内存单元是一个字单元:,mov,word ptr,ds:0,1,inc,word ptr,bx,inc,word ptr,ds:0,add,word ptr,bx,2,8.5,指令要处理的数据有多长?,下面的指令中,用,byte ptr,指明了指令访问的内存单元是一个字节单元:,mov,byte ptr,ds:0,1,inc,byte ptr,bx,inc,byte ptr,ds:0,add,byte ptr,bx,2,8.5,指令要处理的数据有多长?,在没有寄存器参与的内存单元访问指令中,用,word ptr,或,byte ptr,显性地指明所要访问的内存单元的长度是很必要的。,否则,,CPU,无法得知所要访问的单元是字单元,还是字节单元。,8.5,指令要处理的数据有多长?,假设我们用,Debug,查看内存的结果如下:,2000:1000,FF,FF FF FF FF FF,那么指令:,mov ax,2000H,mov ds,ax,mov byte ptr 1000H,1,将使内存中的内容变为:,2000:1000,01,FF FF FF FF FF,8.5,指令要处理的数据有多长?,而指令:,mov ax,2000H,mov ds,ax,mov,word ptr,1000H,1,将使内存中的内容变为:,2000:1000,01 00,FF FF FF FF,为什么?,8.5,指令要处理的数据有多长?,这是因为,mov byte ptr 1000H,1,访问的是地址为,ds:1000H,的字节单元,修改的是,ds:1000H,单元的内容;,而,mov word ptr 1000H,1,访问的是地址为,ds:1000H,的字单元,修改的是,ds:1000H,和,ds:1001H,两个单元的内容。,8.5,指令要处理的数据有多长?,有些指令默认了访问的是字单元还是字节单元,,比如:,push 1000H,就不用指明访问的是字单元还是字节单元,,因为,push,指令只进行字操作。,8.6,寻址方式的综合应用,下面我们通过一个问题来进一步讨论各种寻址方式的作用。,实际应用,8.6,寻址方式的综合应用,关于,DEC,公司的一条记录(,1982,年):,公司名称:,DEC,总裁姓名:,Ken Olsen,排 名:,137,收 入:,40,著名产品:,PDP,1988,年,DEC,公司的信息有了变化:,、,Ken Olsen,在富翁榜上的排名已升至,38,位;,、,DEC,的收入增加了,70,亿美元;,、该公司的著名产品已变为,VAX,系列计算机。,任务:编程修改内存中的过时数据。,8.6,寻址方式的综合应用,首先,我们应该分析一下要修改的数据:,(,1,)(,DEC,公司记录)的(排名字段),(,2,)(,DEC,公司记录)的(收入字段),(,3,)(,DEC,公司记录)的(产品字段)的(第一个字符)、(第二个字符)、(第三个字符),8.6,寻址方式,的综合应用,从要修改的内容,我们就可以,逐步地确定修改的方法:,(,1,)我们要访问的数据是,DEC,公司的记录,所以,首先要确定,DEC,公司记录的位置:,R=seg:60,确定了公司记录的位置后,我们下面就进一步确定要访问的内容在记录中的位置。,(,2,)确定排名字段在记录中的位置:,0CH,。,(,3,)修改,R+0CH,处的数据。,(,4,)确定收入字段在记录中的位置:,0EH,。,(,5,)修改,R+0EH,处的数据。,8.6,寻址方式,的综合应用,从要修改的内容,我们就可以,逐步地确定修改的方法:(续),(,6,)确定产品字段在记录中的位置:,10H,。要修改的产品字段是一个,字符串,(或一个数组),需要访问字符串中的每一个字符。所以我们要进一步确定每一个字符在字符串中的位置。,(,7,)确定第一个字符在产品字段中的位置:,P=0,。,(,8,)修改,R+10H+P,处的数:,P=P+1,。,(,9,)修改,R+10H+P,处的数据:,P=P+1,。,(,10,)修改,R+10H+P,处的数据。,8.6,寻址方式,的综合应用,根据上面的分析,程序如下:,mov ax,seg,mov ds,ax,mov bx,60h,mov,word ptr,bx+0ch,38,add,word ptr,bx+0eh,70,mov si,0,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,;,确定记录地址:,ds:bx,;,排名字段改为,38,;,收入字段增加,70,;,用,si,来定位产品字符串中的字符,8.6,寻址方式的综合应用,如果读者熟悉,C,语言的话,我们可以用,C,语言来描述这个程序,大致应该是这样的:,C,语言描述,我们再按照,C,语言的风格,用汇编语言写一下这个程序,注意和,C,语言相关语句的比对:,汇编语言描述,8.6,寻址方式的综合应用,8.6,寻址方式的综合应用,按照,C,语言的风格,用汇编语言写一下,8.6,寻址方式的综合应用,我们可以看到,,8086CPU,提供的如,bx+si+idata,的寻址方式为结构化数据的处理提供了方便。,使得我们可以在编程的时候,从结构化的角度去看待所要处理的数据。,从上面我们可以看到,一个结构化的数据包含了多个数据项,而数据项的类型又不相同,有的是字型数据,有的是字节型数据,有的是数组(字符串)。,8.6,寻址方式的综合应用,一般来说,我们可以用,bx+idata+si,的方式来访问结构体中的数据。,用,bx,定位整个结构体,用,idata,定位结构体中的某一个数据项,用,si,定位数组项中的每个元素。,为此,汇编语言提供了更为贴切的书写方式。,如:,bx.idata,、,bx.idatasi,。,8.6,寻址方式的综合应用,在,C,语言程序中我们看到,如:,dec.cpi,,,dec,是一个变量名,指明了结构体变量的地址,,cp,是一个名称,指明了数据项,cp,的地址,而,i,用来定位,cp,中的每一个字符。,汇编语言中的做法是:,bx.10hsi,看一下,是不是很相似?,8.7 div,指令,div,是除法指令,使用,div,作除法的时候:,除数:,8,位,或,16,位,,在寄存器或内存单元中,被除数,:(默认,)放在,AX,或,DX,和,AX,中,结果:,运算,8,位,16,位,商,AL,AX,余数,AH,DX,8.7 div,指令,div,指令格式:,div reg,div,内存单元,现在我们可以用多种方法来表示一个内存单元了。,div,指令,示例,8.7 div,指令,div,指令示例,div,byte ptr,ds:0,含义为:,(al)=(ax)/(ds)*16+0),的商;,(ah)=(ax)/(ds)*16+0),的余数,8.7 div,指令,div,指令示例(续),div,word ptr,es:0,含义为:,(ax)=(dx)*10000H+(ax)/(ds)*16+0),的商;,(dx)=(dx)*10000H+(ax)/(ds)*16+0),的余数,8.7 div,指令,div,指令示例(续),div byte ptr bx+si+8,含义为:,(al)=(ax)/(ds)*16+(bx)+(si)+8),的商;,(ah)=(ax)/(ds)*16+(bx)+(si)+8),的余数,8.7 div,指令,div,指令示例(续),div word ptr bx+si+8,含义为:,(ax)=(dx)*10000H+(ax)/(ds)*16+(bx)+(si)+8),的商;,(dx)=(dx)*10000H+(ax)/(ds)*16+(bx)+(si)+8),的余数,8.7 div,指令,编程:,利用除法指令计算,1001/100,。,我们首先分析一下被除数,1001,可用,ax,寄存器存放,除数,100,可用,8,位寄存器存放,也就是说,要进行,8,位的除法。程序如下:,mov ax,1001,mov bl,100,div bl,程序执行后,,(al)=0AH,(即,10,),,(ah)=1,(余数为,1,)。,读者可自行在,Debug,中实践。,8.7 div,指令,编程:,利用除法指令计算,100001/100,。,我们首先分析一下,被除数,100001,大于,65535,,不能用,ax,寄存器存放,所以我们要用,dx,和,ax,两个寄存器联合存放,100001,,也就是说要进行,16,位的除法。,除数,100,小于,255,,可以在一个,8,位寄存器中存放,但是,因为被除数是,32,位的,除数应为,16,位,所以要用一个,16,位寄存器来存放除数,100,。,8.7 div,指令,编程:,利用除法指令计算,100001/100,。(分析续),因为要分别为,dx,和,ax,赋,100001,的高,16,位值和低,16,位值,所以应先将,100001,表示为十六进制形式:,1,86A1,H,。,程序如下,8.7 div,指令,编程:,利用除法指令计算,100001/100,。(程序),mov dx,1,mov ax,86A1H,;(dx)*10000H+(ax)=100001,mov bx,100,div bx,程序执行后,,(ax)=03E8H,(即,1000,),,(dx)=1,(余数为,1,)。,读者可自行在,Debug,中实践。,8.7 div,指令,编程:,利用除法指令计算,100001/100,。(程序),思考:,必须要先把,10,进制数转成,16,进制吗?不转换不行吗?,定义变量,可行吗?,100001,如何定义?,dw,,,db,都不能满足条件,8.8,伪指令,dd,前面我们用,db,和,dw,定义字节型数据和字型数据。,dd,是用来定义,dword,(,double word,双字)型数据的。,示例,8.8,伪指令,dd,示例:,data segment,db 1,dw 1,dd 1,data ends,在,data,段中定义了三个数据:,第一个数据为,01H,,在,data:0,处,占,1,个字节;,第二个数据为,0001H,,在,data:1,处,占,1,个字;,第三个数据为,00000001H,,在,data:3,处,占,2,个字;,Data:0,1,2,3,4,5,6,1,1,0,1,0,0,0,8.8,伪指令,dd,问题,8.1,用,div,计算,data,段中第一个数据除以第二个数据后的结果,商存放在第,3,个数据的存储单元中。,data segment,dd 100001,dw 100,dw 0,data ends,思考后看,分析,。,8.8,伪指令,dd,问题,8.1,分析,data segment,dd 100001,dw 100,dw 0,data ends,data,段中的第一个数据是被除数,为,dword,(双字)型,,32,位,所以在做除法之前,用,dx,和,ax,存储。应将,data:0,字单元中的低,16,位存储在,ax,中,,data:2,字单元中的高,16,位存储在,dx,中。,程序代码,Data:,0,A1,1,86,2,01,3,00,4,64,5,00,6,00,7,00,AX,DX,8.8,伪指令,dd,问题,8.1,程序代码,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,字单元中,Data:,0,A1,1,86,2,01,3,00,4,64,5,00,6,00,7,00,AX,DX,除数,商,8.9 dup,dup,是一个操作符,在汇编语言中同,db,、,dw,、,dd,等一样,也是由编译器识别处理的符号。,它是和,db,、,dw,、,dd,等数据定义伪指令配合使用的,用来进行数据的重复。,示例,8.9 dup,dup,示例,db 3 dup(0),定义了,3,个字节,它们的值都是,0,,,相当于,db 0,0,0,8.9 dup,dup,示例,db 3 dup(0,1,2),定义了,9,个字节,它们是,0,、,1,、,2,、,0,、,1,、,2,、,0,、,1,、,2,,,相当于,db 0,1,2,0,1,2,0,1,2,8.9 dup,dup,示例,db 3 dup(,abc,ABC,),定义了,18,个字节,它们是,abcABCabcABCabcABC,,,相当于,db,abcABCabcABCabcABC,8.9 dup,可见,,dup,的使用格式如下:,db,重复的次数,dup,(重复的字节型数据),dw,重复的次数,dup,(重复的字型数据),dd,重复的次数,dup,(重复的双字数据),8.9 dup,dup,是一个十分有用的操作符,比如我们要定义一个容量为,200,个字节的栈段,如果不用,dup,,则必须用这样的格式:,stack segment,dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,stack ends,8.9 dup,当然,读者可以用,dd,,使程序变得简短一些,但是如果要求定义一个容量为,1000,字节或,10000,字节的呢?,如果没有,dup,,定义部分的程序就变得太长了;,有了,dup,就可以轻松解决。如下:,stack segment,db 200 dup(0),stack ends,小结,
展开阅读全文