複製鏈接
請複製以下鏈接發送給好友

地址計算

鎖定
地址計算(address computation)是指對指針等的地址進行的一系列計算操作,包括獲取變量地址的不同方法以及有效地址計算等等。
中文名
地址計算
外文名
address computation
應用領域
計算機等
對    象
地址
原    理
儲存原理
特    點
在數據存儲區域

地址計算地址計算

地址可 以像整數一樣用作運算的對象。由於地址所表示的是數據所在的存儲區域的第一個位置,計算的結果使得指針變量指在數據存儲區域的第一個位置上。因此,地址的計算是按照與整數的計算不同的方法進行的。
指針變量的運算是根據該變量所指向的數據類型進行的。例如,設有
char *P; int *q;
當執行
++p;++q;
這樣兩個遞增語句時,由於字符型數據的大小是以1個字節為單位的,因此P被遞增1;而由於整型數據的大小通常是以2個字節為單位的,因此q被遞增2。同樣地,當執行
p=p+4; q=q+4;
時,指針變量P被加上4,而指針變量q則被加上8。由此可見,設P為指針變量,p+k的意思是由P所指向的數據後的第k個數據的地址,亦即P的值與k*sizeof(*p)之和。

地址計算獲取變量的地址

要求得變量的地址,大致有兩種方法。

地址計算運算符法

可以在變量前面冠以運算符&。
例如,設有int a;則可用&a來求得變量a的地址。一般説來,該值直到程序運行以前都是未定的。即使程序開始運行了,也未必就有一定的值。可能因運行時的環境不同而取不同的值。因此,幾乎不可以究問一個地址實際上到底取什麼值。 [1] 

地址計算指針變量

有一種指針變量是專門用以表示各種數據的地址的。例如,指向字符型數據地址的指針變量P可以這樣定義:
char *P
同樣,指向整型數據地址的指針變量q可以這樣定義:
int *q;
不用説,可以把表示數據存儲區域的地址賦值給指針變量,此外,也可以考慮指針變量的地址,例如,可以用&q來求指針變量q的地址。可以把該值賦給指針變量,例如,可以把它賦給定義為int **q_P;的指針變量q_P中去。由於指針變量q_P是一個指向一個指向int型數據的指針變量的指針變量,因而其定義中必須用兩個*。
由指針變量所指向的數據(該數據的值被寫在與賦到指針變量中的地址值相同的地址上)是用在指針變量之前冠以運算符*的方法來指定的。
例如,設有char *P;int *q;
那麼,*P就是一個由指針變量P所指向的字符型數據,而*q就是一個由指針變量q所指向的整型數據。不過,在使用*P和*q的時候,必須事先把數據實際所在的地址賦給指針變量p,和q。
例如,設有int a, *P
可以用
p=&a把變量a的地址賦給指針變量P。這時,*P=5; a=5;
這樣兩個語句就有了相同的含義。像*P這樣用指針間接地指定數據的方法就叫作間接指定。

地址計算有效地址計算

在指令的操作碼後面有mod R/M字節時,該字節指定了存儲器操作數的位置,modR/M字節給出了有效地址的計算過程為: [2] 
‘有效地址=段+基地址+(變址木比例因子)+位移量
其中:
位移量:指出了操作數的偏移值,可以使用字節、字或雙字。
基地址:操作數的偏移量由一個通用寄存器作為基地址變量來指定。
(變址球比例因子)+位移量:這是在靜態數據元素中佔2字節、4字節或8字節時對靜態數組變址的一‘種高效方法。由位移量對數組的起始位置尋址,變址寄存器存放所需的數組元素的下標,處理器則利用比例因子自動把下標變成變址。

地址計算內存地址計算

