8086汇编语言:输入一个十六进制的多位数将其转化为十进制输出
发布日期:2021-05-08 03:04:41 浏览次数:21 分类:精选文章

本文共 3561 字,大约阅读时间需要 11 分钟。

一、问题说明:

输入一个十六进制的多位数,将其在程序中转换为十进制的数据输出。

 

二、思路讲解:

和二进制、八进制、十进制相比,十六进制较为特殊,因为其数据构成含有字母(a~f或A~F);在处理数据时会带来其他进制转换所没有的麻烦!为了解决这个问题,我们需要对于输入的数据(位于寄存器al中)进行ASCII值的筛选判断,以确定输入的是数字、大写字母、小写字母;还是其他违法数据。

观察ASCII值我们不难发现:a~f > A~F > 0~9。我们在具体判断时可以利用这一点,构成从大到小筛选梯度,可以减少比较的次数

;判断数据的有效性	;a~f之间的数据:	cmp al,60H		ja nextaf;进一步判断	;A~F之间的数据:		cmp al,40H		ja nextA;进一步判断	;0~9之间的数据:	cmp al,2FH		ja next09;进一步判断	jmp over;都不是,则为违规数据	nextaf:	cmp al,67H		jb minuscules;确定是a~f之间的数据,转入数据累计阶段	jmp over;否则是违规数据			nextA:	cmp al,47H		jb majuscule;确定是A~F之间的数据,转入数据累计阶段	jmp over;否则是违规数据			next09:	cmp al,3AH		jb number;确定是0~9之间的数据,转入数据累计阶段		jmp over;否则是违规数据

再将输入数据(位于寄存器al中)中蕴含的数值剥离出来,针对不同的类型,采用不同的处理

minuscules:;对于小写字母进行处理	sub al,87;剥离出原始数值	mov dl,al;转移数据		jmp addin;将数据加入bx中	majuscule:;对于大写字母进行处理		sub al,55;剥离出原始数值	mov dl,al;转移数据		jmp addin;将数据加入bx中		number:;对于数字进行处理	sub al,48;剥离出原始数值	mov dl,al;转移数据		jmp addin;将数据加入bx中

其他的地方就没啥了,都是比较常见的操作,我代码中也有详细的注释帮助理解!

如果对于下面使用的多位输出函数——outputdata不是很明白的话;可以点击下面的链接直达我往期详细的介绍!这里就不赘述了!

(👈点它)

 

三、具体代码:

