彙編前十三章彙總(複習用)

第二章 寄存器

cpu的主要的部件是寄存器, 不同的cpu,寄存器的個數、結構是不相同的。
在8086cpu中有14個寄存器,這些寄存器是:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。

  1. IP:指令指針,指向當前相互要取出的指令字節,當BIU從內存中取出一個指令後,IP就自動加1,這裏的1指的不是一個字節,而是該條指令所佔的字節數。 IP指向的是指令地址的段內地址偏移量,又稱爲偏移地址(Offset Address)或者有效地址(A, Effective Address)。
  2. CS:代碼段寄存器
  3. DS:數據段寄存器
  4. SS:堆棧寄存器
  5. ES:附加段寄存器

其他的寄存器會在後面相應的章節一一列出作用。

2.1 通用寄存器

8086CPU的所有寄存器都是16位的,可以存放倆個字節。
其中通用寄存器爲AX、BX、CX、DX這四個。
這四個寄存器又可以分爲8個單獨的寄存器來使用,拿AX來說,可以分爲高低倆個字節,名字分別爲AH、AL。
雖說這四個寄存器都是通用寄存器,但是其都有獨自的功能和特點。

  1. AX:累加寄存器,通常用於運算,在乘除指令中指定用來存放操作數,另外,所有的I/O指令都使用這一寄存器與外界設備傳輸數據。
  2. BX:基址寄存器,常用於地址索引。
  3. CX:計數寄存器,常用於計數;常用於保存計算值,如位移指令,循環(loop)和串處理指令中作隱含的計數器。
  4. DX:數據寄存器,常用於數據傳遞。

2.2 字在寄存器中的存儲

分爲倆種

  1. 字節:記爲byte,一個字節由8個bit組成,可以存在8位寄存器中,如AL
  2. 字:記爲word,一個字由倆個字節組成,分別成爲高位字節和低位字節,可以存在16位寄存器中,如AX。

2.3 幾條彙編指令

2.4 物理地址

所有的內存單元構成的存儲空間是一個以爲的線性空間,每一個內存單元在這個空間中都有一個唯一的地址,這個地址就稱爲物理地址。

2.5 16位結構的CPU

16位結構或者說(16位機,機器字長位16位等)描述了CPU具有的結構特性爲

  1. 運算器ALU一次最多可以處理16爲的數據;
  2. 寄存器的最大寬度爲16爲;
  3. 寄存器和運算器之間的通路爲16位;

2.6 8086CPU的物理尋址方法

物理地址由地址加法器算出
物理地址=段地址*16+偏移地址
更一般的說 物理地址=基礎地址+偏移地址
其中基礎地質 = 段地址*16

2.8 段的概念

其實在內存中,並沒有所謂的分段,但是我們可以用分段的方式來管理內存。
我們可以認爲:比如說 地址10000H ~ 100FFH的內存單元構成一個段,段的起始地址(基礎地址)爲10000H,段地址爲1000H,大小爲100H。也可以將該段分爲倆個段,如10000H ~ 1007FH 和 10080H ~ 100FFH。起始地址分別爲1000H 和 1008H。

值得注意的是:段地址*16一定是16的倍數,所以一個段的起始地址一定是16的整數倍;偏移地址爲16位,16位地址的尋址能力爲64KB,所以一個段的最大長度爲64KB。

2.9 段寄存器

8086CPU的段寄存器有四個:CS、DS、SS、ES。

2.10 CS和IP

CS和IP分別爲代碼段寄存器和指令指針寄存器。
CPU讀取指令的過程可以概括爲一下的過程
(1)從CS:IP指向的內存單元讀取指令,讀取的指令進入指令緩衝區。
(2)IP=IP+所讀取指令的長度,從而指向下一條指令。
(3)執行指令。轉到第一個步驟,重複過程。

2.11 修改CS、IP(jmp指令)

不能通過mov指令來設置CS和IP的值。
修改CS、IP的值的指令中有一個:jmp指令。

  1. 如果想同時修改CS、IP的值,可以用“jmp 段地址: 偏移地址”來完成。如
    jmp 2AE3:3,執行完,CS=2AE3H,IP爲0003H,CPU從2AE33H處讀取指令。

  2. 若只想修改IP,可以用“jmp 一個合法寄存器”來完成,如
    mov ax,1000H jmp ax 執行後 IP = 1000H。

第三章 寄存器(內存訪問)

3.1 內存中字的存儲

CPU中,用16位寄存器來存儲一個字。高8位存放高位字節,低8位存放低位字節。在內存存儲中,內存單元式字節單元,那麼一個字就需要用倆哥哥地址連續的內存單元來存放,這個字的低位字節存放在低地址單元中,高位字節存放在高地址單元中。這叫小端方式,還有另外一個存放的方式大端方式。
這裏就涉及到存儲器中數據的組織方式了:

  1. 大端方式‘
    高位字節排放在內存的低地址端,低位字節存放在高地址端

  2. 小端方式
    低位字節存放在內存的低地址端,高位字節存放在高地址端

