芯片解密技术员解析单片机寻址方式与指令系统
由以前的研究中,我们了解了微控制器的内部结构,并已经知道,控制微控制器,让它干我们学习使用指导,我们学到了一些命令,但它是琐碎的,从现在开始,我们将系统地研究了8051指令的一部分。
一、概述
1、指令的格式
我们已知,要让计算机做事,就得给计算机以指令,并且我们已知,计算机很“笨”,只能懂得数字,如前面我们写进机器的75H,90H,00H等等,所以指令的第一种格式就是机器码格式,也说是数字的形式。但这种形式实在是为难我们人了,太难记了,于是有另一种格式,助记符格式,如MOV P1,#0FFH,这样就好记了。 这两种格式之间的关系呢,我们不难理解,本质上它们完全等价,只是形式不一样而已。
2、汇编
我们用汇编格式的指示,只知道计算机和微处理器的机器代码格式,所以我们写的成机器代码格式编制格式的指示,这样的转换,有两种选择:手工汇编和机器组装。手册汇编实际上是一个查找表,因为这两种格式是不相同的格式,它是十二时五十九分,检查名单上的表。但是,手动查表总是麻烦,所以将有计算机软件,利用计算机软件来替代手工查表,这就是机器汇编。
二、单片机的寻址
让我们先来复习一下我们学过的一些指令:MOV P1,#0FFH,MOV R7,#0FFH这些指令都是将一些数据送到对应的位置中去,为什么要送数据呢?第一个因为送入的数能让灯全灭掉,第二个是为了要实现延时,从这里我们能看出来,在用单片机的编程语言编程时,经常要用到数据的传递,事实上数据传递是单片机编程时的一项重要工作,一共有28条指令(单片机共111条指令)。下面我们就从数据传递类指令开始吧。
分析检验MOV P1,#0FFH这个指示,我们可以得出结论,检验手段的第一个字是一个命令动词,它已决定做某件事,检验手段不足采取的步骤写了E,它是“转移”,这是一个令认为做任何事情,有许多参数,分析数字,数据传输,必须有一个“源”这是你要发送的少数人,必须有“目的”,这就是你这个数字要发送到地方去,显然是上述单片机指令之一,要派几个(源)是0FFH,但在本地(送达目的地)是小的登记册。在数据传输型指令是在背面写教学目标,而将源写在最后
这条指令中,送给P1是这个数本身,换言之,做完这条指令后,我们能明确地知道,P1中的值是0FFH,但是并不是任何时候都能直接给出数本身的。例如,在我们前面给出的单片机延时程序例是这样写的:
MAIN: SETB P1.0 ;(1)
LCALL DELAY ;(2)
CLR P1.0 ;(3)
LCALL DELAY ;(4)
AJMP MAIN ;(5)
以下子程序
DELAY: MOV R7,#250 ;(6)
D1: MOV R6,#250 ;(7)
D2: DJNZ R6,D2 ;(8)
DJNZ R7,D1 ;(9)
RET ;(10)
END ;(11)
MAIN: SETB P1.0 ;(1)
MOV 30H,#255
LCALL DELAY ;
CLR P1.0 ;(3)
MOV 30H,#200
LCALL DELAY ;(4)
AJMP MAIN ;(5)
;以下子程序
DELAY: MOV R7,30H ;(6)
D1: MOV R6,#250 ;(7)
D2: DJNZ R6,D2 ;(8)
DJNZ R7,D1 ;(9)
RET ;(10)
END ;(11)
这样一来,我每次调用延时程序延时的时间都是相同的(大致都是0.13S),如果我提出这样的要求:灯亮后延时时间为0.13S灯灭,灯灭后延时0.1秒灯亮,如此循环,这样的程序还能满足要求吗?不能,怎么办?我们能把延时程序改成这样(见表2):调用则见表2中的主程,也就是先把一个数送入30H,在子程序中R7中的值并不固定,而是根据30H单元中传过来的数确定。这样就能满足要求。
由此我们可以得出结论,数据传输是要找出通过几个,很多时候,这个数字不能直接给予改变,从而导致需要一个概念:如何寻找操作,我们必须找到在操作该单位的地址被称为解决。在这里我们直接使用了宿主细胞的地址编号,以找到运作数,所以称这种方法为直接寻址。除了这种方法,有一个,如果我们把工作的登记号码,并从工作寄存器找到数据,当时称为寄存器寻址。例如:mov甲,R0是在R0工作寄存器的数据发送到累加器阿,去。问一个问题:我们知道,工作寄存器内存单元的一部分,如果我们选择工作寄存器0,则R0是内存,从00单位,那么这样的结果,检验手段阿,从00,和MOV甲,R0是在没有它的不同呢?我们为什么要区分呢?事实上,这两个指令的执行结果是完全相同的,这些从00细胞的所有内容发送到,去,但在执行过程中不作为的第一条指令的执行情况同样需要2个周期,而第二只需要一周期,成为第一条指令的代码的最终目标是两个字节(E5H从00),而第二,只要一个字节(E8h)可以是一个。
这么斤斤计较!不就差了一个周期吗,如果是12M的晶体震荡器的话,也就1个微秒时间了,一个字节又能有多少?
不对,如果这条指令只执行一次,也许无所谓,但一条指令如果执行上1000次,就是1毫秒,如果要执行1000000万次,就是1S的误差,这就很可观了,单片机做的是实时控制的事,所以必须如此“斤斤计较”。字节数同样如此。
再来提一个问题,现在我们已知,寻找操作数能通过直接给的方式(立即寻址)和直接给出数所在单元地址的方式(直接寻址),这就够了吗?
看这个问题,要求从30H单元开始,取20个数,分别送入A累加器。
就我们目前掌握的办法而言,要从30H单元取数,就用MOV A,30H,那么下一个数呢?是31H单元的,怎么取呢?还是只能用MOV A,31H,那么20个数,不是得20条指令才能写完吗?这里只有20个数,如果要送200个或2000个数,那岂不要写上200条或2000条命令?这未免太笨了吧。为什么会出现这样的状况?是因为我们只会把地址写在指令中,所以就没办法了,如果我们不是把地址直接写在指令中,而是把地址放在另外一个寄存器单元中,根据这个寄存器单元中的数值决定该到哪个单元中取数据,比如,当前这个寄存器中的值是30H,那么就到30H单元中去取,如果是31H就到31H单元中去取,就能解决这个问题了。怎么个解决法呢?既然是看的寄存器中的值,那么我们就能通过一定的办法让这里面的值发生变化,比如取完一个数后,将这个寄存器单元中的值加1,还是执行同一条指令,可是取数的对象却不一样了,不是吗。通过例程来说明吧。
MOV R7,#20
MOV R0,#30H
LOOP:MOV A,@R0
INC R0
DJNZ R7,LOOP
这个例程,我们能够理解大部分的指示,第一句,是20号会立即传送到R7版本中的价值的r7将用尽应为20的执行情况。二是在30h内人数将立即传送到寄存器R0的工作,所以用尽,R0单位价值在30小时执行,第三句,这是在什么单位价值了R0,看看这个价值地址,考虑到该地址的A,这个时候,这个指令执行的结果单位的内容是为MOV相当于甲,30h内。第四句,从来没有学会,是添加得到R0值,因此,执行用尽,R0是价值31H,第五句,教训,将r7将在一个价值的减少,看它是否等于0,不等于0,然后到标签回路办公室继续执行,因此,刑罚的执行完毕,将转向阿的检验手段的实施,@ R0这句话,这一次是相当于执行的检验手段甲,31H(因为这在时间的价值R0是31H 1),因此,直到r7将连续减法的价值等于0,即周期20倍,到目前为止,实现我们的要求,从30h内:单位开始分为A,20个数据。这也是一种方法找到数据,因为数据是间接地被发现,因此,我们所谓的跨站点地址。请注意,在站点间得到R0或R1地址只可以用于数据存储等。