組合語言——1-6章
彙編指令和機器指令一一對應,有編譯器翻譯識別,計算機無法直接識別
一個儲存單元等於1位元組 1位元組等於8位
1KB=1024Byte(位元組)
1Byte=8bit(位)
CPU中,指令和資料都是二進位制形式存在
磁碟的資料,CPU無法直接使用,只能讀到記憶體中,才能被CPU使用
CPU可以使用的資料,是在儲存器中儲存器被劃分為很多儲存單元,以0開始編號,
一個單元儲存一位元組,即8位
暫存器是一種比記憶體和二級快取更低一層,更接近CPU的儲存器
CPU進行資料讀寫時,必須和外部晶片進行3類資訊交換:
1.地址資訊 即地址匯流排
2.控制資訊 即控制匯流排
3.資料資訊 即資料匯流排
CPU多少根地址匯流排,就代表這個CPU地址匯流排的寬度為多少
就是說cpu定址範圍是2的N次方個儲存單元
資料匯流排N根,即一次可傳送N位二進位制數即N位,例:
16位資料匯流排,可傳輸16位二進位制,即2個位元組
控制匯流排決定CPU對外部器件的控制能力
儲存器分為:隨即儲存器RAM和只讀儲存器ROM
隨即儲存器,斷電後資料丟失,如記憶體,視訊記憶體
只讀儲存器,關機後記憶體不消失,如主機板,網絡卡的BIOS
CPU對各類儲存器只看做一個邏輯的儲存器,每個物理上的儲存器在邏輯上佔有一段地址段,
CPU對其段進行操作,就是對物理儲存進行操作
8086 CPU的記憶體地址分配:
00000—9FFFF為主儲存器
A0000—BFFFF為視訊記憶體地址空間
C0000—FFFFF為各類ROM地址空間
第一章檢測點:
1.
定址能力為8kb,即為8,反向推論,8kb=8192位元組,CPU定址公式:
N=地址匯流排寬度
M=定址大小(單位位元組)
M=2的N次方
這裡M=8192,所以開平方,N就是13,2的13次方為8192位元組
2.
1kb=1024b,因為1個儲存單元大小為1B,所以1kb儲存器可以為1024個儲存單元
編號從零開始,即編號為0——1023
3.
1kb的儲存器為1024個儲存單元,每個儲存單元1Byte,1Byte=8bit,即10248=8192bit位 即1024byte位元組
4.
1GB=1024MB
1MB=1024KB
1KB=1024Byte
5.
地址匯流排寬度為16,那麼定址能力就是2的16次方,65536個儲存單元,即65536Byte,即64kb
6.
1Byte=8bit 8根資料匯流排,一次傳輸8bit,即1Byte
7.
8086為16根資料匯流排,每次讀取16bit,即2位元組,1024位元組,需讀取512次
8.
儲存器中,資料和指令都是二進位制形式存在
第二章:
CPU主要有有運算器,控制器,暫存器,三部分組成
8086 CPU有14個暫存器,如AX,BX,CX,DX,SI。。。。
8086所有暫存器都是16位的,可以存放2個Byte即位元組,16位二進位制數
通用暫存器為4個,是:AX,BX,CX,DX
為了相容8088 CPU,所有通用暫存器,可以單獨分為兩個暫存器使用,即高地址和低地址,如AX可分,AH,AL
一個位元組,即8bit,可以存在8位暫存器中
一個字 word 等於2個位元組,即16bit
在寫一條彙編指令或暫存器時不區分大小寫
mov ax,10和MOV,AX,10 一樣
mov ax,18 意思是把18送入暫存器ax
mov ah,18 意思是把18送入暫存器ah
mov ax,bx 意思是把bx的值輸入暫存器ax中
add ax,5 意思是將暫存器ax的值加上5
add ax,bx 意思是吧bx和ax相加,值存入ax中
H為16進位制的意思
ax=0000H
bx=0000H
8086 16位 一個暫存器能儲存16個2進位制數
例如:al和ah沒有關係,當ah的值超出8位時,CPU就會丟棄資料,當al的值超出8位時,CPU不會丟棄資料
但不會進位到ah暫存器中
彙編指令進行操作時,要注意雙方位數和資料大小溢位問題
檢測點2.1詳解:
mov ax,62627 ax=F4A3H
記住,這裡的62627是十進位制,轉換為十六進位制後,就是F4A3
mov ah,31h ax=31A3H
意思,是把31值送入ah中,並覆蓋,即31A3H
mov al,23h ax=3123h
意思,是把23值送入al中,並覆蓋,即3123H
add,ax,ax ax=6246H
意思就是把AX加上AX在送入AX中,和C語言的a+=a;一個意思
mox bx,826ch bx=826ch
意思就是把826ch的值送入bx中
mov cx,ax cx=6246h
意思就是把ax的值覆蓋cx中
mov ax,bx ax=826ch
意思就是把bx的值覆蓋ax中
add ax,bx ax=04d8h
意思是把bx和ax的值相加,並送入ax中,結果為104d8,
超過8086 CPU的十六位儲存大小,所以拋棄1,即得04d8h
mov al,bh ax=0482h
意思是把bh的值覆蓋al中,bh為82,ax為04d8,覆蓋得0482h
mov ah,bl ax=6c82H
意思是把bl的值覆蓋ah中,bl為6c,ax為0482,覆蓋得6c82h
add ah,ah ax=d882h
意思是把ah加上ah,值放入ah中,即6c+6c=d8,即得d882h
add al,6 ax=d888h
意思把6加入al中,al值為82,82+6即得88,當然是十六進位制演算法,最後得d888h
add al,al ax=d810h
意思是把al加上al的值放入al中,值為110,超出al8位暫存器的大小,故只留10
結果為d810h
mov ax,cx ax=6246h
此題作者怎麼想得,最後問個最簡單的,呵呵
對CPU而言,所有記憶體單元構成的儲存空間是一個一維線性空間
CPU實體地址送入暫存器的只能是一個實體地址,如:0010
8086為16位CPU,16為CPU有以下特性
運算器一次最多處理16位資料
暫存器的寬度為16位
暫存器和運算器的通路為16位
8086有20位地址匯流排,即可傳送20位資料,定址能力為:2的20次方位元組,即1MB
但8086為16位結構,每次處理,儲存,傳送都為16位,即定址能力為2的16次方個位元組,即64kb
為了不浪費使用吧,8086採用內部2個16位暫存器合成一個20位實體地址就行傳輸
具體為:
實體地址=段地址
例如:
段地址為1230,偏移地址為00c8 那經過運算就是123c8的20位實體地址
具體:123016=12300
然後:12300+00c8=123c8
十進位制理解就是:
例如:12812這個數由
1000和2812組成
100010=10000
任何10000+2812=12812
自己慢慢理解理解就可以了!
段地址的概念,是來自CPU,來分段管理記憶體!
10000H——100FFH組成一個段
基礎地址為10000H
段地址為1000H
大小為:
100H
這裡的段地址大小,很多人都暈,確實難理解,想通就好
100H的來源:
100FFH—10000H=FFH
這個FFH,轉換為10進位制就255,而計算機是從零開始,那麼就有0—255,256個數
再把256轉換為16進位制,那就是100,即大小為100H,這是最笨的方法,但初學者好理解些,呵呵
一個段地址必然是16的倍數
偏移地址為16位,16位定址能力為64kb,一個段的最大為64kb
監測點2.2:
1.
00010H—1000FH
0010H-1000FH 有答案是這個,不知道0010H行不行,大家研究!
2.
20000H
sa16+0000=20000
sa
最大2000
最小1001 1000不行,最後只能1001,大家測試
8086 CPU通過段地址和偏移合成物理地址來定址,所以段地址肯定有暫存器,
那就是:CS DS,SS,ES 4個,和前面我們說的4個通用暫存器:AX,BX,CX,DX一樣
CS和IP這兩個暫存器,CS為程式碼段暫存器,IP為指令指標暫存器,8086會從
CS16+IP單元開始讀取指令
關鍵要理解8086CPU的工作過程:
1.從CS:IP指向德記憶體單元讀取指令,指令進入緩衝器
2.IP=IP+所讀指令的長度,從而指向下一條指令
3.執行指令,轉到步驟一,重複這個過程
記住:8086CPU加電覆位後,CS和IP的設定為CS=FFFFH,IP=0000H
即CPU從記憶體FFFF0H單元中讀取執行,也是8086CPU的第一條執行指令
debug進入方式:開始—執行——debug XP系統下
r檢視當前暫存器值,修改
d檢視記憶體地址段的內容
e修改記憶體地址中的內容
u將記憶體地址段的內容翻譯為指令
t執行開始CS:IP處的指令
a輸入彙編指令
實驗任務,根據各自電腦不同,初始值可能不同!大家自己測試,很簡單!
第三章:
CPU用16位暫存器儲存一個字
1字=2位元組
一個記憶體單元為1位元組,所以一個字要用兩個連續的記憶體單元
存放,高地址存放高位元組,低地址存放低位元組
DS暫存器用來儲存訪問資料的段地址
8086CPU位16位結構,即一次傳送16位資料,也就是1個字
在程式設計時,我們可以將一組記憶體單元定義為一個段,這個完全取決於我們
但段的長度必須<=64kb的連續地址,且起始地址為16的倍數
如:123B0H—123B9H
這個段記憶體的段地址就是1230H,長度就是10個位元組了,5個字
棧的定義,入棧PUSH 出棧POP
入棧就是將一個新的資料放入棧頂,出棧就是從棧頂取出一個數據
規律是:後進先出
如: POP ax 就是將棧頂部的資料讀取到AX中
相反,PUSH AX 就是將AX的資料讀取到棧頂
CPU是通過段暫存器SS和暫存器SP來確定棧的位置和棧頂得位置
SP裡面就是棧頂的地址,CPU執行就是從SS:IP處執行
棧的溢位問題,我們要根據位元組的需求,進了用到最大的棧空間以
防止入棧超界,和出棧超界
我們可以將一段記憶體定義為一個段,這個段可以我們位元組安排
如:
定義一個段存放資料,那就是資料段 就是通過DS暫存器控制段地址
如果存放程式碼,那就是程式碼段 就是通過CS暫存器控制段地址,IP暫存器
控制偏移地址
同樣如果當做棧,那就是棧段 就是通過SS暫存器控制段地址,用SP暫存器
控制棧頂的單元地址
第三章概念性東西很少,很多都是上級實驗的所有課後題我就不寫了,大家按照
課後要求,一步一步來,肯定都能做出來!
第四章:
呵呵,本章還是比較簡單的,主要介紹下程式的執行步驟
一個組合語言寫的程式要經過以下的步驟
第一步:編寫彙編源程式
我喜歡用記事本,方便些,新手可以用支援高亮顯示的編輯器,會更好
第二步:是對生成的源程度,.ASM的檔案進行編譯,產生目標檔案
第三步:就是連線,對目標檔案進行連線,生成可執行程式,如:.EXE的
這個過程主要完成對源程式的彙編指令到機器碼的轉變,以後相關描述等
彙編指令分為:偽指令和彙編指令,和標號,其實標號和偽指令和劃分一起
例如:
assume cs:qq
qq segment
MOV,AX,1111H
MOV BX,2222H
ADD AX,BX
MOV AX,4C00H
INT 21H
qq ends
end
這裡面的偽指令如: qq segment… qq ends 如同C語言的{}一樣 ,代表一段組合語言的
開始和結束,偽指令對CPU來說是不認識的,他只是由編譯器認識和執行的
qq segment 代表定義一個段qq,這個段開始
而qq ends 就是結束這個段
如:上面的assume 和end 拿end來說,就是說明這個程式的結束,如果不加,
那麼程式將找不到結束點,後果自己試驗
標號的話,如上面的qq,他代表一個地址,做為一個段的名稱
如果寫一個1+1的程式,那就是
assume cs:qq
qq segment
MOV,AX,1
ADD AX,ax
MOV AX,4C00H
INT 21H
qq ends
end
注意H代表十六進位制,大小寫不區分,程式最後的
mov ax,4c00H
int 21H
他就是固定的意思,就是實現程式執行完成後,返回,注意,他是彙編指令
一個組合語言的編寫,編譯,連線,執行,這個的話,大家建議先勇masm這個完成
前期很簡單,不要開始就用整合環境,這樣能更深入瞭解程式的整個過程,具體過程,
大家看書,有圖,一步一步來
說下組合語言從寫道執行的過程
1.首先先寫一段彙編指令,工具不限,確保正確
2.生成.asm檔案
3.然後拿masm進行編譯,得到目標檔案.obj
4.然後用link進行連線,得到.exe可執行檔案
5.然後載入,載入到記憶體以後,CPU進行讀寫執行,然後返回到相應的裝置上
有時為了解決問題,可以使用debug來跟蹤程式的執行,看到每一步執行後,CPU的結果
好了,重點就是這麼多,具體對某一點仔細理解,都是日後的重點
第五章:
首先大家一定要分清,debug命令和編譯指令,具體看第四章debug命令,進行對比
開始:
mov [0],ax
意思是把 ax的內容送入段地址為ds,偏移地址為0的地址中
送入單元長度,由物件暫存器確定,如ax就是16位,2位元組
al就是8位,1位元組
[bx] 和上面基本一樣,不同點就是他得地址的偏移地址在bx暫存器中
loop指令,迴圈命令,大致步驟
首先進行loop迴圈標記
然後根據cx的值判斷迴圈次數,每次-1,cx為0時,則向下執行
如:計算2的10次方:
assume cs:qq
qq segment
mov ax,2
mov cx,9
q:add ax,ax
loop q
mov ax,4c00h
int 21h
qq ends
end
上面例子中,標號就是q,cx=9,就是迴圈10次執行 add,AX,AX
彙編原程式中,資料不能以字母開頭,如FFFFH,要寫為:0FFFFH
段字首的意思:
例如:
mov ax,ds:[bx]
就是把一個單元地址的內容送人ax中,長度為2位元組
地址的段地址在ds中,偏移地址在bx中
這個ds可以換成其他暫存器,如ss,cs
mov ax,ds:[0]
和上面一樣,唯一不同的就是偏移地址是0
上述的ds,就段的字首,簡稱段字首
一段安全的空間:意思就是在一個一維性的記憶體空間中,有一些地址是系統或其他
重要程式使用的,這些地方我們如果不小心修改將會引起很多錯誤,所以我們要使用一段安全的地址空間
在dos方式下,一般:0:200——0:2ff這個256個地址是安全的地址空間。
其實從第五章開始,以後的課程就很少概念性的東西了,大部分需要大家親自反覆的操作實驗,熟練掌握
第六章:
一般來說,在作業系統環境下,程式所獲得的空間都是安全的
包含多段的程度中,
dw 即定義8個字型資料,即8
db 就是定義位元組嘍
程式中在結尾處,end 後門的標號,對應在程式中的標號位置,就是
程式的入口,也就是第一條執行的命令
將多資料,程式碼,棧,放入不同的段,是為了為了理清思路,便於理解
其次為了解決8086一個段最大64kb的問題
定義一個段:
如:assume cs:ps,ds:pp,ss:oo
其實第六章的內容,就是包含了前面幾章的內容,也就是一個混合應用,
具體的細節不多說,拿一個例項來說,我將對例項進行剖析:
assume cs:qq, ds:ww,ss,ee (把qq與cs扯上關係,其他兩個一樣,不多說)
ww segment
dw 1111h,2222h,3333h,4444h,5555h
ww ends (上面一段聲明瞭資料內容,參照dw的意思,大家都明白了吧)
ee segment
dw 0,0,0,0,0,0
ee ends(上面就是定義出多個棧地址空間)
qq segment
link:mov ax,ee
mov ss,ax
mov sp,20h(上面是把ee段當做棧空間,設定ss:sp為:ee:20)
mov ax,ww
mov ds,ax(希望用ds:bx訪問ww中的資料,ds指向ww段)
mov bx,0(設定第一個ds:bx的訪問ww段單元)
mov cx,5(設定迴圈次數)
s:push[bx]
add bx,2
loop s(將ww段資料依次入棧)
mov bx,0
mov cx,5
s1:pop[]
add bx,2
loop s1(和上面相反,依次出棧)
mov ax,4c00H
int 21h
qq ends
end link (設定程式的入口)
(注意:
1.8086 CPU不允許直接將資料直接送入一個段暫存器
2.上述的,qq,ww,ee,s,s1,link,都是自己定義的
3.上面註釋方式不對,是為了說明問題而寫,大家注意
4.所以的程式碼段,棧,資料段,都是我們人為定義的)