8086CPU採用的是X86結構,採用小端方式。

然後在讀或寫一個內存單元裏面的數據的時候,需要指定起始地址,讀取的長度。讀取的長度是一個字還是一個字節。小端方式的起始地址是低地址。
如使用一個立即數ds:[0],這裏就要指定 是字還是字節,字節:byte ptr ds:[0],字:word ptr ds:[0]

3.2 DS和[address]

CPU在讀寫一個內存單元的時候需要給出該內存單元的地址,內存地址由段地址和偏移地址組成。
DS:用來存放數據的段地址
SS:用來存放棧的段地址
CS:用來存放代碼的段地址
這裏用DS來舉例,比如說我們現在要讀取10000H單元的內容,段地址爲1000H,偏移地址爲0H。那麼就要用一下的代碼來實現。
mov bx,1000H
mov ds,bx
mov al,[0]
像DS這樣的段寄存器,不能直接將一個立即數直接MOV到DS中,並且在訪問內存單元的時候,必須指定DS以後,通過mov 通用寄存器,[偏移地址]來實現。

將一個數送入內存單元也相似
mov bx,1000H
mov ds,bx
mov [0],al

3.3 字的傳送

8086CPU是16位結構,有16根數據線,所以可以一次傳送16位數據,就是一個字,只要用mov指令給出16位的寄存器就可以直接進行16位數據的傳送。比如
mov bx,1000H
mov ds,bx
mov ax,[0]
mov [0],cx
在這裏插入圖片描述
在這裏插入圖片描述
這裏就可以說明小端方式的內存讀取的起始地址的問題。

3.4 mov、add、sub指令

  1. MOV指令的幾種形式
    mov 寄存器,數據 比如:mov ax,8
    mov 寄存器,寄存器 比如:mov ax,bx
    mov 寄存器,內存單元 比如:mov ax,[0]
    mov 內存單元,寄存器 比如:mov [0],ax
    mov 段寄存器,寄存器 比如:mov ds,ax
    mov 內存單元,立即數 比如:mov byte ptr DS:[0], 10
    最後一條要注意 給出的內存單元必須指定寫入或讀取的長度,如byte或word,必須給出段地址:[偏移地址]

  2. add指令
    add ax,8
    add ax,bx
    add ax,[0]
    add [0],ax
    add byte(word) ptr ds;[0],9
    但是注意的是不能 add 段寄存器,立即數或者寄存器

  3. sub指令
    和add指令一樣,爲減指令,用前面一個減去後面一個,結果存在前一個。

3.5 數據段

可以根據需要,將一組內存單元定義爲一個段。我們可以將一組長度爲N(N<= 64KB)、地址連續、起始地址爲16的倍數的內存單元作爲專門存儲數據的內存單元,從而定義了一個數據段。
如123B0H ~ 123B9H這樣的一段內存單元作爲數據段,起始地址爲123B0H,段地址爲123BH,長度爲10字節。

3.6 棧

規則:LIFO(Last In First Out,後進先出)

3.7 CPU提供的棧機制

8086CPU 提供入棧和出棧的指令,分別是:PUSH(入棧)和POP(出棧)。比如push ax,將ax的數據送入棧中,pop ax,將棧頂數據取出送入ax中。

現在有倆個問題:
第一:如果我們將10000H ~ 1000FH作爲棧空間來使用,CPU如何知道這是棧空間?這個時候就要設置SS(棧段寄存器)的段地址,MOV ax,1000H MOV ss,ax
第二:如何知道棧頂的偏移地址,這個時候就要SP(堆棧指針寄存器)出場,設置SP,MOV sp,0010H。
再8086CPU中 push和pop操作也是符合小端方式存儲和取出。
push ax的執行,由以下倆步完成。
(1)SP = SP - 2,SS:SP指向當前棧頂的單元,以當前棧頂前面的單元爲新的棧頂;
(2)將ax中的內容送入SS:SP所指向的內存單元處,SS:SP此時指向新的棧頂。
如圖在這裏插入圖片描述
pop ax的執行和push ax的執行正好相反。
(1)將SS:SP指向的內存單元的出書送入ax
(2)SP=SP+2,SS:SP指向當前棧頂下面的單元,以當前棧頂下面的單元爲新的棧頂。
如圖
在這裏插入圖片描述

3.8 棧頂超界問題

8086CPU不保證對棧的操作會不會出界,這個只能靠自己估算安排。一旦出界可能會修改棧外的內存單元的數據。

3.9 push、pop指令

