码制转换十二进制数ASCII码之间的互相转换BCD.ppt
1,1.码制转换 十、二进制数、ASCII码之间的互相转换。BCD数2进制数 算法:Dn-1*10n-1+D0*100=(Dn-1*10+Dn-2)*10+)*10+D0=(0*10+Dn-1)*10+Dn-2)*10+)*10+D0 即:新的中间结果=中间结果*10+本位数字(中间结果初值为0),4.5 常见程序设计举例,2,程序1:将65535的非压缩BCD数转换成2进制数。程序如下。;数据段定义 mydata SEGMENT decnum DB 5,3,0,1,9;BCD数 53019 binnum DW?mydata ENDS,3,prog SEGMENT ASSUME CS:prog,DS:mydatabegin:MOV AX,mydata MOV DS,AX MOV SI,OFFSET decnum MOV CX,5;5位BCD数 MOV BX,10 XOR AX,AX;中间结果初始值为0Next:MUL BX;中间结果*10+本位数字 ADD AL,SI ADC AH,0 INC SI;指向下位BCD数 LOOP next MOV binnum,AX;保存结果 MOV AH,4CH INT 21Hprog ENDS END begin,4,程序2:把255的非压缩BCD数转换成2进制数 decnum DB 1,5,9;BCD数159 binnum DB?MOV AX,decnum XCHG AH,AL;百位在AH,十位在AL AAD;百位数*10+十位数 MOV AH,AL;中间结果送AH MOV AL,decnum+2 AAD;中间结果*10+个位数 MOV binnum,AL,5,例:从键盘输入两个整数,并求其和。因键入为整数,故要进行如下转换:ASCIIBCD二进制数 ASCIIBCD码很简单,高4位清零即可得到非压缩的BCD码。BCD二进制数在本例中采用用以下方法:(0+千位数)*10+百位数)*10)+十位数)*10+个位数,ASCII码二进制数(用于输入),第一次中间结果,第二次中间结果,第三次中间结果,最终结果,6,开始,两个数分别转换成二进制数,键入两个数,相加,结束,返回DOS,如有溢出则提示,开始,取第一个ASCII码,是负号吗?,数字符个数1,指针1,指针定位,字符个数1,=0?,取数字,与中间结果相加,再乘以10,指向下一个数字字符,加个位数,是负数则求补,存结果,结束,N,Y,Y,N,转换子程序,7,程序如下:DATASEGMENTSTR1DB 10,?,10 DUP(?);第1个数的输入缓冲区STR2DB 10,?,10 DUP(?);第2个数的输入缓冲区NUMDW?,?;存转换后的二进制数SUMDW 0;存和OVERDB Overflow!,13,10,$DATAENDS;CODESEGMENTASSUME CS:CODE,DS:DATAMAINPROCFAR,8,START:MOVAX,DATAMOVDS,AXMOVAH,0AHLEADX,STR1INT21H;输入第一个数字串(设为26)MOVAH,0AHLEADX,STR2INT21H;输入第二个数字串(设为33)LEABX,STR1;串1的首地址送BXLEADI,NUM;存二进制首地址送DI CALLCHANGE;将串1 ASCII码二进制 LEABX,STR2;串2的首地址送BX,9,LEADI,NUM+2;指向CALLCHANGE;将串2 ASCII码二进制MOVAX,NUM;(AX)=NUM=001AH ADDAX,NUM+2;两数相加,(AX)=003BHMOVSUM,AX;存和JNONEXT;无溢出,转NEXTLEADX,OVERMOVAH,9INT21H;显示Overflow!NEXT:MOVAH,4CHINT21H;返回DOS MAINENDP,10,CHANGEPROCMOVCL,BX+1;实际字符数送CLMOVAL,BX+2;第一个字符送ALMOVCH,AL;暂存在CHCMPAL,-;第一个字符是负号吗?JNZNEXT1;不是,转NEXT1DECCL;字符数减1INCBXNEXT1:ADDBX,2;指向第一个数字字符MOVAX,0;清零AX,存二进制数LP1:DECCLJZNEXT2;若(CL)=0,转NEXT2MOVDL,BX;取字符ANDDL,0FH;转换成BCD码 ADD AL,DL;加到中间结果上 ADC AH,0,11,MOV DX,10 MUL DX;*10 INC BX;指向下一个字符 JMP SHORT LP1NEXT2:MOV DL,BX;取个位数 AND DL,0FH;个位ASCII未组合BCD ADD AX,DX;加个位数,(AX)=001AH CMP CH,-;是-?JNZ NEXT3;该数非负,转NEXT3 NEG AX;若为负,求补NEXT3:MOV DI,AX;存二进制结果 RETCHANGE ENDP;CODE ENDS END START,12,02,0A,32,36,0D,02,0A,33,33,0D,00,1A,21,00,3B,00,STR1,STR2,NUM,SUM,10个,10个,O,OVER,?,?,04,0A,31,32,34,STR1,若键入 1234,33,0D,1,2,3,4,设键入第1个数为26,第2个数为33,则在内存各变量分配如下:,13,本例题重点掌握:如何从键盘输入一个字符串ASCII未组合BCD二进制有符号数的运算,对负数和溢出如何处理思考题:若键入第一个数26,第二个数为-4,填写各变量结果。,14,方法1 计算二进制数中所包含的1000的个数、100的个数、10的个数和1的个数。方法2 除10取余。下面举例介绍第一种方法。流程图如下:,二进制数BCD,15,Y,N,二进制数AX令(DL)0,(AX)-1000,0?,(DL)+1,(AX)+1000(AX),DL存至缓冲区,令(DL)0,Y,N,(AX)-10,0?,(DL)+1,(AX)+10(AX),存DL,存AL,返回DOS,求100的个数,结构同上,A,16,汇编程序如下:DATASEGMENTBNUMDB270FHDNUMDB4 DUP(?);存放BCD码的缓冲区DATAENDSCODESEGMENTASSUME CS:CODE,DS:DATABINBCDPROCFARBEGIN:MOVAX,DATAMOVDS,AXMOVAX,BNUM;取二进制数LEABX,DNUM;BCD码缓冲区首地址送BX,17,;计算百位的个数 MOV DL,0;千位的个数计数器AGAIN1:SUB AX,1000;(AX)-1000 JC NEXT1;若0,则退出循环 INC DL;(DL)+1 JMP AGAIN1NEXT1:ADD AX,1000;(AX)(AX)+1000 MOV BX,DL;存千位的个数;计算百位的个数 MOV DL,0;百位的个数计数器AGAIN2:SUB AX,100;(AX)-100 JC NEXT2 INC DL JMP AGAIN2NEXT2:ADD AX,100 MOV BX+1,DL;存百位的个数,18,MOV DL,0;十位的个数计数器AGAIN3:SUB AX,10;(AX)-10 JC NEXT3 INC DL JMP AGAIN3NEXT3:ADD AX,10 MOV BX+2,DL;存十位的个数 MOV BX+3,AL;存个位的个数 MOV AH,4CH INT 21HBINBCD ENDP;CODE ENDS END BEGIN,19,BCDASCII 前面举例介绍过,略。二进制串转换为ASCII码 一个二进制位串若要送显示或打印,需把串中每一位(0或1)化为ASCII码。思路:先将目标串全部预置为30H,再把每个二进制位逐位左移至CF,然后判CF=0?若是,取下一位;若不是,将31H送此单元。流程图如下:,20,初始化,用0填满串,取要转换的数,左移1位,存入1,结束,CF=1?,转换完?,调整指针,N,N,21,汇编程序如下:DATASEGMENTNUMDW6F78HSTRINGDB16 DUP(?)DATAENDS;CODESEGMENTASSUME CS:CODE,DS:DATABINCAPROCFARBEGIN:MOVAX,DATAMOVDS,AXMOVES,AXCLDLEADI,STRINGMOVCX,16;串的长度,22,MOVAL,30HREPSTOSB;串中全部填充为0MOVCX,16LEADI,STRINGMOVAL,1MOVBX,NUM;(BX)=6F78HAGAIN:RCLBX,1;含进位位循环左移JNCNEXT;若为0,转 MOV DI,AL;若为1,对应位送入1NEXT:INCDILOOPAGAIN,23,MOVAH,4CHINT21HBINCAENDPCODEENDSENDBEGIN,24,2.子程序的参数传递 编写子程序时,很重要的一个工作是如何把参数传给子程序,这个过程叫参数传送。传送方法有:把参数放在CPU内部寄存器中把参数放在变量中把参数放在地址表中利用堆栈传送参数,25,下面举例介绍第4种方法,它通常在主程序中把参数或参数地址保存在堆栈中,而在子程序中将参数从堆栈取出来。例:把一个用十六进制表示的字ASCII码,然 后送到屏幕上显示。汇编程序如下:DATASEGMENTNUMDW25AFH;要显示的数STRINGDB4 DUP(?),13,10,$DATAENDS,26,STACKSEGMENTDB 100 DUP(?)TOP EQU$STACKENDS;CODESEGMENTASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACKBEGIN:MOVAX,DATAMOVDS,AXMOVES,AXMOVAX,STACKMOVSS,AX MOV SP,TOP LEABX,STRING;取变量偏址PUSHBX;将偏址压栈PUSHNUM;将变量压栈,00,02,0064H,0062H,(SP),25,AF,0060H,堆栈,27,CALLBINHEX;(SP)=005EH CS:0113 LEADX,STRING;(DX)=0002HMOVAH,9INT21HMOVAH,4CHINT21H;*BINHEXPROCPUSHBP;(SP)=005CHMOVBP,SP;(BP)=005CHPUSHAX;(SP)=005AHPUSHDI;(SP)=0058HPUSHCX;(SP)=0056HPUSHDX;(SP)=0054H,00,02,0064H,0062H,25,AF,0060H,005EH,01,13,005CH,(SP),返回地址,(IP),原(BP),28,00,02,0064H,0062H,25,AF,0060H,005EH,01,13,xx,xx,005CH,(BP),PUSHF;(SP)=0052H MOV AX,BP+4;(AX)=25AFH MOV DI,BP+6;(DI)=0002H ADD DI,LENGTH STRING-4;(DI)=0005H MOV DX,AX;(DX)=25AFH MOV CX,4 STD;从后往前存AGAIN:AND AX,0FH;第一次(AX)=000FH CALL HEXD;转换为ASCII码 STOSB PUSH CX MOV CL,4 SHR DX,CL;逻辑右移4位 MOV AX,DX;第1次(AX)=025AH POP CX LOOP AGAIN;(CX)-1=0?不等,转,+4,29,POPFPOPDX POPCXPOPDIPOPAXPOPBPRET4 BINHEX ENDP;*HEXD PROC CMP AL,0AH JL LP ADD AL,7LP:ADD AL,30H RETHEXD ENDPCODE ENDS END BEGIN,0064H,0062H,0060H,005EH,005CH,00,02,25,AF,01,13,xx,xx,(SP),30,从本例可知,通过堆栈传递的两个参数分别为:变量NUM的内容25AFH和变量STRING的偏移地址。这两个参数在调用子程序之前压入堆栈,当CALL指令返回时,其(SP)=0060H,不是初值0064H。故采用带参数返回指令RET 4。本例重点掌握:进一步了解堆栈的使用 学会RET n的应用 子程序嵌套,31,其他例子,宏的使用例子逻辑尺的例子查表法求立方值作业:p194 4.6(1),4.10,4.17,4.18(用逻辑尺),