这是我单片机实验作业的源码,统计正负数个数。写得不好,仅供参考。如有BUG,欢迎指正。
;;;;本程序从键盘获取输入,并统计输入的正整数和负整数的个数,结果存于40H、41H;
;;;;此处把0归于正数。数值范围 -128 - 127
ORG 00H
LCALL GETKEY ;从键盘获取数据,输入的必须是十进制整数,可带负号,每个整数之间必须有其他字符
LCALL Static ;统计正负数个数
SJMP $
;; 统计正负数个数
Static:
MOV R1, #30H ;数据地址指针
MOV 41H, #00H ;统计正数个数 由于统计用地址单元与数据区单元很近,数据区最多存放16个数据
MOV 40H, #00H ;统计负数个数
MOV 90H, R7
MOV R2, 90H ;R2存放数据个数
WHIL: ;取下一个数,判断正负
MOV A, @R1
JB ACC.7, Nege
INC 40H ;正数
SJMP IncR
Nege:
INC 41H ;负数
IncR:
INC R1
DJNZ R2, WHIL
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 Deci
RET
;提示字符串:Enter a group decimal integer:
MSG: DB 0x45,0x6e,0x74,0x65,0x72,0x20,0x61,0x20,0x67,0x72,0x6f,0x75,0x70,0x20,0x64,0x65,0x63,0x69,0x6d,0x61,0x6c,0x20,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,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
;;可转化的字符串格式:-12, 30, -45 每个数之间必须有其他字符隔开 -12@34 也行 表示-12和34
Deci:
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
JNZ Trans ;
SETB 0D1H ;A=0,为字符串结束标志, 标记结束
SJMP Derive ; 并跳转,合成最后一个整数
Trans:
CLR C
SUBB A, #30H ;将字符转化为数字
JC Neg ;C=1,A<30H。不是数字, 跳转去判断是否为负号
CJNE A, #0AH, C1 ;大于等于10,C=0
C1:JNC Derive ;大于等于10, C=0,不是数字,数字结束转去合成
MOV @R1, A ;将转化后的数字存进中间结果单元
INC R1 ;后移中间结果位置
INC R2 ;记录中间结果位数
SJMP While
Neg:
MOV A, @R0
CLR C
SUBB A, #2DH
JNZ Derive ;不是负号,转去合成
SETB F0 ;标记为负数
SJMP While
Derive: ;将中间结果合成为最后结果
CJNE R2, #00H, Deri ;判断R2是否为0
JNB 0D1H, While ;判断是否结束 0D1H != 1 继续循环
SJMP Over ;0D1H = 1 结束
Deri:
MOV R1, #90H ;将R1重新指向开始位置
CLR A
Der:
MOV B, #0AH
MUL AB
ADD A, @R1
INC R1
DJNZ R2, Der
JNB F0, Stor ;是正数,跳转,直接保存
XRL A, #0FFH
INC A
CLR F0
Stor:
MOV 90H, A ;先把结果存进90H, 再存进30H
MOV A, R3 ;R3不能间址,只好借助其他寄存器
INC R3
INC R7
MOV R1, A
MOV @R1, 90H
MOV R1, #90H
JNB 0D1H, While ;结束标志位不为1,则继续读取字符串
Over:
RET
END