[BX]和loop指令
1.[bx]表示內存的用法,loop指令的用法
語法格式
loop 標號
通常我們用loop指令來實現循環功能,cx中存放循環次數。
cpu執行指令過程
1.cx=cx-1
2.判斷cx的值是否為0
如果cx不等於0,跳轉到標號出執行
如果cx=0,執行loop後面的其它指令。
2.綜合應用loop和[BX]編程時,對於類型不一致(8位,16位)、數據超出範圍等情形的處理(結合5.3節程序5.3和5.5節實例)
在匯編程序中,數據不能以字母開頭。例:A000h在匯編程序中要寫為:0A000h
從ds中可以得到PSP的段地址SA,PSP的偏移地址為0,則物理地址為SA*16+0,可用段地址和偏移地址表示為:SA+10h:0
遇到loop指令時,可以用p指令執行,debug自動重復執行循環代碼,直到(cx)=0,也可以用g命令來達到目的。
類型不一致時,例:ffff:6單元中是一個字節單元,ax是一個16位寄存器,數據長度不一樣,如何賦值?
我們說的是“賦值”,就是說,讓ax中的數據的值(數據的大小)和ffff:0006單元中的數據的值(數據的大小)相等。8位數據01h和16位數據0001h的數據長度不一樣,但它們的值是相等的。那麽我們如何賦值,設ffff:0006單元中的數據是xxh,若要ax中的值和ffff:0006單元中的相等,ax中的數據應為00xxh。所以,若實現ffff:0006單元向ax賦值,應該令(ah)=0,(al)=(ffff6h)。
有兩個問題:類型的匹配和結界的不超界。具體的說,就是在做加法的時候,我們有兩種方法:
1.(dx)=(dx)+內存中的8位數據;
2.(dl)=(dl)+內存中的8位數據。
第一種方法中的問題是兩個運算對象的類型不匹配,第二種方法中的問題是結果有可能超界。解決這兩個看似矛盾的問題,目前的方法就是得用一個16位寄存器來做中介,將內存單元中的8位數據賦值到一個16位寄存器ax中,再將ax中的數據加到dx上,從而使兩個運算對象的類型匹配並且結果不會超界。
assume cs:code code segment mov ax,0ffffh mov ds,ax mov bx,0 ;初始化ds:bx指向ffff:0 mov dx,0 ;初始化累加寄存器dx,(dx)=0 mov cx,12 ;初始化循環計數寄存器cx,(cx)=12 s: mov al,[bx] mov ah,0 add dx,ax ; 間接向dx中加上((ds)*16+(bx))單元的數值 inc bx ; ds:bx指向下一個單元
loop s mov ax,4c00h int 21h code ends end
3.debug工具中t命令、p命令、g命令用法
t命令
單步執行;遇loop會進入循環內部繼續單步執行;遇int會進入中斷程序內繼續單步執行;
p命令
單步執行;遇loop或int會當作整體執行,不進入內部單步執行;
g命令
執行到指定地址;或遇程序結束或int,則終止執行。
4.debug和masm在處理內存單元上的不同及問題處理方式
在debug中編程實現
mov ax,2000 mov ds,ax mov al,[0] mov bl,[1] mov cl,[2] mov dl,[3]
匯編源程序實現
assume cs:code code segment mov ax,2000h mov ds,ax mov al,[0] mov bl,[1] mov cl,[2] mov dl,[3] mov ax,4c00h int 21h code ends end
可以看出,debug和編譯器masm對形如“mov ax,[0]”這類指令在解釋上的不同,debug和編譯器對這些指令中的“[idata]”有不同的解釋。debug將它解釋為“[idata]”是一個內存單元,“idata”是內存單元的偏移地址;而編譯器將“[idata]"解釋為“idata”。
那麽解決方法是,可將偏移地址送入bx寄存器,用[bx]的方式來訪問內存單元。比如我們可以這樣訪問2000:0單元。
mov ax,2000h mov ds,ax ;段地址2000h送入ds mov bx,0 ;偏移地址0送入bx mov al,[bx] ;ds:bx單元中的數據送入al
[BX]和loop指令