不同系統的內存地址計算方式不同,在此以8086系列處理機為例進行説明。
若知道8086系列處理機是如何訪問內存的,就容易理解使用不同存儲方式的規則和地址的計算方法。8086用於存放有關處理過程或程序控制信息的寄存器有14個,分成如下幾類:通用寄存器、基數指針和變址寄存器、段寄存器和控制寄存器 [3] 
8086CPU所有寄存器都是16位(2字節)。通用寄存器是CPU寄存器中最重要的部分。值都放在其中,進行算術運算,比較和分支(跳轉)指令也放在其中。通用寄存器以兩種方式存取:作為一個16位寄存器,或者作為兩個8位寄存器。
基數指針和變址寄存器相對尋址、棧指針和塊區移動指令等提供支持。
段寄存器支持8086內存分段。CS寄存器存放當前碼段,DS寄存器存放當前數據段,ES寄存器存放附加段,SS寄存器存放堆棧段。
最後,控制寄存器包括狀態標誌寄存器指令指針寄存器。狀態標誌寄存器存放CPU的狀態,而指令指針寄存器指向CPU下一個要執行的指令。
8086用分段存儲結構,總尋址空間為1兆字節(該系列其它功能更強者,尋址空間還要大)。要存取1兆字節RAM至少要用20位地址。8086處理機系列的20位地址在機器內部用2個字(32位)表示,實際上只用20位。但是在8086處理機上,20位地址分放在兩個寄存器中:一個寄存器放段地址,因此它必須是段寄存器,一個段在RAM中佔64K。段的起點正好是16字節的偶數倍。8086用四個段,即代碼段、數據段、堆棧段和附加段。段內任一字節的地址叫偏移量。任一字節20位地址在機器內是段號和偏移量的組合。
要算出段號和偏移量組合所指字節的實際地址,必須先將段寄存器中內容左移四位,再把偏移量加到移位後的段地址上去。20位地址就是這樣形成的。舉個例子,如果段寄存器內放的是10H,而偏移量是100H,那麼,下列步驟説明了實際(物理)地址的計算過程·
段寄存器 t 00000000000 10000(10H)
移位後的段寄存器l 0000000000010000
偏移量 1 0000000100000000(100H)
段+偏移量 t ooooo000001000000000(200H)
如果只存取當前段寄存器中的段內地址,則只要裝入地址的偏移量。若存取的地址不在當前段內,必須把要訪問的地址的段號和偏移量都裝入。
地址在8086中最常用的形式是“段:偏移量”。上面的例子若寫成此種形式就是0010:0100H。同一字節可用多個“段:偏移量”組合表示。例如,0000:0010和0001:0000是一回事。

地址計算地址映射關係

(在此以VGA為例進行説明)在所有的VGA圖形模式下,顯示存儲器與屏幕象素點之間的映射關係都是線性的,即顯示存儲器中的每個象素數據按光柵掃描的順序依次對應於屏幕上的每個象素點。在使用位面技術時,象素在每個位面上各佔一個數據位,每位具有相回的地址;在沒有采用位面技術時:一個象素點的多個數據位在顯示存儲器中連續存放,只是在24位色模式下有些特殊。下面描述屏幕上的某一個像素點在顯示存儲器中所處位置的計算方法。 [4] 

地址計算變量説明

屏幕座標原點為屏幕左上角,向右為X軸的正方向,向下為Y軸的正方向。X,Y象素點在屏幕上的位置;
width——當前分辨率下的水平象素數;
Height——當前分辨率下的垂直象素數;
BitN——當前色彩模式下每個象素所在顯示存儲器中所佔的二進制位數;
PlaneN——當前色彩模式下所具有的位面數,在沒有使用位面技術時,設該數為1;
BitPP——在當前色彩模式下每個象素點在地址空間中所佔的二進制位數;
scanLeng——一條掃描線在地址空間中所佔用的字節數;
Page—素點在顯示存儲器中所處的頁;
Offset——-象素點在所處頁中的地址偏移量;
Bit——象素點在所在字節中所處的位(僅在1 6色模式有用)。
另有兩個在編程中需要考慮的參數:
TotalPage—在當前顯示模式下的總頁數:
smsL一地址空間尺寸(64K)與ScanLeng相除的餘數,當該數等於零時意味着可以整除,該數大於零則意味着不能整除。

地址計算地址計算方法

BitPP=BitN/PlaneN
ScanLeng=Width*BitPP/8(不適於24位色模式)
Page=(ScanLeng+Y+X*BitPP/8)/1 00 00H
Offset=(ScanLeng+Y+X*BitPP/8)%1 0000H
Bit=X%8(只在16色模式下需要)
在24位色模式下,如果每個象素點連續存放在顯示存儲器中,這時分頁就必然會出現在某個象素點上,為避免這種情況,在每條掃描線之後空出了若干字節。在320×200分辨率下,每條掃描線佔用1024個字節,其實際只需要960個字節;在640×480分辨率下,每條掃描線佔用2 048個字節,其實際需要1920個字節。在每條掃描線中,各象素點數據靠前連續存放。在24位色模式下ScanLeng不能通過計算得到,而需要直接取得。
另兩個參數的計算方法如下:
TotalPage=(ScanLeng*Height一1)/1 0000H+1
SmSL=1 0000H%ScanLeng
參考資料
  • 1.    杜建成,潘金貴編著.C和C++程序設計基礎:南京大學出版社,1993.1
  • 2.    王路敬主編 徐旭等編著.高檔微機硬件實用技術基礎:中國水利水電出版社,1999年07月
  • 3.    盧有傑 吳煒煜.C語言高級程序設計:清華大學出版社,1991年09月
  • 4.    羅健輥.VGA實用編程技術:清華大學出版社,1996年01月第1版