寄存器---汇编学习笔记
第二章 寄存器
2.0 寄存器的緒論
一個典型的CPU由運算器、控制器、寄存器(CPU工作原理)等器件構成。內部總線實現 CPU 內部各個器件之間的聯系,外部總線實現CPU和主板其他器件的聯系。
在CPU中(下列重要內容)
- 運算器進行信息處理;
- 寄存器進行信息存儲;
- 控制器控制各個器件進行工作;
- 內部總線連接各種器件,在它們之間進行數據的傳送。
對于匯編程序員來說,CPU中的主要部件是寄存器。寄存器是CPU中與程序員可以用指令讀寫的部件。
不同的CPU,寄存器的個數、結構是不相同的。
2.1 通用寄存器
8086CPU的所有寄存器都是16位的。
通用寄存器:AX、BX、CX、DX.
一個16位寄存器的邏輯結構:
8086CPU的上一代CPU中的寄存器都是8位的。
為了保證兼容,8086的16bit寄存器可分為兩個獨立8bit寄存器
- AX可分為AH和AL.
- BX可分為BH和BL.
- CX可分為CH和CL.
- DX可分為DH和DL.
如圖,AX的高8bit是AH,低8bit是AL:
一個8bit寄存器所能存儲的數據的最大值為255。
2.2 字在寄存器中的存儲
- 字節(byte):一個字節有8個bit組成,可以存在8位寄存器中。
- 字(word):一個字由兩個字節組成,這兩個字節分別稱為高位字節和低位字節
一個字可以存在一個16位寄存器中,這個字的高位字節和低位字節自然就存在這個寄存器的高8位寄存器和低8位寄存器中。一個word數據20000的例子,如圖:
其中,信息本身是二進制數據,而不是十進制數據,別搞混。
再強調一遍,信息本身就是二進制數據。
2.3 初識匯編指令
| mov a,b | 將b的數據送入a中 | a = b |
| add a,b | 將a+b的數據送入a中 | a = a+b |
a代表寄存器,b代表數據或者寄存器。
問題2.1:指令執行后AX中的數據是多少?
mov ax,4E20H ;AX=4E20H add ax,1406H ;AX=6226H mov bx,2000H ;BX=2000H add ax,bx ;AX=8226H mov bx,ax ;BX=8226H add ax,bx ;AX=044CH指令執行后AX中的數據為 004CH。
問題2.2:指令執行后AX中的數據是多少?
指令執行后AX中的數據為 0158H。
檢測點 2.1
(1) 寫出每條匯編指令執行后相關寄存器中的值。
(2) 只能使用目前學過的匯編指令,最多使用4條指令,編程計算2的4次方。
MOV AX,2 ;AX = 2 ADD AX,AX ;AX = 4 ADD AX,AX ;AX = 8 ADD AX,AX ;AX = 162.4 物理地址
所有的內存單元構成的存儲空間是一個一維的線性空間,每一個內存單元在這個空間中都有一個唯一的地址,稱為物理地址。
CPU通過地址總線送入存儲器的,必須是一個內存單元的物理地址。
2.5 16位結構的CPU
8080、8085是8位機,8086是16位機。
16位結構的CPU具有的結構性質
- 運算器一次最多可以處理16位的數據;
- 寄存器的最大寬度位16位;
- 寄存器和運算器之間的通路為16位。
8086是16位結構的CPU,也就是說,能夠一次性處理、傳輸、暫時存儲的信息的最大長度是16位的。
2.6 8086CPU給出物理地址的方法
8086CPU有20位地址總線,可以傳送20位地址,達到1MB的尋址能力。8086CPU是16位結構,在內部一次性處理、傳輸、暫時存儲的地址為16位。從表面上看CPU只能尋址64KB。
8086CPU采用一種內部用兩個16位地址合成的方法來形成一個20位的物理地址。
如圖:
當8086CPU要讀寫內存時
- CPU中的相關部件提供兩個16位的地址,一個稱為段地址,另一個稱為偏移地址;
- 段地址和偏移地址通過內部總線送入一個稱為地址加法器的部件;
- 地址加法器將兩個16位合成為一個20位的物理地址;
- 地址加法器通過內部將20位物理地址送入輸入輸出控制電路;
- 輸入輸出控制電路將20位物理地址送上地址總線;
- 20位物理地址被地址總線傳送到存儲器。
地址加法器采用物理地址 = 段地址x16+偏移地址
地址加法器工作過程(圖中數據皆用十六進制表示):
由段地址x16引發的討論
“段地址x16”有一個更為常用的說法是左移4位。
一個例子:
| 0 | 10B | 2H | 2 |
| 1 | 100B | 4H | 4 |
| 2 | 1000B | 8H | 8 |
| 3 | 10000B | 10H | 16 |
| 4 | 100000B | 20H | 32 |
觀察上面移位數和各種進制數據的關系,我們可以發現:
- 一個數據的 二進制形式左移 1位,相當于該數據 乘以2;
- 一個數據的 二進制形式左移 N位,相當于該數據乘以2的N次方;
- 地址加法器如何完成段地址x16的運算?就是將以二進制形式存放的段地址左移4位。
不難得出,一個數據的十六進制形式左移1位,相當于乘以16。
2.7 “段地址x16+偏移地址=物理地址”的本質含義
本質含義是:CPU在訪問內存時,用一個基礎地址(段地址x16)和偏移地址相加,給出內存單元的物理地址。(可以理解為從基礎地址出發+偏移量 = 你要去的目的地)
2.8 段的概念
實際上,內存并沒有分段,段的劃分來自于CPU。
我們可以在邏輯上將內存“分段”,如圖
編程時,可以根據需要,將若干個地址連續的內存單元看做一個段(注意:段地址一定是16的倍數,一個段的長度最大為64KB)。
內存單元地址小結
(1)觀察下面的地址,你有什么發現?
| 21F60H | 2000H | 1F60H |
| 21F60H | 2100H | 0F60H |
| 21F60H | 21F0H | 0060H |
| 21F60H | 21F6H | 0000H |
| 21F60H | 1F00H | 2F60H |
結論:CPU可以用不同的段地址(SA)和偏移地址(EA)形成同一個物理地址。
(2)如果給定一個段地址,僅通過變化偏移地址來尋址最多可定位多少個內存單元?
結論:如果給定一個段地址,僅通過變化偏移地址來尋址最多可定位64KB個內存單元。
數據在 21F60H 內存單元中,CPU 表示 形式為 2000:1F60 單元中。
檢測點 2.2
(1)給定段地址為0001H,僅通過變化偏移地址尋址,CPU的尋址范圍為 0001:0000 到 0001:FFFF 。
(2)有一數據存放在內存 20000H 單元中,現給定段地址為SA,若想用偏移地址尋到此單元。則SA應滿足的條件是:最小為 1001H ,最大為 2000H 。
2.9 段寄存器(提供段地址)
8086CPU有4個段寄存器:CS、DS、SS、ES。
2.10 CS和IP
CS為段寄存器,IP為指令指針寄存器。
一個例子(展示CPU執行指令原理,比較長)
從下面一系列的圖展示過程。
下面,首先初始化
將CS、IP的內容送入地址加法器
地址加法器將物理地址送入輸入輸出控制電路
輸入輸出控制電路將物理地址送到地址總線
內存中存放的機器指令被送入CPU
輸入輸出控制電路將指令送入指令緩沖器
IP中的值自動增加,以使CPU可以讀取下一條指令
執行控制器執行指令
指令被執行后,AX內容發生了變化
同上過程,讀取下一條指令
再讀取下一條!
又讀取一條!
到此為止,4條指令執行歷程結束!
通過上面的例子,8086CPU的工作過程可以簡要描述如下。
8086CPU加電啟動或復位后,CS和IP被設置為CS=FFFFH,IP=0000H(重要,也就是說FFFF0H是8086PC機開機后執行的第一條指令)。
2.11 修改CS、IP的指令
CPU從何處執行指令?
顯然,由CS、IP中的內容決定的。
我們如何改變CS、IP的值呢?
8086CPU提供相應的指令。
我們在初步了解匯編指令的時候使用過 mov 指令,那我們能夠使用mov指令來修改CS、IP的內容嗎?
答案是不可以的,因為8086CPU的mov指令沒有提供這樣的功能。
我們將用最簡單的可以修改CS、IP的指令: jmp 指令。
使用方式形如: jmp 段地址 : 偏移地址。這個指令的功能是修改CS和IP的值。
還有另一種修改方式: jmp 某一合法寄存器。這個指令的功能是修改IP的值。
問題 2.3
指令執行序列如下:
2.12 代碼段
對于8086PC機,在編程時,可以將一組內存單元定義為一個段。我們可以將長度為 N(N<=64KB) 的一組代碼,存在一組地址連續、起始地址為16的倍數的內存單元中。我們可以認為,這段內存是用來存放代碼的,從而定義了代碼段。
例如:
MOV AX,0000H ;(B8 00 00) ADD AX,0123H ;(05 23 01) MOV BX,AX ;(8B D8) JMP BX ;(FF E3)這段長度為10個字節的指令,存放在123B0H~123B9H的一組內存單元中,我們就可以認為,123B0H~123B9H這段內存時用來存放代碼的,是一個代碼段,它的段地址為123BH,長度為10個字節。
這段代碼如何被執行呢?
顯然,只要將CS = 123BH,IP = 0000H即可。
2.9~2.12 小結
檢測點 2.3
下面的3條指令執行后,CPU幾次修改IP?都是在什么時候?最后IP中的值是多少?
答案:一次修改 IP,在 JMP AX 的時候,最后 IP 為0000H。
實驗1 查看CPU和內存,用機器指令和匯編指令編程
1.預備知識:Debug的使用
(1)什么是Debug?
Debug是 DOS、Windows 都提供的實模式(8086 方式)程序的調試工具。使用它,可以查看CPU各種寄存器中的內容、內存的情況和在機器碼級跟蹤程序的運行。
(2)我們用到的Debug功能。
- 用Debug的R命令查看、改變CPU寄存器的內容;
- 用Debug的D命令查看內存中的內容;
- 用Debug的E命令改寫內存中的內容;
- 用Debug的U命令將內存中的機器指令翻譯成匯編指令;
- 用Debug的T命令執行一條機器指令;
- 用Debug的A命令以匯編指令的格式在內存中寫入一條機器指令。
Debug的命令比較多,共有20多個,但這6個命令是和匯編學習密切相關的。在以后還有用到一個P命令。
(3)進入Debug。
Debug是在DOS方式下使用的程序。我們在進入Debug前,應先進入到DOS方式。
用以下方式可以進入DOS。
在這里,我用的是 實驗樓 的環境。這樣降低了學習成本。
(4)用 R命令 查看、改變CPU寄存器的內容。
如下,成功顯示了寄存器的內容
如下,成功修改了AX寄存器的內容
我們注意到 DS:0000 = 0 以后的章節會介紹。還看到了最下面一行出現的 TEST …的匯編指令。
可以用 R命令 修改CS和IP的內容。
(5)用Debug的 D命令 查看內存中的內容。
用Debug的D命令,可以查看內存中的內容,D命令的格式比較多。
可以用:D 段地址 : 偏移地址,如下。
使用D命令,Debug將輸出3部分內容,如下。
- 中間是從指定地址開始的128個內存單元的內容,用十六進制的格式輸出。每行的輸出從16的整數倍的地址開始,最多輸出16個單元的內容。
- 左邊是每行的起始地址。
- 右邊是每個內存單元中的數據對應的可顯示的 ASCII 碼字符。
(6)用 Debug 的 E命令 改寫內存中的內容。
E 10 ;修改當前數據段10H號單元內容 E ES:100 ;修改附加段100H號單元內容 D ES:100 ;查看一下100H單元的內容是否修改了(7)用E命令向內存中寫入機器碼,用U命令查看內存中機器碼的含義,用T命令執行內容從中的機器碼。
E命令其他用法
編寫一個如下代碼的匯編程序
MOV AX,0001 ;B80100 MOV CX,0002 ;B90200 ADD AX,CX ;01C8編寫代碼如下:
修改CS、IP寄存器
使用T命令執行匯編指令
觀察以上所有圖片寄存器的變化(眼睛都花了)。
(8)用Debug的 A命令 以匯編指令形式在內存中寫入機器指令。
如圖。
從最后一行可以看出,內存1000H段的內容已經被修改成功。
最后,在一張命令表格吧。
| R命令 | 查看、修改CPU |
| D命令 | 查看內存中的內容 |
| E命令 | 修改內存中的內容 |
| U命令 | 將內存中的內容解釋為機器指令和對應的匯編指令 |
| T命令 | 執行CS:IP指向的內存單元處的指令 |
| A命令 | 以匯編指令的形式向內存中寫入指令 |
2. 實驗任務
(1)使用 Debug,將下面的程序段寫入內存,逐條執行,觀察每條指令執行后,CPU中相關寄存器中內容的變化。
匯編指令 機器碼 MOV AX,4E20H ;B8 20 4E ADD AX,1416H ;05 16 14 MOV BX,2000H ;BB 00 20 ADD AX,BX ;01 D8 MOV BX,AX ;89 C3 ADD AX,BX ;01 D8 MOV AX,001AH ;B8 1A 00 MOV BX,0026H ;BB 26 00 ADD AL,BL ;00 D8 ADD AH,BL ;00 DC ADD BH,AL ;00 C7 MOV AH,0 ;B4 00 ADD AL,BL ;00 D8 ADD AL,9CH ;04 9CDebug下用A命令輸入匯編指令:
再用D命令查看是否輸入匯編指令到內存:
在使用R命令查看和修改CS、IP的值,修改成代碼段的開始位置:
最后,T命令執行,自行實驗觀察步驟。
整個過程只要觀察AX和BX就好,最后AX=0002,BX=4026。
(2)將下面3條指令寫入從 2000:0 開始的內存單元中,利用這3條指令計算2的8次方。
mov ax,1 add ax,ax jmp 2000:0003分析,我們知道 mov ax,1 占了3個內存單元。所以我們代碼段的開始位置為2000H。
如下(要算2的8次方,add ax,ax,這個跟算法的快速冪一樣,我們只要add ax,ax四次就行,因為ax初始化為1):
(3)查看內存中的內容。
PC機主板上的ROM中寫有一個生產日期,在內存 FFF00H~FFFFFH 的某幾個單元中,請找到這個生產日期,在內 FFF00H~FFFFFH 的某幾個單元中,請找出這個生產日期并試圖改變它。
顯然,用D FFF0 : 0000 L 100就可以得出答案,如下。
(4)向內存從B8100H開始的單元中填寫數據,如:
-e B8100:0000 01 01 02 02 03 03 04 04發現:數據沒有被改變,為什么呢?
原因:我們閱讀第一章的時候,我們知道我們將所有內存當做一個邏輯連續的內存。而B810H地址段是ROM(只讀)的內存段。
真的太多了,碼了一天。
總結
以上是生活随笔為你收集整理的寄存器---汇编学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做数据产品经理要学习那些东西?
- 下一篇: Python解释器