push和pop指令的格式可以如下:
push 寄存器
pop 寄存器
push 段寄存器
pop 段寄存器
push 內存單元
pop 內存單元

第五章 [BX]和loop指令

1.[bx] 和內存單元的描述
[bx],就相當於[0],bx作爲偏移地址

2.loop指令
這是一個循環指令,默認的計數器爲cx,及cx表示循環的次數,在每一次循環的末尾cx-1,到cx爲0退出循環。
如代碼
mov cx, 3
mov bx,0
mov dx,0
s: mov al, ds:[bx]
mov ah,0
add dx,ax
inc bx
loop s

3.定義()
(ax)表示ax的內容,(20000H)表示20000H單元裏面的內容。
((ds)*16+(bx)) 表示偏移地址爲bx,段地址爲ds的內存單元裏面的內容。

4.約定符號idata表示常量

5.1 [BX]

用法就是BX作爲偏移地址。
這裏有一個指令
inc bx 表示bx自加一,比add bx,1要快不少

5.2 Loop指令

用cx寄存器來存放循環次數
格式爲
標號:循環代碼
loop 標號
如:
s:mov ax,1
loop s
CPU在執行loop時要進行倆步操作: (1) (cx) = (cx) - 1 (2) 判斷cx的值,不爲0則跳轉值標號處執行程序。
不管cx的值,循環段代碼至少執行1次。

5.5 [bx]和loop結合使用

相當於就是循環加可變的偏移值

5.6 段前綴

段前綴就是如同 ds:[bx] 裏面的ds:
有 ds: cs: ss: es: 這些稱爲段前綴

5.7 一段安全的空間

一般來說在dos方式下,0:200 ~ 0:2ff ( 00200H ~ 002ffH ) 的256個字節空間是不會有程序使用的。
所以這一段空間是安全的。不過爲了安全起見,進入DOS後可以Debug查看一下這一段空間是不是都爲0.

所以以後向一個段中寫入內容時,使用0:200 ~ 0:2ff 這段空間

第七章 更靈活的定位內存地址的方法

7.1 and 和 or 指令

(1)and 指令:邏輯與指令,按位與運算。
(2)or指令:邏輯或指令,按位或運算。

7.2 關於ASCII碼

“a”的ASCII碼爲61H(0110 0001b),“A”的ASCII碼爲41H(0100 0001b)
大小寫轉化的時候,小寫轉爲大寫只要 -20H 或者 and(1101 1111b)就行。
相應的,大寫轉化爲小寫只要 +20H 或者 or (0010 0000b)就行。當然還可以是其他的答案,不影響轉化就行。

7.5 [bx+idata]

含義是:偏移地址爲 (bx) + idata
可以寫成:
mov ax, [bx+idata]
mov ax, idata[bx]
mov ax, [bx].idata

7.6 用[bx+idata]的方式進行數組的處理

比如將datasg 中定義的第一個字符串轉化爲大寫,第二個字符串轉化爲小寫。
在這裏插入圖片描述
代碼段:
在這裏插入圖片描述

7.7 SI和DI

si 和 di 是8086CPU 中和bx功能相近的寄存器,只是 si 和 di 不能分成兩個 8 位寄存器來使用。

7.10 不同的尋址方式的靈活運用

(1)[idata] 用一個常量來表示地址,可以直接定位一個內存單元
(2)[bx],[si],[di] 用一個變量來表示內存地址,可以用於間接定位一個內存單元
(3)[bx+idata]
(4)[bx+si] si可以換成di
也可以寫成:[bx][si]
(5)[bx+si+idata] si 可以換成 di

第八章 處理數據的倆個基本問題

這倆個認問題是:
(1)處理的數據在什麼地方?
(2)要處理的數據有多長?

reg表示以惡搞寄存器,sreg表示一個段寄存器
reg的集合包括:ax、bx、cx、dx、ah、al、bh、bl、ch、cl、dh、dl、sp、bp、si、di;
sreg的集合包括:da、ss、cs、es。

8.1 bx、si、di和dp

在這裏插入圖片描述

8.4 尋址方式

在這裏插入圖片描述

8.5 指令要處理的數據有多長

8086 CPU 的指令,可以處理倆種尺寸的數據,byte 和 word,所以在機器指令中要指明指令進行的是字操作還是字節操作,
(1)通過指定寄存器名指明要處理的數據的尺寸。
如指定是 ax 還是 al 等

(2)在沒有寄存器的名稱存在的時候,用操作符 x prt 指明內存單元的長度, x 在彙編指令中可以是 word(字)或者 byte(字節)。
如:
mov word ptr ds:[0], 1
inc word ptr [bx]
mov byte ptr ds:[0], 1
inc byte ptr [bx]等

