总结:
输入的字符首先要转换为数的形式存在内存中,再进行转换输出。
1、字符转换成数:
①二进制输入:将输入的二进制字符用二进制来表示,即-30h,得到的0/1则是我们想要得到的数,此时0/1存在al的最低一位,即最右边一位,采用逻辑右移SHR指令,将0/1送往CF,再对bx使用带进位的循环左移RCL,则0/1送往bx的最低一位,循环如此,即可实现将二进制的输入在bx中用二进制来表示。
②十六进制输入:将上一次的结果往前推一位,即×16。
③八进制输入:将上一次的结果往前推一位,即×8。
④无符号十进制输入:将上一次的结果往前推一位,即×10。
⑤有符号十进制输入:用cx装载-1表示负数,否则为正数,若是正数和无符号数输入一样,若为负数则要对该数进行求补。
2、转换成进制输出:
①二进制输出:依次左移输出字符,左移16次。
②十六进制输出:用到换码指令,需先把表格的首地址放在BX寄存器中,将相对于表格首地址的偏移量放在AL中,得到的AL就是转换后的地址里的内容,也就是转换后的代码。
③八进制输出:先取bx中存放的二进制的后三位,转换为ASCII码,压栈,后面可输出,然后对bx逻辑右移三位,取后三位,转换为ASCII码压栈,依次直到bx为0。pop bx,可得到对应的八进制数。
④有符号十进制输出:用OR来判断该数为正数还是负数,若为负数,则先输出负号,且对该数进行求补,若为正数则不做改变。
一、二进制与十六进制
1.编写一段程序,从键盘接收一个四位的十六进制数,并在终端上显示与它等值的二进制数。
DATAS SEGMENT
NUM DW 0
CRLF DB 0DH,0AH,'$'
DATAS ENDS
STACKS SEGMENT
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV DX,0
MOV CX,4
L: MOV AH,1
INT 21H
CMP AL,40H
JG L1
JL L2
L1: SUB AL,07H;大写字母多减7,得到0ah...
L2: SUB AL,30H;说明是数字字符要将ASCII码转成对应数字
PUSH AX
MOV AX,NUM
MOV BX,16
MUL BX
POP BX
ADC AL,BL
MOV NUM,AX
LOOP L;循环4次,使输入的16进制数变成10进制数
LEA DX,CRLF
MOV AH,9
INT 21H;换行
MOV CX,16
MOV BX,NUM
L3: MOV DL,31H
SAL BX,1;左移1位,改变CF
JC L4;CF为1,输出1
SUB DL,1;CF为0,所以DL减去1,输出0
L4: MOV AH,2
INT 21H
LOOP L3
MOV AH,4CH
INT 21H
CODES ENDS
END START
解题思路:将输入的十六进制字符转换为十六进制整数,整数会以二进制形式存在内存中,所以依次左移输出字符即可得到对应二进制数。
二、二进制与八进制
1.编写一个程序,从键盘输入一个不大于16位的2进制数,然后以8进制形式显示出所输入的数。
DATA SEGMENT
x dw 0ah,0dh,'$'
InputBuffer db 17,0,17 dup (0) ;第一个字节为用户定义的最大字符数(0-255);第二个字节是实际输入字符的个数;第三个字节,字符串开始按字节存入缓冲区
UserInput dw 0
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
call GetUserInput ;输入子程序
mov UserInput,ax ;取得输入值16进制,也是2进制
lea dx,x
mov ah,9
int 21h
mov bx,UserInput ;取得输入值
mov cl,3 ;移位数
mov ch,0 ;计数
next:
mov ax,bx
and ax,0000000000000111b ;取低3(111)位,即八进位
or al,'0' ;转ascii:30H二进制与0-7的二进制相或=30H+0-7.即也可以用ADD AL,30H来表示
push ax ;保存
inc ch ;计数
shr bx,cl ;右移3位,即下一位
or bx,bx ;是否完了
jnz next ;未
mov cl,ch ;取得计数
mov ch,0 ;清0
next1:
pop dx ;弹出dl,即将压栈的AX弹出赋值给DX
mov ah,2 ;印出结果
int 21h
loop next1
mov ah,7 ;暂停
int 21h
quit:
MOV AH,4CH ;带返回码结束功能
INT 21H ;返回系统
;-----------------------
GetUserInput:
mov dx,offset InputBuffer ;指向输出缓冲
mov ax,0c0ah ;输入函数,先清空键盘缓冲,mov ah,0ch清除键盘缓冲区,mov al,0ah输入字符到缓冲区
int 21h
mov si,offset InputBuffer + 2;字符串开始的第一个字符
mov cx,0
mov cl,[si-1] ;取实际输入数
jcxz GetUserInput ;无输入,测试CX内容为0则转移
Call GetValue ;取值子程序,ax传回该值,cf=1表示错误,可能输入非数字
jc GetUserInput ;输入错误,非数字
ret
;--------------------------------------------------------------------------
;转值子程序,把输入的字符转成16进制(2进制)
;输入:ds:si数字字符串起点,以0dh结束
;输出:ax=转换后的16进制值,cf=1表示有非数字字符
GetValue:
push bx
push di
xor bx,bx
mov di,10
GetV10:;实现将输入的二进制字符转换成二进制形式存在BX中
lodsb ;指向起点,将由源变址寄存器(此处值si寄存器)指向的数据段中某单元的内容送到AL、AX、EAX中去
mov ah,0 ;清除
cmp al,0dh
jz Getvx
cmp al,30H ;输入的不是0或1则输入错误,置CF=1
jb Getvy
cmp al,'1'
ja Getvy
sub al,30H ;ascii -> 值
shr al,1 ; cf=1,1 cf=0,0,逻辑右移
rcl bx,1 ;一位接一位的旋入bx,带进位的循环左移
jmp short GetV10
Getvx: mov ax,bx ;ascii转值后由ax转回
clc ;成功cf=0
jmp short Getvz
Getvy:
stc ;错误 cf=1
Getvz:
pop di
pop bx
ret
;------------------------------------
CODE ENDS
END START
解题思路:
①将输入的二进制字符用二进制来表示,即-30h,得到的0/1则是我们想要得到的数,此时0/1存在al的最低一位,即最右边移位,采用逻辑右移SHR指令,将0/1送往CF,再对bx使用带进位的循环左移RCL,则0/1送往bx的最低一位,循环如此,即可实现将二进制的输入在bx中用二进制来表示。
②八进制输出:先取bx中存放的二进制的后三位,转换为ASCII码,压栈,后面可输出,然后对bx逻辑右移三位,取后三位,转换为ASCII码压栈,依次直到bx为0。pop bx,可得到对应的八进制数。
三、二进制与十进制
1.编写一个程序,计算 1 + 2 + 3 + 4 + … + 100的累加和,并把累加和以2进制形式显示出来。(十进制整数转换为二进制输出)
(要使用循环累加方法,不能使用公式S=N*(N+1)/2=50*101=5050)。
DATAS SEGMENT
sum dw 0
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
mov ax,0
mov bx,1
lp1: ;实现累加和,ax中装总和数
add ax,bx
inc bx
cmp bx,101
je next
jmp lp1
next:
mov cx,16
mov bx,ax
lp3:
shl bx,1;逻辑左移指令
jc lp2 ;进位为1则转移
mov ah,2
mov dl,0
add dl,30h
int 21h
dec cx
cmp cx,0
je exit
jmp lp3
lp2:
mov ah,2
mov dl,1
add dl,30h
int 21h
dec cx
cmp cx,0
je exit
jmp lp3
exit:MOV AH,4CH
INT 21H
CODES ENDS
END START
解题思想:在内存中存在的十进制整数其实是以二进制形式存在,所以直接将数每次逻辑左移一位(左移十六次),根据CF位,选择将1或0放入dl中,进行输出即可。
2.二进制输入,十进制输出。
DATAS SEGMENT
CRLF DB 0DH,0AH,24H;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
MAIN PROC NEAR
MOV AX,DATAS
MOV DS,AX
CALL I2;调用子程序
CALL D10
MOV AH,4CH
INT 21H
MAIN ENDP
I2 PROC NEAR
PUSH BX;确保不会影响主程序的值
PUSH CX
PUSH DX
PUSH SI
PUSH DI
XOR BX,BX;bx清零
MOV CX,16;cx装载计数
L20:MOV AH,1;一号调用输入字符
INT 21H
CMP AL,0DH;输入回车,则不再进行输入字符程序
JE L21
CMP AL,30H;输入的数比0小或比1大,则继续输入字符
JB L20
CMP AL,31H
JA L20
AND AX,01H ;完成二进制输入的功能
SHL BX,1
ADD BX,AX;bx装的是二进制数
LOOP L20
L21:MOV AX,BX;把bx装的二进制数送回ax中
POP DI
POP SI
POP DX
POP CX
POP BX
RET
I2 ENDP
D10 PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV BX,AX;二进制数在ax中
MOV AH,9;9号调用输出字符串,是crlf的字符串
LEA DX,CRLF;把crlf地址送入dx
INT 21H
OR BX,BX;判断是正数还是负数
JNS L100;符号位s为0即为正数就跳转,否则就输出负号,并且对二进制数求补
MOV AH,2;二号调用输出单个字符
MOV DL,"-"
INT 21H
NEG BX;对bx求补
L100:MOV AX,BX
XOR CX,CX;cx清零
MOV SI,10
L101:XOR DX,DX;dx清零,为了后面装余数
DIV SI;div已经自动将内存里的进制转成十进制。十进制数除10得到的余数装载在dx中,将余数压入栈然后输出
PUSH DX
INC CX
CMP AX,0;比较ax(商)是否为0,若不为0则继续除10,为0则出栈输出字符
JNZ L101
L102:POP DX
MOV AH,2
ADD DL,30H;数字转换为字符输出
INT 21H
LOOP L102
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
D10 ENDP
CODES ENDS
END MAIN
四、八进制与十进制
五、八进制与十六进制
六、十进制与十六进制
1.编写一个程序,从键盘输入一个0~65535之间的10进制无符号数,然后以16进制形式显示出所输入的数。
data segment
string db 0dh
num db 4 dup(?),'H$'
tab db '0123456789ABCDEF'
data ends
code segment
assume cs:code,ds:data
begin: mov ax,data
mov ds,ax ;初始化代码段
xor bx,bx ;bx清零
mov cx,10 ;进制
next: ;输入十进制
mov ah,1 ;输入字符,存进AL的是字符的ASCII码
int 21h
cmp al,0dh
jz conv ;如果是回车,表示输入结束,转换开始
push ax ;保存输入值,当然还有AH,因为堆栈的存取必须以字为单位
mov ax,bx
mul cx
mov bx,ax ;将先前的结果向上推一位
pop ax ;取回本次输入
and al,0fh ;屏蔽掉无用位,类SUB AL,30H
xor ah,ah ;高位归零
add bx,ax ;合并本次输入
jmp next
conv: mov ax,bx ;开始转换
mov ch,4
lea bx,tab ;bx直接定址表
mov cl,4
lea si,num
lopa: rol ax,cl ;把高4位移到低4位
push ax
and ax,000fh ;取出低4位
xlat
mov [si],al ;按地址由低到高的顺序将结果由高到低存放
inc si
pop ax
dec ch
jnz lopa
lea dx,string;9号调用,先把要输出的字符串首地址的偏移地址存入DX中 /lea dx,num
mov ah,9
int 21h ;回车换行
mov ah,4ch
int 21h
code ends
end begin
解题思路:
①将输入的字符转换成十进制数形式存放在内存中,将先前的结果往前推一的方法。
②将得到的十进制数转换成十六进制输出,用到换码指令,需先把表格的首地址放在BX寄存器中,将相对于表格首地址的偏移量放在AL中,得到的AL就是转换后的地址里的内容,也就是转换后的代码。