關於西門子間接定址的一些理解

不愿透露姓名的小村村發表於2024-04-18

間接定址。它很基礎,基礎到我們無時無刻都在用,但是同時它也很難理解,因為其實暫存器的概念已經被漸漸隱藏了。

  1. 地址的概念
    我們通常提到的物理輸入輸出印象區P,印象輸入區I,印象輸出區Q,位儲存區M,定時器T,計數器C,資料區DB,背景資料區DI,本地資料區L。
    每個區域(除T/C)都可以用BIT,BYTE,WORD,DWORD來指定它們的大小。
    區域+區域位置和長度,其實構成了我們描述一個地址的必要條件。
  • 儲存的區域
  • 這個區域中具體的位置
//例子: A Q2.0
A = 指令符;
Q = 輸出印象區;
2.0 = 輸出印象區的第二個位元組的第0位;

//例子: DBX200.0
DB = 資料區;
X = 位;
200 = 具體位置
0 = 具體的位位置

所以一個地址的確切構成應該是<儲存區符號><儲存區尺寸符號><尺寸數值>.<位數值>。把<儲存區符號><儲存區尺寸符號>統一看作<地址標誌符>,那麼地址組成又可以寫成<地址標誌符><數值單元>

  1. 間接定址
  • 間接定址對應的是直接定址,那什麼是直接定址?
    直接給出指令的確切運算元就叫直接定址。
    地址的最小單元是BIT。
//直接操作Q20.0的地址,直接定址
A Q20.0
  • 對應的,間接給出的定址方式。就是間接定址。
    用[ ]標明的內容,間接指代地址
    其中MD100和DBW100被稱為指標Pointer,它指向它們包含的數值所代表的地址
