iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 7
2
Software Development

8086下16位元DOS組合語言學習筆記系列 第 7

[Day07] 字型數據的儲存和數據段暫存器

字在記憶體中的儲存

接下來開始進入記憶體的部分,一個記憶體單元可以儲存一個 字節 (byte) 的資訊。

0 | 01H
1 | 02H
2 | 03H
4 | 04H
5 | 05H

一個字等於兩個字節,那 在記憶體中如何存放呢,以 503C 為例。

0 | 3CH
1 | 50H

記憶體的排列順序是由 低位到高位,50 為高位 3C 為低位,所以在記憶體中的順序是先 3C 後 50,和一般顯示方式剛好相反,腦子需要轉一下。

示意圖:

https://ithelp.ithome.com.tw/upload/images/20181022/20106865cYPqfqL7DG.jpg

DS 數據段暫存器

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]   ; 讀取一個字節大小的數據

Debug 和編譯器的不同

中括號加上 常數 的用法 [0] 僅限於 Debug 工具,編譯器的語法則有些不同,如果括號內放的是常數,必需在括號前明確指出段地址存放的暫存器,否則會將括號中的內容當成數值而不是偏移地址。

mov bx, 0100H
mov ds, bx
mov ax, ds:[0]   ; 明確指出 ds 段暫存器
mov ax, [0]      ; 將 0 賦值給 ax

統整一下 mov 指令的用法

前面提到 mov 可以對暫存器、段暫存器和記憶體進行操作,統整一下用法:

mov ax, 0     ; 暫存器   <-  數據
mov ax, bx    ; 暫存器   <-  暫存器
mov ds, bx    ; 段暫存器 <-  暫存器
mov ax, [0]   ; 暫存器   <-  記憶體
mov [0], ax   ; 記憶體   <-  暫存器

結語

研究過字型編碼的朋友,有沒有發現字在記憶體中是用 小端序 (little-endian) 儲存,小端序會將 低位字節 存放在記憶體的 低位地址,剛開始閱讀可能會不習慣,例如記憶體中的 10 20 要讀成 2010H,對編碼有興趣可以看這篇文章 [C#] 難字處理心得

組合語言的段暫存器通常都會配合偏移地址使用,例如 CS + IPDS + []、還有下一篇要介紹的棧段暫存器 SS + SP,今天就到這裡摟,感謝大家觀看。


上一篇
[Day06] Debug 工具的使用
下一篇
[Day08] 棧段暫存器
系列文
8086下16位元DOS組合語言學習筆記12

尚未有邦友留言

立即登入留言