




已阅读5页,还剩141页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章 程序设计的一些编程技巧,9.1 表处理程序设计 9.2 代码转换程序 9.3 算术运算 9.4 数值分析,9.1 表处理程序设计,9.1.1 表的处理 表的用途十分广泛:求平方值、立方值需要使用平方值表和立方值表,程序实现分支要用到跳转表等;大量供各种运算、查询等用的机器执行的任务,一组组的结果,一系列有关联的数据等等,都需要使用表来存储或处理。对表的处理通常包括查询、插入、删除、排序和搜索等几个方面。将一新的内容插入到表中某个单元以前或以后,这里就需要先将插入位置以后的数据后移,然后再将数据插入,同时表元素的个数也应做相应的修改(增加);需要将表中某些内容删除时,为保持表的完整,应将被删内容以后的数据前移,并修改表元素个数;需要按某种规律(升序或降序)将表中内容重新排列组织;需要在特定的表中查找给定某元素,看是否存在此元素,存在何处,并做些其他处理等等。,9.1.2 表处理程序设计 在表处理程序设计中,经常要用到XLAT指令,XLAT指令称为查表转换指令,在3.2.1节数据传送指令中已作过介绍。它是用表中的一个字节(称为换码字节)来置换累加器AL中的内容,用此指令以前,要求先把表的起始地址送入BX寄存器,且在AL中置好所需的初值,AL中的初值为所需的换码字节在表中的相对位置(用字节数给出),又可称为查找所需换码字节的索引值,然后XLAT指令将BX内容加上AL内容所形成的地址单元中的内容(即所需的换码字节)放到AL中去。,1XLAT指令应用举例 例9-1 利用XLAT指令把十六进制数转换成ASCII码。 编程的基本思想是通过查表来实现进制的转换。 进制转换的方法有很多,这里介绍使用表的方法来实现转换。XLAT指令是对表进行处理的,因此,要使用XLAT指令,就必须建立符合要求的表。程序中HEXTAB是十六进制数表,而TAB_DA是ASCII码表。,TABLE SEGMENT TAB_DA DB 30H,31H,32H,33H DB 34H,35H,36H,37H DB 38H,39H,41H,42H DB 42H,43H,44H,45H,46H COUNT EQU $-TAB_DA HEXTAB DB 0,1,2,3,4,5 DB 6,7,8,9,0AH DB 0BH,0CH,0DH,0EH,0FH,ASIBUF DB 16 DUP(?) TABLE ENDS STACK SEGMENT PARA STACK STACK STAPN DB 100 DUP(?) STACK ENDS COSEG SEGMENT ASSUME CSCOSEG,DSDATA ASSUME ESTABLE,SSSTACK STR PROC FAR,START PUSH DS MOV AX,0 PUSH AX MOV AX, TABLE MOV ES,AX MOV DS,AX MOV BX,OFFSET TAB_DA MOV SI,OFFSET HEXTAB MOV DI,OFFSET ASIBUF MOV CX,COUNT,NEST: LODSB XLAT TAB_DA STOSB LOOP NEST RET STR ENDP COSEG ENDS END START,例9-2 数据或程序的加密和解密。 为了使数据能够保密,可以建立一个密码表,利用XLAT指令将数据加密。程序接收键入的一个数字,如果是09之间的一个数,加密后存入MIMA单元。密码表可选择为 原数字: 0,1,2,3,4,5,6,7,8,9 密码数字: 7,5,9,1,3,6,8,0,2,4,加密程序描述如下: DATA SEGMENT MITAB DB 7591368024 ;加密密码表 CONT EQU $-MITAB JMITAB DB 7384915062 ;解密密码表 MIMA DB ? DATA ENDS CODE SEGMENT ASSUME CSCODE,DSDATA STAR PROC FAR PUSH DS MOV AX,0,PUSH AX MOV AX,DATA MOV DS,AX MOV AH,1 INT 21H AND AL,0FH LEA BX,MITAB XLAT MITAB MOV MIMA,AL RET START ENDP CODE ENDS END STAR,为了使程序能连续地接收键盘输入数字,可将程序设计成循环程序,遇到某一规定的标志字符时结束输入,并将输入的数字加密后存到内存缓冲区。在数据通信中也可以用类似的方法,先将要发送的代码加密以后再发送。为将加密后的数据或程序复原,可编写解密程序。下述程序段可将MIMA单元中的数据解密,结果送屏幕显示。,MOV AL,MIMA AND AL,0FH LEA BX,JMITAB MOV AH,0 ADD BX,AX MOV DL,BX MOV AH,6 INT 21H HLT,还可以利用XLAT指令将键盘输入的密码数字解密,下述程序接收键盘输入一个密码数字,解密后的数字在AL中。 MOV AH,1 INT 21H AND 0FH LEA BX,JHITAB XLAT JMITAB HLT,2查找、排序应用举例 例9-3 有一个100个字节数据组成的数据表,其元素已按从小到大的顺序排列好了。现要求在此表上进行查找元素,具体的规则是:若表内有此元素,则结束;否则,按顺序将此元素插入表中的适当位置上并修改表长。 这是一个线性有序表的查找与插入的问题。我们已经知道,线性表的插入操作是指在线性表的第i-1个数据元素和第i个数据元素之间插入一个新的数据元素,就是要使长度为n的线性表 (ai,ai-1,ai,an) 变成长度为n+1的线性表 (a1,ai-1,b,ai,an),数据元素ai-1和ai之间的逻辑关系发生了变化。由100个字节数据组成的数据表若采用顺序存储结构,则逻辑上相邻的数据元素在物理位置上也是相邻的,因此,除非in+1,否则必须移动元素才能反映这个逻辑关系的变化。 线性表的删除操作是指在第i (1in)个元素之前删除一个元素,这时需将第i至第n(共n-i+1)个元素向后移动一个位置,即要使长度为n的线性表 (a1,ai-1,ai,ai+1,an) 变成长度为n-1的线性表 (a1,ai-1,ai+1,.,an),数据元素ai-1、ai和ai+l之间的逻辑关系发生了变化,为了在存储结构上反映这个变化,同样需要移动元素。因此,本题设计的基本思想是:当发现表中无此元素时,应将其插在表中的适当位置上,即插在大于(或等于)前一个元素且小于(或等于)后一个元素的位置上,并将其后的元素依次后移。程序描述如下:,DATA SEGMENT LTH DB 100 ;数据表长 TAB DB 5FH, ;有序数据表 TEH DB X ;设给定的元素是X DATA ENDS STACK SEGMENT PARA STACK STACK DB 100 DUP(?) STACK ENDS CODE SEGMENT ASSUME CSCODE,DSDATA ASSUME ES:DATA STR PROC FAR,SYART:PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV BX,OFFSET TAB ;BX指向数据表 MOV AL,TEM ;取出给定的元素 MOV CX,LTH ;取出表长的值,LOP: CMP AL,BX ;在表中进行查找 JE SOP ;若找到,则转SOP JL INST ;若给定元素小于表内元素,转INST插入 INC BX DEC CX JNZ LOP MOV BX,AL ;给定元素始终大于(或等于)表内元素 JMP JUST ;应将给定元素插在表的末尾 INST:MOV AH,BX ;取出表中元素暂存于AH MOV BX,AL ;插入给定的元素 INC BX,LOPI:MOV AL,BX MOV BX,AH ;表中插入位置后的元素后移 INC BX MOV AH,BX MOV BX,AL INC BX DEC CX DEC CX JNZ LOPI JUST: INC LTH ;修改表长 SOP: RET STR ENDP CODE ENDS END START,例9-4 顺序查找法。 如果要查找的内容与表之间没有什么规律可循,则只好从表首开始逐个比较、查找,即采用顺序查找(Sequential Search)的方法。顺序查找的查找过程为:从表中第n个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较相等,则查找成功,找到所查记录;反之,若直至第一个记录,其关键字和给定值都不等,则表明表中没有所查记录,查找不成功。,设一组数据存放在内存以SSEG为首址的连续单元中,用DB定义,可描述如下: SSEG DB 40H,79H,24H,30H,33H,1AH,0EH 根据上述顺序查找的基本思想,可写出如下的程序: SEQ_DATA SEGMENT SSEG DB 40H,79H,24H,30H,33H,1AH,0EH,6DH,87H,9BH ;定义数据表 XX DB ? ;设定待查找的元素 SEQ_DATA ENDS,STACK SEGMENT PARA STACK STACK DB 100 DUP(?) STACK ENDS SEQ_CODE SEGMENT ASSUME CS: SEQ_CODE,DS: SEQ_DATA ASSUME ES: SEQ_DATA,SS:STACK SEARCH PROC FAR START: PUSH DS MOV AX,0 PUSH AX MOV AX,SEQ_DATA MOV DS,AX,MOV ES,AX MOV AL,XX ;设任给的数据元素在XX单元中 MOV CX,10H ;取表长 MOV BX,OFFSET SSEG ;BX指向表的首地址 MOV AH,0 LOP1:CMP AL,BX JE AT INC AH INC BX L00P L0P1 MOV AL,0FFH ;若查找不到,0FFH送AL RET,AT: MOV AL,AH ;查找到时,AH中为对应 的十六进制数 RET SEARCH ENDP SEQ_CODE ENDS END START,例9-5 折半查找法。 折半查找(Binary Search)的查找过程是:对一个有序表,先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。 如已知如下11个数据元素的有序表: (02,11,17,20,35,51,60,77,83,89,97) 现要查找关键字为20和85的数据元素。 假设指针L和H分别指示待查元素所在范围的下界和上界,指针M指示区间的中间位置,即M = (L+H)/2。在此例中,L和H的初值分别为1和11,即1,11为待查范围。,查找给定值K20的过程: 02 11 17 20 35 51 60 77 83 89 97 L M H 先令查找范围中间位置的数据元素的关键字BUFM与给定值K相比较,因为BUFM K,说明待查元素若存在,必在区间L,M-1的范围内,则令指针H指向第M-1个元素,重新求得M= (1+5)/23 02 11 17 20 35 51 60 77 83 89 97 L M H,仍以BUFM和K相比,因为BUFM K,说明待查元素若存在,必在M+1,H范围内,则令指针L指向第M+1个元素,求得M的新值为4,比较BUFM和K,因为相等,则查找成功,所查元素在表中序号等于指针M的值。 02 11 17 20 35 51 60 77 83 89 97 L H M,查找K=85的过程: 02 11 17 20 35 51 60 77 83 89 97 L M H BUFM K,令L M + 1: 02 11 17 20 35 51 60 77 83 89 97 L M H BUFM K,令L M + 1: 02 11 17 20 35 51 60 77 83 89 97 L H M,BUFM K,令H M -1: 02 11 17 20 35 51 60 77 83 89 97 H L 此时,因为下界L大于上界H,则说明表中没有关键字等于K的元素,查找不成功。从上述例子可见,折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等于给定值或者查找区间的大小小于零时(表明查找不成功)为止。,NAME BINARY_SEARCHIHG BUF_DAT SEGHENT BUFFER DB $ AGHI NRSTUVWXYZ COUNT EQU $-BUFFER ;存放查找次数或未找到标记 PTRN DW ? ;关键字A CHAR EQU A BUF_DAT ENDS STACK SEGHENT PARA STACK STACK STACK ENDS,CODE SEGMENT ASSUME CSCODE,DSBUF_DAT ASSUME ESBUF_DAT STR PROC FAR START: PUSH DS MOV AX,0 MOV AX,BUF_DAT MOV DS,AX MOV ES,AX MOV SI,OFFSET BUFFER ;区间上限送SI,MOV CX,COUNT MOV DX,1 ;记录查找次数 MOV AX,SI ADD AX,CX ;最后一个数的地址加1 MOV DI,AX ;下限送DI MOV AL,CHAR CONTL:MOV BX,SI ADD BX,DI SHR BX,1 ;BX中为M CMP AX,BX ;关键字与BUFM比较 JZ FOUND ;找到转FOUND,PUSHF ;保护标志 CMP BX,SI ;M上限否 JZ NOFID ;相等未找到 POPF JL LESS ;关键字 BUFM MOV SI,BX ;M作上限 JMP NEXT LESS: MOV DI,BX ;M作下限 NEXT:INC DX ;查找次数加1 JMP CONTL,NOFID: MOV DX,0FFFFH ;未找到标记设为0FFFFH FOUND:MOV AX,DX MOV PTRN,AX ;结果送PRTN单元 RET STA ENDP CODE ENDS END START,9.2 代码转换程序,对于许多应用实例来说,代码转换是必需的。例如,当从键盘上输入一个数字,机器中接收到的是它的ASCII码值。为使这个数字能参与运算,必须先将其转换成二进制数或十进制数。如果内存中的二进制数要在屏幕上以十进制形式显示出来,则首先要将其转换成十进制数,再转换成ASCII码才能够输出。常用的进制有:二进制、十进制、十六进制、BCD码、ASCII码等。本节主要讨论ASCII码转换成BCD码、BCD码转换成ASCII码、二进制数转换为ASCII码和ASCII码转换成二进制数等问题。,例9-6 ASCII码转换成BCD码。 在微机中,从键盘上输入的十进制数的每一位数码(即09中任一个),都是以它的ASCII码表示的;要向CRT输出的十进制数的每一位代码也是用ASCII码表示的。而在机器中,一个十进制数,或者把它转换为相应的二进制数存放,或者是以BCD码形式存放。若在内存的输入缓冲区中,已有若干个用ASCII码表示的十进制数据,则每一个存储单元只存放一位十进制数码。要求把它转换为相应的BCD码,且把两个相邻单元的十进制数码的BCD码合并在一个存储单元中,且地址高的放在前4位,这样就可以节省一半的存储单元。十进制数的ASCII码转换为BCD码的方法是把高4位变为0;若是以组合方式存储转换后的BCD码,则要把两位并在一个存储单元中,可将地址高的字节左移4位,再与地址低的字节组合在一起。,程序描述如下: DATA SEGMENT ASCBUF DB 31H,32H,33H,34H,35H,36H,37H,38H,39H,30H COUNT EQU $-ASCBUF BCDBUF DB 5 DUP(?) DATA ENDS STACK SEGMENT PARA STACK STACK STAPN DB 100 DUP(?) STACK ENDS COSED SEGMENT ASSUME CSCOSEG,DSDATA,ESDATA,SSSTACK,STR PROC FAR GO: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV SI,OFFSET SACBUF MOV DI,OFFSET BCDBUF MOV CX,COUNT ROR CX,1 ;右移最低位进CF,若数据个数为偶数则转移,JNC NEXT ROL CX,1 LODSB ;取一数进AL,指针SI+1 AND AL,0FH ;转换成BCD码 STOSB ;送入内存单元,DI+1 DEC CX ;数据个数减1 ROR CX,1 ;数据个数除2 NEXT:LODSB AND,AL,0FH MOV BL,AL ;转换一个ASCII码到BCD码 LODSB PUSH CX ;保护CL的内容,MOV CL,4 SAL AL,CL ;再转换一个ASCII码到BCD码存入高四位 POP CX ADD AL,BL ;两个BCD码合为一个字节 STOSB LOOP NEXT ;CX-1,CX0转NEXT,重复,直到CX0结束 RET STR ENDP COSE ENDS END GO,需要说明的是,输入缓冲区中,已存放的ASCII码的个数可能是偶数,也可能是奇数。若是奇数,则先把地址最低的一个ASCII码转换为BCD码(高四位为0),然后把剩下的偶数个ASCII码按统一的方法处理。程序中的指令ROR CX,1的作用是用于判断已存放的ASCII码的个数是否奇偶。具体方法是将CX的最低位右移进CF,若CF=0,则为偶数,否则为奇数。,例9-7 BCD码转换成ASCII码。 BCD码的十进制数在CRT上显示时,首先应将其转换为ASCII码。下述程序自动在CRT上输出098之间的十进制数。由于是显示098之间的数,因此,不论是哪一个数,其数字均在09之间,而不会出现AF的情况。BCD码转换成ASCII码采用的是BCD码+30H的方法。,STACK SEGMENT PARA STACK STACK STP DB 100 DUP(?) STACK ENDS DATA SEGMENT ;定义缓冲区 BUFR DB 3 DUP(?) DATA ENDS COSEG SEGMENT ASSUME CSCOSEG,DSDATA,ESDATA,START: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV BL,-1 PUSH BX ;保护BL,GOON: MOV SI,OFFSET BUF MOV DL,0DH ;输出回车 MOV AH,2 INT 21H MOV DL,0AH ;输出换行 MOV AH,2 INT 21H POP BX MOV AL,BL ;产生098之间的数据 INC AL DAA,CMP AL,99H JNC OVER ;若数字大于98,结束程序 MOV BL,AL PUSH BX ;保护BL,以便下个循环在此数上加1 MOV DL,AL ;暂存入DL,以备转成ASCII码用 MOV CL,4 SHR AL,CL ;右移四次 OR AL,30H ;高位十进数转成ASCII码 MOV SI,AL ;存到缓冲区 INC SI MOV AL,DL ;恢复原十进制数,AND AL,0FH OR AL,30H ;低位十进制数转成ASCII码 MOV SI,AL INC SI MOV AL,$ MOV SI,AL ;$存入缓冲区,9号调用要求的 MOV DX,OFFSET BUFR MOV AH,9 INT 21H ;缓冲区数据输出显示 MOV CX,0FFFFH,AGN: DEC CX ;延时后再显下一个数 JNE AGN JMP GOON OVER: COSEG ENDS END START,通过本例,有两点是值得我们学习的: (1) 数据自动产生的方法。即使用一段循环程序,在进入循环程序之前,先将-1送BL寄存器,然后执行下述的循环: MOV AL,BL INC AL DAA CMP AL,99H JC NEXT MOV AL,0,(2) 延时程序的编制。该程序使用延时的目的是使数据在屏幕上有足够的显示时间。延时程序段描述如下: MOV CX,0FFFFH AGN:DEC CX JNE AGN,例9-8 二进制数转换为ASCII码。 设CX寄存器中有一个带符号的二进制数,现将其以十进制形式输出到CRT。CX中的数是十六进制数,所表示的数的范围在-32 768+32 767之间。程序应先检查CX中数的符号位,以决定输出“”或“”。若是负数,应先求补,得到原码,然后再将其转换为十进制数。转换方法是先将其减10000,看其中包含几个10000,那么它的十进制数的万位数字就是包含的一万的个数,不够减时再用余下的数减1000,统计其中包含1000的个数,得到千位上的数字,依此类推,求出百位、十位的数字,剩下的就是个位数字了。转换后的十进制数在缓冲区的存放格式如图9-1所示。有了十进制数字后,要在CRT显示出来,还要将其转换成ASCII码才能输出。程序描述时采用子程序的形式:,图9-1 内存缓冲区存放格式,DATA SEGMENT COUNT DW ? BUF DB 9 DUP(?) DATA ENDS STACK SEGMENT PARA STACK STACK DB 100 DUP(?) STACK ENDS COSGE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK,START PROC FAR PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV CX,COUNT ;CX中为待输出的二进制数 CALL PTDN RET,START ENDP ;输出16位二进制带符号数的子程序 ;入口参数:CX中为待输出的数据 ;所用子程序:CHANG PTDN PROC PUSH AX PUSH BX PUSH DX PUSH SI ;保护现场 MOV BX,OFFSET BUF ;BX指向缓冲区,MOV AL,0DH MOV BX,AL ;回车符存入缓冲区以便显示时回车 INC BX MOV AL,0AH MOV BX,AL ;换行符存入缓冲区 INC BX MOV AL,CH OR AL,AL ;查看符号位 JNS PLUS ;正数转PLUS,NEG CX ;负数求补 MOV AL,- MOV BX,AL ;缓冲区存入负号 JMP GOON PLUS: MOV AL,+ MOV BX,AL ;缓冲区存入正号 GOON: INC BX MOV SI,10000 CALL CHANG ;求万位数,并转换为ASCII码存入缓冲区 MOV SI,1000 CALL CHANG ;求千位数 MOV SI,100,CALL CHANG ;求百位数 MOV SI,10 CALL CHANG ;求十位数 MOV AL,30H ADD AL,CL MOV BX,AL ;求个位数 INC BX MOV AL,$ ;$送入缓冲区尾,9号功能调用所要求 MOV BX,AL MOV DX,OFFSET BUF,MOV AH,9 ;9号功能调用输出显示 INT 21H POP SI POP DX POP BX ;恢复现场 POP AX RET PTDN ENDP,;本子程序统计CX寄存器所包含权(在SI中)的个数,并把这个个数转换成ASCII码 ;入口参数:SI为权码,CX中为给定的数,BX指向ASCII码结果缓冲区 ;出口参数:结果缓冲区的当前单元存放转换完的ASCII码,并且调整BX指向缓冲区的下 ; 一个单元 CHANG PROC MOV DL,0 ;DL存放权的个数,初值0 AGAIN: SUB CX,SI JC DOWN ;不够减转DOWN INC DL ;够减DL加1 JMP AGAIN ;再减权,DOWN: ADD CX,SI ;恢复CX MOV AL,30H ADD AL,DL MOV BX,AL ;转ASCII码并存入缓冲区 INC BX ;指针调整 RET CHANG ENDP CODE ENDS END START,例9-9 ASCII码转换成二进制数。要求编制接收从键盘上输入的十进制整数的程序(设数的范围为-32 768到+32 767)。 接收键盘输入可用10号功能调用,10号功能调用要求预先定义一个缓冲区,缓冲区的第一单元存放缓冲区长度,第二单元留作存放实际输入的字符个数,第三单元开始存放数据,这可在数据段加以定义。,从键盘接收的十进制数字的ASCII码字符,应将它转换为二进制数,转换的方法是:先将其转换成十进制数字,再用累加和乘10加X的方法变成二进制数。如,将369转换成二进制数,可先将累加和赋为0,再计算(010+3)10+6)10+9),结果就是二进制数,然后再由符号位决定是否需要求补。 程序的编制采用子程序的结构,能实现从键盘上接收两个带符号十进制数,将它们转换成二进制数,并且求出这两个数的乘积,然后再将乘积的高、低位字节分别转换成十进制数在屏幕上显示出来的功能。,DATA SEGMENT BUF DB 10 DB ? DB 10 DUP(?) ;定义输入缓冲区 SIGN DB ? ;存放输入数据的正负标志 BLK DB 9 DUP(?) ;输出缓冲区 DATA ENDS STACK SEGMENT PARA STACK STACK DB 100 DUP(?) STACK ENDS COSGE SEGMENT ASSUME CS:COSEG,DS:DATA,ES:DATA,SS:STACK,START PROC FAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX CALL GETD ;接收键入的第一个带符号十进制数并转换成二进制数 PUSH CX MOV DL,0DH,MOV AH,2 INT 21H MOV DL,0AH MOV AH,2 INT 21H ;输出回车换行 CALL GETD ;接收第二个十进制数,并转换成二进制数 POP AX IMUL CX ;两个数相乘结果在DX,AX CALL PUTDN ;准备将二进制积转换为十进制,先处理符号,MOV CX,DX CALL GOON ;积的高位字转换为十进制数输出 MOV CX,AX CALL GOON ;积的低位字转换为十进制数输出 RET START ENDP ;输入十进制数,并将其转换成二进制数 ;结果在CX中 ;所用寄存器:AX,BX,DX,SI GETD PROC,PUSH AX PUSH BX PUSH CX PUSH SI MOV DL,: MOV AH,2 INT 21H ;输出提示符“:” MOV DX,OFFSET BUF MOV AH,10 MOV 21H ;接收键盘输入 MOV SI,OFFSET BUF+1 MOV BL,SI ;实际输入的字符个数送BL DEC BL,;记录符号位 INC SI MOV AL,0 MOV SIGN,AL ;符号单元送0 MOV AL,SI ;取实际符号位 CMP AL,+ JZ NEXT1 ;若实际符号位为负 MOV AL,1 ;则符号单元送1 MOV SIGN,AL ;ASCII码转换成BCD码 NEXT1: PUSH BX ;保存字符个数,NEXT2:INC SI MOV AL,SI AND AL,0FH MOV SI,AL ;ASCII码转换成BCD码送回 DEC BL ;字符个数减1 JNZ NEXT2 ;若不等于0,继续转换 POP BX ;BCD码转换成二进制码 MOV DI,OFFSET BUF+3 MOV CX,0 ;累加和置初值,AG1: PUSH BX ADD CX,CX MOV BX,CX ADD CX,CX ADD CX,CX ADD CX,BX ;累加和*10 MOV BL,DI MOV BH,0 INC DI ADD CX,BX ;累加和乘10后加下一个BCD数字 POP BX,DEC BL JNE AG1 ;未转换完时继续 MOV AL,SIGN OR AL,AL ;查看符号位 JZ DONE NEG CX ;若为负数求补 DONE: POP SI POP DX POP BX POP AX RET,GETD ENDP ;本过程根据DX和AX中的一个带符号数的正负号在缓冲区建立符号标志,并输出 ;所用寄存器:BX、CX ;入口参数:DX和AX中为一带符号二进制数 ;出口参数:DX和AX中的内容为原数的原码 PUTDN PROC PUSH CX PUSH BX MOV BX,OFFSET BLK MOV CL,0DH,MOV BX,CL INC BX MOV CL,0AH MOV BX,CL ;回车、换行送输出缓冲区 INC BX OR DH,DH JNS PLUS NOT AX NOT DX ADD AX,1 JNC AD1 INC DX ;负数求补,AD1: MOV CL,- MOV BX,CL JMP RON PLUS: MOV CL,+ MOV BX,CL RON: INC BX MOV CL,$ MOV BX,CL PUSH AX MOV DX,OFFSET BLK MOV AH,9 INT 21H ;输出回车、换行、数的负号 POP AX POP BX POP CX RET,PUTDN ENDP ;下述过程将CX中无符号数转换成十进制数并输出 ;所用寄存器:BX,AX,DX,SI ;入口参数:CX中为二进制无符号数 ;出口参数:缓冲区BLK中为转换成的十进制数字的ASCII代码 ;所用子程序:CHANG GOON PROC PUSH AX PUSH BX,PUSH DX PUSH SI MOV BX,OFFSET BLK MOV SI,10000 CALL CHANG MOV SI,1000 CALL CHANG MOV SI,100 CALL CHANG MOV SI,10 CALL CHANG MOV AL,30H,ADD AL,CL MOV BX,AL MOV AL,$ INC BX MOV BX,AL MOV DX,OFFSET BLK MOV AH,9 INT 21H POP SI POP DX POP BX POP AX RET,说明: (1) 主程序中调用了3个子程序: GETD:接收从键盘键入的带符号的十进制数并转换成二进制数; PUTDN:将二进制数相乘的积转换成十进制数并处理符号位; GOON:积转换成十进制数并输出。 (2) 在子程序GOON中调用了CHANG,它完成的功能是:二进制数转换成ASCII码并输出。,(3) 程序中累加和乘以10的运算没有使用乘法指令,而是用下述3条指令来实现的: ADD CX,CX ADD CX,CX ADD CX,BX,9.3 算 术 运 算,例9-10 内存中以FIRST和SECOND开始的单元中分别存放两个16位组合的十进制(BCD码)数,每个数占4个存储单元,存放时低字节存放在地址处。编程求这两个组合的十进制数的和,并存到THIRD开始的单元。,此例在例3-42中已讲述过,当时使用的是一般的数据传送指令MOV。描述如下: MOV BX,OFFSET FIRST MOV SI,OFFSET SECOND MOV DI,OFFSET THIRD MOV CX,8 CLC,AGN: MOV AL,BX ADC AL,SI INC BX ADC BYTE PTRBX,0 DAA MOV DI,AL INC SI INC DI DEC CX JNZ AGN HLT,在讲述了串操作指令后,使用串操作指令LODS重写实现这一功能的程序,描述如下: DATA SEGMENT FIRST DB 11H,52H, SECOND DB 66H,69H, THIRD DB 11 DUP(?) DATA ENDS STACK SEGMENT PARA STACK STACK DB 100 DUP(?) STACK ENDS CODE SEGMENT,ASSUME CSCODE,DSDATA,ESDATA STR PROC FAR START PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV SI,OFFSET FIRST MOV BX,OFFSET SECOND MOV DI, OFFSET THIRD MOV CX, LENGTH THIRD DEC CX CLD CLC,ADIT: LODS FIRST ADC AL,BX INC BX ADC BYTE PTRBX,0 DAA STOS THIRD LOOP ADIT ADC AH,0 MOV AL,AH STOSB RET STR ENDP CODE ENDS END START,若要把内存单元FIRST和SECOND这两个字节的内容相乘,乘积放在THIRD和FOURTH单元中,可以用以下程序段: MOV AL,FIRST MUL SEC0ND MOV THIRD,AX,例9-11 编制一个实现两个字(16位)相乘的程序。 MY_DATA SEGMENT M1 DW 00FFH ;被乘数 M2 DW 00FFH ;乘数 P1 DW ? ;存积 P2 DW ? MY_DATA ENDS STACK SEGMENT PARA STACK STACK STAPN DB 100 DUP(?) STACK ENDS COSEG SEGMENT,ASSUHE CSCOSEG,DSMY_DATA,ESMY_DATA STR PROC FAR MULT: PUSH DS MOV AX,0 PUSH AX MOV AX,MY_DATA MOV DS,AX MOV ES,AX MOV AX,M1 MUL M2,MOV P1,AX ;存结果 MOV P2,DX RET STR ENDP C0SEG ENDS END STR,例9-12 BCD码相乘。 80X86中有两个未组合的十进制数相乘后的调整指令。可实现一位未组合十进制数X与一个十进制串相乘。把串中的未组合的十进制数从低位开始送入AL,与X相乘,对乘积进行调整,然后把乘积的低位与上一次的高位(即进位部分)相加。这样一位位乘下去,最后可得乘积。能实现上述过程的程序如下:,DATA SEGMENT A DB 3,7,5,4,9 ;十进制数94573 COUNT EQU $-A B DB 6 C DB COUNT+1 DUP(?) DATA ENDS STACK SEGMENT PARA STACK STACK STAPN DB 100 DUP(?) STACK ENDS COSEG SEGMENT ASSUME CSCOSEG,DSDATA,ESDATA STR PROC FAR,GO: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV ES,AX MOV DS,AX CLD MOV SI,OFFSET A MOV DI,OFFSET C MOV CX,COUNT MOV BYTE PTRDI,0,CYCLE: LODSB AND AL,0FH MUL B AAM ADD AL,DI AAA STOSB MOV DI,AH LOOP CYCLE RET STR ENDP COSEG ENDS END GO,例9-13 两个两位的BCD码相乘。 80x86中的乘法指令可实现8位或16位二进制数相乘或两个未组合的十进制数相乘(要经过AAM调整)。但若是两个两位的用BCD码表示的十进制数,就不能直接相乘(即没有相应的调整指令),但可以用累加的方法,编一个程序来实现两位组合的十进制数乘法。算法是对被乘数累加乘数所规定的次数,被乘数的每次累加和都要经过DAA调整;乘数每次减1以后也要经过调整。程序如下所示:,NAME MULTIPLY BCD DATA SEGMENT FIRST DB 25H SECOND DB 25H THIRD DB 2 DUP(?) DATA ENDS STACK SEGMENT PARA STACK STACK STAPN DB 100 DUP(?) STACK ENDS COSEG SEGMENT ASSUME CSCOSEG,DSDATA,ESDATA,STR PROC FAR START: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX MOV BL,FIRST ;取乘数 MOV CL,SECDND ;取被乘数 MOV DX,0 ;DX存积 MOV AL,BL,AGAIN: OR AL,AL JZ DONE ;若乘数为0,则转DONE MOV AL,DL ADD AL,CL DAA ;结果在AL MOV DL,AL MOV AL,DH ADC AL,0 ;处理进位(加进位) DAA MOV DH,AL MOV AL,BL SUB AL,1 ;乘数减1 DAS MOV BL,AL JMP AGAIN,DONE: MOV BX,OFFSET THIRD MOV BX,DX RET STR ENDP COSEG ENDS END START,例9-14 若内存的数据段中,有个缓冲区BUFFER,前两个字节是一个16位带符号的被除数,第三、四字节是一个16位带符号的除数。接着两个字节放商,再下来的两个字节放余数。能实现该除法运算的程序段为 LEA BX,BUFFER MOV AX,BX CWD IDIV 2BX ;带符号数除法 MOV 4BX,AX MOV 6BX,DX,9.4 数 值 分 析,9.4.1 二分法求解方程 例9-15 用二分法求方程x3-x-1在区间0,10内的一个实根,精度为1。 基本思想:设函数f(x)在区间a,b上连续,且f(a).f(b)0,根据连续函数的性质可知方程f(x)=0在a,b内一定有实根,并称a,b为方程f(x)=0的有根区间。为明确起见,不妨假定它在a,b内有惟一的实根x*。,说明根
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 脚手架施工方案的论文
- 618活动福利方案策划
- 湿接缝及横隔梁施工方案
- 洗澡游泳活动方案策划
- 文明比赛活动方案策划
- 烤鱼门店活动策划方案
- 轻质混凝土施工方案
- 数据库培训科普知识课件
- 2025年高中语文开学第一课指导课件
- 质感漆施工方案
- 健康管理中心运营与服务流程规范
- GB/T 2820.7-2024往复式内燃机驱动的交流发电机组第7部分:用于技术条件和设计的技术说明
- 2023年法律职业资格《主观题》真题及答案
- HG∕T 4281-2011 塑料焊接工艺规程
- 职业技术学院《汽车维修接待》课程思政标准
- 自考08257《舆论学》备考试题库(含答案)
- HG20202-2014 脱脂工程施工及验收规范
- 定制家具工厂外包合同模板
- 中学舆情应急处置方案
- TD/T 1046-2016 土地整治权属调整规范(正式版)
- 20G520-1-2钢吊车梁(6m-9m)2020年合订本
评论
0/150
提交评论