//間接訪問地址,間接定址
A Q[MD100]
A T[DBW100]
  • 指標格式(儲存器間接定址
    1. 儲存器間接定址具有兩個指標格式:單字和雙字。單字指標是一個16bit的結構,從0-15bit,指示一個從0-65535的數值,這個數值就是被定址的儲存區域的編號。雙字指標是一個32bit的結構,從0-2bit,共三位,按照8進位制指示被定址的位編號,也就是0-7;而從3-18bit,共16位,指示一個從0-65535的數值,這個數值就是被定址的位元組編號。這句話說明相比於單字指標,雙字指標可以多表達0-7bit的位編號
    2. 指標可以存放在M、DI、DB和L區域中,也就是說,可以用這些區域的內容來做指標。
//
L DW#16#35 //將32位16進位制數35存入ACC1
T MD2 //這個值再存入MD2,這是個32位的位儲存區域
L +10 //將16位整數10存入ACC1,32位16進位制數35自動移動到ACC2
T MW100 //這個值再存入MW100,這是個16位的位儲存區域
OPN DBW[MW100] //開啟DBW10。這裡的[MW100]就是個單字指標,存放指標的區域是M區,MW100中的值10,就是指標間接指定的地址,它是個16位的值!
//
L L#+10 //以32位形式,把10放入ACC1,此時,ACC2中的內容為:16位整數10
T MD104 //這個值再存入MD104,這是個32位的位儲存區域
A I[MD104] //對I1.2進行與邏輯操作!
=DIX[MD2] //賦值背景資料位DIX6.5!
//
A DB[MW100].DBX[MD2] //讀入DB10.DBX6.5資料位狀態
=Q[MD2] //賦值給Q6.5
//
A DB[MW100].DBX[MD2] //讀入DB10.DBX6.5資料位狀態
=Q[MW100] //錯誤!!沒有Q10這個元件

透過上面發現:雙字指標描述byte.bit的這種結構,單字指標只能描述儲存區域。
換句話說,單字指標不能描述P,I,Q,L這些區域,因為描述它們要精確到bit。
對雙字指標而言,似乎一切都好,但是也有一個限制,對於非位區域定址的時候,它的描述必須要保全其0-2bit都是0,也就是說對於非位區域,它的的精度到不了位
也正是由於雙字指標是一個具有位的指標,因此,當對位元組、字或者雙字儲存區地址進行定址時,必須確保雙字指標的內容是8或者8的倍數

上訴例子中有段程式碼是

A I[MD104] //對I1.2進行與邏輯操作!

那麼,為什麼是I1.2呢?

原因:
透過L L#+10,MD104應該是等於十進位制的10,轉換為32位二進位制數如下:
MD104 = 2#0000 0000 0000 0000 0000 0000 0000 1010;
按照雙字指標的概念,3-18bit指定byte,0-2bit指定最終要操作的位,那麼計算出來的結果就應該是1.2!
按照雙字指標的概念,3-18bit指定byte,0-2bit指定最終要操作的位,那麼計算出來的結果就應該是1.2!
按照雙字指標的概念,3-18bit指定byte,0-2bit指定最終要操作的位,那麼計算出來的結果就應該是1.2!
  • 指標格式(暫存器間接定址
    1. 儲存器間接定址暫存器間接定址有什麼不一樣:
      在先前所說的儲存器間接定址中,間接指標用M、DB、DI和L直接指定,就是說,指標指向的儲存區內容就是指令要執 行的確切地址數值單元。但在暫存器間接定址中,指令要執行的確切地址數值單元,並非暫存器指向的儲存區內容,也就是說,暫存器本身也是間接的指向真正的地址數值單元。

    2. 暫存器間接定址的途徑

      • 區域內暫存器間接定址
      • 區域間暫存器間接定址
    3. 暫存器間接定址的格式

      • <地址標誌符><暫存器,P#byte.bit>
//舉個例子
DIX[AR1,P#1.5] //要定址的地址區域事先已經確定(DI),AR1可以改變的只是這個區域內的確切地址數值單元,所以我們稱之為區域內暫存器間接定址方式,相應的,這裡的[AR1,P#1.5] 就叫做區域內定址指標。
X[AR1,P#1.5] //要定址的地址區域和確切的地址數值單元,都未事先確定,只是確定了儲存大小,這就是意味著我們可以在不同的區域間的不同地址數值單元以給定的區域大小進行定址,所以稱之為:區域間暫存器間接定址方式,相應的,這裡的[AR1,P#1.5] 就叫做區域間定址指標。
  • AR的格式
    地址暫存器AR是專門用於定址的一個特殊指標區域,西門子的地址暫存器一共2個,AR1和AR2,每個32位
    • 區域內定址暫存器裡面,AR的內容只是指代數值單元,因為其他的已經確認,所以這種情況的的AR等同於儲存暫存器中的雙字指標,也就是0-2指代bit,3-18指代byte位元組,其中第31位固定為0。
    • 區域間定址暫存器31位固定為1,24-26bit可以被定義用於指定儲存區域,它其實是一種我們常見的區域劃分標誌(如B#16#84表示DB區的概念就來自於此)。
# 比較區域內定址暫存器和區域間定址暫存器的格式差別
區域內定址暫存器:
AR:0000 0000 0000 0BBB BBBB BBBB BBBB BXXX

區域間定址暫存器:
AR:1000 0YYY 0000 0BBB BBBB BBBB BBBB BXXX

# 差別1:區域間的第31位固定為1了。
# 差別2:區域間的第24-26位可以被定義和修改了。
  • 區域標誌符(區域間定址暫存器24-26位)
    • 我們一定不會陌生的知識如下:

      1. 資料區P,B#16#80(2#000)
      2. 資料區I,B#16#81(2#001)
      3. 資料區Q,B#16#82(2#010)
      4. 資料區M,B#16#83(2#011)
      5. 資料區DB,B#16#84(2#100)
      6. 資料區DI,B#16#85(2#101),表示背景DB
      7. 資料區L,B#16#86(2#111)
    • 當我們把這些AR的內容全部表達出來:

      1. 資料區P,B#16#800xxxxx
      2. 資料區I,B#16#810xxxxx
      3. 資料區Q,B#16#820xxxxx
      4. 資料區M,B#16#830xxxxx
      5. 資料區DB,B#16#840xxxxx
      6. 資料區DI,B#16#850xxxxx
      7. 資料區L,B#16#860xxxxxx

我們從上面能得到一個初步結論:果AR中的內容是8開頭,那麼就一定是區域間定址。

//舉個例子
AR = 16#840000D4
//我們可以轉換位二進位制顯示
AR = 2# 1000 0100 0000 0000 0000 0000 1101 0100
 // bit31=1,表示區域間暫存器定址
// bit24-26=100,表示DB
// bit3-18=26,表示區域位置是26
// bit0-2=100,表示4
//合計如下
AR表達的地址是DBX26.4
  • P#指標是什麼
    P#中的P是Pointer,是個32位的直接指標。所謂的直接,是指P#中的#後面所跟的數值或者儲存單元,是P直接給定的。

L P#Q1.0 //把Q1.0這個指標存入ACC1,此時ACC1的內容=82000008(hex)=Q1.0
L P#1.0 //把1.0這個指標存入ACC1,此時ACC1的內容=00000008(hex)=1.0(這是個區域內暫存器定址指標,如X[AR1,P#1.5])
L P#MB100 //錯誤!必須按照byte.bit結構給定指標。
L P#M100.0 //把M100.0這個指標存入ACC1,此時ACC1的內容=83000320(hex)=M100.0
L P#DB100.DBX26.4 //錯誤!DBX已經提供了儲存區域,不能重複指定
L P#DBX26.4 //把DBX26.4這個指標存入ACC1,此時ACC1的內容=840000D4(hex)=DBX26.4
//對P#指定帶有儲存區域時,累加器中的內容和區域間定址指標內容完全相同。事實上,把什麼樣的值傳給AR,就決定了是以什麼樣的方式來進行暫存器間接定址。

在暫存器定址中,P#XXX作為暫存器AR指標的偏移量,用來和AR指標進行相加運算,運算的結果,才是指令真正要操作的確切地址數值單元!

  • P#的運算規則
//運算的法則是:AR1和P#中的數值,按照BYTE位和BIT位分類相加。BIT位相加按八進位制規則運算,而BYTE位相加,則按照十進位制規則運算。

對於[AR1,P#2.6],若AR1=26.4 >>>AR1(26.4)+P#(2.6)=29.7,這是區域內暫存器間接定址的最終確切地址數值單元
對於[AR1,P#2.6],若AR1=DBX26.4 >>>AR1(DBX26.4)+P#(2.6)=DBX29.7,這是區域間暫存器間接定址的最終確切地址數值單元
  • AR的地址運算
//1.直接賦值,保證直接數是32位,包含相關區域,位置,地址資訊
L DW#16#83000320
LAR1
//2.間接賦值,可以用儲存器間接定址指標給定AR1內容。具體內容儲存在MD100中
L [MD100]
LAR1
//3.指標賦值,使用P#這個32位“常數”指標賦值AR。
LAR1 P#26.2

相關文章