DATAS SEGMENT    CRLF DB 0AH,0DH,"$";回车换行DATAS ENDSSTACKS SEGMENT    ;此处输入堆栈段代码STACKS ENDSCODES SEGMENT    ASSUME CS:CODES,DS:DATAS,SS:STACKSSTART:    MOV AX,DATAS    MOV DS,AX       call inputdata    lea dx,crlf    mov ah,9    int 21h    mov ax,bx    call outputdata      	MOV AH,4CH    INT 21H;出口参数:bx   ;接收一个16进制的数据,将其转换成为一个十进制的数据累计在寄存器bx中    inputdata proc 	push ax;数据入栈,防止丢失	push cx	push dx		;对于相关数据进行初始化	mov bx,0;用于记录累计的结果	mov cl,16;用于后续的乘法运算	inputagain:;依次循环输入数据并加以判断		mov ah,1	int 21h;接收数据,并且存在寄存器al中ASCII码的形式		;判断数据的有效性	;a~f之间的数据:	cmp al,60H		ja nextaf;进一步判断	;A~F之间的数据:		cmp al,40H		ja nextA;进一步判断	;0~9之间的数据:	cmp al,2FH		ja next09;进一步判断	jmp over;都不是,则为违规数据	nextaf:	cmp al,67H		jb minuscules;确定是a~f之间的数据,转入数据累计阶段	jmp over;否则是违规数据			nextA:	cmp al,47H		jb majuscule;确定是A~F之间的数据,转入数据累计阶段	jmp over;否则是违规数据			next09:	cmp al,3AH		jb number;确定是0~9之间的数据,转入数据累计阶段		jmp over;否则是违规数据					minuscules:;对于小写字母进行处理	sub al,87;剥离出原始数值	mov dl,al;转移数据		jmp addin;将数据加入bx中	majuscule:;对于大写字母进行处理		sub al,55;剥离出原始数值	mov dl,al;转移数据		jmp addin;将数据加入bx中		number:;对于数字进行处理	sub al,48;剥离出原始数值	mov dl,al;转移数据		jmp addin;将数据加入bx中			addin:;将数据加入bx中	mov ax,bx	mul cl	mov dh,0	add ax,dx	mov bx,ax		jmp inputagain;loopover:	pop dx;数据出栈,恢复数值	pop cx	pop ax	retinputdata endp     ;入口参数:ax;多位输出函数,以十进制形式输出存储在ax中的多位数outputdata proc 	push cx	push dx;数据入栈,防止丢失		;数据初始化	mov ch,0;用于计数	mov cl,10;作为除数separateagain:;数据剥离	cmp ax,0		je outputagain;进入具体输出	div cl;剥离数据,存在ah中	push ax;后续取用前八位	mov ah,0;使得ax与al的值相同,便于下次操作	inc ch;计数加一		jmp separateagain;loop	outputagain:;数据输出	cmp ch,0		je inputover;输出结束	pop dx	mov dl,dh;获取前八位有用的数据	add dl,48	mov ah,2	int 21h	dec ch;计数减一		jmp outputagain;loopinputover:	pop	dx;数据出栈,恢复数据	pop cx	retoutputdata endp CODES ENDS    END START

 

四、运行示例:

 

五、代码极限:

在写完这个代码之后,我想着写都写完了,看看允许输入的最大值为多少?

对于十六进制数据接收函数——inputdata函数;我们对其分析一下不难发现:限制这个函数的上限在于乘法运算的ax寄存器;更为具体的说是ax寄存器的低八位——寄存器al;因为在8086汇编语言中,乘法运算要将参与乘法的一个因数放置在寄存器al中,运算的结果放置在寄存器ax中。

因此在极限条件下,al存储的数据到达了最大,即255。然后乘上16,将结果放置在寄存器ax中,即255x16=4080。再加上输入的最后一个数值,取最大为F(即15);最终在寄存器ax中存储的最大数值为255x16+15=4085。

但是!输入一个价值 3840 的 f00 数据,它也接收不了!

Why?因为不能只考虑输入,你也要保证输入的数据能输出出来!

对于十进制形式输出多位数函数——outputdata函数;我们对其分析一下不难发现:限制这个函数的上限在于除法运算的ax寄存器(没错,又是它!o(* ̄▽ ̄*)ブ);更为具体的说是ax寄存器的低八位——寄存器al(没错,又是它!o(* ̄▽ ̄*)ブ);因为在8086汇编语言中,我们将被除数放置在寄存器ax中,除完之后的商放置在寄存器al中,余数放置在寄存器ah中;在该程序中对于除法的使用,我们可以发现:放置在ah中的余数是一定不会溢出的,因为最大的就是9;所以只需要管寄存器al就可以了!

因为这是除法,数值会随着运算的进行越变越小,所以我们对第一次进行着重分析;第一次的极限条件就是al为255;ah最大为9;于是乎ax可接受的最大值就是255x10+9=2559(对应十六进制数为:9FF)。

验证一下!

再大一个都不行!譬如:输入9FFH+1H=0a00h就报错了!

 

综上可得,我们分析了两个板块可以接受的极限值,我们取其中的最小值——2559(9FFH),即为整个程序所能接受的最大输入值!

 

Ending... ...

上一篇:回溯法求解:最佳调度问题
下一篇:回溯法求解:工作分配问题

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月09日 19时05分34秒