前言
不同的架构不同的指令系统,没事别乱学汇编。
我现在学的是51单片机的汇编,运行在Keil5上。希望慢慢熟悉更多的指令,因为更多的指令意味着更多的选择,在实现功能时能更轻松一点。
玩硬件的我又穷又头痛,就这个小任务我写了一天了才做出来。最后的效果可以清楚显示从00到16的值,但是更多的次数就会出错了。
先贴出全部代码,下面再解释
org 0000h
sjmp main
main:
mov dptr,#TAB
mov r0,#0
start:
mov p3,#0fh
message:
mov a,p3
anl a,#0fh
cjne a,#0fh,show
ljmp message
show:
mov a,r0
clr c
subb a,#10
jnc normal ;无借位
mov a,#0
lcall show_shiwei
mov a,r0
ljmp just_show_geiwei
normal:
push acc ;保存减去10后的a的值
mov a,#1
lcall show_shiwei
pop acc
just_show_geiwei:
movc a,@a+dptr
mov p2,#0e3h
mov p0,a
lcall delay
INC r0
ljmp start
show_shiwei:
movc a,@a+dptr
mov p2,#0e7h
mov p0,a
lcall delay
ret
delay:
mov r3,#200
L1:
mov r4,#500
djnz r4,$
djnz r3,L1
ret
TAB:
db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,77h,7ch,39h,5eh,79h,71h
end
- 标识符确定的模块放的位置很关键。如果是单独的函数,那么需要放在程序底下(END前)或者顶上(ORG 000H下)的一些边缘位置。如果是程序内的循环和条件判断需要特别考虑。这些是一些编程规范(不这么写也许行)
- 汇编也没有函数的定义,并且对于玩过《7 Billion Humans》的人来说,难度不是很大。毕竟益智类的编程游戏没有函数概念,只有跳转和判断。在汇编中,没有单独的条件判断,其必须由条件跳转来实现---------下面黑框中,向上跳的绿色表示这是一个循环。向下跳的蓝色箭头表示这是一个判断。
延迟模块,DJNZ跳转语句表示减一不为0跳转
先给寄存器R3送一个数
再给寄存器R4送一个数
接着拿R4减一,再原地跳转
然后拿R3减一,跳到L1标识符处
RET返回
delay:
mov r3,#200
L1:
mov r4,#500
djnz r4,$
djnz r3,L1
ret
TAB也是自定义表示符,DB表示从当前PC(程序指针)所指向的地址开始放入数据,放一个PC指针移动一个单元。
TAB:
db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,77h,7ch,39h,5eh,79h,71h
开头的部分分别是
开头两行:确定PC起点,跳到MAIN标识符处
把TAB标识符的地址给DPTR这个16位指针
把0送给R0寄存器,也就是这个寄存器用于计数
然后这个START标识符的意义是每次显示完,再跳回START初始化P3
- 我单片机独立按键k1=P3.1 k2=P3.0 k3=P3.2 k4=P3.4
- 不同的单片机或是自己做的或是Proteus仿真的情况不同就可能是另外情况了
org 0000h
sjmp main
main:
mov dptr,#TAB
mov r0,#0
start:
mov p3,#0fh
这个是程序的核心部分之一。属于等待按键输入模块。
我的按键输入是P3的三个口,所以先把P3传递给累加器A
然后用ANL与操作来屏蔽高4位
CJNE表示两者数值不同就跳转(相当于前者减后者,如果为零就跳转---------如果前者大,那么PSW寄存器的进位位C是1,否则是0)
独立按键是为零就表示闭合了。
拿累加器A的值和00001111比较,如果低4位某个位0,那么一定有键被按下
最后是一个LJMP长跳转,跳回MESSAGE标识符
message:
mov a,p3
anl a,#0fh
cjne a,#0fh,show
ljmp message
下面这个就是如何把R0计数的值显示出来的核心部分了
P3作为按键输入
P0作为数码管显示输出
P2作为数码管片选控制
show:
mov a,r0 ;把R0计数的值传给A
clr c ;清楚进位C
subb a,#10 ;带进位的相减,(A) = (A)- 10
jnc normal ;无借位 ;如果没有产生进位,表示按键次数超过9
;有进位,向下执行 表示按键次数不超过9
mov a,#0 ;设置十位的值为0
lcall show_shiwei ;调用显示10位的函数
mov a,r0 ;个位部分还是正常的,所以要再把R0传过来
ljmp just_show_geiwei
normal:
push acc ;保存减去10后的a的值 把A的值压如栈
mov a,#1 ;设置十位的值为1
lcall show_shiwei ;调用显示10位的函数
pop acc ;把值取出传给A
just_show_geiwei:
movc a,@a+dptr
mov p2,#0e3h
mov p0,a
lcall delay
INC r0
ljmp start
;显示十位的共同部分
show_shiwei:
movc a,@a+dptr ;把TAB的地址和偏移量A表示的表里的值取出,传给A
mov p2,#0e7h ;1110 0111选择倒数第二片
mov p0,a ;显示
lcall delay ;延迟
ret ;函数返回