(3)其他方法
有些指令默認訪問的是字單元還是字節單元,比如push 指令只進行字操作。

8.7 div 指令

div 是出發指令,使用div 做除法的時候要注意以下問題。
(1)除數:有8位和16位倆種,在一個reg或內存單元中
(2)被除數:默認放在AX 或 DX和AX中,如果除數爲8位,被除數則爲16位,默認放在AX中;如果除數位16位,被除數則位32位,存放在DX和AX中,DX存放高16位,AX存放低16位。
(3)結果,若除數爲8爲,則AL存放商,AH存放餘數。若除數爲16位,AX存放商,DX存放餘數。

在這裏插入圖片描述

在這裏插入圖片描述

8.8 僞指令dd

db 和 dw 定義字節型數據和字型數據。dd是用來定義dword(double word,雙字)型數據的,佔倆個字。

dup

在這裏插入圖片描述

彙編——第九章轉移指令的原理

** 可以修改IP,或者同時修改CS 和IP 的指令統稱爲轉移指令。**概括來講,轉移指令就是可以控制CPU執行內存種某處代碼的指令。

在這裏插入圖片描述

9.1 操作符 offset

在這裏插入圖片描述

9.2 jmp 指令

jmp爲無條件轉移指令,可以只修改IP也可以同時修改CS和IP。
jmp指令要給出兩種信息:
(1)轉移的目的地址
(2)轉移的距離(段間轉移、段內短轉移、段內近轉移)

9.3 依據位移進行轉移的jmp指令

jmp short 標號(轉移到標號處執行指令)
這種實現的時段內短轉移,它對IP的修改範圍爲-128 ~ 127,也就是說它向前最多轉移128個字節,向後轉移最多127個字節。jmp指令中的“short”符號說明指令是短轉移。jmp指令中的“標號”是代碼段中的標號,指明瞭指令要轉移的目的地,轉移指令結束後,CS:IP應該指向標號處的指令。
在這裏插入圖片描述

9.6 轉移地址在內存中的jmp指令

轉移地址在內存中的jmp指令有兩種格式。
(1)jmp word ptr 內存單元地址(段內轉移)
功能:從內存單元地址處開始存放着一個字,是轉移的目的偏移地址。
(2)jmp dword ptr 內存單元地址(段間轉移)
功能:從內存單元地址處開始存放着兩個字,高地址處的字是轉移的目的段地址,低地址處是目標的偏移地址。
(CS)=(內存單元地址+2)
(IP)=(內存單元地址)

9.7 jcxz指令

jcxz指令是一個有條件轉移指令所有的條件住哪一指令都是短轉移。 IP的修改範圍都爲:-128 ~ 127。
指令格式:jcxz 標號(如果(CX) = 0,轉移到標號處執行。)
其功能的解釋相當於:if((CX) == 0) jmp short 標號。

9.8 loop 指令

loop 指令爲循環指令,所有的循環指令都是短轉移。IP修改的範圍爲:-128 ~ 127.
指令格式:loop 標號((CX) = (CX) - 1, 如果(CX) != 0,轉移到標號處執行。)

9.9 根據唯一進行轉移的意義

在這裏插入圖片描述

第十章 CALL和RET指令

call 和 ret 指令都是轉移指令, 他們都修改IP, 或者同時修改CS 和 IP。 它們經常被共同用來實現子程序的設計。

10.1 ret 和 retf

ret指令用棧中的數據,修改IP的內容,從而實現近轉移;
retf指令用棧中的數據,修改CS和IP的內容,從而實現遠轉移;

CPU執行ret指令時,進行下面倆步操作:
(1)(IP) = ((ss)*16 +(sp));
(2)(sp) = (sp) + 2

CPU執行retf指令時,進行下面四個操作:
(1)(IP)=((ss)*16 + (sp));
(2)(sp)= (sp) + 2;
(3)(CS)= ((ss) *16 + (sp));
(4)(sp) = (sp) + 2;

ret 相當於 pop IP;
retf 相當於 pop IP , pop CS;

所以使用 retf 的時候, 先壓入CS在壓入IP。

10.2 call 指令

CPU執行call 指令的時候,進行倆步操作:
(1)將當前的IP或者CS和IP壓入棧中;
(2)轉移;

10.3 依據位移進行轉移的call 指令

call 標號(將當前的IP壓入棧後,轉移到標號處執行指令)
CPU執行此種格式的call指令時,進行如下操作:
(1)(sp) = (sp) - 2;
(2)((ss) *16 + (sp)) = (IP);
(3)(IP) = (IP) + 16位位移。
16位位移=標號處地址-call指令後的第一個字節的地址;
16爲位移的範圍爲-32768 ~ 32767;
call 標號 相當於 push IP ;jmp near ptr 標號

