您的位置:首页 > 其它

用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位寄存器支持的最大整数)即可,否则的话就出现溢出了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: