输入两位十六进制数,输出其十进制值
题目:
输入:ff
输出:255
输入:12
输出:018
(默认字符为小写)
方法一
代码
stack segment
stack ends
data segment
string_1 db 'please input a num: $'
string_2 db 0ah,0dh,'the result is : $'
result db 0,0,0 ;3个0分别用来存储转换10进制后的值 因为最大为255 所以有三位
data ends
code segment
assume cs:code,ds:data,ss:stack
start:
mov ax,data
mov ds,ax
;显示提示语句
lea dx,string_1
mov ah,09h
int 21h
;从键盘上读第一个字符
mov ah,01h
int 21h
;先减去30h 再判断是数字 还是a~f
sub al,30h
cmp al,10
jb shuzi ;是数字 跳转
;是字母a~f 则还要再减去27h
sub al,27h
mov cl,4
shl al,cl ;左移4位,相当于乘以16
mov bl,al
jmp in_2
shuzi:
mov cl,4
shl al,cl
mov bl,al
;输入第二个字符
in_2:
mov ah,01h
int 21h
sub al,30h
cmp al,10
jb shuzi_2
sub al,27h
add bl,al
jmp change
shuzi_2:
add bl,al
;开始进制转换
change:
mov bh,0
mov ax,bx
mov bx,offset result+2
mov cx,3
mov si,10
;转换方法就是 循环除以10 得到每个位置的数
;比如255 255%10=5 25%5=5 2%5=2 这样就把255分成了2 5 5 了
do:
div si
mov [bx],dl
mov dx,0 ;因为除以的是si 16位的,所以被除数为32位,就是高16位为dx,低16位为ax,但dx会用来存余数,所以需要及时对dx清零
dec bx
mov ah,0
loop do
;显示结束语句
lea dx,string_2
mov ah,09h
int 21h
mov bx,offset result
mov cx,3
shuchu:
mov dl,[bx]
add dl,30h
mov ah,02h
int 21h
inc bx
loop shuchu
mov ax,4c00h
int 21h
code ends
end start
结果
改进版
stack segment
db 10 dup(?)
stack ends
data segment
string_1 db 'please input a num: $'
string_2 db 0ah,0dh,'the result is: $'
result db 0,0,0
data ends
code segment
assume cs:code,ss:stack,ds:data
start:
mov ax,data
mov ds,ax
lea dx,string_1
mov ah,09h
int 21h
mov cx,2
xor bl,bl
input:
push cx
mov cl,4
mov ah,01h
int 21h
shl bl,cl
sub al,30h
cmp al,10
jb shuzi
sub al,27h
shuzi:
add bl,al
pop cx
loop input
mov bh,0
mov ax,bx
mov bl,10
mov cx,3
mov si,offset result+2
change:
div bl
mov [si],ah
dec si
mov ah,0
loop change
lea dx,string_2
mov ah,09h
int 21h
mov cx,3
mov si,offset result
output:
mov dl,[si]
add dl,30h
mov ah,02h
int 21h
inc si
loop output
mov ax,4c00h
int 21h
code ends
end start
方法二:
DATAS SEGMENT
bin dw 10 dup(?) ;存放二进制结果
buf db 5 dup(?) ;存放十进制数 各个数位上的数值 如100,存放为 1,0,0
msg1 db 'please input a hex number',13,10,'$'
msg2 db 'the dec number:',13,10,'$'
crlf db 13,10,'$' ;回车换行
DATAS ENDS
stack segment
db 10 dup(?)
stack ends
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS
mov cx,2
START:
push cx
MOV AX,DATAS
MOV DS,AX
mov bx,0 ;初始化bx
LEA dx,msg1 ;输出提示字符串
mov ah,9
int 21h
input:
mov ah,1 ;输入一个字符
int 21h
sub al,30h ;把al中的ascii码转换成数值
jl init
cmp al,10 ;输入的数在0-9之间跳转
jl toBin
sub al,27h ;再转换为a-f
cmp al,0ah ;输入的字符比a小
jl init ;结束输入
cmp al,10h ;输入的字符比f大
jge init ;结束输入
toBin: ;转换为二进制,把输入组合成意义上的数值
mov cl,4
shl bx,cl ;bx左移4位
mov ah,0
add bx,ax ;把输入后并从ascii码转换来的值与bx相加
mov bin,bx ;转换成二进制数后存到内存bin
jmp input ;继续输入
init: ;初始化,准备转换
mov ax,bin
mov bx,10
mov si,4 ;循环四次,最大到万位
toDec: ;转为各个数位上的数值,如100转换为1,0,0 百位为1...
mov dx,0
div bx ;除10法得到各个位上的数值
mov [buf+si],dl ;余数为该位上的值,第一次循环为个位,第二次为十位...;存到内存中
dec si
cmp ax,0 ;商是否为0,为0算法结束
ja toDec
lea dx,crlf ;显示提示
mov ah,9
int 21h
lea dx,msg2
mov ah,9
int 21h
output: ;输出内存中存放的各个数位上的数值
inc si
mov dl,[buf+si]
add dl,30h ;转为ascii
mov ah,2
int 21h
cmp si,4
jb output
mov cx,0
pop cx
loop START
MOV AH,4CH
INT 21H
CODES ENDS
END START
总结
- 计算机存储数据其实是以二进制数存储的,但是在debug模式下,我们看到的数都是以十六进制显示。
- 键盘输入其实存储的是对应的ASCII值,比如输入:f 其实存的是:66h
- 为了使输入:f 计算机存储的也是f,需要-57h 如果是数字的话,需要 -30h
- 这里是两位十六进制的数,输入一个字符后,在最后计算结果的时候,其实是第一个字符乘以16再加上第二个字符,在计算机中,乘以十六,相当于左移四位。所以在这里我的方法是:获得第一个字符后,左移四位,在与第二个字符进行相加。得到的就是我们需要的。
- 输出也是需要ASCII值,记得+30h
- div的用法需要搞清楚