250 likes | 341 Views
1. 常用进制数据输入的程序实现 ① 16 进制数输入 → 2 进制数存储 算法: D n-1 *16 n-1 +……+D0*16 0 ② 10 进制数输入 → 2 进制数存储 算法: D n-1 *10 n-1 +……+D0*10 0 ③ 2 进制数输入 → 2 进制数存储 算法: D n-1 *2 n-1 +……+D0*2 0. 5.5 常见程序设计举例. 例 1 :从键盘输入一个四位的 16 进制 数,以 2 进制 形式保存到 BX 中 INP_HXB PROC NEAR XOR BX, BX MOV CX, 4
E N D
1.常用进制数据输入的程序实现 ① 16进制数输入 → 2进制数存储 算法:Dn-1*16n-1+……+D0*160 ②10进制数输入 → 2进制数存储 算法:Dn-1*10n-1+……+D0*100 ③2进制数输入 → 2进制数存储 算法:Dn-1*2n-1+……+D0*20 5.5 常见程序设计举例
例1:从键盘输入一个四位的16进制数,以2进制形式保存到BX中例1:从键盘输入一个四位的16进制数,以2进制形式保存到BX中 INP_HXB PROC NEAR XOR BX, BX MOV CX, 4 NEXT_INP:MOV AH, 01H INT 21H CMP AL, 61H ;'a'-'z' JGE UPPER CMP AL, 41H ;'A'-'Z' JGE LOWER SUB AL, 30H ;'0'-'9' JMP ADJUST UPPER: SUB AL, 61H ADD AL, 10
LOWER: SUB AL, 41H ADD AL, 10 ADJUST: CBW ;BX=BX*16+AX XCHG AX, BX MOV DX, 16 MUL DX XCHG AX, BX ADD BX, AX LOOP NEXT_INP RET INP_HXB ENDP ;替换代码 PUSH CX MOV CL, 4 SHL BX, CL ADD BX, AX POP CX 16进制输入,若输入为:1234,则(BX)=1234H; 10进制输入,若输入为:1234,则(BX)=04D2H。
2.常用进制数据输出的程序实现 ① 2进制数存储 → 16进制数显示 方法1:显示时将2进制数每4位分成一组,按组求对应的ASCII码送显示即可。 方法2:除16取余。将2进制数除以16,得到第一个商和余数,此第一个余数就是所求的16进制数的个位;再用第一个商除以16,得到第二个商和余数,此第二个余数就是所求16进制数的十位;重复这一过程直至商为0,此时的余数就是所求16进制数的最高位。所得余数依次入栈,显示时依次出栈并转换成ASCII码即可。 方法3:将2进制数除以所求16进制数最高位的权值(如,4位16进制数最高位权值为4096),得到一个商和余数,此第一个商就是所求的16进制数的最高位;再用第一个余数除以次高位的权值,得到第二个商和余数,此第二个商就是所求16进制数的次高位;重复这一过程直至权值为1,此时的商就是所求16进制数的个位,将所得商依次转换为ASCII码送显示即可。
例2:将BX中的16位2进制数转换成4位16进制数送出显示例2:将BX中的16位2进制数转换成4位16进制数送出显示 方法1: DISP_BXH PROC NEAR MOV CL,4 MOV CH,4NEXT_DISP: ROL BX, CL ;从高到低依次析取MOV AL,BL AND AL,0FH ADD AL,30H CMP AL,3AH JL OUTP ADD AL,07H ;是A~F,要多加7
OUTP: MOV DL,AL MOV AH,02H INT 21H DEC CH CMP CH,0 JA NEXT MOV DL,’H’ ;显示字母“H” MOV AH,2 INT 21H RETDISP_BXH ENDP
方法2: DISP_BXH PROC NEARMOV SI, 16 XOR CX, CX MOV AX, BX NEXT:MOV DX,0 DIV SI ;商在AX中,余数在DX中 PUSH DX;余数压栈 INC CX CMP AX,0;商为0则完成转换 JNZ NEXT OUTP:POP DX;出栈 ADD DL,30H MOV AH,2 INT 21H LOOP OUTP RET DISP_BXH ENDP
方法3: DISP_BXH PROC NEAR MOV CX, 4096 CALL HEX_DIV MOV CX, 256 CALL HEX_DIV MOV CX, 16 CALL HEX_DIV MOV CX, 1 CALL HEX_DIV RETDISP_BXH ENDP HEX_DIV PROC NEAR MOV AX, BX MOV DX, 0 DIV CX MOV BX, DX MOV DL, AL ADD DL, 30H MOV AH, 02H INT 21H RET HEX_DIV ENDP 16进制显示,设(BX)=1234H,则显示结果为:1234H; 10进制显示,若(BX)=1234H,则显示结果为:4460H。
②2进制数存储 → 10进制数显示 方法1:除10取余。 方法2:除权值取商。 ③2进制数存储 → 2进制数显示 方法1:按位显示。 方法2:除2取余。 方法3:除权值取商。 ④对有符号数显示的扩展应用CMP BX,0JGE ZSMOV DL,’-’MOV AH,2INT 21HZS:CALL DISP_BXD
开始 开始 输入10进制数 输入10进制数 转换成2进制数 以BCD码形式保存 进行算术运算 进行算术运算 结果转换成10进制数显示 BCD码调整 结束 逐个显示BCD码 结束 3.10进制数算术运算的码制转换
例3: 用乘法指令实现32位二进制数的相乘 DATA SEGMENT DAT1 DW 1234H, 2345H DAT2 DW 5678H, 6789H RESULT DW 4 DUP(?) DATA ENDS STACK SEGMENT PARA STACK DW 20 DUP(0) STACK ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA, SS:STACK START: MOV AX, DATA MOV DS, AX MOV AX, DAT1+2 MUL DAT2+2 MOV RESULT+6, AX MOV RESULT+4, DX
MOV AX, DAT1 MUL DAT2+2 ADD RESULT+4, AX ADC RESULT+2, DX ADC RESULT, 0 MUL DAT2 ADD RESULT+4, AX ADC RESULT+2, DX ADC RESULT, 0 MOV AX, DAT1 MUL DAT2 ADD RESULT+2, AX ADC RESUTL, DX MOV AH, 4CH INT 21H CODE ENDS END START DAT1 34 12 45 23 DAT2 78 56 89 67 RESULT RESULT+2 RESULT+4 RESULT+6
例4: 计算N!(N≥0) 这是一个递归调用的计算方法,N!=N*(N-1)*(N-2)…*1 N!=1, N=0 N!=N*(N-1)!, N>0 阶乘子程序说明,名称:FACT,入口参数:AL=N,出口参数:DX=N! DATA SEGMENT D1 DB 4 ;N=4 D2 DW 2 DUP(?) ;存放运算结果 DATA ENDS STACK SEGMENT PARA STACK 'STACK' SA DW 100 DUP(?) STACK_TOP DB 0 STACK ENDS
CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK MAIN PROC FAR START:MOV AX,STACK MOV SS,AX LEA SP,STACK_TOP MOV AX,DATA MOV DS,AX ;初始化DS,SS,SP MOV DX,0 MOV AH,0 MOV BX,OFFSET D1 MOV AL,[BX] ;AL=N CALL FACT MOV [BX+1],DX ;D2=N! RET MAIN ENDP
FACT PROC ;N!子程序 CMP AL,0 JNZ CHN MOV DL,1 ;N=0则N!=1 RET CHN: PUSH AX ;N入栈 DEC AL ;N-1 CALL FACT ;递归调用FACT子程序 POP AX ;N出栈 MUL DL ;N逐层返回相乘,结果在AX中 MOV DX,AX ;送结果到DX RET FACT ENDP CODE ENDS END START
AL=3, DL=3! AL=1, DL=1! AL=0, DL=0! AL=2, DL=2! FACT PROC CMP AL,0 JNZ CHN MOV DL,1 RET CHN: PUSH AX DEC AL CALL FACT POP AX MUL DL MOV DX,AX RET FACT ENDP FACT PROC CMP AL,0 JNZ CHN MOV DL,1 RET CHN: PUSH AX DEC AL CALL FACT POP AX MUL DL MOV DX,AX RET FACT ENDP FACT PROC CMP AL,0 JNZ CHN MOV DL,1 RET CHN: PUSH AX DEC AL CALL FACT POP AX MUL DL MOV DX,AX RET FACT ENDP FACT PROC CMP AL,0 JNZ CHN MOV DL,1 RET CHN: PUSH AX DEC AL CALL FACT POP AX MUL DL MOV DX,AX RET FACT ENDP
例5:从键盘输入两个整数,并求其和。 因键入为整数,故要进行如下转换: ASCII→BCD→二进制数 ASCII→BCD码很简单,高4位清零即可得到非压缩的BCD码。 BCD→二进制数在本例中采用用以下方法: ((((0+千位数)*10+百位数)*10)+十位数)*10+个位数 第一次中间结果 第二次中间结果 第三次中间结果 最终结果
转换子程序 开始 开始 取第一个ASCII码 N 是负号吗? 键入两个数 Y 数字符个数-1,指针+1 两个数分别转换 成二进制数 指针定位 字符个数-1 相加 Y = 0? 加个位数 如有溢出则提示 N 是负数 则求补 取数字,与中间结果 相加,再乘以10 返回DOS 指向下一个数字字符 存结果 结束 结束
程序如下: DATA SEGMENT STR1 DB 10,?,10 DUP(?) ;第1个数的输入缓冲区 STR2 DB 10,?,10 DUP(?) ;第2个数的输入缓冲区 NUM DW ?,? ;存转换后的二进制数 SUM DW 0 ;存和 OVER DB ‘Overflow!’,13,10,’$’ DATA ENDS ; CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR
START: MOV AX,DATA MOV DS,AX MOV AH,0AH LEA DX,STR1 INT 21H ;输入第一个数字串(设为26) MOV AH,0AH LEA DX,STR2 INT 21H ;输入第二个数字串(设为33) LEA BX,STR1 ;串1的首地址送BX LEA DI,NUM ;存二进制首地址送DI CALL CHANGE ;将串1 ASCII码→二进制 LEA BX,STR2 ;串2的首地址送BX
LEA DI,NUM+2 ;指向下一个数 CALL CHANGE ;将串2 ASCII码→二进制 MOV AX,NUM ;(AX)=[NUM]=001AH ADD AX,NUM+2 ;两数相加,(AX)=003BH MOV SUM,AX ;存和 JNO NEXT ;无溢出,转NEXT LEA DX,OVER MOV AH,9 INT 21H ;显示’Overflow!’ NEXT: MOV AH,4CH INT 21H ;返回DOS MAIN ENDP
CHANGE PROC MOV CL,[BX+1] ;实际字符数送CL MOV AL,[BX+2] ;第一个字符送AL MOV CH,AL ;暂存在CH CMP AL,’-’ ;第一个字符是负号吗? JNZ NEXT1 ;不是,转NEXT1 DEC CL ;字符数减1 INC BX NEXT1: ADD BX,2 ;指向第一个数字字符 MOV AX,0 ;清零AX,存二进制数 LP1: DEC CL JZ NEXT2 ;若(CL)=0,转NEXT2 MOV DL,[BX] ;取字符 AND DL,0FH ;转换成BCD码 ADD AL,DL ;加到中间结果上 ADC AH,0
MOV DX,10 MUL DX ;*10 INC BX ;指向下一个字符 JMP SHORT LP1 NEXT2: MOV DL,[BX] ;取个位数 AND DL,0FH ;个位ASCII→未组合BCD ADD AX,DX ;加个位数,(AX)=001AH CMP CH,’-’ ;是’-’? JNZ NEXT3 ;该数非负,转NEXT3 NEG AX ;若为负,求补 NEXT3: MOV [DI],AX ;存二进制结果 RET CHANGE ENDP ; CODE ENDS END START
设键入第1个数为26, 第2个数为33,则在内存各变量分配如下: STR1 0A 02 32 36 10个 若键入 ‘1234’ 0D … STR2 0A STR1 0A 02 04 33 ‘1’ 31 33 32 ‘2’ 10个 0D 33 ‘3’ … 34 ‘4’ NUM 1A 0D ? 00 … 21 … ? 00 SUM 3B 00 OVER ‘O’ … …
本例题重点掌握: *如何从键盘输入一个字符串 *ASCII→非压缩BCD→二进制 *有符号数的运算,对负数和溢出如何处理 思考题: 若键入第一个数26,第二个数为-4,填写各变量结果。