單片機匯編指令集中,每條指令均有長度,這個長度,其實指的是這條指令的機器代碼的字節長度。每條指令的機器代碼中,第一字節必然是機器指令碼,其它字節則是操作數。 數據要在不同存儲位之間傳輸,首先必須在指令中明確操作數的所在存儲器種類和地址,即必須明確源操作數在哪種存儲器中、其地址在哪,目的操作數在哪種存儲器中,其地址在哪。 我們舉一個例子: 匯編指令: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指定。 另外再細說明一下,教材中所指的“立即數”、“立即尋址”,其實就是指該數據存于機器指令碼之后的一個單元中,該數據在匯編工具將整個程序匯編成機器碼時,緊跟在該機器指令碼之后,燒寫工具按其順序寫入程序存儲器中。 個人見解,不妥之處請高手指正。
|