10.4 轉移的目的地址在指令中的call指令

“call far ptr 標號” 實現的是段間轉移。
在這裏插入圖片描述

10.5 轉移地址在寄存器中的call指令

在這裏插入圖片描述

10.6 轉移地址在內存中的call指令

轉移地址在內存中的call指令由倆種格式。
(1)call word ptr 內存單元地址
相當於 push IP; jmp word ptr 內存單元地址
(2)call dword ptr 內存地址單元
相當於 push CS; push IP; jmp dword ptr 內存單元地址

10.7 call 和 ret 的配合使用

在這裏插入圖片描述
在這裏插入圖片描述

10.8 mul 指令

(1)兩個相乘的數,要麼都是8位,要麼都是16位。如果是8位一個默認放在AL中,另一個放在8位reg或者內存單元中;如果是16位,一個默認在AX中,另外一個放在16位reg或者內存單元中。
(2)結果:如果是8位乘法,結果默認放在AX中,如果是16位乘法,結果高位默認放在DX中,低位在AX中。
在這裏插入圖片描述

10.9 模塊化程序方法

使用call 和 ret 設計子程序可以實現模塊化程序設計

10.10 參數和結果傳遞問題

在這裏插入圖片描述

10.11 批量數據的傳遞

如果數據有很多個,單純的寄存器個數滿足不了需求,**這個時候會可以將批量數據存在內存中,然後將他們所在的內存空間的首地址放在寄存器中,傳遞給需要的子程序。對於具有批量數據的返回結果,也可以使用同樣的方法。
比如下面例子:
在這裏插入圖片描述

10.12 寄存器衝突的問題

設計一個子程序,將data段中的字符串全部轉化爲大寫。
下面代碼是錯誤的,錯誤分析在代碼後面說明
在這裏插入圖片描述
在這裏插入圖片描述
這裏很容易發現子程序修改了cx和si的值,出現錯誤。
這個時候可以使用堆棧來存CX和si的值。
這個時候可以引入一個堆棧,來存放循環時的CX,在ret後

第十一章 標誌寄存器

標誌寄存器具有以下三個作用:
(1)用來存儲相關指令的某些執行結果;
(2)用來爲CPU執行相關指令提供行爲依據;
(3)用來控制CPU的相關工作方式。
在這裏插入圖片描述

11.1 ZF標誌

flag的第6位是ZF,零標誌位。他記錄相關的指令執行後,其結果是否爲0。如果爲0那麼ZF=1;反之ZF=0;

注意:在8086CPU指令集中,有的指令的執行是影響標誌寄存器的,比如,add、sub、mul、div、inc、or、and等,它們大都是運算指令(進行邏輯或算術運算);有的指令的執行對標誌寄存器沒有影響,比如,mov、push、pop等,它們大都是傳送指令。

11.2 PF標誌

flag的第2位是PF,奇偶標誌位。它相關指令記錄執行後,其結果的所有bit位中1的個數是否爲偶數。如果1爲偶數,pf=1,如果爲奇數,那麼pf=0.

11.3 SF標誌

flag的第7位是SF,符號標誌位。它記錄相關指令執行後,其結果是否爲負。如果結果爲負,sf=1;如果非負,sf=0。

在計算機中通常使用補碼來表示有符號數據。計算機中的一個數據可看稱是是有符號數,也可以看成是無符號數。比如:
00000001B可以看成無符號數1,或者有符號數+1;
10000001B可以看成無符號數129,或者有符號數-127.
在這裏插入圖片描述

11.4 CF標誌

flag的第0爲是CF,進位標誌位。一般情況下,在進行無符號數運算的時候,它記錄了運算結果的最高有效位向更高位的進位值,或者從更高位的借位值。
在這裏插入圖片描述

11.5 OF標誌

flag的第11位是OF,溢出標誌位。一般情況下,OF記錄了有符號數運算的結果是否發生了溢出。如果發生溢出,OF=1;如果沒有,OF=0。

11.6 adc指令

adc是帶進位加法指令,它利用CF位上記錄的進位值。

指令格式:adc 操作對象1, 操作對象2
功能:操作對象1 = 操作對象1 + 操作對象2 + CF。

adc和add的配合就可以對更大的數據進行加法運算。

11.7 sbb指令

sbb是帶借位減法指令,它利用了CF位上記錄的借位值。

指令格式:sbb操作對象1,操作對象2
功能:操作對象1 = 操作對象1 - 操作對象2 - CF。

sbb和sub的配合就可以對更大的數據進行減法運算。

11.8 cmp指令

cmp是比較指令,cmp的功能相當於減法指令,只是不保存結果。cmp指令執行後,將對標誌寄存器產生影響。其他相關指令通過識別這些被影響的標誌寄存器位來得知比較的結果。

