目錄
- 0 前言
- 0.1 先告訴你結論
- 1 8086匯編語言中的字符串
- 1.1 字符串的定義與使用
- 1.2 直接定義的細節
- 1.2.1 使用DB數據類型
- 1.2.2 使用其他數據類型
- 1.3 直接使用的細節
- 1.3.1 賦值給寄存器
- 1.3.2 賦值給內存單元
- 1.3.3 字符串直接使用的本質
- 1.4 應用
- 2 擴展:數據定義的方式
- 3 附錄:題目和回顧
0 前言
本文使用emu8086軟件進行8086匯編語言編輯和運行。
順便說一句,匯編語言源程序中的數字,默認是十進制,因此使用十六進制的數字的時候,必須有h或H后綴,本文也都遵循這樣的原則。
至于為什么默認十進制,我只能說,編譯器默認你是個人(不要笑!事實如此,如果默認你是機器,那么數字就默認十六進制了)。
0.1 先告訴你結論
在8086匯編語言中,定義字節類型的數據,比如
- 字符
- 字符串
- 字節數值數組
都用DB進行定義,表示其后的數據都是字節型數據,并且按照順序依次存儲。
舉例說明:
db 'a'
db 'abcdefghijk' ; 相當于 db 'a','b','c','d'……
db 0,1,2,3,4,5,6,7
1 8086匯編語言中的字符串
通常情況下,匯編語言中的字符串,都會被賦予DB
(字節)數據類型,那么,為什么這樣做?
不能使用DW數據類型嗎?
當然可以,但是不建議使用。
1.1 字符串的定義與使用
- 定義后使用:可以在任何位置這樣定義,不過建議在數據段內定義,然后再通過一些方式訪問并使用它們
data1 db 'hello'
data2 db 'world'
- 直接使用:可以在指令中作為立即數直接使用
mov ax,'ab'
1.2 直接定義的細節
1.2.1 使用DB數據類型
使用DB作為數據類型的時候,字符串長度不受限制,默認字符串的每一個字符占一個字節,并且存儲過程中,是按照一個字符占一個字節的方式,順序依次存儲的。
源程序如下:
assume ds:data
data segmentdata1 db 'abcchsadhkjhsfaksaskhasf'data ends
對應的內存單元,原來是這樣的
0710:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0710:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0710:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
放入代碼段數據之后是
0710:0000 61 62 63 63 68 73 61 64-68 6B 6A 68 73 66 61 6B abcchsadhkjhsfak
0710:0010 73 61 73 6B 68 61 73 66-00 00 00 00 00 00 00 00 saskhasf........
0710:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
這里,data1
的值將會被編譯為這串字符串的首地址對應的偏移地址,也就是0000
,此時,data1并不能夠代表字符串的全部字符,你可以把它理解為data1 db 'a'
,也就是第一個字符a是字節型數據,它的標號是data1,但是它后面的字符是沒有標號的。
這也就意味著,mov ax,data1
會報錯,因為data1是字節型數據,而mov al,data1
會得到al = 61H
。
將字符串規定為字節類型,是常用的,其他的了解即可,基本不會用到,下面簡單介紹。
1.2.2 使用其他數據類型
例如使用dw
數據類型,則最多存儲2個字節。
data1 dw 'ab'
也就是說,如果不是db類型的字符串,則存儲字符的數量,是與數據類型相關聯的,例如dw 'abc'
就是錯誤的,因為超越了2個字節。
對于其他數據類型,dd
、dq
等也是一樣的,不過這些并不常用。
1.3 直接使用的細節
對于8086CPU來說
- 寄存器最大16位,也就是2個字節,比如
ax
,或者也可以是8位,比如al
- 可以操作的內存單元,也是如此,最大是
word ptr ds:[address]
(16位),或者byte ptr ds:[address]
(8位)
如果你想說32位或者更多,那是間接完成,也需要通過16位輔助來完成,我們這里說的是一步到位,直接使用。
這也就意味著,我們使用的字符串,只能使用'a'
或者'ab'
,這里的字母代表任何ASCII字符,在ASCII碼中,一個字符占1個字節,所以我們只有這兩種選擇,并且,要注意數據類型的匹配,比如mov al,'ab'
就是非法的,mov ax,'abcd'
也是非法的。
我來列舉一些常見情況,至于其他情況,都是其衍生品罷了。
1.3.1 賦值給寄存器
匯編語言程序為
mov al,'a'
mov ax,'a'
mov ax,'ab'
對于以上3條,編譯后的結果是
mov al,061h
mov ax,00061h
mov ax,06162h
執行后的結果是
al = 61h
ax = 0061h
ax = 6162h
1.3.2 賦值給內存單元
這里,假設ds = 1000h
匯編語言程序為(注意,要加上數字h!,目的是為了美觀)
mov byte ptr ds:[0],'a'
mov word ptr ds:[10h],'a'
mov word ptr ds:[20h],'ab'
編譯后的結果為
mov byte ptr [10000],061h
mov word ptr [10010],00061h
mov word ptr [10020],06162h
執行前內存為
1000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
執行后內存為
1000:0000 61 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 a...............
1000:0010 61 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 a...............
1000:0020 62 61 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ba..............
思考:你是不是發現了什么規律,是不是對于某些地方也感到困惑?思考一下,然后再往下看
1.3.3 字符串直接使用的本質
就一句話,將字符按照ASCII碼規則,轉換為數字,這個數字可以理解為立即數,其余的事情,就是立即數相關問題了。
你可能看見了,當mov word ptr ds:[20h],'ab'
之后,內存中是ba
而不是ab
,我想你知道原因了,這與在數據段定義不同,那里是順序的,這里是倒序的,原因在于,在數據段用db數據類型存儲,是一個一個字符存儲的,而這里是作為一個字來存儲的,是一個整體。
1.4 應用
思考題: 如果你有以下數據段的定義
assume ds:data
data segmentdata1 db 'dox'data ends
現在,你需要將'dox'
修改為'DOX'
,應該如何做?如果要修改為'VEX'
,又該怎么做?
提示:
- 第一個問題,可以轉換為小寫字母變成大寫字母的問題
- 第二個問題,就是內存修改問題
- 你可以使用
mov ax,'V'
的方式,直接替換 - 也可以先定義好
data2 db 'VEX'
數據,再進行替換
- 你可以使用
2 擴展:數據定義的方式
為了避免內容冗雜,我單獨寫了一篇文章,鏈接在此
我希望你知道的是,學會了字符串的定義,也就學會了各種數據的定義,因為字符串定義的本質,就是數字定義,只需要按照編碼規則換成數字就行了。
3 附錄:題目和回顧
來自于《匯編語言》(王爽)第七章,此處只是為了記錄,讀者可不看。
; 全變成大寫字母,并且將外循環次數暫存到內存中
assume ds:data
data segmentdata1 db 'abc gg 'data2 db 'hello hq 'cycleCount dw ?data endsassume ss:stack
stack segmentcycle dw ? stack endsassume cs:code
code segment
start:mov ax,datamov ds,axmov ax,stackmov ss,ax ; 下面兩條語句不能二合一,因為匯編程序追求的是格式的統一與極簡mov sp,offset cycle ; 不要使用 Magic Numbersub sp,2mov bx,0 ; 外層 控制行mov cx,2s0:;mov cycleCount,cx;push cycle ; 注意此處,不是推入偏移地址這個數據,push offset cycle,而是直接推入數據; 【數據傳送】指令; 【錯誤!】推的是cx,不是cyclepush cx mov si,0 ; 內層 控制列mov cx,8s1: ; 字傳送,不浪費mov ax,[bx][si] ; 為什么沒有造成不匹配報錯 【按照地址找數據,類型是自動匹配的】; 【自動匹配】【強制匹配】and ax,0DFDFHmov [bx][si],axadd si,2loop s1add bx,16;mov cx,cycleCountpop cxloop s0mov ax,4c00hint 21h
code ends
end start