欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 匯編之51單片機尋址原理詳解(二) [打印本頁]

作者: 慢慢思考    時間: 2019-3-12 09:17
標題: 匯編之51單片機尋址原理詳解(二)
我想把第一個寫匯編教材的人痛扁一頓先。
在匯編語言中,尋址方式是我們學習的重點之一,也是難點,讓人很容易犯迷糊。個人覺得吧,這個犯迷糊的原因,不在于你,而在于,教材中有關尋址方式的一套說法,本身就很迷糊。下面,我們就尋址方式這一事,探究一下。
先說兩點很基礎的概念:一,“尋址”的方式本身就只有兩大類:一是將一個具體的地址值給處理器,一個是在機器指令碼中已經暗含了地址(寄存器);二,尋址,不應只如教材中所說的只針對源操作數(源數據),也應包括目的操作數(目的地)。教材中說的分類及解釋,反正本人覺得很那個。
提示一下,上一個貼子,是以舉例的形式,建立一些概念性的東西。
言歸正傳,下面我們展開了說:
一、“尋址”的內涵及應該做的前期工作
首先,我們弄清楚“尋址”這個概念的內涵,就是說要把一個源數據存放在存儲器中的地址,告訴處理器,這個就是尋址。萬變不離其宗,我們只要牢記,所謂“尋址”只是把地址告訴別人,至于將告訴別人地址的方式稱乎成直接尋址、間接尋址、變址尋址之類的還是稱乎成其它什么的,我們可以不管它。
我們再往前一步:要告訴別人這個地址,首先你要知道這個地址,也就是說,你要“獲得”這個地址。
再往前推,我們要把這個數據(源數據)送出去,說明這個數據已經存在某個單元中了,那么,為了“獲得”這個地址,我們就要弄明白,當初這個數據存進去的時候,它的地址是多少?是怎么確定的?
還有一點,教材中所謂的尋址的對象,指的是對源數據(源操作數)的地址的尋找,而不是目的操作數,目的操作數的地址,都是由程序員在該條程序中直接、精準地給出了的。
二、源數據存入時的地址選定方式
首先,所有源數據的存入,都是由程序員在程序中來規(guī)劃的,但是,51機芯片本身在這方面有些原則和規(guī)定,所以,我們至少應從這兩方面來了解說明。
另一方面,所有源數據存入時的地址,都是由程序員來選定的,但寫入時間分為兩種情況,一種是在程序運行前就已寫入,這個情況指的是程序存儲器中的數據;另一種情況是在程序運行中寫入,這個指的是數據存儲器中的數據,也就是中間數據和結果數據。
(一)程序存儲器中的數據
51機程序存儲器屬兩字節(jié)地址型,即每個單元的地址為16位二進制數。
1、緊跟在機器指令碼后面的單元中
也即數據存在該機器指令碼之后的一系列單元中,有多少字節(jié)數據就占用多少個單元。這里面又分為三種:一字節(jié)立即數據,如MOV Rn#data,二字節(jié)立即數據,一組數據的表數據。
屬于相對地址,基地址為該條指令的機器指令碼所在單元的地址。
2、另劃存儲區(qū)的表數據
這個就是在存儲區(qū),由程序員指定一個獨立的絕對起始地址,把一組數據順序寫進去。我們常見的ORG偽指令,就是來指定絕對起始地址的。
這個屬于絕對地址,程序員在ORG中給出了一個絕對地址數值。
(二)數據存儲器中的數據
51機數據存儲器(內部256B)屬單字節(jié)地址型,即每個單元的地址為8位二進制數。
這個是在程序執(zhí)行中才會發(fā)生數據的存入,其存儲單元的地址,也是由程序員規(guī)劃的,可以在源程序中直接指出,也可以在運行過程中通過計算得出。
源程序中直接指出地址的方式,也有幾種,一種是將其地址值寫在源程序中(燒寫后存在程序存儲器中);另一種,就是51機的指令規(guī)定了,它在機器指令碼中直接指向了存儲單元,即前面所說的機器指令碼暗含地址,這個在51機的設計中,只針對部分寄存器,想了解哪些寄存器有這種設計,看機器指令對照表就是了。
三、如何獲得源數據的地址
要想讓處理器找到地址,程序員必須讓處理先獲得地址。其實,根據源數據存入時地址的選定方式,我們很容易想到如何獲得其地址。
這個在后面結合起來講。
四、地址值放在哪并如何告訴處理器
處理器根據地址值才能找到源數據,但是,這個地址值,得先放在一個地方,讓處理器去取,所以,你得將地址值放在一個地方,并將這個地方告訴處理器。
(一)程序存儲器中的源數據的地址值(十六位地址值)
1、跟在機器指令碼后面的單個或兩個數據
這個,機器指令碼自己就知道地址,也就是說,其源數據單元地址指向已在機器指令碼中明確,就不勞你另外費心了。這個屬于立即尋址。
MOV A#data,這個是單個數據,該指令的機器指令碼為74H,這個74H自己就知道要取的數據就在自己的屁股后面。
MOV DPTR#data16,這個是兩個數據(兩字節(jié))。
2、跟在機器指令碼后面的表數據
這個地址的獲得,是以該機器指令碼的PC值作為基地址值,A中的值作為要取的源數據的順序值(偏離量),兩者相加,即為絕對地址值。這個絕對地址值放在什么地方我不知道(按51機設計者的尿性,多半在A中),這個也不重要,因為處理器得到這個值后直接就去取數據了,不需要你再另加指令。
匯編指令:MOVC A@A+PC,查表指令之一
操作時,源數據的順序值,必須先送入A中,這個,就得用到其它指令。下面第3條也是一樣。
3、絕對地址表數據
這個地址的獲得,是以DPTR(前面ORG中給出的起始絕對地址值)中的值為基地址值,以A中的值作為要取用的源數據的順序值(偏移量),兩者相加,即為絕對地址。其它情況同上。這個屬于有的書上所說的變址尋址。
匯編指令:MOVC A@A+DPTR,查表指令之二。
PS1:說明一下,51機的機器代碼指令集中,針對程序存儲器只設計了這三種地址獲得的方式,而且,對于程序存儲器中的表數據,也是只設計了傳給A,想傳到其它地方?對不起,你只能先傳給A后再說。為什么這樣設計?一個是因為8位機最多只能有256條機器指令,不夠用啊;二個是,你覺得這樣設計合理么?(這部分涉及到51機數據傳輸的原理,在這里稍微提一下讓人有個概念)
PS2:查表指令用起來真的很麻煩,可以考慮將小量的并常用的表數據,在程序開始時復制到數據存儲器中,這樣運行速度可能要快些。
(二)數據存儲器中源數據的地址值(八位地址值)
程序存儲器中的原數據,屬于永久數據,其地址也是永久的,哪怕是程序重啟后也不會改變。
但數據存儲器中的源數據不是這樣的,數據存儲器的特點之一就是可以復用,程序員在編程時,對同一單元可以不斷更改其用途,也可以在整個程序運行期內,指定部分單元存入固定用途(固定值)的數據。
所以,數據存儲器中的源數據,其實都是程序運行過程中的中間數據或結果。其地址值,都是由程序員在編程時確定的,也是或者直接指定,或者通過計算得出。
數據存儲器中的源數據的地址值,在傳輸開始前,放在以下幾種位置:
1、程序存儲器中
這個屬于直接指定類,也就是程序員在源程序中直接給出源數據的單元地址(絕對地址),其地址值則放在機器指令碼之后的一個程序存儲器單元中,如MOV Adirect,機器代碼為“E5 直接地址”,這個就是所謂的直接尋址,這種情況是目的地址已在機器指令碼中指出,如果要分個類,可以稱為寄存器對數據存儲器的直接尋址。
還有一種,就是MOV direct,direct,這個也是直接尋址,三字節(jié)指令,源地址與目的地址都是直接給出地址值,其機器代碼為“85 direct direct”,也可以說直接地址到直接地址類的直接尋址。
2、工作寄存器中
源數據的地址值存放在工作寄存器中,處理器將工作寄存器中的值當作源數據的地址值來取數據。如MOV A@Ri,這個就屬于間接尋址,這個例子屬于單字節(jié)指令,源地址和目的地址均在機器指令碼中指出。需要說明一下的是,工作寄存器的地址值不需另外給出,它一定已經包括在機器指令碼中了。
這種方式一般用于需用具體數值來表示源數據地址值、但是其地址值并未在程序存儲器中給出的情況,對于計算出來的地址值,必須采用這種方式,這個跟程序存儲器中的查表法有點不一樣,計算得出的地址值一定要先放入寄存器中,而不是該指令在得出地址值后直接就去取數據了。
其實這種方式跟直接尋址差不多一回事,都是要有具體的地址值才能找到源數據,區(qū)別在于一個的地址值在程序存儲器中,另一個在Ri中。
這里注意一點,這個地址值只能送入R0R1中,為什么不能送入其它R中?因為51機的設計者沒有這樣設計。為什么要這樣設計?見前所述。
千萬注意:對于具有256B(不計入SFR)容量的數據存儲器的51機,128B值以上的地址如果采用直接尋址方式,則它會在SFR中找數據,如果采用間接尋址方式,則它會在用戶數據區(qū)找數據。也就是說,對于SFR的地址值,只能在程序存儲器中給出。
PS:個人覺得吧,SFR區(qū)也不是完全不能作為用戶數據區(qū),比如吧,對于電路上空置的端口,用了也不會有什么后果吧?要知道,它們也是可以位尋址的,更是可以直接尋址的。至于這樣做有沒有意義?這樣說吧,至少思路有意義。
3、機器指令碼直接指定
也就是說機器指令碼它自己就知道源數據在哪,也就是書上所說的寄存器尋址,如MOV directA,這條語句具體應用時的機器代碼是0F5H direct,兩字節(jié)指令,這里面的0F5H是機器指令碼,它已經明確了源數據在A中(這個是由51機的設計者設計成這樣的)。
這種情況,只適用于部分寄存器,這部分包括ARnRiDPTR,還有半個PC,一個位尋址C,其它的寄存器沒有設計這個功能(不會又問為什么沒設計吧),包括把其當作源地址以及當作目的地址。你只要記住只有這幾個有所謂的寄存器尋址功能,不管是把它們當全源地址還是目的地址,你就能很熟練地運用了。
PS1:如果數據傳送的兩頭都是寄存器,51機設計者還給設計了一部分直通車,也就是在機器指令碼中直接指明了兩頭是誰,也就是單字節(jié)指令,如MOV AR0,它直接一條機器指令碼0E8,就把數據從R0傳輸到了A
PS2:從前面的說明可以看出,所謂“寄存器尋址”的說法,并不恰當,準確的說法,應該是“機器指令碼定址尋址”,定址包括對源地址和目的地址(再重復一遍)。
五、說明
以上所說,均只針對片內的存儲器。
每一條機器指令碼,對應著一套實現該指令功能的硬件邏輯電路。
匯編語言并不能說難,至少,對于目前一些教材中所說的實例,編程起來不會比C復雜。
匯編程序員的大量且復雜的工作,應該是對存儲器的規(guī)劃。小程序還好說,大程序,真的是要好好規(guī)劃,不然的話,要么存儲器不夠用,要么數據發(fā)生沖突而無法達到目的。
題外PS:寫得蠻傷神,這些東西跟教材上的思路不一樣,也不知說清楚沒,更擔心有什么說錯了的害人,盼大蝦指正。


作者: 慢慢思考    時間: 2019-3-18 08:23
    光看匯編,有時容易讓人糊涂,想要了解清楚,得結合機器語言。
    “MOV 30,P0”與“MOV 30,A”,源數據尋址都是對寄存器尋址,很容易讓人認為這兩條都是寄存器尋址方式,實際不是,前一條是3字節(jié)指令,后一條是2字字指令,前一條翻譯成機器代碼,P0會譯成P0的地址值80H,而后一條中的A則翻譯到機器指令碼中去了。
作者: 慢慢思考    時間: 2019-3-21 11:17
    有的人說P0之類的為什么寫成P0,是英特爾公司規(guī)定的。這個說法是有問題的,它其實并不是芯片層面的,芯片只認識二進制數。它是軟件層面的,是在編譯工具中這樣規(guī)定的,你可以在編譯工具中改成你自己喜歡的稱號。或者你很牛你喜歡手工編譯,那你寫成任意中文就一點問題都沒有了。




歡迎光臨 (http://www.raoushi.com/bbs/) Powered by Discuz! X3.1