cmp通常和條件轉移指令相配合。

11.9 檢測比較結果的條件轉移指令

“轉移”指的是它能夠修改IP,而“條件”指的是它可以根據某種條件。決定是否修改IP。
比如jcxz就是一個條件轉移指令,它可以檢測cx中的數值,如果(cx)=0,就修改IP,否則什麼也不做,所有的條件轉移指令的轉移位移都是[-128,127]。

cmp通常和條件轉移指令相配合,cmp可以同時進行倆種比較,也就是無符號數比較和有符號數比較。所以更具cmp指令的比較結果進行轉移指令也分爲兩種,即根據無符號數的比較結果進行轉移的條件轉移指令(它們檢測zf和cf)和根據有符號數的比較結果進行轉移的條件轉移指令(它們檢驗sf、pf和zf的值)。

在這裏插入圖片描述

11.10 DF標誌和串傳送指令

flag的第10位是DF,方向標誌位。在串處理指令中,控制每次操作後si、di的遞減。
df=0 每次操作後si、di遞增;
df=1 每次操作後si、di遞減。

對於串傳送指令。
格式:movsb
功能:執行movsb指令相當於進行以下幾個操作。
(1)((es) *16 + (di)) = ((ds) *16 + (si))
(2)如果df=0 則, (si)=(si)+ 1;(di)=(di)+ 1;
. 如果df=0 則, (si)=(si)- 1;(di)=(di)- 1;
movsb是將ds:si指向的內存單元中的字節送入es:di中,然後更具標誌寄存器df位的值,將si和di遞增或遞減。

對於傳送字的串傳送指令如下。
格式:movsw
功能:將ds:si指向的內存字單元中的字送入es:di中,然後根據標誌寄存器df位的值,將si和di遞增2或遞減2。

一般來說movsb和movsw都和rep配合使用,格式如下。
rep movsb 或 rep movsw
相當於:
s:movsb
loop s
rep的作用就是根據cx的值,重複執行後面的串傳送指令。

設置df的指令。
在8086CPU中,有兩條指令對df位進行設置。
cld指令:將標誌寄存器的df位置設置爲0;
std指令:將標誌寄存器的df位置設置爲1。

兩個例子
在這裏插入圖片描述

在這裏插入圖片描述

11.11 pushf和popf

pushf的功能是將標誌寄存器的值壓棧,而popf是從棧中彈出數據,送入標誌寄存器中。
pushf和popf,爲直接訪問標誌寄存器提供了一種方法。

11.12 標誌寄存器在Debug中的表示

在這裏插入圖片描述

第十二章 內中斷

12.1 內中斷的產生

CPU內部有下面的情況發生的時候,將產生生相應的終端信息。
(1)除法錯誤,比如,執行div指令產生的除法溢出;
(2)單步執行;
(3)執行into指令;
(4)執行int指令。
在8086 CPU中,上述4種中斷信息的來源,簡稱中斷源,在8086CPU 中的中斷類型碼如下。
分別爲(1)0(2)1(3)4(4)n,int 指令的格式爲int n,指令中的n爲字節型立即數,是提供給CPU的中斷類型碼。這個n最大爲255。

12.2 中斷處理程序

CPU在收到中斷信息後,就要轉去執行中斷信息的處理程序,需要找到相應的CS和IP,而中斷類型碼可以在中斷向量表中找到一個地址,這個地址存儲了相應的CS和IP。

12.3 中斷向量表

在這裏插入圖片描述
在這裏插入圖片描述

12.4 中斷過程

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

12.5 中斷處理程序和iret指令

在這裏插入圖片描述

12.6 除法錯誤中斷的處理

除法中斷是0號中斷。對於下面程序,1000h除以1得到1000h,可知是8位除法,商1000h存放在al中,發生溢出,產生0號中斷。
在這裏插入圖片描述

12.7 編程處理0號中斷

我們現在考慮一下改變0號中斷喫力程序的功能,功能是在屏幕中間顯示“overflow!”,然後返回操作系統。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

12.8 安裝

可以使用movsb指令,將do0的代碼送入0:200處。程序如下
在這裏插入圖片描述
在這裏插入圖片描述

12.9 do0

首先我們看下面的程序,這個程序是不對的
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
最後的就是設置中斷向量了。

12.10 設置中斷向量

在這裏插入圖片描述

12.11 單步中斷

在這裏插入圖片描述
在這裏插入圖片描述

12.12 響應中斷的特殊情況

在這裏插入圖片描述
在這裏插入圖片描述

3# 第十三章 int指令

13.1 int指令

int 指令的格式爲:int n,n爲中斷類型碼,它的功能是引發中斷過程。
CPU執行int n指令,相當於引發一個n號中斷過程,過程如下:
(1)取中斷類型碼n;
(2)標誌寄存器入棧,IF = 0, TF = 0;
(3)CS、IP入棧;
(4)(IP) = (n *4),(CS) = (n *4+2);

