用MASM汇编语言实现从10进制/16进制到2进制的转换
2012-04-15 22:01
681 查看
最近由于学校课程的缘故,开始涉及汇编,当然是从8086开始,虽说已是老古董了,但关键是原理吗,下面的内容是一道作业题目,是我自己目前写的比较复杂的一个程序,当然是对我这样的菜鸟而言啦~拿出来纪念一下,说实话这段代码没什么用的,各位轻拍。。。
要求是这样的:即在终端上输入(注意输入不是已知参数)12或者12H(即打1输出1,打2需要在1的时候继续显示2,打H需要在12的后面显示H),如果打得是回车,你需要在第二行能够输出第一行数字的二进制,假设上一行顺序输入1,2,回车,那么第二行应该显示1100;如果第一行输入1,2,H,回车,那么第二行应该显示 00010010。只做显示两行的程序,即一次输入数据+回车之后程序输出并直接退出。(程序不考虑健壮性,默认所有输入是正确的)
下面直接上代码~
代码如下:
DATAS SEGMENT
DB 16 DUP(0) ;该段内存作为存储输入字符串的空间,在程序中被用来模拟栈空间,但不是真正的栈
DB 100 DUP(0) ;用来存放结果
DATAS ENDS
STACKS SEGMENT
DW 200 DUP(0)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV SI,0 ;将SI设置为存放字符串的内存地址的首地址
CALL GETSTR
MOV AH,4CH
INT 21H
GETSTR: ;处理键盘输入的子程序
PUSH AX
GETSTRS:
MOV AH,0
INT 16H
CMP AL,20H ;判断从键盘得到的输入是否为字符
JB NOCHAR
MOV AH,0 ;字符入栈
CALL CHARSTACK
MOV AH,2 ;显示字符
MOVDX,0 ;位置为第0行、第0列
CALL CHARSTACK
JMP GETSTRS NOCHAR
NOCHAR:
CMP AH,0EH
JE BACKSPACE
CMP AH,1CH
JE ENTERS
JMP GETSTRS BACKSPACE
BACKSPACE: ;处理退格键
MOV AH,1 ;字符出栈
CALL CHARSTACK
MOV AH,2 ;显示字符
MOV DX,0 ;位置为第0行、第0列
CALL CHARSTACK
JMP GETSTRS ENTERS
ENTERS: ;处理确认键
CALL TRANSFER ;对当前字符串进行转换
CALL SHOWRESULT ;显示结果
POP AX
RET
CHARSTACK: ;对输入的字符进行处理,ah=0,调用CHARPUSH,字符入栈,ah=1,调用CHARPOP,字符出栈,ah=2,调用CHARSHOW,显
示字符串
JMP SHORT CHARSTART
TABLE DW CHARPUSH,CHARPOP,CHARSHOW
TOP DW 0 ;表明了字符串中字符的个数
CHARSTART:
PUSH BX
PUSH DX
PUSH DI
PUSH ES
CMP AH,2
JA SRET
MOV BL,AH
MOV BH,0
ADD BX,BX
JMP WORD PTR TABLE[BX]
CHARPUSH: ;字符入栈
MOV BX,TOP
MOV [SI][BX],AL
INC TOP
JMP SRET CHARPOP
CHARPOP: ;字符出栈
CMP TOP,0 ;判断字符串是否为空
JE SRET
DEC TOP
MOV BX,TOP
MOV AL,[SI][BX]
JMP SRET CHARSHOW
CHARSHOW: ;显示字符串
MOV BX,0B800H
MOV ES,BX
MOV AL,160
MOV AH,0
MUL DH ;计算行位置
MOV DI,AX
ADD DL,DL ;计算列位置
MOV DH,0
ADD DI,DX ;计算字符串在屏幕上显示的位置
MOV BX,0
CHARSHOWS:
CMP BX,TOP
JNE NOEMPTY
MOV BYTE PTR ES:[DI],' '
JMP SRETNOEMPTY
NOEMPTY:
MOV AL,[SI][BX]
MOV ES:[DI],AL
MOV BYTE PTR ES:[DI+2],' '
INC BX
ADD DI,2
JMP CHARSHOWSSRET
SRET:
POP ES
POP DI
POP DX
POP BX
RET
TRANSFER: ;对输入的字符串进行转换,将结果保存至内存
PUSH AX
PUSH CX
PUSH DX
MOV BX,TOP ;得到栈顶的位置
CMP BX,0 ;如果栈为空,则直接退出
JE QUIT
SUB BX,1
MOV AH,[BX] ;得到栈顶前的字符
CMP AH,48H ;判断输入的字符是否为H,及字符串是否为16进制数
JE HTOB
CMP AH,68H ;判断输入的字符是否为h,及字符串是否为16进制数
JE HTOB
JMP DTOB HTOB
HTOB: ;处理16进制数的转换,运用移位指令shl,不使用除法计算
MOV CX,TOP
SUB CX,1 ;得到16进制数的位数
MOV BX,0
MOV DI,16 ;将di设置为保存结果的内存的起始地址
AGAIN: ;外层循环,对16进制数的每一位进行转换
MOV AH,[BX]
PUSH CX ;将cx入栈,内层循环也要用到cx
MOV CX,4 ;移位的次数
CMP AH,39H ;判断该位的字符是否为数字
JA chars
SUB AH,30H ;将ASCII码转换为数字的真实值
JMP dochars
chars: ;对A-F和a-f进行处理
AND AH,11011111B ;先一律将字符转换成大写
SUB AH,37H ;将ASCII码转换为数字的真实值
do:
SHL AH,1 ;将转换好的数字向左移位四次,及将值提到ah的高四位
SHL AH,1
SHL AH,1
SHL AH,1
inagain: ;内部循环四次,将ah中的高四位通过左移位取出,存到内存中
SHL AH,1
PUSHF
POP DX
AND DL,00000001B ;将标致寄存器中的CF位取出
ADD DL,30H ;将数字转换成ASCII码
MOV [DI],DL
INC DI
LOOP inagain
POP CX ;将cx出栈,进行外层循环的检测
INC BX
LOOP AGAIN
JMP QUIT DTOB
DTOB: ;处理10进制数的转换,运用移位指令shl,不使用除法计算
MOV CX,TOP ;得到10进制数的位数
MOV BX,0
MOV DI,16 ;将di设置为保存结果的内存的起始地址
MOV DX,0 ;转换完成的10进制数
AGAIN2: ;将字符串转换成10进制数字
MOV AL,[BX]
SUB AL,30H ;将ASCII码转换为数字
MOV AH,0
CALL TENPOWER ;调用10的n次方方法,n=cx-1,结果存在ax中
ADD DX,AX ;将每个位上的值累加到dx上
INC BX
LOOP AGAIN2
MOV CX,16 ;移位的次数
CMP DX,0 ;考虑0的情况
JNE AGAIN3 ;如果不是0,则直接进入正常处理
MOV DL,30H ;是0的话,直接向内存中写0的ASCII码
MOV [DI],DL
ADD DI,1
JMP QUIT AGAIN3
AGAIN3: ;进行移位处理的循环
SHL DX,1
PUSHF
POP AX
AND AL,00000001B
CMP AL,0 ;将前面的0在显示时省略掉
JNE continue ;如果不是0则直接写入内存
MOV SI,16 ;如果是0,则查看内存中存储结果的第一个字符,若是31h及1的ASCII码表示,将结果直接写入内存
MOV AH,[SI]
CMP AH,31H
JE continue ;如果内存中存储结果的第一个字符不是1,则将得到的0省略掉,不予显示
SUB CX,1 ;因为不经过loop语句,须将cx值减1
JMP AGAIN3 continue
continue:
ADD AL,30H
MOV [DI],AL
INC DI
LOOP AGAIN3 QUIT
QUIT:
POP DX
POP CX
POP AX
RET
TENPOWER: ;10的n次方方法,用于将字符串转化成10进制数
PUSH CX
PUSH BX
PUSH DX
SUB CX,1
CMP CX,0
JE EXIT
MOV BX,10
power:
MUL BX
LOOP power EXIT
EXIT:
POP DX
POP BX
POP CX
RET
SHOWRESULT: ;按下enter键后,用于显示结果的方法
PUSH AX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
MOV AX,0B800H
MOV ES,AX
SUB DI,16 ;di为每次存储结果结束时内存中的下表,减去16及为结果的位数,用作循环的次数
MOV CX,DI
MOV DI,160
MOV SI,16
show:
MOV DL,[SI]
MOV BYTE PTR ES:[DI],DL
ADD DI,2
INC SI
LOOP show
POP SI
POP DI
POP DX
POP CX
POP AX
RET
CODES ENDS
END START
说明:
1、将10进制和16进制转换成2进制的方法没有采用递归除法方式,而是采用了移位方法,通过shl指令以及读取标致寄存器的cf位得到2进制表示
2、对输入的要求,首先必须是正确的输入,然后是对输入位数的限制,对于16进制数而言,最多输入16位(包括最后的h),没办法,代码中我就给了这么大的空间,对于10进制而言,因为没有考虑大整数的情况,所以显示结果最多为16位,及输入的数不要大于65535(一个16位寄存器支持的最大整数)即可,否则的话就出现溢出了~
要求是这样的:即在终端上输入(注意输入不是已知参数)12或者12H(即打1输出1,打2需要在1的时候继续显示2,打H需要在12的后面显示H),如果打得是回车,你需要在第二行能够输出第一行数字的二进制,假设上一行顺序输入1,2,回车,那么第二行应该显示1100;如果第一行输入1,2,H,回车,那么第二行应该显示 00010010。只做显示两行的程序,即一次输入数据+回车之后程序输出并直接退出。(程序不考虑健壮性,默认所有输入是正确的)
下面直接上代码~
代码如下:
DATAS SEGMENT
DB 16 DUP(0) ;该段内存作为存储输入字符串的空间,在程序中被用来模拟栈空间,但不是真正的栈
DB 100 DUP(0) ;用来存放结果
DATAS ENDS
STACKS SEGMENT
DW 200 DUP(0)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV SI,0 ;将SI设置为存放字符串的内存地址的首地址
CALL GETSTR
MOV AH,4CH
INT 21H
GETSTR: ;处理键盘输入的子程序
PUSH AX
GETSTRS:
MOV AH,0
INT 16H
CMP AL,20H ;判断从键盘得到的输入是否为字符
JB NOCHAR
MOV AH,0 ;字符入栈
CALL CHARSTACK
MOV AH,2 ;显示字符
MOVDX,0 ;位置为第0行、第0列
CALL CHARSTACK
JMP GETSTRS NOCHAR
NOCHAR:
CMP AH,0EH
JE BACKSPACE
CMP AH,1CH
JE ENTERS
JMP GETSTRS BACKSPACE
BACKSPACE: ;处理退格键
MOV AH,1 ;字符出栈
CALL CHARSTACK
MOV AH,2 ;显示字符
MOV DX,0 ;位置为第0行、第0列
CALL CHARSTACK
JMP GETSTRS ENTERS
ENTERS: ;处理确认键
CALL TRANSFER ;对当前字符串进行转换
CALL SHOWRESULT ;显示结果
POP AX
RET
CHARSTACK: ;对输入的字符进行处理,ah=0,调用CHARPUSH,字符入栈,ah=1,调用CHARPOP,字符出栈,ah=2,调用CHARSHOW,显
示字符串
JMP SHORT CHARSTART
TABLE DW CHARPUSH,CHARPOP,CHARSHOW
TOP DW 0 ;表明了字符串中字符的个数
CHARSTART:
PUSH BX
PUSH DX
PUSH DI
PUSH ES
CMP AH,2
JA SRET
MOV BL,AH
MOV BH,0
ADD BX,BX
JMP WORD PTR TABLE[BX]
CHARPUSH: ;字符入栈
MOV BX,TOP
MOV [SI][BX],AL
INC TOP
JMP SRET CHARPOP
CHARPOP: ;字符出栈
CMP TOP,0 ;判断字符串是否为空
JE SRET
DEC TOP
MOV BX,TOP
MOV AL,[SI][BX]
JMP SRET CHARSHOW
CHARSHOW: ;显示字符串
MOV BX,0B800H
MOV ES,BX
MOV AL,160
MOV AH,0
MUL DH ;计算行位置
MOV DI,AX
ADD DL,DL ;计算列位置
MOV DH,0
ADD DI,DX ;计算字符串在屏幕上显示的位置
MOV BX,0
CHARSHOWS:
CMP BX,TOP
JNE NOEMPTY
MOV BYTE PTR ES:[DI],' '
JMP SRETNOEMPTY
NOEMPTY:
MOV AL,[SI][BX]
MOV ES:[DI],AL
MOV BYTE PTR ES:[DI+2],' '
INC BX
ADD DI,2
JMP CHARSHOWSSRET
SRET:
POP ES
POP DI
POP DX
POP BX
RET
TRANSFER: ;对输入的字符串进行转换,将结果保存至内存
PUSH AX
PUSH CX
PUSH DX
MOV BX,TOP ;得到栈顶的位置
CMP BX,0 ;如果栈为空,则直接退出
JE QUIT
SUB BX,1
MOV AH,[BX] ;得到栈顶前的字符
CMP AH,48H ;判断输入的字符是否为H,及字符串是否为16进制数
JE HTOB
CMP AH,68H ;判断输入的字符是否为h,及字符串是否为16进制数
JE HTOB
JMP DTOB HTOB
HTOB: ;处理16进制数的转换,运用移位指令shl,不使用除法计算
MOV CX,TOP
SUB CX,1 ;得到16进制数的位数
MOV BX,0
MOV DI,16 ;将di设置为保存结果的内存的起始地址
AGAIN: ;外层循环,对16进制数的每一位进行转换
MOV AH,[BX]
PUSH CX ;将cx入栈,内层循环也要用到cx
MOV CX,4 ;移位的次数
CMP AH,39H ;判断该位的字符是否为数字
JA chars
SUB AH,30H ;将ASCII码转换为数字的真实值
JMP dochars
chars: ;对A-F和a-f进行处理
AND AH,11011111B ;先一律将字符转换成大写
SUB AH,37H ;将ASCII码转换为数字的真实值
do:
SHL AH,1 ;将转换好的数字向左移位四次,及将值提到ah的高四位
SHL AH,1
SHL AH,1
SHL AH,1
inagain: ;内部循环四次,将ah中的高四位通过左移位取出,存到内存中
SHL AH,1
PUSHF
POP DX
AND DL,00000001B ;将标致寄存器中的CF位取出
ADD DL,30H ;将数字转换成ASCII码
MOV [DI],DL
INC DI
LOOP inagain
POP CX ;将cx出栈,进行外层循环的检测
INC BX
LOOP AGAIN
JMP QUIT DTOB
DTOB: ;处理10进制数的转换,运用移位指令shl,不使用除法计算
MOV CX,TOP ;得到10进制数的位数
MOV BX,0
MOV DI,16 ;将di设置为保存结果的内存的起始地址
MOV DX,0 ;转换完成的10进制数
AGAIN2: ;将字符串转换成10进制数字
MOV AL,[BX]
SUB AL,30H ;将ASCII码转换为数字
MOV AH,0
CALL TENPOWER ;调用10的n次方方法,n=cx-1,结果存在ax中
ADD DX,AX ;将每个位上的值累加到dx上
INC BX
LOOP AGAIN2
MOV CX,16 ;移位的次数
CMP DX,0 ;考虑0的情况
JNE AGAIN3 ;如果不是0,则直接进入正常处理
MOV DL,30H ;是0的话,直接向内存中写0的ASCII码
MOV [DI],DL
ADD DI,1
JMP QUIT AGAIN3
AGAIN3: ;进行移位处理的循环
SHL DX,1
PUSHF
POP AX
AND AL,00000001B
CMP AL,0 ;将前面的0在显示时省略掉
JNE continue ;如果不是0则直接写入内存
MOV SI,16 ;如果是0,则查看内存中存储结果的第一个字符,若是31h及1的ASCII码表示,将结果直接写入内存
MOV AH,[SI]
CMP AH,31H
JE continue ;如果内存中存储结果的第一个字符不是1,则将得到的0省略掉,不予显示
SUB CX,1 ;因为不经过loop语句,须将cx值减1
JMP AGAIN3 continue
continue:
ADD AL,30H
MOV [DI],AL
INC DI
LOOP AGAIN3 QUIT
QUIT:
POP DX
POP CX
POP AX
RET
TENPOWER: ;10的n次方方法,用于将字符串转化成10进制数
PUSH CX
PUSH BX
PUSH DX
SUB CX,1
CMP CX,0
JE EXIT
MOV BX,10
power:
MUL BX
LOOP power EXIT
EXIT:
POP DX
POP BX
POP CX
RET
SHOWRESULT: ;按下enter键后,用于显示结果的方法
PUSH AX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
MOV AX,0B800H
MOV ES,AX
SUB DI,16 ;di为每次存储结果结束时内存中的下表,减去16及为结果的位数,用作循环的次数
MOV CX,DI
MOV DI,160
MOV SI,16
show:
MOV DL,[SI]
MOV BYTE PTR ES:[DI],DL
ADD DI,2
INC SI
LOOP show
POP SI
POP DI
POP DX
POP CX
POP AX
RET
CODES ENDS
END START
说明:
1、将10进制和16进制转换成2进制的方法没有采用递归除法方式,而是采用了移位方法,通过shl指令以及读取标致寄存器的cf位得到2进制表示
2、对输入的要求,首先必须是正确的输入,然后是对输入位数的限制,对于16进制数而言,最多输入16位(包括最后的h),没办法,代码中我就给了这么大的空间,对于10进制而言,因为没有考虑大整数的情况,所以显示结果最多为16位,及输入的数不要大于65535(一个16位寄存器支持的最大整数)即可,否则的话就出现溢出了~
相关文章推荐
- js实现从10进制转换为2/8/16进制
- PHP进制转换[实现2、8、16、36、64进制至10进制相互转换]
- 链栈实现10进制转换2进制
- c# 中 2进制、8进制、10进制、16进制...各种进制间的轻松转换
- 关于2进制,8进制,16进制间的转换问题
- 2进制、8进制、10进制、16进制...各种进制间的轻松转换(c#)
- VC++ 中实现进制2进制,10进制,16进制的相互转换
- VC++ 中实现进制2进制,10进制,16进制的相互转换
- 2进制、8进制、10进制、16进制...各种进制间的轻松转换(c#) (转载)
- 汇编语言中常用进制数据输出的程序实现
- ntohs的一个简单实现(将网络流中用两个字节16进制表示的资源数(如DNS)和长度转换为整形)
- 进制数转换器的VB算法实现(2/8/10/16进制数可以相互转换)
- 数据结构的应用——使用栈实现十进制到其他(2、8、16)进制的转换
- 2进制、8进制、10进制、16进制...各种进制间的轻松转换(c#)
- 汇编语言:实现大小写字母转换
- C# 2进制、8进制、10进制、16进制...各种进制间的转换(三) 数值运算和位运算
- 数据结构的应用——使用栈实现十进制到其他(2、8、16)进制的转换
- C# 2进制、8进制、10进制、16进制...各种进制间的转换(一) convert 类中的方法
- vb.net 2进制、8进制、10进制、16进制...各种进制间的轻松转换
- 汇编语言中常用进制数据输出的程序实现