接下來開始進入記憶體的部分,一個記憶體單元可以儲存一個 字節
(byte) 的資訊。
0 | 01H
1 | 02H
2 | 03H
4 | 04H
5 | 05H
一個字等於兩個字節,那 字
在記憶體中如何存放呢,以 503C
為例。
0 | 3CH
1 | 50H
記憶體的排列順序是由 低位到高位
,50 為高位 3C 為低位,所以在記憶體中的順序是先 3C 後 50,和一般顯示方式剛好相反,腦子需要轉一下。
示意圖:
DS 是數據段暫存器,會搭配中括號 []
使用,括號內放的是偏移地址,就像 CS 和 IP 一樣。DS 和 CS 同樣是段暫存器,因此不能直接進行賦值,中間必需透過通用暫存器,例如想讀取記憶體 1001H 位置的內容。
mov bx, 0100H
mov ds, bx
mov ax, [1]
寫入做法和讀取類似,差在最後一行將暫存器和偏移地址的位置交換。
mov bx, 0100H
mov ds, bx
mov [1], ax
上面例子使用的 ax 是 16 位暫存器,所以每次存取的是 字
大小的數據,那如果想存取 字節
呢,還記得之前有提到 8086 CPU 通用暫存器可以分為高位 ah 和低位 al 使用,只要改用 8 位暫存器,CPU 會自動判斷大小,讀取對應大小的記憶體內容。
mov bx, 0100H
mov ds, bx
mov al, [1] ; 讀取一個字節大小的數據
中括號加上 常數
的用法 [0]
僅限於 Debug 工具,編譯器的語法則有些不同,如果括號內放的是常數,必需在括號前明確指出段地址存放的暫存器,否則會將括號中的內容當成數值而不是偏移地址。
mov bx, 0100H
mov ds, bx
mov ax, ds:[0] ; 明確指出 ds 段暫存器
mov ax, [0] ; 將 0 賦值給 ax
前面提到 mov 可以對暫存器、段暫存器和記憶體進行操作,統整一下用法:
mov ax, 0 ; 暫存器 <- 數據
mov ax, bx ; 暫存器 <- 暫存器
mov ds, bx ; 段暫存器 <- 暫存器
mov ax, [0] ; 暫存器 <- 記憶體
mov [0], ax ; 記憶體 <- 暫存器
研究過字型編碼的朋友,有沒有發現字在記憶體中是用 小端序
(little-endian) 儲存,小端序會將 低位字節
存放在記憶體的 低位地址
,剛開始閱讀可能會不習慣,例如記憶體中的 10 20
要讀成 2010H
,對編碼有興趣可以看這篇文章 [C#] 難字處理心得。
組合語言的段暫存器通常都會配合偏移地址使用,例如 CS + IP
、DS + []
、還有下一篇要介紹的棧段暫存器 SS + SP
,今天就到這裡摟,感謝大家觀看。