13.2 編寫供應用程序調用的中斷例程

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

13.3 對int、iret和棧的深入理解

在這裏插入圖片描述
在這裏插入圖片描述

13.4 BIOS和DOS所提供的中斷例程

在這裏插入圖片描述

13.5 BIOS和DOS中斷例程的安裝過程

在這裏插入圖片描述
在這裏插入圖片描述

13.6 BIOS中斷例程應用

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

13.7 DOS中斷例程應用

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
從鍵盤輸入兩個1位的十進制數,相加以後以藍底黃字顯示在屏幕的第5行第16列
CODES SEGMENT
ASSUME CS:CODES
START:
mov cx,2
mov byte ptr ds:[0],0
s:mov ah,1
int 21h
add ds:[0],al
loop s

sub byte ptr ds:[0], 48

mov ax, 0b800h
mov es, ax
mov al, ds:[0]
mov es:[340h], al
mov byte ptr es:[341h],1bh

MOV AH,4CH
INT 21H

CODES ENDS
END START

assume ds:data, es:table, cs:code

data segment
db ‘1975’, ‘1976’, ‘1977’, ‘1978’, ‘1979’, ‘1980’, ‘1981’, ‘1982’, ‘1983’
db ‘1984’, ‘1985’, ‘1986’, ‘1987’, ‘1988’, ‘1989’, ‘1990’, ‘1991’, ‘1992’
db ‘1993’, ‘1994’, ‘1995’

dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514  
dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000  

dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226  
dw 11542, 14430, 15257, 17800

data ends

table segment
db 21 dup ('year summ ne ?? ')
table ends

code segment
start:
mov ax, data
mov ds, ax
mov ax, table
mov es, ax

mov bx, 0
mov si, 0
mov di, 0
mov cx, 21

s: mov ax, 0[bx]
mov es:0[si], ax
mov ax, 2[bx]
mov es:2[si], ax
mov al, 20H
mov es:4[si], al
mov ax, 84[bx]
mov es:5[si], ax
mov ax, 86[bx]
mov es:7[si], ax
mov al, 20H
mov es:9[si], al
mov ax, 168[di]
mov es:10[si], ax
mov al, 20H
mov es:12[si], al
mov ax, [bx+84]
mov dx, [bx+86]
mov bp, [di+168]
div bp
mov es:13[si], ax
mov al, 20H
mov es:15[si], al
add bx, 4
add si, 16
add di, 2
loop s

mov ax, 4c00H
int 21H

code ends
end start

assume cs:codesg, ss:stacksg, ds:datasg

stacksg segment
dw 0, 0, 0, 0, 0, 0, 0, 0
stacksg ends

datasg segment
db '1. display ’
db '2. brows ’
db '3. replace ’
db '4. modify ’
datasg ends

codesg segment
start: mov ax, stacksg
mov ss, ax
mov sp, 16
mov ax, datasg
mov ds, ax
mov bx, 0
mov cx, 4

 s: push cx
    mov di, 3
    mov cx, 4

s0: mov al, [bx+di]
    and al, 11011111b
    mov [bx+di], al
    inc di
    loop s0

    pop cx
    add bx, 16
    loop s

    mov ax, 4c00h
    int 21h

codesg ends
end start

將任意輸入的十進制數轉化四位十六機制進行輸出顯示
assume cs:code, ss:stack, ds:data

data segment
string_input db 'Please input a number(<32768): stringexitdbClickESCtoexit!' string_exit db 'Click ESC to exit!
data ends

stack segment
db 16 dup(0);
stack ends

code segment
start:
mov ax, data
mov ds, ax
lea dx, offset string_input
mov ah, 09h ;顯示輸入提示
int 21h
mov ax, stack
mov ss, ax
mov sp, 16
and bx, 0
and dx, 0
mov cx, 5

;5次輸入,如果遇到回車或者換行就中斷,並跳轉到s1
s: mov ah, 01h
int 21h
;cmp指令本身不進行跳轉,只是根據結果設置相關的條件標誌位(SF、ZF、CF、OF)
;CMP指令後往往跟着條件轉移指令,實現根據比較的結果產生不同的程序分支的功能。
cmp al, 0dh
jz s1
cmp al, 0ah
jz s1
cmp al, 1bh
jz exit
mov bl, al
and bl, 0fh
mov ax, dx
mov dx, 0ah
mul dx
add ax, bx
mov dx, ax
loop s

s1:mov cx, 4
mov ax, dx
s2:and dx, 0
mov bx, 10h
div bx
push dx
loop s2

s3:mov dx, 0ah
mov ah, 02h
int 21h
mov dx, 0dh
int 21h

