单片机汇编之查找最大数

本题来自实验作业。此乃我写的源码,特在此分享。仅供参考,若有不足,不吝赐教!

;;;;本程序从键盘获取输入存入片内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
posted @ 2020-11-12 08:22  流水自净  阅读(1226)  评论(0编辑  收藏  举报