1. 程式人生 > >多種定址方式定位記憶體地址

多種定址方式定位記憶體地址

當資料存放在記憶體中時,我們可以使用多種方式來給定這個記憶體單元的偏移地址,這種定位記憶體單元的方法被稱為定址方式。
這裡寫圖片描述

1. 直接定址

定址方式:
[idata]
含義:
EA=idata
定址過程:
例: 上圖中的 mov ax,ds:[000E]
CS和IP中的地址通過地址加法器進行移位相加得到程式碼的實體地址,通過地址匯流排進入記憶體,取出相應地址的機器碼000EA1,通過資料匯流排傳到指令緩衝暫存器,讀取指令判斷是直接定址,則通過段地址ds和偏移地址[000E]得到資料的實體地址,在記憶體中取出。

2.暫存器間接定址

定址方式:
[bx]
含義:
EA=(bx)
定址過程:
例: 上圖中的 mov ax,[bx]
CS和IP中的地址通過地址加法器進行移位相加得到程式碼的實體地址,通過地址匯流排進入記憶體,取出相應地址的機器碼078B,通過資料匯流排傳到指令緩衝暫存器,讀取指令判斷是暫存器間接定址,則通過段地址ds和暫存器BX提供的偏移地址得到資料的實體地址,在記憶體中取出。

3.暫存器相對定址

定址方式:
[bx+idata]
含義:
EA=(bx)+idata
定址過程:
例: 上圖中的 mov ax,[bx+1]
CS和IP中的地址通過地址加法器進行移位相加得到程式碼的實體地址,通過地址匯流排進入記憶體,取出相應地址的機器碼01478B,通過資料匯流排傳到指令緩衝暫存器,讀取指令判斷是暫存器相對定址,則通過段地址ds和暫存器BX提供的內容加上一得到偏移地址從而得到資料的實體地址,在記憶體中取出。

4.基址變址定址

定址方式:
[bx+si] ; [bx+di]
含義:
EA=(bx)+(si) ; EA=(bx)+(di)
可以表示為[bx][si],相當於一個二維陣列
定址過程:
例: 上圖中的 mov ax,[bx+si]
CS和IP中的地址通過地址加法器進行移位相加得到程式碼的實體地址,通過地址匯流排進入記憶體,取出相應地址的機器碼008B,通過資料匯流排傳到指令緩衝暫存器,讀取指令判斷是基址變址定址,則通過段地址ds和暫存器BX提供的內容加上源暫存器SI提供的內容得到偏移地址從而得到資料的實體地址,在記憶體中取出。

5.相對基址變址定址

定址方式:
[bx+si+idata] ; [bx+di+idata]
含義:
EA=(bx)+(si)+idata ; EA=(bx)+(di)+idata
定址過程:
例: 上圖中的 mov ax,[bx+si+1]
CS和IP中的地址通過地址加法器進行移位相加得到程式碼的實體地址,通過地址匯流排進入記憶體,取出相應地址的機器碼01408B,通過資料匯流排傳到指令緩衝暫存器,讀取指令判斷是相對基址變址定址,則通過段地址ds和暫存器BX提供的內容加上源暫存器SI提供的內容再加上一得到偏移地址從而得到資料的實體地址,在記憶體中取出。

6.為什麼我們需要這麼多的定址方式

這是為了在效率和方便性上找一個平衡。立即數定址和暫存器定址在效率上是最快的,但暫存器僅有幾個非常寶貴不可能將運算元都存入其中等待使用,立即數的使用場合也非常有限,這樣就需要將資料儲存在記憶體中,然後使用直接定址、暫存器間接定址、暫存器相對定址、基址加變址定址、相對基址加變址定址這些定址方式將記憶體中的資料移入暫存器中。
(摘自http://m.blog.csdn.net/article/details?id=6911132

7.應用舉例

問題1:程式設計將datasg段中每個單詞的頭一個字母改為大寫字母。
assume cs:codesg,ds:datasg
datasg segment
db ‘1. file ’
db ‘2. edit ’
db ‘3. search ’
db ‘4. view ’
db ‘5. options ’
db ‘6. help ’
datasg ends
codesg segment
start: ….…
mov 4c00h
int 21h
codesg ends
end start
這裡寫圖片描述
注意這裡定義的字串後面是有空格個,湊成的一行16個位元組

直接定址方式
[bx+idata] 起始bx設為0,為第一行第一個單元的地址,idata設為3,表示這一行第三個單元即單詞首字母

mov ax,datasg
mov ds,ax
mov bx,0
mov cx,6      ;迴圈六次
s: mov al,[bx+3]
and al,11011111b  ;與運算,小寫變成大寫
mov [bx+3],al
add bx,16       ;bx加16,跳到下一行開始位置

問題2:程式設計將datasg段中每個單詞改為大寫字母
assume cs:codesg,ds:datasg
datasg segment
db ‘ibm ’
db ‘dec ’
db ‘dos ’
db ‘vax ’
datasg ends
codesg segment
start: ……
codesg ends
end start
這裡寫圖片描述
注意這裡定義的字串後面是有空格個,湊成的一行16個位元組

暫存器間接定址二重迴圈
4 個字串,可以看成一個 4行16列的二維陣列,要修改二維陣列的每一行的前3列,則構造4x3次的二重迴圈

mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0: mov si,0
mov cx,3

s: mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s    ;內層迴圈

add bx,16
loop s0   ;外層迴圈

但是這樣做只有一個cx,執行完內層迴圈後就變成0了,無法完成外層迴圈
這裡可以用棧儲存cx

stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends

mov ax,stacksg
mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4

s0: push cx   ;將外層迴圈的cx值壓棧 
mov si,0
mov cx,3     ;cx設定為記憶體迴圈的次數

s: mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s       

add bx,16
pop cx       ;從棧頂彈出原cx的值,恢復cx
loop s0