lea dx, offset string_exit
mov ah, 09h
int 21h

mov bx, 0b800h
mov es, bx
mov si, 1996

s4:pop dx
cmp dx, 9
;jbe 當 al小於或等於bl時跳到標號處
;這裏使用了cmp配合使用
jbe s5
add dx, 7h
s5:add dx, 30h
mov es:[si], dx
mov byte ptr es:[si+1], 1eh
add si, 2
cmp sp, 16
jz exit
loop s4
exit:
mov ax, 4c00h
int 21h
code ends
end start

用7ch中斷例程完成jmp near ptr s指令的功能,用bx向中斷例程傳送轉移指令,在屏幕第十二行顯示data段中,以0結尾的字符串
assume cs:code
data segment
db ‘welcome to masm!’,0
data ends
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset nr
mov ax,0
mov es,ax
mov di,200h
mov cx,offset nrend-offset nr
cld
rep movsb

    mov word ptr es:[7ch*4],200h
    mov word ptr es:[7ch*4+2],0

    mov ax,data
    mov ds,ax
    mov si,0
    mov ax,0b800h
    mov es,ax
    mov di,12*160

s: cmp byte ptr [si],0
je ok
mov al,[si]
mov es:[di],al
inc si
add di,2
mov bx,offset s-offset ok
int 7ch

ok: mov ax,4c00h
int 21h

nr: push bp
mov bp,sp
add [bp+2],bx

nrret: pop bp
iret
nrend: nop

code ends
end start

loop指令的功能用7ch中斷例程完成 loop指令的功能。

應用舉例:在屏幕中間顯示80個‘!’。
assume cs:code
code segment
start: mov ax,0b800h
mov es,ax
mov di,160*12
mov bx,offset s - offset se;設置從標號se到標號s的轉移位移
mov cx,80
s: mov byte ptr es:[di],’!’
add di,2
int 7ch ;如果(cx)≠0,轉移到標號s處
se: nop
mov ax,4c00h
int 21h
code ends
end start

7ch中斷例程如下:
lp: push bp
mov bp,sp
dec cx
jcxz lpret
add [bp+2],bx
lpret: pop bp
iret

2.1 顯示屬性
顯示器的屏幕劃分爲行列顯示。
在2580彩色字符模式下,從0行0列到24行79列共有2000個字符位置。
內存的B8000H—BFFFFH共32KB的區域是25
80彩色字符模式的顯示緩衝區。如果向這個區域寫入數據,寫入的字符可以立即顯示在屏幕上。
每個字符,顯存中都有相應的單元與之對應。

每個字符用兩個字節表示。
第1個字節:ASCII碼
第2個字節:屬性

2.2顯示位置
對於25*80彩色字符模式:
一屏字符要佔用4000個字節,32KB的顯存分爲8頁,每頁4KB
B8000H-B8F9FH : 第0頁
每行80個字符,160個字節(A0H),對應關係:
000H –09FH 對應第0行
0A0H- 13FH 對應第1行
140H -1DFH 對應第2行
。。。。。
F00H-F9FH 對應第24行
00H,01H 對應第0列
02H,03H 對應第1列
04H,05H 對應第2列
。。。。。
9EH,0FH 對應第79列
偶地址存放ASCII碼,奇地址存放屬性。
字符的位置計算公式:
  位置=行號×160+列號×2

在屏幕的2行3列上顯示藍底黃字的字符串“Good!”
Data segment
disp db ‘Good!’
Data ends
Code segment
assume cs:code,ds:data
Start: mov ax,data
mov ds,ax
mov ax,0b800h ;顯存首地址es
mov es,ax
Mov al,disp[0]
Mov es:[146h],al ;第1個字母->ales:146h
Mov byte ptr es:[147h],1eh ; 屬性設置

Mov al,disp[1]
Mov es:[148h],al ;第2個字母->ales:146h
Mov byte ptr es:[149h],1eh ; 屬性設置
……
Mov ah,4ch
Int 21h
Code ends
End start

  1. BP寄存器
    它的確是一個寄存器,名字叫基址指針,是16位,它的用途有點特殊,是和堆棧指針copySP聯合使用的,作爲SP校準使用的,只百有在尋找堆棧裏的數據和使用個別的尋址方式時候才能用到。
    比如說,堆棧中壓入了很多數據或者地址度,你肯定想通過SP來訪問這些數據或者地址,但SP是要指向棧頂的,是不能隨便亂改的,這時候你就需要使用BP,把SP的值傳遞給BP,通過BP來尋找堆棧裏數據或者地址。
    ————————————————
    版權聲明:本文爲CSDN博主「放過@」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
    原文鏈接:https://blog.csdn.net/wxy2635618879/article/details/105512391
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章