本题来自实验作业。此乃我写的源码,特在此分享。仅供参考,若有不足,不吝赐教!
;;;;本程序从键盘获取输入存入片内RAM 30H为首地址的单元,R7保存十六进制数个数,R0保存最大数
ORG 00H
LCALL GETKEY ;从键盘获取数据,十六进制格式为 2FH, 不支持0x2F, 和小写字母: feH FEh
LCALL MAX ;找出最大数
SJMP $
;;从片内RAM取数,并找出最大数
MAX:
MOV R1, #30H ;数据地址指针
MOV R0, #0H ;存较大数
WHIL: ;取下一个数,比较大小
MOV A, @R1
CLR C
SUBB A, R0
JC JUD ; c=1 是个较小数,跳过
MOV A, @R1 ; 存较大数
MOV R0, A
JUD: ;判断是否还有数,有数就进入循环
INC R1
DJNZ R7, WHIL
MOV 40H, R0
RET
;;串口通信模式1初始化
initmod1:
MOV TMOD, #20H ; 设置T1为模式2
MOV TL1, #0E8H ; 装入定时常数, 波特率1200bit/s
MOV TH1, #0E8H ; 自动重装
MOV SCON, #50H ;设置串行通信模式1 ,允许接收
SETB TR1 ; 启动T1
RET
;;;获取键盘输入,数据暂存50H, 再转换成数字存进30H
GETKEY:
LCALL String ;输出提示字符串
LCALL Input ;获取键盘输入的字符串
LCALL Hex
RET
;提示字符串:Enter a group hexadecimal numbers end with H:
MSG: DB 0x45,0x6e,0x74,0x65,0x72,0x20,0x61,0x20,0x67,0x72,0x6f,0x75,0x70,0x20,0x68,0x65,0x78,0x61,0x64,0x65,0x63,0x69,0x6d,0x61,0x6c,0x20,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x20,0x65,0x6e,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x48,0x3a,0x00
;;发送字符串
String:
LCALL initmod1 ;串口通信模式1初始化
MOV DPTR, #MSG ;取发送数据区首地址
Show:
CLR A
MOVC A, @A+DPTR
JZ Finish ;检查字符是否为结束标志0H, A=0,则字符输出完成
MOV SBUF, A ;在UART窗口显示字符
CLR TI
JNB TI, $
INC DPTR
SJMP Show
Finish:
CLR TR1 ;关闭定时器T1
RET
;;读取键盘输入字符串并存入以50H为首地址的单元
Input:
LCALL initmod1 ;串口通信模式1初始化
MOV R0, #50H ;设接收数据的地址指针为R0
Read: ;从UART窗口读取数据并打印
CLR RI
JNB RI, $
MOV A, SBUF
CJNE A, #0DH, Continue ;检查回车字符0DH, 不是回车继续读取
SJMP ReadOver ;回车字符,结束读取
Continue: ;打印用户输入并保存
MOV SBUF, A ;打印接收到的数据
CLR TI
JNB TI, $
CJNE A, #08H, Store ;检查退格字符\b, 不是退格,则保存数据
DEC R0 ;是退格,数据指针回退
SJMP Read
Store:
MOV @R0, A ;保存数据
INC R0 ;后移数据指针
SJMP Read ;循环读取
ReadOver: ;读取结束,在字符串后加上结束符0H
MOV @R0, #00H
CLR TR1 ;关闭定时器
RET
;;将首地址为50H的单元中的字符串转化为十六进制数,存30H, 个数存R7
Hex: ;注意十六进制字母不支持小写
MOV R3, #30H ;R3指向存放十六进制数的地址
MOV R1, #90H ;R1指向存放中间结果的地址
MOV R2, #00H ;R2存放中间结果的位数
MOV R0, #50H ;R0指向数据源
MOV R7, #00H ;R7存放最后结果个数
SJMP Wh
While:
INC R0 ;有些分支直接跳转过来,R0还没加1,只好这样做了。
Wh:
MOV A, @R0
JZ TransOver ;A=0,为字符串结束标志
CLR C
SUBB A, #48H ;检查是否为十六进制后缀H 48H
JZ Derive ;A=0,跳转。将前面的数字合成一个数字
MOV A, @R0
CLR C
SUBB A, #30H ;将字符转化为数字
JC While ;C=1,A<30H。不是数字
CJNE A, #0AH, C1 ;大于等于10,C=0
C1:JC It ;小于10, C=1,跳转,标号必须首字母大写
CLR C
SUBB A, #07H ;大于10,再减7,可得字母对应的十六进制数字
CJNE A, #0AH, C2 ;与10比较
C2:JC While ;结果小于10,不是十六进制字符
CJNE A, #10H, C3 ;与16比较
C3:JNC While ;大于等于16,不是十六进制字符
It: ;小于10大于0直接存数
MOV @R1, A ;将转化后的数字存进中间结果单元
INC R1 ;前后移中间结果位置
INC R2 ;记录中间结果位数
SJMP While
Derive: ;将中间结果合成为最后结果
MOV R1, #90H ;将R1重新指向开始位置
CLR A
Der:
MOV B, #10H
MUL AB
ADD A, @R1
INC R1
DJNZ R2, Der
MOV 90H, A ;先把结果存进90H
MOV A, R3 ;R3不能间址,只好借助其他寄存器
INC R3
INC R7
MOV R1, A
MOV @R1, 90H
MOV R1, #90H
SJMP While
TransOver:
RET
END