這一章節(jié)中畦木,就通過(guò) debug 的方式來(lái)對(duì)寄存器中的內(nèi)容進(jìn)行操作,如果你想提前試試匯編指令申窘,
可以翻到最后一小節(jié)舱沧,熟悉下匯編指令之后,再去分析每條指令執(zhí)行之后各個(gè)寄存器的值偶洋。
一個(gè)典型的 CPU由運(yùn)算器熟吏、控制器、寄存器等器件構(gòu)成玄窝,這些器件靠?jī)?nèi)部總線相連牵寺。前面所說(shuō)的總線,相對(duì)于 CPU 而言是外部總線恩脂。內(nèi)部總線實(shí)現(xiàn) CPU 內(nèi)部各個(gè)器件之間的聯(lián)系帽氓,外部總線實(shí)現(xiàn) CPU 和 主板其他器件的聯(lián)系。
在CPU中:
- 運(yùn)算器進(jìn)行信息處理俩块;
- 寄存器進(jìn)行信息存儲(chǔ)黎休;
- 控制器控制各種器件進(jìn)行工作浓领;
- 內(nèi)部總線連接各種器件,在它們之間進(jìn)行數(shù)據(jù)的傳送
對(duì)于一個(gè)匯編程序員來(lái)說(shuō)势腮,CPU中的主要部件是寄存器联贩。寄存器是CPU中程序員可以用指令讀寫(xiě)的部件。
程序員通過(guò)改變各種寄存器中的內(nèi)容來(lái)實(shí)現(xiàn)對(duì)CPU的控制捎拯。
不同的CPU泪幌,寄存器個(gè)數(shù)、結(jié)構(gòu)不同署照。 8086 CPU有 14 個(gè)寄存器祸泪,每個(gè)寄存器都有一個(gè)名稱。這些寄存器是:AX建芙、BX没隘、CX、DX禁荸、SI右蒲、DI、SP屡限、BP、IP炕倘、CS钧大、SS、DS罩旋、ES啊央、PSW。
3.1 通用寄存器
8086CPU 的所有寄存器都是 16 位的涨醋,可以存放兩個(gè)字節(jié)瓜饥。
AX、BX浴骂、CX乓土、DX 這 4 個(gè)寄存器通常用來(lái)存放一般性的數(shù)據(jù),被稱為通用寄存器溯警。
以 AX 為例趣苏,寄存器的邏輯結(jié)構(gòu)如圖 3-1 所示:
一個(gè) 16 位寄存器可以存儲(chǔ)一個(gè) 16 位的數(shù)據(jù),數(shù)據(jù)在寄存器中存儲(chǔ)情況如圖 3-2 所示.
思考一下梯轻,一個(gè) 16 位寄存器所能存放的數(shù)據(jù)最大值為多少食磕?
答: 2^16 - 1 = 65535 (0 ~ 65535 ,共65536個(gè)數(shù)字)
8086CPU的上一代CPU中寄存器都是 8 位喳挑,為了保證兼容彬伦,是原來(lái)基于上一代CPU編寫(xiě)的程序稍加修改就可以運(yùn)行在8086之上滔悉,8086CPU 的AX、BX单绑、CX拆又、DX這 4 個(gè)寄存器都可分為兩個(gè)獨(dú)立使用的 8 位寄存器來(lái)用:
- AX 可分為 AH 和 AL;
- BX 可分為 BH 和 BL康吵;
- CX 可分為 CD 和 CL戒幔;
- DX 可分為 DH 和 DL;
以 AX 為例份氧, 8086CPU 的16位寄存器可分為兩個(gè)8位寄存器情況如圖 3-3 所示:
AX 的低 8 位(0~7位)構(gòu)成了 AL 寄存器唯袄,高8位(8~15)構(gòu)成了AH寄存器。AL和AH都可以獨(dú)立使用8位寄存器蜗帜。
圖 3-4 展示了 16 位寄存器及它所分成的兩個(gè) 8 為寄存器的數(shù)據(jù)存儲(chǔ)情況恋拷。
思考一下,一個(gè) 8 位寄存器所能存儲(chǔ)的數(shù)據(jù)的最大值為多少厅缺?
答: 2 ^ 8 - 1= 255 (0~255,共 256個(gè)不同數(shù)字)
3.2 字在寄存器中的存儲(chǔ)
出于對(duì)兼容性的考慮蔬顾, 8086CPU可以一次性處理兩種尺寸的數(shù)據(jù)。
- 字節(jié):記為 byte湘捎, 一個(gè)字節(jié)由 8 個(gè) bit 組成诀豁,可以存儲(chǔ)在 8 位寄存器中;
-
字:記為 word窥妇, 一個(gè)字由兩個(gè)字節(jié)組成舷胜,這兩個(gè)字節(jié)分別稱為這個(gè)字的高位字節(jié)和低位字節(jié), 如圖 3-5 所示
一個(gè)字可以存儲(chǔ)在一個(gè) 16 位寄存器總活翩,這個(gè)字的高位字節(jié)和低位字節(jié)自然就存儲(chǔ)在這個(gè)寄存器高8位寄存器和低8位寄存器中烹骨。
如圖 3-4 所示,一個(gè)字型數(shù)據(jù) 2000材泄, 存儲(chǔ)在 AX 寄存器中沮焕,在 AH 中存儲(chǔ)了它的高 8 位,在 AL 中存儲(chǔ)了它的低 8 位拉宗。 AH 和 AL 中的數(shù)據(jù)峦树,既可以看成是一個(gè)字型數(shù)據(jù)的高 8 為和低 8 位,這個(gè)字型數(shù)據(jù)的大小是: 20000旦事; 又可以看成是兩個(gè)獨(dú)立的字節(jié)型數(shù)據(jù)空入,它們的大小分別是 78 和 32。
3.3 關(guān)于數(shù)制的討論
任何數(shù)據(jù)族檬,到了計(jì)算機(jī)中都是以二進(jìn)制形式存放的歪赢。為了描述不同的問(wèn)題,又經(jīng)常將它們用其他的進(jìn)制來(lái)表示单料。比如圖 3-4 中寄存器 AX 中的數(shù)據(jù)是 0100111000100000埋凯, 這就是 AX 中信息本身点楼,可以用不同的邏輯意義來(lái)看待它“锥裕可以將它看做一個(gè)數(shù)值掠廓,大小是 20000。
當(dāng)然甩恼, 二進(jìn)制數(shù) 0100111000100000 本身也可以表示一個(gè)數(shù)值的大小蟀瞧,但是人類習(xí)慣于十進(jìn)制,用十進(jìn)制20000表示可以使我們直觀地感受這個(gè)數(shù)值的大小条摸。
十六進(jìn)制數(shù)的一位相當(dāng)于二進(jìn)制數(shù)的四位悦污, 如 0100111000100000 可表示成: 4(0100)、E(1110)钉蒲、2(0010)切端、0(0000) 四個(gè)十六進(jìn)制數(shù)。
由于一個(gè)內(nèi)存單元可存放 8 位數(shù)據(jù)顷啼,CPU 中的寄存器又可存放 n 個(gè) 8 位數(shù)據(jù)踏枣。也就是說(shuō),計(jì)算機(jī)中的數(shù)據(jù)大多是由 1~N個(gè) 8 位數(shù)據(jù)構(gòu)成钙蒙。很多時(shí)候茵瀑,需要直觀地看出組成數(shù)據(jù)的各個(gè)字節(jié)數(shù)據(jù)的值,用十六進(jìn)制來(lái)表示數(shù)據(jù)可以直觀的看出這個(gè)數(shù)據(jù)由哪些 8 為數(shù)據(jù)構(gòu)成的躬厌。
比如马昨, 20000 寫(xiě)成 4E20 就可以了直觀的看出這個(gè)數(shù)據(jù)由 4E 和 20 兩個(gè) 8 為數(shù)據(jù)構(gòu)成,如果AX中存放4E20烤咧,則 AH 存放的是 4E偏陪, AL存放的是 20抢呆。這種方式表示數(shù)據(jù)便于直觀地分析問(wèn)題煮嫌,我們多用十六進(jìn)制來(lái)表示一個(gè)數(shù)據(jù)。
在以后的課程中抱虐,為了區(qū)分不同的進(jìn)制昌阿,在十六進(jìn)制表示的數(shù)據(jù)后面加 H,二進(jìn)制后面加 B恳邀,十進(jìn)制不加懦冰。
例如:
十進(jìn)制: 20000
十六進(jìn)制:4E20
二進(jìn)制: 0100111000100000B
3.4 幾條匯編指令
這小節(jié)主要分析寄存器中的值,可以先看后面的實(shí)驗(yàn)谣沸,然后通過(guò)匯編指令去驗(yàn)證
通過(guò)匯編指令控制CPU進(jìn)行工作中刷钢,如圖 3-6 中幾條指令
匯編指令不區(qū)分大小寫(xiě)。
接下來(lái)看些匯編指令乳附,執(zhí)行完后内地,各個(gè)寄存器中數(shù)據(jù)的變化:
如圖 3-7
程序段最后一條指令 add ax,bx, 在執(zhí)行前 ax 和 bx 中的數(shù)據(jù)都為 8226H伴澄。
相加之后所得值: 1044CH ,但是 ax 為 16 為寄存器,只能存放 4 位十六進(jìn)制數(shù)據(jù)阱缓,所以高位 1 不能再 ax 中保存非凌,ax 中的數(shù)據(jù)為: 044CH。
程序最后一條指令 add al,93H, 在執(zhí)行前荆针,al 中的數(shù)據(jù)為 C5H敞嗡,相加后所得的值為 158H,但是 al 為 8 位寄存器航背,只能存放十六進(jìn)制的數(shù)據(jù)喉悴,所以最高位的 1 丟失,ax 中的數(shù)據(jù)為: 0058H沃粗。
注意粥惧,這里的al是作為一個(gè)獨(dú)立的 8 位寄存器來(lái)使用和 ah 沒(méi)有關(guān)系,CPU 在執(zhí)行這條指令時(shí)認(rèn)為 ah 和 al 是兩個(gè)不相關(guān)的寄存器最盅。不要錯(cuò)誤的認(rèn)為突雪, add al,93H 指令產(chǎn)生的進(jìn)位會(huì)存儲(chǔ)到 ah 中涡贱,add al,93H 是進(jìn)行的 8 位運(yùn)算咏删。
如果執(zhí)行 add ax,93H, 低 8 位的進(jìn)位會(huì)存儲(chǔ)在 ah 中, CPU 在執(zhí)行這條執(zhí)行時(shí)認(rèn)為只有一個(gè) 16 位 寄存器 ax,進(jìn)行的是 16 位運(yùn)算问词。指令 add ax,93H 執(zhí)行后督函,ax 中的值為: 0158H。此時(shí)激挪,使用的寄存器是 16 位寄存器ax辰狡, add ax,93H 相當(dāng)于將 ax 中的 16 位數(shù)據(jù) 00c5H 和 另一個(gè) 16 位數(shù)據(jù) 0093H 相加垄分,結(jié)果是 16 位的 0158H宛篇。
注意:
在進(jìn)行數(shù)據(jù)傳送或者運(yùn)算時(shí),要注意指令的兩個(gè)操作對(duì)象的位數(shù)應(yīng)當(dāng)一致
mov ax,bx
mov bx,cx
mov ax,18H
mov al, 18H
add ax,bx
add ax,20000
上面這些指令都是正確的薄湿,而
mov ax,bl
mov bh,al
mov al,20000
add al,100H
這些指令都是錯(cuò)誤的叫倍,原因都是指令的兩個(gè)操作對(duì)象位數(shù)不一致。
3.5 物理地址
我們知道豺瘤,CPU 訪問(wèn)內(nèi)存單元時(shí)吆倦,要給出內(nèi)存單元的地址。所有的內(nèi)存單元構(gòu)成存儲(chǔ)空間是一個(gè)一維的線性空間坐求,每一個(gè)內(nèi)存單元在這個(gè)空間中都有唯一的地址蚕泽,我們將這個(gè)唯一的地址稱為物理地址。
CPU 通過(guò)地址總線送入存儲(chǔ)器的桥嗤,必須是一個(gè)內(nèi)存單元的物理地址须妻。在 CPU 向地址總線發(fā)出物理地址之前派任,必須要在內(nèi)部先形成這個(gè)物理地址。不同的CPU可以有不同的形成物理地址的形式璧南。這里討論 8086CPU是如何在內(nèi)部形成內(nèi)存單元的物理地址掌逛。
3.6 16 位機(jī)結(jié)構(gòu)的CPU
什么是 16 位結(jié)構(gòu)的CPU呢?
- 運(yùn)算器一次最多可處理 16 位的數(shù)據(jù)
- 寄存器的最大寬度為 16 位
- 寄存器和運(yùn)算器之間的通路為 16 位
8086 是 16 位結(jié)構(gòu)的CPU司倚,也就是說(shuō)豆混,在 8086 內(nèi)部,能夠一次性處理动知、傳輸皿伺、暫存的信息最大長(zhǎng)度是 16 位。內(nèi)存單元的地址在送上地址總線之前盒粮,必須在 CPU 中處理鸵鸥、傳輸和暫存,對(duì)于 16 位 CPU丹皱,能一次性處理妒穴、傳遞和暫存的 16 位的地址。
3.7 8086CPU 給出物理地址的方法
8086CPU 有 20 位地址總線摊崭,可以傳送 20 位地址讼油,達(dá)到 1 MB 尋址能力。
8086CPU 又是 16 位結(jié)構(gòu)呢簸,在內(nèi)部一次性處理矮台、傳輸、暫存地址為 16 為根时。從 8086CPU 的內(nèi)部結(jié)構(gòu)來(lái)看瘦赫,如果將地址從內(nèi)部簡(jiǎn)單發(fā)出去,那么它只會(huì)形成 16 位地址蛤迎,表現(xiàn)出的尋址能力是 64KB确虱。
為了形成 20 位物理地址,達(dá)到 1 MB 的物理尋址能力忘苛,8086CPU 采用一種在內(nèi)部用兩個(gè) 16 位地址合成的方法來(lái)形成一個(gè) 20 位的物理地址蝉娜。
如圖 3-9唱较, 當(dāng) 8086CPU 要寫(xiě)內(nèi)存時(shí):
1) CPU 中相關(guān)部件提供兩個(gè) 16 位的地址扎唾,一個(gè)稱為段地址,另一個(gè)稱為偏移地址南缓;
2)段地址和偏移地址通過(guò)內(nèi)部總線進(jìn)入一個(gè)稱為地址加法器的部件胸遇;
3)地址加法器將兩個(gè) 16 地址合成一個(gè) 20 為的物理地址;
4)地址加法器通過(guò)內(nèi)部總線將 20 位物理地址送入輸入輸出控制電路
5)輸入輸出控制電路將 20 位物理地址送上地址總線
6)20 位物理地址被地址總線傳送到存儲(chǔ)器
地址加法器采用物理地址=段地址x16 + 偏移地址的方法用段地址和偏移地址合成物理地址汉形。
例如纸镊, 8086CPU 要訪問(wèn)地址為 123C8H的內(nèi)存單元倍阐,此時(shí),地址加法器的工作過(guò)程如下:
3.8 “段地址 x16 + 偏移地址 = 物理地址” 本質(zhì)含義
本質(zhì)含義:CPU 在訪問(wèn)內(nèi)存時(shí)逗威,用一個(gè)基礎(chǔ)地址(段地址x16) 和一個(gè)相對(duì)于基礎(chǔ)地址的偏移地址相加峰搪,給出內(nèi)存單元的物理地址。也就是說(shuō) 8086CPU 的這種尋址功能是 “基礎(chǔ)地址+偏移地址=物理地址”尋址模式的一種具體實(shí)現(xiàn)方案凯旭。 8086CPU中概耻,段地址x16可看做是基礎(chǔ)地址。
3.9 段的概念
3.10 段寄存器
3.11 CS 和IP
3.12 修改 CS 罐呼、 IP 的指令
3.13 代碼段
實(shí)驗(yàn)1 查看 CPU 和 內(nèi)存鞠柄,用機(jī)器指令和匯編指令編程
1. 預(yù)備知識(shí): Debug 的使用
什么是 Debug?
Debug 是 DOS嫉柴、Windows 都提供的程序調(diào)試工具(8086)厌杜。使用它可以查看 CPU 個(gè)中寄存器中的內(nèi)容、內(nèi)存情況和在機(jī)器碼級(jí)跟蹤程序運(yùn)行计螺。-
常用Debug功能
- R 命令查看和改變CPU寄存器的內(nèi)容夯尽;
- D 命令查看內(nèi)存中的內(nèi)容;
- E 命令改寫(xiě)內(nèi)存中的內(nèi)容登馒;
- U 命令將內(nèi)存中的機(jī)器指令翻譯成匯編指令呐萌;
- T 命令執(zhí)行一條機(jī)器指令;
- A 命令以匯編指令的格式在內(nèi)存中寫(xiě)入一條機(jī)器指令
Debug 命令比較多谊娇,總共 20 多個(gè)肺孤,這 6 個(gè)是和匯編密切相關(guān)的。
2. Debug 模式開(kāi)啟
這里使用的是 DOSBox 0.74
全屏:option + enter济欢, 退出全屏 option + enter
3. 用 R 命令查看赠堵、改變 CPU 寄存器內(nèi)容
我們先查看下 AX 、 BX 法褥、 CX 茫叭、 DX 、CS 半等、IP 這 6 個(gè)寄存器內(nèi)容揍愁,其他的暫時(shí)忽略。
注意 CS 和 IP 的值杀饵, CS=073F, IP = 0100切距,也就是說(shuō)朽缎,內(nèi)存 073F:0100處的指令為 CPU 當(dāng)前要讀取、執(zhí)行的指令。在所有寄存器的下方话肖, Debug 還列出了 CS:IP 所指向的內(nèi)存單元出所存放的機(jī)器碼北秽,并將它翻譯為匯編指令。
可以看到最筒,CS:IP所指向的內(nèi)存單元為 073F:0100,此處存放的機(jī)器碼為 198B1E52 對(duì)應(yīng)的匯編指令為 SBB [BP + DI +521E], CX 贺氓。暫時(shí)先看這些,其他指令自行忽略床蜘。
除了查看寄存器的內(nèi)容之外掠归,還可以修改寄存器的內(nèi)容:
若要修改一個(gè)寄存器中的值,比如 AX 中的值悄泥,可用 R 命令后加寄存器的名來(lái)進(jìn)行虏冻,輸入 r ax 后回車,將出現(xiàn) “:”作為輸入提示弹囚,在后面輸入要寫(xiě)入的數(shù)據(jù)后厨相,enter 完成,即完成了對(duì) AX 中內(nèi)容的修改鸥鹉。若想要再次查看AX中的內(nèi)容蛮穿,可再用 R 命令查看。如圖所示:
在 上圖中毁渗,一旦進(jìn)入DEBUG践磅,用 R 命令查看,CS:IP 指向 073F:0100灸异,此處存放的機(jī)器碼為 07府适,對(duì)應(yīng)的匯編指令 POP ES;
接著肺樟,用 R 命令將 IP 修改為 200檐春, 則 CS:IP 指向 073F:0200,此處存放的機(jī)器碼為 C27529 對(duì)應(yīng)的匯編指令:RET 2975么伯;
接著疟暖,用 R 命令修改CS為 ff00, 則 CS:IP 指向 ff00:0200, 此處存放的機(jī)器碼為 000 對(duì)應(yīng)的匯編指令 ADD [BX+SI], AL;
4. 用 D 命令查看內(nèi)存中的內(nèi)容
D 命令可以查看內(nèi)存中的內(nèi)容田柔。如果我們想知道內(nèi)存 10000H 處的內(nèi)容俐巴,可以用 'd 段地址:偏移地址' 格式來(lái)查看
要查看內(nèi)存 10000H 處的內(nèi)容 ,首先將這個(gè)地址表示為段地址:偏移地址的格式硬爆,可以是 1000:0欣舵,然后用 ’d 1000:0 ' 列出 1000:0 處的內(nèi)容。
使用 D 命令摆屯, Debug 將輸出 3 部分內(nèi)容:
- 中間部分是從指定地址開(kāi)始的 128(8行 16 列) 個(gè)內(nèi)存單元的內(nèi)容用十六進(jìn)制的格式輸出邻遏,每行的輸出從 16 的整數(shù)倍的地址開(kāi)始,最多輸出 16 個(gè)單元的內(nèi)容虐骑。從圖中准验,可以知道內(nèi)存 1000:0 單元中的內(nèi)容是 92H,1000:1 單元中的內(nèi)容是 B2H廷没,內(nèi)存 1000:0~1000:F中的內(nèi)容都在第一行糊饱;內(nèi)存 1000:10 中的內(nèi)容是 00H, 內(nèi)存 1000:11 中的內(nèi)容是 40H颠黎,內(nèi)存 1000:10~1000:1F 中的內(nèi)容都在第二行另锋。注意,每行的中間有一個(gè) “-”狭归,它將每行的輸出分為兩部分夭坪,在“-”前后各8個(gè)單元,這樣便于查找过椎。比如尋找 1000:6B 單元中的內(nèi)容室梅,我們知道第 7 行,然后從中間的“-”向后樹(shù) 3 個(gè)單元內(nèi)容 0AH疚宇。(這一部分內(nèi)容亡鼠,每一句都要對(duì)著上面的圖進(jìn)行查看)
- 左邊是每行的起始地址。
- 右邊是每個(gè)內(nèi)存單元中數(shù)據(jù)對(duì)應(yīng)的可現(xiàn)實(shí)的ASCII碼字符敷待。比如间涵,第一行 1000:11, 1000:1C, 1000:7D 中存放的數(shù)據(jù)是 40H、38H榜揖、21H勾哩,它們對(duì)應(yīng)的ASCII字符分別是 @, 8, !。而 1000:0 內(nèi)存單元举哟,92H沒(méi)有對(duì)應(yīng)的可可顯示 ASCII 字符钳幅,Debug就用 “.”來(lái)代替。
注意炎滞,我們看到的內(nèi)存中的內(nèi)容敢艰,在不同的計(jì)算機(jī)中是不一樣的,也可能每次用Debug看到的內(nèi)容都不同册赛,因?yàn)槲覀冇肈ebug看到的都是原來(lái)就在內(nèi)存中個(gè)的內(nèi)容钠导,這些內(nèi)容受隨時(shí)都可能變化的系統(tǒng)環(huán)境的影響。當(dāng)然森瘪,我們也可以改變內(nèi)存牡属、寄存器中的內(nèi)容。
我們使用 d 1000:9 查看 1000:9 處的內(nèi)容扼睬,Debug將怎樣輸出呢逮栅?如圖所示:
Debug 從 1000:9 開(kāi)始顯示悴势,一直到 1000:88 ,一共顯示 128 個(gè)字節(jié)措伐。第一行 1000:0~1000:8 單元中的內(nèi)容不顯示特纤。
在一進(jìn)入 Debug 后,用 D 命令直接查看侥加,將列出 Debug 預(yù)設(shè)的地址處的內(nèi)容 如圖所示
在使用了 “d 段地址:偏移地址”之后捧存,接著使用 D 命令,可列出后續(xù)內(nèi)容担败,如圖:
也可以指定 D 命令查看范圍昔穴,此時(shí)采用 “d 段地址: 起始偏移地址 結(jié)尾偏移地址”格式。比如要查看 1000:0 ~ 1000:9 中的內(nèi)容提前,可以用 “d 1000: 0 9" 實(shí)現(xiàn)
如果我們想查看內(nèi)存單元 10000H 中的內(nèi)容吗货,可以用如下的方式中任意一種:
-
用 Debug 的 E 命令改寫(xiě)內(nèi)存中的內(nèi)容
可以使用 E 命令來(lái)改寫(xiě)內(nèi)存中內(nèi)容,比如狈网,要將內(nèi)存 1000:0~1000:9 單元中的內(nèi)容分別寫(xiě)成 0卿操、1、2孙援、3害淤、4、5拓售、6窥摄、7、8础淤、9崭放,可以用 "e 起始地址 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) ... ..." 格式來(lái)進(jìn)行
也可以采用提問(wèn)的方式來(lái)一個(gè)一個(gè)地改寫(xiě)內(nèi)存中的內(nèi)容
上面的操作步驟為:
- 輸入 e 1000:10, enter
- 屏幕顯示其實(shí)地址 1000:10 和第一個(gè)單元(1000:0010 單元)的原始內(nèi)容鸽凶,然后光標(biāo)停在 "." 后面提示要輸入的數(shù)據(jù)币砂,此時(shí)可以有兩個(gè)選擇:輸入數(shù)據(jù),然后空格繼續(xù)輸入下一個(gè)單元玻侥;其二不輸入數(shù)據(jù)决摧,直接空格,則不修改當(dāng)前內(nèi)存單元內(nèi)容
- 所有內(nèi)存單元修改完畢之后凑兰,enter 結(jié)束 E 命令操作掌桩。
可以用 E 命令向內(nèi)存單元中寫(xiě)入字符,比如姑食,用 E 命令從內(nèi)存 1000:0 開(kāi)始寫(xiě)入數(shù)值 1波岛、 字符‘a(chǎn)’、數(shù)值 2音半、字符'b'则拷、數(shù)值 3 贡蓖、字符 'c',可采用如下方法進(jìn)行:
從圖中可以看出, Debug 對(duì) E 命令執(zhí)行的結(jié)構(gòu)是, 向 1000:0, 1000:2, 1000:4 單元中寫(xiě)入數(shù)值 1煌茬、2斥铺、3,向 1000:1 宣旱、 1000:3 仅父、1000:5 單元中寫(xiě)入字符 'a', 'b','c' 的ASCII 碼值: 61H叛薯、62H浑吟、63H。
也可以用E命令向內(nèi)存中寫(xiě)入字符串耗溜,比如用E命令從內(nèi)存 1000:0 開(kāi)會(huì)寫(xiě)入: 數(shù)值 1组力, 字符串'a+b', 數(shù)值 2抖拴、 字符串 'C++'燎字、字符 3 、字符串 'IBM'.
- 用 E 命令向內(nèi)存中寫(xiě)入機(jī)器碼阿宅,用 U 命令查看內(nèi)存中機(jī)器碼的含義候衍,用 T 命令執(zhí)行內(nèi)存中的機(jī)器碼。
如何向內(nèi)存中寫(xiě)入機(jī)器碼呢洒放?
我們知道蛉鹿,機(jī)器碼也是數(shù)據(jù),當(dāng)然可以用 E 命令將機(jī)器碼寫(xiě)入內(nèi)存往湿。比如我們要從內(nèi)存 1000:0 單元開(kāi)始寫(xiě)入這樣一段機(jī)器碼:
b80100 mov ax, 0001
b90200 mov cx, 0002
01c8 add ax, cx
U 命令的顯示輸出分為 3 部分
1) 每一條機(jī)器指令的地址妖异;
2)機(jī)器指令
3)機(jī)器指令所對(duì)應(yīng)的匯編指令
我們可以看到:
1000: 0 地址單元存放的是寫(xiě)入的機(jī)器碼 b8 01 00 所組成的機(jī)器指令,對(duì)應(yīng)的匯編指令是 mov ax领追,0001;
1000: 3 地址單元存放的是寫(xiě)入的機(jī)器碼 b9 02 00 所組成的機(jī)器指令他膳,對(duì)應(yīng)的匯編指令是 mov cx,0002;
1000: 6 地址單元存放的是寫(xiě)入的機(jī)器碼 01 c8 所組成的機(jī)器指令绒窑,對(duì)應(yīng)的匯編執(zhí)行是 add ax, cx;
由此棕孙,我們可以再一次看到內(nèi)存中的數(shù)據(jù)和代碼沒(méi)有任何區(qū)別,關(guān)鍵在于如何解釋些膨。
如何執(zhí)行我們寫(xiě)入的機(jī)器指令呢散罕?使用 Debug 的 T 命令可以執(zhí)行一條或者多條指令,簡(jiǎn)單第使用 T 命令可以執(zhí)行 CS:IP 指向的指令傀蓉,如圖:
首先欧漱,通過(guò)E命令向內(nèi)存單元 1000:0 開(kāi)始寫(xiě)入了 6 個(gè)字節(jié)的機(jī)器碼,然后通過(guò) R 命令查看 CPU 寄存器中的狀態(tài)葬燎,可以看到CS=073F IP=0100误甚,指向內(nèi)存:073f:0100缚甩;如要 T 命令控制 CPU 執(zhí)行我們寫(xiě)到 1000:0 的指令,必須先讓 CS:IP 指向 1000:0 ,所以我們通過(guò) R 命令 修改 CS 和 IP 中的內(nèi)容窑邦,使 CS:IP 指向 1000:0擅威。
完成上面的步驟之后,就可以了用 T 命令來(lái)執(zhí)行我們寫(xiě)入的指令了(此時(shí)冈钦, CS:IP 指向我們的指令所在的單元)郊丛。執(zhí)行 T 命令之后,CPU 執(zhí)行 CS:IP 指向的指令瞧筛,則 1000:0 處的指令 b8 01 00(mov ax,0001)得到執(zhí)行厉熟,執(zhí)行指令后,Debug 顯示寄存器的狀態(tài)
注意较幌, 指令執(zhí)行后揍瑟,AX 中的內(nèi)容被改寫(xiě)為 1, IP 改變?yōu)?IP+3(因?yàn)?mov ax乍炉,0001 的指令長(zhǎng)度是 3 個(gè)字節(jié))绢片, CS:IP 指向下一條指令。
我們可以繼續(xù)使用T命令岛琼,指向下面的指令
如上圖所示底循,用 T 命令繼續(xù)執(zhí)行后面的指令,注意每條指令執(zhí)行后槐瑞,CPU 相關(guān)寄存器的變化熙涤。
-
Debug 的 A 命令以匯編指令的形式在內(nèi)存中寫(xiě)入機(jī)器指令
前面我們使用 E 命令寫(xiě)入機(jī)器指令,這樣很不方便随珠,最好能直接以匯編指令的形式寫(xiě)入指令灭袁。為此 Debug 提供了 A 命令。 A 命令使用方法如下:
先用 A 命令窗看,以匯編語(yǔ)言向從 1000:0 開(kāi)始的內(nèi)存單元寫(xiě)入幾條指令茸歧,然后用 D 命令查看 A 命令執(zhí)行之后的結(jié)果∠陨颍可以看到软瞎,在使用 A 命令寫(xiě)入指令時(shí),我們輸入的是匯編執(zhí)行拉讯,debug 將這些匯編指令翻譯成對(duì)應(yīng)的機(jī)器指令涤浇,將它們的機(jī)器執(zhí)行寫(xiě)入內(nèi)存。
使用 A 命令寫(xiě)入?yún)R編指令時(shí)魔慷,在給出的起始地址后直接按 enter 表示操作結(jié)束
簡(jiǎn)單地用 A 命令只锭,從一個(gè)預(yù)設(shè)的地址開(kāi)始輸入指令:
執(zhí)行預(yù)設(shè)地址中的指令:
本次實(shí)驗(yàn)中用到的命令:
1. 查看和修改CPU中寄存器的內(nèi)容: R 命令;
2. 查看內(nèi)存中的內(nèi)容: D 命令
3. 修改內(nèi)存中的內(nèi)容: E命令(可以寫(xiě)入數(shù)據(jù)院尔、指令蜻展,在內(nèi)存中它們沒(méi)有區(qū)別)
4. 將內(nèi)存中的內(nèi)容解釋為機(jī)器指令和對(duì)應(yīng)的匯編指令: U 命令
5. 執(zhí)行 CS:IP 指向的內(nèi)存單元除的指令: T 命令
6. 以匯編指令的形式向內(nèi)存中寫(xiě)入指令: A 命令