SMS32V50汇编循环时钟代码解析及疑问解答
SMS32V50汇编循环时钟代码解析与疑问解答
1. DB后的数值是什么?是否为ASCII码?
这些数值绝对不是ASCII码,它们是给七段数码管用的段码——简单说就是用来控制数码管亮哪些段,从而显示0-9这些数字的二进制编码。
你肯定知道ASCII码里数字'0'到'9'对应十六进制值是0x30到0x39,和代码里的FA、0A完全不搭边。七段数码管有7个发光条(标记为a-g段),部分还带小数点,用一个字节的每一位对应一段的亮灭(比如1代表点亮、0代表熄灭,或者反过来,取决于数码管是共阳极还是共阴极类型)。代码里的注释已经标得很清楚:DB FA ; 0就是说FA这个值能让数码管显示数字0,DB 0A ; 1对应显示数字1,以此类推,这些都是根据硬件预先调试好的编码。
2. 为何要给BL寄存器加03?
这是为了找对段码在内存中的存储位置,咱们捋清楚内存布局就懂了:
- 代码第一行的
JMP start是跳转指令,在SMS32V50架构中这条指令占据2个字节的内存空间(地址00H和01H)。 - 后面10个
DB存储的段码,是从内存地址02H开始排列的:02H是数字0的段码FA,03H是数字1的段码0A,一直到0BH是数字9的段码DE。
再看代码里的数字处理逻辑:
- 处理个位时,
MOD BL, 0A把当前计数值(0-59)除以10取余数,得到0-9的个位数字并存入BL。 - 处理十位时,
DIV BL, 0A把计数值除以10取商,得到0-5的十位数字并存入BL。
要从内存中取出对应数字的段码,必须让BL的值等于段码所在的内存地址才行。这里加03,就是把数字n(0-9)转换成对应的段码地址——比如数字0加03得到03H,对应数字1的段码?别急,看代码里个位处理完取段码后还加了INC AL,说明存储的段码是实际需要输出的值减1,加1之后就匹配个位数码管的硬件要求了。十位不需要加1,可能是十位数码管的硬件定义不同,但核心逻辑就是:加03是为了让计算出的数字偏移到段码存储的内存区域,确保能拿到正确的显示编码。
完整代码逐行解析
JMP start ; 先跳转到start标签,跳过下面的段码定义(避免把段码当指令执行) DB FA ; 0 ; 存储数字0的七段段码(十六进制,对应数码管亮段的编码) DB 0A ; 1 ; 存储数字1的段码 DB B6 ; 2 ; 存储数字2的段码 DB 9E ; 3 ; 存储数字3的段码 DB 4E ; 4 ; 存储数字4的段码 DB DC ; 5 ; 存储数字5的段码 DB FC ; 6 ; 存储数字6的段码 DB 8A ; 7 ; 存储数字7的段码 DB FE ; 8 ; 存储数字8的段码 DB DE ; 9 ; 存储数字9的段码 start: MOV DL, 00 ; 初始化计数值DL为0,从0开始计数 start1: MOV [90], DL ; 将当前计数值存入内存地址90H的单元,方便后续复用 MOV BL, [90] ; 从90H单元读取计数值到BL MOD BL, 0A ; BL = 计数值 % 10,计算得到个位数字(例如59的个位是9) ADD BL, 03 ; 将个位数字转换为对应段码的内存地址 MOV AL, [BL] ; 从BL指向的地址取出段码到AL INC AL ; 段码加1,修正为适合个位数码管的输出值(硬件要求) OUT 02 ; 将AL的值输出到端口02H,控制个位数码管显示 MOV BL, [90] ; 再次读取计数值到BL,准备计算十位 DIV BL, 0A ; BL = 计数值 / 10,计算得到十位数字(例如59的十位是5) ADD BL, 03 ; 将十位数字转换为对应段码的内存地址 MOV AL, [BL] ; 取出十位对应的段码到AL OUT 02 ; 将AL的值输出到端口02H,控制十位数码管显示 NOP ; 空操作,用于延时(让数码管有足够时间稳定显示) NOP NOP INC DL ; 计数值加1,准备计数下一个数 CMP DL, 3C ; 比较DL和3C(十六进制3C对应十进制59) JNZ koniec ; 如果DL不等于59,跳转到koniec继续循环 MOV DL, 00 ; 如果计数值到59,重置DL为0,准备从0开始计数 JMP start1 ; 跳回start1,重新开始计数 koniec: JMP start1 ; 跳回start1,继续下一次计数循环 END ; 程序结束标记
内容的提问来源于stack exchange,提问作者Robertoo999
相关产品推荐
相关产品推荐

