由程序状态标志寄存器psw中的rs1和rs0两位决定的,rs1=0,rs0=0,则选择的是工作寄存器0组,rs1=0,rs0=1,则选择的是工作寄存器1组,rs1=1,rs0=0,则选择的是工作寄存器2组,rs1=1,rs0=1,则选择的是工作寄存器3组,只要改变rs1和rs0的值就可以改变当前工作寄存器。
只要把汇编指令都写出来了,你就可以到指令表中找到每一条指令所对应的机器码,然后你只要在机器码后面加上操作数即可,比如,把一个30H单元送入A累加器;指令是这样的:MOV A , 30H .那么你可以在指令表中查到执行这条指的机器码是1110 0101,但是由于这条指令后面的那个30H单元的数是根据你的要求在不断的变的,机器没规定你只能用30H单元,所以这个30的操作数必须由你填,它们和在一块儿,这条指令的机器码是:1110 0101 0011 0000用十六进制来表示:E530,很明显前两位E5是机器指定的,而后两位30是你自己加进去的。共是十六位,占用两个字节……。
你说的LED灯闪烁,不知是指的流水灯还是一只发光二极管在不停地闪烁?但不管是哪一种,有一点很重要。你在编写此程序时必须要考虑延时,因为51单片机的晶体振荡器最低频率可能是6M(具体数值我已记不清了)。也就是说单片机的每一个机器周期所占用的时间仅2微秒,如果你不考虑延时的话,那么你设计的那盏灯,它闪烁的结果是;亮2微秒,熄2微秒,也就是说每一秒钟要亮暗50万次,肉眼看这盏灯根本就不会有熄灭的时候,只是比不闪的灯暗了一半。我们生活中用的白炽灯,每秒钟亮暗100次,你能感觉出灯泡有熄灭的时候吗?更何况那是50万次啊!
比如设计流水灯的程序,不妨可以这样考虑它的算法。计数寄存器的高八位加上低八位,合起来也只有十六位,它能数的数最大也就是65535,就算单片机用的是最低的6M的晶体振荡器,一个机器周期是12个机器节拍,所以,每一个机器周期占用2微秒时间,从0数到65535,仅用了131070微秒就数完了,约130毫秒,如果就按这个延时去改变灯的亮暗时间,那么这盏灯每秒钟要亮暗3、4次,肉眼虽然能够看到灯有熄灭的时间了。但是眼睛看这样的灯总不会那么舒服,所以至少应让它延时到1秒钟亮暗一次。为了计算方便,就让计数器数100毫秒的时间吧!等计数器数到100毫秒后,就让它再数一次,然后再数一次……,等它数满5次后,这就是500毫秒(半秒钟),然后,我们再去改变灯的亮暗状态。
这个程序可以这样来编:
MOV A ,#0FEH ;最低位设为0
MOV P1, A ;点亮最低位灯
MOV TCON,#10H ;T1为方式1,定时
BEGIN: MOV R7 ,#05H ;设循环5次
STAR: MOV TH1 #3CH ;计数器数100毫秒
MOV TL1 #AFH
SETB TR1 ;开始计数
ROU: JBC TF1 SE ;100毫秒到否?
SJMP ROU ;等待到100毫秒
SE: CLR TR1 ;关闭计数器
DJNZ R7 STAR ;5次循环到否? RL A ;把0向左移一位
MOV P1 ,A ;改下一只灯亮
SJMP BEGIN
51的单片机
ORG 0000H
MAIN:MOV R2,#2
L1:MOV R3,#200
L2:MOV R4,#200
L3:NOP
NOP
DJNZ R4,L3
DJNZ R3,L2
DJNZ R2,L1
CPL P1.7
JMP MAIN
END
Medwin编写C51汇编
这是别人的答案,不知道能不能帮到你
有个程序状态字PSW,它的第四和第三位RS1,RS0是用来选择工作寄存器组的。他们俩的值和寄存器组的关系:
RS1/RS0 0/0 0/1 1/0 1/1
使用的工作寄存器 0 1 2 3
地址 00-07 08-0F 10-17 18-1F
写程序的时候就是通过定义程序状态字来选择使用不同的寄存器组。也可以直接对RS1和RS0赋值。
只要把汇编指令都写出来了,可以到指令表中找到每一条指令所对应的机器码,然后只要在机器码后面加上操作数即可。
寄存器是CPU内部重要的数据存储资源,是汇编程序员能直接使用的硬件资源之一。由于寄存器的存取速度比内存快,所以,在用汇编语言编写程序时,要尽可能充分利用寄存器的存储功能。
寄存器一般用来保存程序的中间结果,为随后的指令快速提供操作数,从而避免把中间结果存入内存,再读取内存的操作。在高级语言(如:C/C++语言)中,也有定义变量为寄存器类型的,这就是提高寄存器利用率的一种可行的方法。
另外,由于寄存器的个数和容量都有限,不可能把所有中间结果都存储在寄存器中,所以,要对寄存器进行适当的调度。根据指令的要求,如何安排适当的寄存器,避免操作数过多的传送操作是一项细致而又周密的工作。有关“寄存器的分配策略”在后续课程《编译原理》中会有详细的介绍。