在匯編源程序中,數據不能以字母開頭,故要加0識別!
debug程序開始時DS指向的是PSP的頭地址,而CS=DS+10H
不能將一個數值直接送入段寄存器,要通過其它寄存器進行傳送!
(N/16+1)*16 意思是總取多16個字節存放多出的字節.N+16不等價左邊的式子.
它等價于(int(N/16)+1).
一般來說,當我們要暫存數據時,都應該使用棧!
(1)只有bx,si,di,bp用在[]里進行內在單元的存取.
(2)bx,si,di,bp只能以bx與si,bx與di,bp與si,bp與di四種組合出現
形像些:
si
/
bx
\
di
si
/
bp
\
di
(3)只要在[]中使用寄存器bp,而指令中沒有顯性地給出段地址,段地址就默認在ss中,其它的 是不是默認存放在ds中?
數據處理的分類:寫入,讀取,運算!
數據存在的三個地方:CPU內,內存,端口!
push只進行字操作,pop呢?
用dd定義的數的存放,如100001它的十六進制為186A1H,則它在內存的存放形式是
A1 86 01 00
剛剛好是32位,和我們的邏輯000186A1不一樣(規律:倒過來).
在一個數據段里定義的數據是連續存放的,但要看清楚它們是什么類型(dd,dw,db).
db '1634'里面一個字符占一個字節,保存的是相應的ACSII碼.
loop指令是先把CX寄存器的值減1然后再判斷是否是0
assume cs:code
code segment
mov ax,4c00H
int 21H
start: mov ax,0
s: nop
nop
mov di,offset s ;以下四行復制s2的第一條指令給s
mov si,offset s2 ;剛剛好覆蓋了s的兩條nop指令
mov ax,cs:[si] ;復制過去的內容是:"向前或向后移動多少"
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21H
mov ax,0
s2: jmp short s1 ;機器碼EBF6;意思是"向前移動10d個字節"
nop
code ends
end start
;9D:0000 B8004C MOV AX,4C00
;9D:0003 CD21 INT 21
;9D:0005 B80000 MOV AX,0000
;9D:0008 EBF6 JMP 0000 EBF6復制過來后前移10個字節即跳到0000
;9D:000A BF0800 MOV DI,0008
;9D:000D BE2000 MOV SI,0020
;9D:0010 2E CS:
;9D:0011 8B04 MOV AX,[SI]
;9D:0013 2E CS:
;9D:0014 8905 MOV [DI],AX
;9D:0016 EBF0 JMP 0008
;9D:0018 B80000 MOV AX,0000
;9D:001B CD21 INT 21
;9D:001D B80000 MOV AX,0000
對call指令的一些理解:
call word ptr 內存單元地址
書上理解:
push IP
jmp word ptr 內存單元地址
我的理解:
(1)IP的值先變成CALL指令后的第一個字節的偏移地址,然后才被壓入棧;
(2)壓入后再改變IP的值,即(IP)=內存單元地址的值.
call dword ptr 內存單元地址
書上理解:
push cs
push ip
jmp dword ptr 內存單元地址
開始是將此時的CS,IP(IP應該是CALL命令后的第一個字節)壓入棧,CS是先壓入錢的,
然后跳到內存單元中內容所指的地址,
即CS=((內存單元地址)+2),IP=(內存單元)//其實這兩個是JMP指令的理解.
對X/N=int(H/N)*65536+(rem(H/N)*65536+L)/N的理解
int(H/N)*65536求出的是高16位的值,即 16位的值0000
后面16位是低16位的值,因為后面的商不會超過16位,求出的商就是低16的值,加到0000上
而(rem(H/N)*65536+L)/N算得的余數就是本X/N的余數.
注意*65536的含義是向左移多少位,后面的補零.
先算16進制再算十進制!
int是將子程序裝入內在先,然后通過代號進行調用.(靜態)
而call就如動態執行這樣,等到運行時才裝入內存.(動態)
P246的中斷例程的理解
lp:push bp ;此時棧里的情況是:bp ip cs 標志寄存器
mov bp,sp
dec cx
jcxz lpret
add [bp+2],bx ;因為bp默認的段寄存器是ss,故使用了bp,而+2就指向了ip的值.
lpret:
pop bp
iret ;由cx 來決定是循環還是向下繼續執行,
編寫中斷例程的步聚:
(1)先將代碼復制到指定的位置,注意這里要指出要復制字節的長度
(2)再把指定的代碼存放位置放到向量表中,因為是通過向量表進行訪問的.
(3)你可以編寫你的中斷例程了!記得開始與結尾標志!
在in與out指令中,只能使用ax或al來存放從端口中讀入的數據或要發送到端口中的數據,訪問8位端口時用AL,訪問16位端口時要用AX.
shl,shr指令移位多于一位時一定要將移的位數放在cl里.
BCD碼4位確定一個數,如26的BCD碼為0010 0110
7.8 已知對應于中斷類型碼為18H的中斷服務程序存放在0020H:6314H開始的內存區域中,求對應于18H類型碼的中斷向量存放位置和內容。
在編寫程序時,為什么通常總要用STI和CLI中斷指令來設置中斷允許標志?8259A的中斷屏蔽寄存器IMR和中斷允許標志IF有什么區別?
【解答】偏移地址EA=18H×4=60H,18H中斷向量在中斷向量表中的入口地址為00000H+60H=00060H。中斷服務程序存放在0020H:6314H開始的內存區域中,所以(00060H)=0020H,(00061H)= 6314H。
IF是8086微處理器內部標志寄存器Flags的中斷允許標志位。若IF=1,則CPU可以接受中斷請求;若IF=0,8086就不接受外部可屏蔽中斷請求INTR引線上的請求信號。在編寫程序時,用STI指令使中斷允許標志位IF=1,目的是使CPU能夠接受中斷請求,或實現中斷嵌套。而用CLI指令使中斷允許標志位IF=0,則可以關中斷,使CPU拒絕接受外部中斷請求信號。
如果8259A的中斷屏蔽寄存器IMR中的某位為1,就把這一位對應的中斷請求輸入信號IR屏蔽掉,無法被8259A處理,也無法向8086處理器產生INTR請求。
注意:在后面加有":"的地址標號,只能在代碼段中使用,不能在其他段中使用.
$表示的是本行地址,
$$則表示開始匯編的地址.
2.3總結:
執行mov指令不改變CS寄存器
執行jmp 段地址:偏移地址 改變CS和IP
執行jmp 寄存器 只改變IP不改變CS
實驗五總結:
還沒加載程序前:
CS:IP指向程序段的第一條指令,故CS可以知道.
SS=CS-2
DS=SS-10H ;這個知道有沒有用?
加載后:
SS=CS-1;
DS=CS-2;