第一節 顯卡和顯存
- 通過彙編代碼在屏幕上顯示文字,需要用到兩個硬件:顯卡和顯示器
- 顯卡:爲顯示器提供內容
- 顯示器:將顯卡所提供的內容呈現在屏幕上
- 集成顯卡:集成在主板上,和主板是一體的
- 獨立顯卡:獨立生產與銷售的一個獨立的部件,但仍需插到主板上使用
- 每個顯卡都有自己的存儲器,稱之爲顯示存儲器,簡稱“顯存”
- 顯示器可以顯示的最小單位是像素
- 顯示器顯示黑白色圖像是最簡單的,只需要控制每個像素是亮或是不亮即可,如何控制像素?
- 利用顯存,把亮抽象爲1,把不亮抽象爲0,將顯存中的每個比特和顯示器中的每個像素一一對應起來
- 顯卡會週期性的從顯存中提取比特,在顯示器上顯示
- 週期性:顯卡不斷的讀取顯存中的內容,每讀取一次,屏幕便會刷新一次,讀取的速度越快,屏幕刷新的頻率也就越快
- 顯示器顯示黑白色圖像是最簡單的,只需要控制每個像素是亮或是不亮即可,如何控制像素?
- 1、圖形模式:黑白模式/真彩色模式
- 如上圖所示,顯存中第一個字節的內容爲
11110000
,第二個字節中的內容爲11111111
,其餘字節內容爲00000000
,在顯示器上就會先顯示4個亮點,然後顯示4個黑點,再顯示8個亮點,最後全部顯示黑點,由於像素是僅僅連在一起的,故先看到一條白色的短線,間距4個像素的距離,再顯示一條黑色的長線。 - 顯示器的分辨率越高,需要的顯存就越大
- 黑白模式的圖像只要一個比特就可以表示一個像素
- 真彩色模式的圖像使用24個比特(3個字節)來表示顏色,可以表示16777216種顏色
- 若使用真彩色模式,顯存中的3個字節對應屏幕中的一個像素
- 如上圖所示,顯存中第一個字節的內容爲
- 2、文本模式:BIOS會執行一個硬件的初始化,它會將顯存的顯示模式初始化爲80×25的文本模式
80×25
:在屏幕上顯示25行,每一行80個字符,若滿屏狀態下,共計2000個字符
- 一個字符由大量像素組合而成,不同字符的像素分佈同樣不同,故顯示字符較麻煩
- 爲解決字符顯示麻煩的問題,
字符發生器
由此誕生- 在顯示器中的哪個位置顯示哪個字符,只需要在顯存的對應位置存入字符的ASCII碼,然後顯卡會先將顯存中的內容讀取到字符發生器中,由字符發生器決定顯示器中顯示的字符
- 在文本模式下,顯存中的內容和顯示器中的像素之間沒有直接關係
- 顯存中存的是要顯示字符的ASCII碼
- 字符發生器對ASCII碼進行解析之後交由顯示器顯示
- 3、顯存的2個字節對應顯示器上的一個字符
- 前一個字節用於存儲字符的ASCII碼,後一個字節用於存儲字符的屬性
- 字符屬性這一字節的前四位決定了字符的背景色,後四位決定了字符的前景色
- 背景色:
- K = 0 時不閃爍,K = 1 時閃爍
- 前景色:
- 前景色中的I值和
RGB
組合,會產生不同的顏色
- 前景色中的I值和
- 背景色:
- 顯存的位置及地址
- 顯存至於外圍板卡中,顯存的地址爲
B8000-BFFFF
- 顯存至於外圍板卡中,顯存的地址爲
第二節 爲訪問顯存做準備
-
mov ax, 0xb800 ;將b800傳送到累加寄存器寄存器ax中 mov es, ax ;將累加寄存器ax中的值(b800)傳送到附加段寄存器es中
-
上述第二行代碼爲什麼不直接寫成
mov es, 0xb800
?- 因爲
intel
處理器不允許直接將一個數傳送到段寄存器中 - 只允許:
move 段寄存器, 通用寄存器/內存單元
- 所以上述代碼需要用通用寄存器(累加寄存器ax)來做中轉,再將值傳送到附加段寄存器ES中
- 因爲
-
將
b800
傳送到附加段寄存器ES中的目的是什麼?- 附加段寄存器ES用途:存儲數據段的段地址,顯存就相當於一個數據段
- 顯存的段地址爲
b800
,顯示文本需要訪問顯存 - 上述兩行代碼執行完以後,顯存數據段的段地址(
b800
)存儲到附加段寄存器es中,以便後續用於訪問顯存
-
第二行代碼處也可以用數據段寄存器
DS
,但數據段寄存器DS
後續有其他用途,故此處用附加段寄存器ES -
上述兩行代碼的目的:爲後面訪問顯存做準備
第三節 向顯存寫入數據
mov byte [es:0x00], 'L'
(對應顯存的第一個存儲單元,存儲字符L
的ASCII
碼)- 可以使用字符L的字面值,但是需要用
''
引起來,編譯器在編譯時會自動將''
內的字符轉換爲ASCII碼 - 編譯器會將字符自動編譯爲
二進制形式
進行存儲 - 代碼作用:將"字符L的ASCII碼"存儲到顯存的第一個存儲單元中
- 可以使用字符L的字面值,但是需要用
- 地址
[es:0x00]
- 地址必須使用方括號
[]
括起來 - 若地址中沒有聲明附加段寄存器ES,處理器會默認段地址在數據段寄存器DS中
- 地址中第一個值爲附加段寄存器ES,附加段寄存器ES中存儲的是顯存的段地址(上一節中的
b800
) - 地址中第二個值爲偏移地址
00
- 段地址
b800
+ 偏移地址00
指向顯存的第一個存儲單元
- 地址必須使用方括號
- byte/word
- 8086處理器爲16位操作系統,因此進行單次數據操作的寬度可以是8位,也可以是16位
- 在編譯器無法進行判斷是8位指令還是16位指令時,需用byte/word進行修飾
- 明確的告訴編譯器這條指令的數據寬度是1個字節/字
- 補充:
- 1字節(byte) = 8比特(bit)
- 字(word)的大小取決於具體系統的總線寬度,如果是32位的系統,則一個字是4個字節,如果是64位的系統,則一個字是8個字節
- 補充:
- 編譯器會根據byte/word進行相應的編譯
- 不需要byte/word修飾的例子:
mov [00], AL
- 源操作數是8位通用寄存器AL,AL寄存器的大小爲1個字節
(1byte = 8bit)
,故按字節操作
- 源操作數是8位通用寄存器AL,AL寄存器的大小爲1個字節
mov AX, [00]
- 目的操作數爲16位通用寄存器AX,AX寄存器的大小爲1個字
(1word = 2 byte = 16bit)
,故按字操作
- 目的操作數爲16位通用寄存器AX,AX寄存器的大小爲1個字
mov byte [es:0x01], 0x07
(對應顯存的第二個存儲單元,存儲字符L
的屬性
)- 將"字符L的屬性"存儲到顯存的第二個存儲單元中
- 屬性值07:黑底白字、無閃爍、無加亮
mov byte [es:0x00], 'L'
;將"字符L的ASCII碼"存儲到顯存的第一個存儲單元中
;move byte [es:0x01], 0100 1100b / 76 /0x4C
;(L ASCII碼的二進制形式/十進制形式/十六進制形式)
;如果地址指令前沒有byte,那地址指令[es:0x00]`未指明是多少位,因此編譯器無法判斷第一條指令是8位還是16位
;不需要修飾:mov [00], AL / mov AX, [00]
mov byte [es:0x01], 0x07
;將"字符L的屬性"存儲到顯存的第二個存儲單元中
;屬性值07:黑底白字、無閃爍、無加亮
mov byte [es:0x02], 'a'
mov byte [es:0x03], 0x07
mov byte [es:0x04], 'b'
mov byte [es:0x05], 0x07
mov byte [es:0x06], 'e'
mov byte [es:0x07], 0x07
mov byte [es:0x08], 'l'
mov byte [es:0x09], 0x07
mov byte [es:0x0a], ' '
mov byte [es:0x0b], 0x07
mov byte [es:0x0c], "o"
mov byte [es:0x0d], 0x07
mov byte [es:0x0e], 'f'
mov byte [es:0x0f], 0x07
mov byte [es:0x10], 'f'
mov byte [es:0x11], 0x07
mov byte [es:0x12], 's'
mov byte [es:0x13], 0x07
mov byte [es:0x14], 'e'
mov byte [es:0x15], 0x07
mov byte [es:0x16], 't'
mov byte [es:0x17], 0x07
mov byte [es:0x18], ':'
mov byte [es:0x19], 0x07
第四節 MOV
指令
- 功能:用於數據的傳送
- 格式:
Mov 目的操作數, 源操作數
Mov AX, 0x22
- 注意:
- 1、"目的操作數"必須是一個容器 ----> 寄存器或者內存單元,而源操作數則沒有限制,可以是寄存器、內存單元或者數字
- 2、“傳送"的本質是"複製”,只改變目的操作數中的值,並不會影響源操作數中的值
- 3、目的操作數和源操作數的數據寬度必須是一致的
- 4、目的操作數和源操作數不能同時爲內存單元
- 原因:內存內部構造導致(RAM存儲器的存儲單元都是互相獨立的,不能將一個內存單元中的內容直接傳送到另一個存儲單元中)
- 5、
intel
處理器不允許
數字直接傳送到段寄存器中,需要經過寄存器或內存單元進行中轉Mov 段寄存器, 通用寄存器/內存單元
- 目的操作數爲寄存器的情況
Mov AX, BX
- 源操作數爲寄存器
Mov AX, [0x33]
- 源操作數爲內存單元
Mov AX, 0x66
- 源操作數爲數字/立即數
- 稱作
立即數
的原因:Mov AX, [0x33]
指令中,源操作數爲內存單元,需要先到內存地址爲0x33
的位置處取出數據,然後將數據傳送到通用寄存器AX中;而Mov AX, 0x66
指令中,源操作數爲數字,可以直接將數字傳送到通用寄存器AX中
- 稱作
- 源操作數爲數字/立即數
- 目的操作數爲內存單元的情況
Mov [0x04], BX
- 源操作數爲寄存器
Mov [0x04], [0x33]
錯誤!!
,源操作數和目的操作數同爲內存單元
Mov [0x04], 0x66
- 源操作數爲數字/立即數
- 其他情況:
Mov AX, BL
錯誤!!
,通用寄存器AX爲16位,而BL爲8位,造成源操作數和目的操作數的數據寬度不一致
Mov CS, 0x22
錯誤!!
,目的操作數代碼段寄存器CS爲段寄存器,而源操作數爲數字,intel
處理器不允許
數字直接傳送到段寄存器中
第五節 標號和彙編地址
-
1、彙編地址
-
將彙編源程序進行編譯後會生成兩個文件,bin文件(.bin)和列表文件(.lst)
-
bin文件:機器指令,提交給處理器執行的文件
-
列表文件:存儲關於源程序的詳細信息
- 編譯器會將源程序中的每一條指令進行編號
- 編號從00000000開始,第一條指令長度爲
3個字節
,故第二條指令編號爲00000003,第二條指令長度爲2個字節
,故第三條指令編號爲00000005,第三條指令長度爲6個字節
,故第四條指令編號爲0000000B,第四條指令長度爲6個字節
,故第五條指令編號爲00000011,第五條指令長度爲6個字節
,故第六條指令編號爲00000017,······· ,以此類推。
行號 編號(彙編地址) 機器指令 彙編代碼 1 00000000 B800B8 mov ax, 0xb800 2 00000003 8EC0 mov es, ax 3 00000005 26C60600004C mov byte [es:0x00], ‘L’ 4 0000000B 26C606010007 move byte [es:0x01], 0x07 5 00000011 26C606020061 mov byte [es:0x02], ‘a’ 6 00000017 26C606030007 mov byte [es:0x03], 0x07 ··· ··· ··· ··· ··· ··· ··· ··· 131 00000100 0000000000 number db 0, 0, 0, 0, 0
-
-
將整個程序當作一個段,讀取到內存中,指令的編號等於在段內的偏移地址
-
將前三行指令加載到內存中,如下圖所示:
- 第一條指令中
B8
爲段地址開始的地址,在段內對應的偏移地址爲0
- 第一條指令的編號爲0,偏移地址爲0
- 第二條指令中
8E
在段內的偏移地址對應爲3
- 第二條指令的編號爲3,偏移地址爲3
- 第三條指令中
26
在段內偏移地址對應爲5
- 第三條指令的編號爲5,偏移地址爲5
- 編號是由編譯器通過編譯得到,編號的值等於指令在段內的偏移地址,所以也稱編號爲
彙編地址
-
-
2、標號
- 由編譯器自動生成
- 關係:標號 = 彙編地址
- 第131行彙編代碼,程序的開頭爲number,number即爲
標號
- 作用:相當於指令彙編地址的符號表示,
number
代表0100
- 若在程序的其他位置使用了number,編譯器在編譯過程中會自動將
number
替換爲0100
參與運算
- 作用:相當於指令彙編地址的符號表示,
- 在程序中需要使用某一條指令的彙編地址的時候,在該指令前添加
標號
,在需要使用匯編地址的地方使用標號
代替具體的彙編地址 - 編譯器允許在每一條指令前添加
標號
,標號的書寫規範較爲寬鬆,一般以字母開頭就不會出現問題。
第六節 需求分析
- 將第131行代碼的彙編地址的
十進制
顯示在屏幕上- 第一步:通過標號:number,拿到
彙編地址
(二進制) - 第二步:分解各個數位
- number =
0x0100
=1 0000 0000B
- 1、 1 0000 0000 除以 1010 商 = 1 1001 餘數 = 110 (6:個位)
- 2、 0001 1001 除以 1010 商 = 10 餘數 = 101 (5:十位)
- 3、 10 除以 1010 商 = 0 餘數 = 10 (2:百位)
- 4、因爲商(被除數) = 0,所以運算到此結束
- number =
- 第三步:推算出標號十進制形式的每個數值的ASCII碼
- 將第二步得到的每個數位的二進制的值加
11 0000
得到十進制數所對應的ASCII碼,將得到的ASCII碼寫入顯存- 數字0的ASCII碼是 11 0000 = 0 + 11 0000
- 數字1的ASCII碼是 11 0001 = 1 + 11 0000
- 數字2的ASCII碼是 11 0010 = 10 + 11 0000
- 數字3的ASCII碼是 11 0011 = 11 + 11 0000
- 數字4的ASCII碼是 11 0100 = 100 + 11 0000
- ··· ··· ···
- 將第二步得到的每個數位的二進制的值加
- 第一步:通過標號:number,拿到
第七節 DB指令和僞指令
-
跳轉指令
-
infi jmp near infi ;無限循環
-
-
db指令(僞指令)
-
db: declare byte 聲明並初始化數據
-
僞指令:不能調動處理器執行指令,只能調動編譯器進行數據的聲明和初始化
- 作用:編譯器在規定的位置(0100)預留出5個字節的空間並按照指令要求進行賦值(
佔位
)
- 作用:編譯器在規定的位置(0100)預留出5個字節的空間並按照指令要求進行賦值(
-
number db 0, 0, 0, 0, 0 ;標號:number = 彙編地址 = 0x0100 ;書寫規範:以字母開頭 ;db:聲明並初始化數據 ;聲明數據的本質就是在內存中佔用一塊空間 ;初始化數據的本質就是給這個空間賦予一個值 ;在內存中佔用了5個字節的空間,這5個字節的值都是0
-
-
Mov指令
:會被編譯器編譯爲對應的機器指令
- 作用:
控制處理器
,將數據傳送到指定位置
- 作用:
-
DB指令:會被編譯器編譯爲對應的
數據
B
:byte
的意思,表示聲明的每個數值佔用1個字節的寬度- 作用:
控制編譯器
,聲明並初始化數據
-
DW
指令、DD
指令、DQ
指令W
:word
的意思,表示聲明的每個數值佔用2個字節的寬度D
:double word
的意思,表示聲明的每個數值佔用4個字節的寬度Q
:quad word
的意思,表示聲明的每個數值佔用8個字節的寬度
第八節 DIV指令
- DIV指令:除法
- div: division
- 16位數 ÷ 8位數
- 除數:由8位通用寄存器或者內存單元來提供
intel
處理器規定,被除數必須存儲在16位寄存器AX中:- 不能用內存單元(立即數)直接參與運算,必須進行轉化,存儲到AX寄存器中再進行運算
- 16位通用寄存器AX:被除數
- 商被存儲到寄存器AL(AX寄存器中的低八位)中,餘數被存儲到寄存器AH(AX寄存器中的高八位)中
- 計算完成後,商和餘數會覆蓋掉被除數
- 結構:div 除數
- div 後只跟除數的原因:被除數必須存儲在AX寄存器中
- div
CL
(CX
寄存器中的低八位)
- 32位數 ÷ 16位數
- 被除數爲32位數,處理器和寄存器都是16位數,故32位數需要用到兩個16位寄存器來存儲
- 除數:由16位通用寄存器或者內存單元來提供
- 被除數的高16位被存儲在
DX
寄存器中,低16位被存儲在AX寄存器中(intel
處理器的規定) DX
:被除數的高16位AX
:被除數的低16位
- 商被存儲到寄存器
AX
(低十六位)中,餘數被存儲到寄存器DX
(高十六位)中
- 商被存儲到寄存器
- 結構:div 除數
- div
CX
(CX
爲十六位通用寄存器)
- div
- 16位數 ÷ 8位數
第九節 運算前的準備
-
mov ax, number ;將“標號”number存儲到AX寄存器中,作爲下面除法運算的被除數的低16位 ;編譯器在編譯的時候會將number替換爲其所對應的彙編地址 mov dx, 0 ;將0存儲到DX寄存器中,作爲下面除法運算的被除數的高16位 ;由於低十六位number的值只有9位,故用不到被除數的高十六位,所以高十六位設置爲0 mov bx, 10 ;將10,也就是二進制的1010存儲到BX寄存器中,作爲下面除法運算的除數 ;以上三條指令爲第2個步驟的除法運算做好了準備工作
第十節 定位內存地址
-
mov cx, cs ;將代碼段寄存器CS中的值,也就是0x000,傳送到CX寄存器中 mov ds, cx ;將CX寄存器中的值,也就是0x000傳送到數據段寄存器DS中 ;DS寄存器中存儲的是本程序在內存中的段地址
-
寫好彙編程序
-
對其進行編譯,拿到機器指令
-
將機器指令,也就是bin文件寫入硬盤的主引導扇區
-
啓動計算機
-
BIOS將主引導扇區(程序)加載到內存地址爲
7C00
的位置處 -
BIOS通過一條跳轉指令
jump 0x0000, 0x7C00
- 將代碼段寄存器CS的值設置爲
0x0000
, 指令指針寄存器IP
的值設置爲0x7C00
- 段的起始位置(代碼段的段地址):代碼段寄存器CS左移四位 -->
00000
- 指令指針寄存器
IP
的值爲7C00
,程序從段內偏移地址爲7C00的位置處開始加載
- 段的起始位置(代碼段的段地址):代碼段寄存器CS左移四位 -->
- 使處理器跳轉到
7C00
的位置處執行程序 - 使用DB指令所預留的內存空間的段地址爲
00000
,第一個字節的偏移地址爲7C00 + 0100
,第二個字節的偏移地址爲07C00 + 0100 + 1
,第三個字節的偏移地址爲07C00 + 0100 + 2
, ··· ···
- 將代碼段寄存器CS的值設置爲
-
注意:
- 下圖的程序不是從段開始的位置
00000
處加載的,而是從段內偏移地址爲7C00
的位置處開始加載的 - 程序是作爲一個段被加載到內存中的,並沒有對程序進行分段,故程序的數據段和代碼段的地址是相同的
- 下圖的程序不是從段開始的位置
第十一節 分解各個數位
-
div bx ;對應第一次除法運算 ;商存儲在AX寄存器(低十六位)中,作爲下次運算的被除數 ;餘數,也就是標號的個位上的值,存儲在DX寄存器(高十六位)中 mov [0x7c00 + number + 0x00], dl ;將第一次除法運算所得到的標號的個位上的值 ;存入了使用db聲明的第一個存儲單元中(標號個位上的值對應第一個存儲單元) ;十六位的DX寄存器被分爲兩個八位的通用寄存器DH和DL,而此時的餘數只有三位,只佔用了DL寄存器中的低三位,故此處使用dl寄存器存儲餘數即可 ;mov操作數數據寬度要一致,db所聲明的第一個存儲單元的大小爲8位,故用8位dl指令,若用dx則會將操作數傳入第一個和第二個存儲單元中,會佔據兩個存儲單元的容量 xor dx, dx ;異或指令:對兩個數進行異或運算,並將結果存儲到目的操作數中 ;異或運算的特點:相同爲0,不同爲1 ;這條指令的作用:將DX寄存器中的值清零 ;使用指令操作的原因:AX爲低十六位寄存器,DX爲高十六位寄存器,在本節運行第一次除法運算的時候,餘數被存儲到DX寄存器中,故DX寄存器中含值,在進行第二次除法運算之前需對DX寄存器中的值清零,爲第二次除法運算做準備 div bx ;對應第二次除法運算 mov [0x7c00 + number + 0x01], dl ;將第二次除法運算所得到的標號的十位上的值 ;存入了使用db所聲明的第二個存儲單元中 xor dx, dx ;爲第三次除法運算做準備 div bx ;對應第三次除法運算 mov [0x7c00 + number + 0x02], dl ;將第三次除法運算所得到的標號的百位上的值 ;存入了使用db所聲明的第三個存儲單元中
第十二節 顯示各個數位
mov al, [0x7c00 + number + 0x02]
;將標號百位上的數值傳送給AL寄存器
add al, 0x30
;獲得標號百位上數值的ASCII碼
;0x30的二進制爲110000
mov [es: 0x1a], al
;將標號百位上數值的ASCII碼存入顯存
;前一個字節:存儲字符的ASCII碼
mov byte [es: 0x1b], 0x04
;將0x04存入顯存中偏移地址爲0x1b的存儲單元
;顯存中的兩個字節對應屏幕上的一個字符
;後一個字節,存儲字符屬性04:黑底、紅字、無閃爍、無加亮
mov al, [0x7c00 + number + 0x01]
;將標號十位上的數值傳送給al寄存器
add al, 0x30
;獲得標號十位上數值的ASCII碼
mov [es: 0x1c], al
;將標號十位上數值的ASCII碼存入顯存
mov byte [es: 0x1d], 0x04
mov al, [0x7c00 + number + 0x00]
;將標號個位上的數值傳送給AL寄存器
add al, 0x30
;獲得標號個位上數值的ASCII碼
mov [es: 0x1e], al
;將標號個位上數值的ASCII碼存入顯存
mov byte [es: 0x1f], 0x04
mov byte [es: 0x20], 'D'
;前一個字節:將字符D的ASCII碼存入顯存
mov byte [es: 0x21], 0x07
;後一個字節:存儲字符屬性值07:黑底白字、無閃爍、無加亮
第十三節 無限循環
infi jmp near infi
;infi:標號,等於該條指令的彙編地址00FD
;無限循環
;對應的機器指令爲E9FDFF,其中E9爲操作碼,FDFF爲操作數
-
jmp 0x005c, 0x003d
- 直接給出段地址
0x005c
和偏移地址0x003d
- 指令執行完畢,CS寄存器的值變爲
0x005c
,IP
寄存器的值變爲0x003d
- 執行到下一個週期,處理器會將
CS
寄存器中的值左移四位,形成一個段地址,加上IP
寄存器中的偏移地址,形成邏輯地址 - 處理器到邏輯地址中取指令並加以執行
- 直接給出段地址
-
jmp near infi
-
jmp
:跳轉指令,用於改變CS寄存器
和IP寄存器
中的值CS寄存器
和IP寄存器
決定了處理器將要執行哪條任務
-
jmp
作用:使處理器轉移到指定位置執行 -
near:修飾符,表示指令的操作數是16位的
-
000000FD E9FDFF
-
操作數 = 標號的彙編地址 - 當前指令的彙編地址 - 當前指令的長度
- 標號的彙編地址 = 當前指令的彙編地址
- 當前指令
E9FDFF
的長度爲3 - 故
jmp near infi
的操作數爲-3
-3
在計算機中如何存儲?- 整數在計算機中的存儲規則:無符號表示法、符號加絕對值表示法、補碼錶示法
- 1.將
3
轉化爲二進制11
- 2.
near
操作數是16位,故需在前補0,0000000000000011
- 3.判斷正負,
-3
爲負數,故取其補碼1111111111111101
,轉換爲16進制數爲FFFD
,操作數爲0xFFFD
,由於intel
處理器爲小端存儲,故會將操作數進行一個反轉,操作數最終結果爲FDFF
-
這條指令不會改變代碼段寄存器CS的值,只改變指令指針寄存器IP的值
-
處理器在執行指令時的做法:
- 指令指針寄存器
IP
+ 該指令的操作數 + 該指令的長度 =xxx
,再將xxx
存儲到IP
寄存器中
- 指令指針寄存器
-
該指令執行完畢,
CS
寄存器和IP
寄存器的值都不會改變,故處理器會再次跳轉到該指令繼續執行該指令,由此使處理器陷入無限循環 -
該結構
jmp
指令的運行效果:讓處理器跳轉到指定的標號位置處執行
-
第十四節 主引導扇區的有效標誌
times 249 db 0
;僞指令,讓編譯器重複生成db 0 ---- 249次
db 0x55, 0xaa
;硬盤主引導扇區的有效標誌
- 添加最後兩行代碼的意義:
- 硬盤要求主引導扇區最後兩個字節的數據必須是
0x55
和0xaa
- 一個扇區有512個字節,必須保證
0x55
和0xaa
這兩個字節在第511和第512個字節處,若沒有times 249 db 0
指令,則位置不符合扇區要求
- 硬盤要求主引導扇區最後兩個字節的數據必須是
第十五節 編譯並運行程序
- 編寫完成源程序
demo.asm
- 打開
NASM-IDE
軟件 --> 文件 --> 打開源程序 --> 選擇demo.asm
打開 --> 文件 --> 編譯本文檔(編譯後會得到兩個文件:bin文件
<存儲機器指令>和lst文件
<存儲程序詳細信息>) --> 將bin文件
寫入硬盤主引導扇區 --> 啓動虛擬機中創建的虛擬硬盤bin文件
寫入硬盤主引導扇區:- 打開
Vhd Writer
軟件 --> 選擇虛擬硬盤文件 --> 選擇虛擬硬盤.vhd
並雙擊 --> 下一步 --> 選擇數據文件(bin文件
) --> 下一步 --> 寫入文件 --> 完成
- 打開