单片机汇编指令集中,每条指令均有长度,这个长度,其实指的是这条指令的机器代码的字节长度。每条指令的机器代码中,第一字节必然是机器指令码,其它字节则是操作数。 数据要在不同存储位之间传输,首先必须在指令中明确操作数的所在存储器种类和地址,即必须明确源操作数在哪种存储器中、其地址在哪,目的操作数在哪种存储器中,其地址在哪。 我们举一个例子: 汇编指令:MOV R0,#data 汇编程序中例子:MOV R0,#22H 程序功能说明:将十进制数据22送入寄存器R0中,即把程序存储器中的一个数据22H,送入数据存储器中的工作寄存器R0中。 机器指令: 1001110 00010110 (即78H 22H,前面78H为操作指令码,后面22H为被操作数(一般称为源操作数))。 该指令中的源操作数存于程序存储器这类存储器中,其地址为紧跟操作指令码78H所在单元之后的一个单元; 目的地为数据存储器中低128B区中,其地址为R0的地址。 我们来看看在这条指令中,是如何明确这几个内容的: 源操作数所在存储器种类:操作指令码直接明确指出为程序存储器; 源操作数所在程序存储器中的地址:操作指令码直接明确指出在操作指令码之后的一个单元中; 目的操作数所在存储器种类:操作指令码直接明确指出为数据存储器中; 目的操作数所在数据存储器中的地址:数据存储中低128B中的R0(如果是第一组工作寄存器,则其地址为00H)。 综上所述,我们可以明白,51单片机为“将程序存储器中机器指令码之后的一个单元中的数据送入单片机内工作寄存器R0,单设计了一条机器指令码。同样的,51单片机也为R1~R7各自对应设计了一条机器指令码,对应的为79H~7FH。 该条指令为2字节指令,执行完成后,PC值+2。 吐槽:51单片机为8位机,最多只能做到256条机器指令码,这每一个位置都是宝贵的资源。象这样8个工作寄存器每个都对应设计一条机器指令码,显然不是最优化设计,在这种功能上平时也用不了这么多吧。也许是51出来得太早,当时考虑得并不是那么科学合理吧。现在要改也不是不行,但是兼容性是个绕不过去的坎。 处理器操作过程:处理器从程序存储器中取出78H,并被当作指令被送入指令解析控制器;指令解析控制器见到是78H,立即解析成将程序存储器中下一个地址中的内容取出并将其当作操作数送入R0中。(如果程序存储器中存的不是78H而是79H,那么紧随其后的内容就会被送入R1而不是R0,汇编程序就写成MOV R1,#22H)。操作完成后,程序存储中的下一个内容将被当作操作指令码。 解读:从以上过程可以看出,现有汇编语言所称的立即数,其实是指存于程序存储器中紧随操作指令所在地址之后的一个地址中的内容。所以,以上程序例子可以这样解读:将一个操作数据送入R0中,该数据原存放于程序存储器中该操作指令所在地址之后的一个地址中;或者说将程序存储器中的一个数据送入R0中,该数据原存放于程序存储器中该操作指令所在地址之后的一个地址中。PC值的变化与该指令的字节长度一致。 该指令功能的其它实现方法:我们知道数据存储器低128B区是可以直接寻址的,所以,我们也可以用MOV direct,#data这个比较通用的语句来实现,其中的direct ,直接写成R0的地址就是了。但是,这就变成了3字节指令,单片机的执行时间必然延长,且只能使用一个固定的R0。这也是为什么本来可以用MOV direct,#data来实现却占用宝贵的资源专门来设计一类2字节指令的原因。 MOV direct,#data的机器指令码为75H,在这条语指令中,75H指出了源操作数存于程序存储器中该机器指令码之后的一个单元中,目的操作数在数据存储器中,其地址则由direct指定。 另外再细说明一下,教材中所指的“立即数”、“立即寻址”,其实就是指该数据存于机器指令码之后的一个单元中,该数据在汇编工具将整个程序汇编成机器码时,紧跟在该机器指令码之后,烧写工具按其顺序写入程序存储器中。 个人见解,不妥之处请高手指正。
|