汇编进制转化总结
10、2进制无符号输入
- 如果是10进制,把n值改成10即可
- 如果是2进制,把n值改成2即可
DATAS SEGMENT
x dw ?
n dw 10 ;规定进制数,这里是10进制。如果是2进制,改成2即可。
DATAS ENDS
STACKS SEGMENT stack
db 100h dup(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
mov bx,0 ;bx作为一个累加存储作用
L1:;循环输入
mov ah,1 ;1号调用,输入一个字符
int 21h
cmp al,0dh ;回车就跳出
jz l2
sub al,30h ;减30h,让数字字符成为数字
mov ah,0
xchg bx,ax
mul n ;乘以10
;如果是2进制,可以用逻辑左移!
add bx,ax ;再加上新输入进来的
jmp l1
L2:
mov x,bx
MOV AH,4CH
INT 21H
CODES ENDS
END START
10、2进制无符号输出
- 如果是10进制,把b值改成10000,1000,100,10,1即可
- 如果是2进制,把b值改成64,32,16,8,4,2,1即可
- cx控制位数。注意要跟着变。
.model small
.data
x dw 123
b dw 10000,1000,100,10,1 ;最高支持5位数的输出,而且是10进制的。
flag db 0 ;如果是2进制,则改成 32,16,8,4,2,1
.stack 100h
.code
start: mov ax,@data
mov ds,ax
mov ax,x ;把输出的数放在ax中
mov bx,offset b ;把进制控制放在bx中
mov flag,0 ;控制0要不要输出
mov cx,5 ;5位数的输出
r1: mov dx,0 ;dx ax / bx, 因此要dx置零
div word ptr [bx]
mov si,dx ;保存余数
cmp ax,0 ;看结果是否为零
jz r2 ;是
mov flag,1 ;如果不是零,则下一个数为0时,可以输出
r2: cmp flag,0 ;看可不可以输出
jz r3 ;flag为0,代表到目前为此,还没有出现不是0的数,因此不输出
mov dl,al ;否则,进行输出
add dl,30h
mov ah,2
int 21h
;r3的作用是更新循环条件
r3: add bx,2 ;注意,这里一定是加2!!!!!因为是 dw 定义的!!!!
mov ax,si ;把保存的余数放回ax中
loop r1
mov ah,4ch
int 21h
end start
经典例题
包含的两段子程序有两种功能:
- 第一个是2进制的输入
- 第二个是带符号的10进制的输出。而且采用的是求模取余法。
;下面程序输入16位以内的二进制数(输入时回车作为输入结束),然后以有符号十进制数形式显示出来。将空格处指令补充完整,使得程序能完整实现所需要的功能。
DATA segment
CRLF DB 0DH,0AH,24H
DATA ends
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
MAIN PROC NEAR
mov ax,data
mov ds,ax
CALL I2
CALL D10
mov ah,9cH ;返回dos系统 )……………①
INT 21H
MAIN ENDP
;I2 ----------------------------------------------------------------------
I2 PROC NEAR
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI ;保护现场
XOR BX,BX ;自己异或自己,相当于清零
MOV CX,16 ;16位数的二进制
L20: MOV AH,1
INT 21H
cmp al, 0dH; 看是不是回车。是就跳出 )……………②
JE L21
CMP AL,30H ;如果小于0,则退出
JB L20
CMP AL,31H ;如果大于1,则退出
JA L20
AND AX,01H ;因为数字0的ascill码是30H,数字1的ascill码是31H,与上一个01H,可以把最低位的数字取出来
SHL BX,1 ;逻辑左移,相当于乘以2
ADD BX,AX ;累加
loop L20 ;循环输入 )……………③
L21: MOV AX,BX
POP DI
POP SI
POP DX
POP CX
POP BX ;还原现场 )……………④
RET
I2 ENDP
;I2 ends ----------------------------------------------------------------------
D10 PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
mov bx, ax ;可以看到,下面的操作都是操作bx的。说明数存在bx中 )……………⑤
;为什么放在bx中?可以看到调用dos调用,要用到ax
MOV AH,9
LEA DX,CRLF ;输出换行回车
INT 21H
OR BX,BX ;自己异或自己,虽然不改变数值,但改变标志位
JNS L100 ;如果符号位不是1(即正数)
MOV AH,2
mov dl,"-" ;是负数,先输出负号
INT 21H
NEG BX ;如果是负数,求补,成为正数!!!!
L100: MOV AX,BX ;把数放回ax中,因为要作除法了
XOR CX,CX ;清零
MOV SI,10 ;进制的控制!!!如果是2进制,改成2 即可
L101: XOR DX,DX ;dx清零,因为要 dx,ax / si 了
div si ;除以进制 )……………⑦
PUSH DX ;把余数压栈
INC CX ;统计进栈的数的数量
CMP AX,0
JNZ L101 ;如果ax还没有到0,要继续循环
L102: POP DX
MOV AH,2
dec cx ; 保证循环正常结束 )……………⑧
INT 21H
LOOP L102
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
RET
D10 ENDP
CODE ENDS
END MAIN
16进制无符号输入
DATAS SEGMENT
x dw ?
n dw 16 ;规定进制数,这里是16进制
DATAS ENDS
STACKS SEGMENT stack
db 100h dup(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
mov bx,0 ;bx作为一个累加存储作用
L1:;循环输入
mov ah,1 ;1号调用,输入一个字符
int 21h
cmp al,0dh ;回车就跳出
jz L2
cmp al,39H
ja upperThanNine
lowerThanNine:
sub al,30h ;减30h,让0~9数字字符成为数字
jmp calcu
upperThanNine:
sub al,37H ;让字母A~F转化为数字
calcu:
mov ah,0
xchg bx,ax
mul n ;乘以16
add bx,ax ;再加上新输入进来的
jmp L1 ;循环输入
L2:
mov x,bx
MOV AH,4CH
INT 21H
CODES ENDS
END START
16进制无符号输出
DATAS SEGMENT
;用查表的方法来做
nums db 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,41H,42H,43H,44H,45H,46H
x dw 12 ;要输出的数
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
;此处输入代码段代码
MOV CX,0 ;计算有多少个数在栈里面
MOV AX,X ;要输出的数
MOV BX,16 ;进制是16
L1:
MOV DX,0 ;因为 Dx,ax / bx , 所以dx清零
DIV BX
PUSH DX ;余数入栈
INC CX ;统计多少个数在栈里面
CMP AX,0
JZ OUTPUT ;如果是为0,则输出
jmp L1
OUTPUT:
POP SI
MOV DL,nums[SI] ;查表,把数字转化成字符
MOV AH,2
INT 21h
LOOP OUTPUT
MOV AH,4CH
INT 21H
CODES ENDS
END START
带符号数的输入输出
DATAS SEGMENT
A dw ?
B dw ?
X dw ?
ERR DB 'Input Error!$'
ENT DB 0DH,0AH,24H
DATAS ENDS
STACKS SEGMENT STACK
DB 100H DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
MAIN PROC
START:
MOV AX,DATAS
MOV DS,AX
CALL INNUM
MOV X,AX ;AX是INNUM子程序最终的输入结果
CALL ENTER1 ;输出换行回车。因为这里要用到dos调用,所以用X作为暂存
MOV AX,X
CALL OUTNUM
MOV AH,4CH
INT 21H
MAIN ENDP
INNUM PROC
MOV B,0 ;B作为累和的存储
MOV A,0 ;A记录符号位
BIN: MOV AH,1
INT 21H
CMP AL,0DH
JZ EXIT ;回车跳出
CMP AL,2DH ;2DH 是 “-” 负号
JNZ GO
MOV A,1 ;如果是负号,则A置为1
JMP BIN ;循环输入
GO: CMP AL,30H
JB ERROR
CMP AL,39H
JA ERROR ;不在0~9的,都报错
MOV BL,10 ;BL代表进制,这里是10进制
XOR BH,BH ;BH清零,因为
SUB AL,30H ;让符号成为数字
XOR AH,AH ;AH清零,因为接下来要把AX压栈
PUSH AX ;AX压栈,因为接下来要用最后的累和数作乘法
MOV AX,B ;把最后的累积数送往AX
MUL BL ;乘以进制
MOV B,AX
POP AX
ADD B,AX
JMP BIN ;循环输入
ERROR: CALL ENTER1
LEA DX,ERR
MOV AH,9
INT 21H
RET
EXIT: CMP A,0
JZ NOTE ;如果是正数,直接把最终结果给AX即可
NEG B ;如果是负数,则对B求补
NOTE: MOV AX,B
RET
INNUM ENDP
;------------------------
; 输出回车换行
;------------------------
ENTER1 PROC
LEA DX,ENT
MOV AH,9
INT 21H
RET
ENTER1 ENDP
;------------------------
; 输出一个数字,入口参数AX
;------------------------
;用的是求模取余法
OUTNUM PROC
CMP AX,0
JGE L0 ;如果数>=0, 非负
NEG AX ;如果是负数,先求补
PUSH AX
MOV DL,'-' ;输出负号
MOV AH,2
INT 21H
POP AX
L0: MOV CX,0
L1: MOV DX,0 ;因为要 DX,AX / BX, 所以DX要清零
MOV BX,10 ;bx代表进制数
DIV BX
PUSH DX ;把余数压栈
INC CX ;统计有几个数进栈了
CMP AX,0
JZ L2 ;到0,那么就不用再继续了
JMP L1
L2: POP DX
ADD DL,30H ;原文是OR,我改成了AND
MOV AH,2
INT 21H
LOOP L2
RET
OUTNUM ENDP
CODES ENDS
END START