綜述
一般情況下, 指令順序執(zhí)行, 實(shí)際中, 常需要改變程序的執(zhí)行流程
這就用到轉(zhuǎn)移指令
- 可以控制cpu 執(zhí)行內(nèi)存中某處代碼的指令
- 可以修改ip, 或同時修改cs 和ip 的指令
分類
按行為分類
- 段內(nèi)轉(zhuǎn)移: 只修改ip, 如
jmp ax
- 段間轉(zhuǎn)移: 同時修改cs 和ip, 如
jmp 1000:0
根據(jù)指令對ip 修改范圍不同分類
- 段內(nèi)短轉(zhuǎn)移: ip 修改范圍-128~127
- 段內(nèi)近轉(zhuǎn)移: ip 修改范圍-32768~32767
按轉(zhuǎn)移指令分類
- 無條件轉(zhuǎn)移, jmp
- 條件轉(zhuǎn)移指令, jcxz
- 循環(huán)指令, loop
- 過程
- 中斷
操作符offset
用offset 取得標(biāo)號的偏移地址
格式: offset 標(biāo)號
assume cs:code
code segment
start:
mov ax,offset start ;相當(dāng)于mov ax,0
s: movax,offset s ;相當(dāng)于, mov ax,3
code ends
end start
jmp 指令
無條件轉(zhuǎn)移, 可以只修改ip, 也可以同時修改cs和ip
jmp 指令要給出兩種信息
- 轉(zhuǎn)移目的地址
- 轉(zhuǎn)移距離
- 段間轉(zhuǎn)移(遠(yuǎn)轉(zhuǎn)移), jmp 2000:1000
- 段內(nèi)短轉(zhuǎn)移: jmp short 標(biāo)號, ip 修改范圍-128~127, 8 位的位移
- 段內(nèi)近轉(zhuǎn)移: jmp near ptr, ip 修改范圍-32768~32767, 16 位的位移
jmp 指令是依據(jù)位移進(jìn)行轉(zhuǎn)移的
jmp short 指令中, 包含的是跳轉(zhuǎn)到指令的相對位置, 而不是轉(zhuǎn)移的目標(biāo)地址
assume cs:code
code segment
start:
mov ax,0
jmp short s
add ax,1
nop
nop
s:inc ax
code ends
end
執(zhí)行順序
- (ip)=0003, cs:ip 指向
EB 05
, jmp 的機(jī)器碼 - 讀取指令碼
EB 05
進(jìn)入指令緩沖器 - (ip)=(ip)+多讀取指令長度=(ip)+2=0005, cs:ip 指向
add ax,0001
- cpu 指向指令緩沖器里的指令
EB 05
- 指令
EB 05
執(zhí)行后, (ip)=(ip)+05=000AH, cs:ip 指向inc ax
兩種段內(nèi)轉(zhuǎn)移
短轉(zhuǎn)移
jmp short 標(biāo)號
功能: (ip)=(ip)+8 位位移
原理:
- 8 位位移="標(biāo)號" 處的地址-jmp指令后的第一個字節(jié)的地址
- short 指明此處的位移為8 位位移
- 8 位位移的范圍-128~127, 用補(bǔ)碼表示
- 8 位位移由編譯程序在編譯時算出
近轉(zhuǎn)移
jmp near ptr 標(biāo)號
功能: (ip)=(ip)+16位位移
原理:
- 16 位位移="標(biāo)號" 處的地址-jmp指令后的第一個字節(jié)的地址
- near ptr 指明此處的位移為16 位位移, 進(jìn)行的是段內(nèi)近轉(zhuǎn)移
- 16 位位移的范圍-32768~32767, 用補(bǔ)碼表示
- 16 位位移由編譯程序在編譯時算出
遠(yuǎn)轉(zhuǎn)移
遠(yuǎn)轉(zhuǎn)移jmp far ptr 標(biāo)號 | 近轉(zhuǎn)移jmp near ptr 標(biāo)號 |
---|---|
far ptr 指明了跳轉(zhuǎn)的目的地址, 包含了標(biāo)號的段地址cs 和偏移地址ip | near ptr 指明了相對于當(dāng)前ip 的轉(zhuǎn)移位移, 而不是轉(zhuǎn)移的目的地址 |
far ptr轉(zhuǎn)移
jmp轉(zhuǎn)移地址
地址010B指令
|
near ptr轉(zhuǎn)移
jmp 位移地址
位移轉(zhuǎn)移
|
轉(zhuǎn)移地址在寄存器中的jmp 指令
格式 jmp 16 位寄存器
功能: ip=(16位寄存器)
例如: jmp ax
jmp word ptr 內(nèi)存單元地址 | jmp dword ptr 內(nèi)存單元地址 |
---|---|
從內(nèi)存單元地址處開始存放著一個字, 是轉(zhuǎn)移的目的偏移地址 | 從內(nèi)存單元地址處開始存放兩個字, 搞地質(zhì)是轉(zhuǎn)移地址的目的段地址, 低地址存放偏移地址 |
一個字的偏移地址
|
兩個字的偏移地址
|
jmp 指令小結(jié)
格式 | 示例 |
---|---|
jmp 標(biāo)號 | - 段間轉(zhuǎn)移(遠(yuǎn)轉(zhuǎn)移): jmp far ptr 標(biāo)號 - 段內(nèi)短轉(zhuǎn)移: jmp short 標(biāo)號, 8 位的位移 - 段內(nèi)近轉(zhuǎn)移: jmp near ptr 標(biāo)號, 16 位的位移 |
jmp 寄存器 | jmp bx; 16 位的位移 |
jmp 內(nèi)存單元 | 段內(nèi)轉(zhuǎn)移: jmp word ptr 內(nèi)存單元地址; jmp word ptr [bx] 段間轉(zhuǎn)移: jmp dword ptr 內(nèi)存單元地址; jmp dword ptr [bx] |
其他轉(zhuǎn)移指令
jcxz 指令
格式: jcxz 標(biāo)號
功能:
如果(cx)=0, 則轉(zhuǎn)移到標(biāo)號處執(zhí)行
當(dāng)(cx)≠0, 程序向下執(zhí)行
jcxz 是有條件的轉(zhuǎn)移指令
所有的有條件轉(zhuǎn)移指令都是短轉(zhuǎn)移
對ip 的修改范圍都為-128~127
在對應(yīng)的機(jī)器碼中包含轉(zhuǎn)移的位移, 而不是目的地址
loop 指令
格式: loop 標(biāo)號
操作:
(cx)=(cx)-1
-
當(dāng)(cx)≠0, 轉(zhuǎn)移到標(biāo)號處執(zhí)行
(cx)=0, 程序向下執(zhí)行
如果(cx)≠0, (ip)=(ip)+8位位移
- 8 位位移="標(biāo)號" 處的地址 - loop 指令后的第一個字節(jié)地址
- 8 位范圍為-128~127, 補(bǔ)碼表示
- 8 位位移由編譯程序在編譯時算出
call 指令和ret 指令
調(diào)研子程序: call 指令
返回: ret 指令
mov ax,0
call s
mov ax,4c00h
int 21h
s:add ax,1
ret
實(shí)質(zhì): 流程轉(zhuǎn)移指令, 它們都修改ip, 或同時修改cs 和ip
call 指令
實(shí)質(zhì): 流程轉(zhuǎn)移, 實(shí)現(xiàn)轉(zhuǎn)移的方法和jmp 指令的原理類似
過程:
- 將當(dāng)前的ip 或cs 和ip 壓入棧中
- 轉(zhuǎn)移到標(biāo)號處執(zhí)行指令
call 標(biāo)號
- 16 位位移="標(biāo)號" 處地址 - call 指令后的第一個字節(jié)地址
- 16 位范圍-32768~32767, 補(bǔ)碼表示
- 位移由編譯程序編譯時計算
call far ptr 標(biāo)號, 實(shí)現(xiàn)段間轉(zhuǎn)移
-
(sp)=(sp)-2
((ss)*16+(sp))=(cs)
(sp)=(sp)-2
((ss)*16+(sp))=(ip)
-
(cs)=標(biāo)號所在段地址
(ip)=標(biāo)號所在偏移地址
相當(dāng)于:
push cs
push ip
jmp far ptr 標(biāo)號
"call 標(biāo)號" 類似于"jmp near ptr 標(biāo)號", 對應(yīng)的機(jī)器指令中為相對于當(dāng)前ip 的轉(zhuǎn)移位移, 而不是轉(zhuǎn)移的目的地址, 實(shí)現(xiàn)段內(nèi)轉(zhuǎn)移. "call far ptr 標(biāo)號" 實(shí)現(xiàn)的是段間轉(zhuǎn)移
轉(zhuǎn)移地址在寄存器中的call 指令
格式: call 16位寄存器
功能:
- (sp)=(sp)-2
- ((ss)*16+(sp))=(ip)
- (ip)=(16位寄存器)
相當(dāng)于
- push ip
- jmp 16位寄存器
轉(zhuǎn)移地址在內(nèi)存中的call 指令
call word ptr 內(nèi)存單元地址
相當(dāng)于:
- push ip
- jmp word ptr 內(nèi)存單元地址
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
執(zhí)行后, (ip)=0123h, (sp)=0Eh
call dword ptr 內(nèi)存單元地址
相當(dāng)于:
- push cs
- push ip
- jmp dword ptr 內(nèi)存單元地址
mov sp,10h
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
call dword ptr ds:[0]
執(zhí)行后, (cs)=0, (ip)=0123h, (sp)=0Ch
返回指令, ret 和retf
ret | retf | |
---|---|---|
功能 | 用棧中的數(shù)據(jù), 修改ip 內(nèi)容, 從而實(shí)現(xiàn)近轉(zhuǎn)移 | 用棧中的數(shù)據(jù), 修改cs 和ip 內(nèi)容, 從而實(shí)現(xiàn)遠(yuǎn)轉(zhuǎn)移 |
相當(dāng)于 | pop ip | pop ip pop cs |
舉例 | ret指令
|
retf指令
|
舉例:
assume cs:code,ss:stack
stack segment
db 8 dup(0)
db 8 dup(0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,1000
call s
mov ax,4c00h
int 21h
s:
add ax,ax
ret
code ends
end start
mul 乘法指令
格式:
mul 寄存器
mul 內(nèi)存單元
8位乘法 | 16位乘法 | |
---|---|---|
被乘數(shù)(默認(rèn)) | al | ax |
乘數(shù) | 8位寄存器或內(nèi)存字節(jié)單元 | 16位寄存器或內(nèi)存單元 |
結(jié)果 | ax | dx高位和ax低位 |
例 | mul bl; --(ax)=(al)(bl) mul byte ptr ds:[0]; --(ax)=(al) * ((ds)16+0) |
mul word ptr [bx+si+8]; --(ax)=(ax) * ((ds)*16+(bx)+(si)+8)結(jié)果的低16位; (dx)=(ax) * ((ds) * 16+(bx)+(si)+8)結(jié)果的高16位 |
模塊化程序設(shè)計
- 調(diào)用子程序: call 指令
- 返回: ret 指令
- 子程序: 根據(jù)提供的參數(shù)處理一定的事務(wù), 處理后, 將結(jié)果(返回值) 提供給調(diào)用者
參數(shù)和結(jié)果傳遞的問題
例如, 計算N 的3 次方
參數(shù)N 存放位置, 計算結(jié)果放在哪里?
方案
- 寄存器傳遞參數(shù)
- 內(nèi)存單元傳遞參數(shù)
- 用棧傳遞參數(shù)
寄存器來存儲參數(shù)和結(jié)果是最常用的方法
- 參數(shù)存放到bx 中, (bx)=N
- 子程序中用多個mul 指令計算N 的3 次方
- 將結(jié)果放到dx 和ax 中, (dx:ax)=
遇到的問題, 如果傳遞更多參數(shù), 寄存器不夠了怎么辦?
assume cs:code
data segment
dw 1,2,3,4,5,6,7,8
dd 0,0,0,0,0,0,0,0
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov di,16
mov cx,8
s:
mov bx,[si]
call cube
mov [di],ax
mov [di].2,dx
add si,2
add di,4
loop s
cube:
mov ax,bx
mul bx
mul bx
ret
mov ax,4c00h
int 21h
code ends
end start
內(nèi)存單元批量傳遞數(shù)據(jù)
- 將普亮數(shù)據(jù)放到內(nèi)存中, 然后將他們坐在內(nèi)存空間的首地址放在寄存器中, 傳遞給子程序
- 對于具有批量數(shù)據(jù)的返回結(jié)果, 也可以用同樣的方法
assume cs:code
data segment
db 'conversation'
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov cx,12
call capital
mov ax,4c00h
int 21h
capital:
and byte ptr [si],11011111b
inc si
loop capital
ret
code ends
end start
用棧傳遞參數(shù)
原理: 由調(diào)用者將徐亞傳遞給子程序的參數(shù)壓入棧中, 子程序從棧中取得參數(shù)
任務(wù): 計算(a-b)^3, 將a 和b 為word 型數(shù)據(jù)
- 進(jìn)入子程序前, 參數(shù)a, b 入棧
- 調(diào)用子程序, 將使棧頂存放ip
- 結(jié)果(dx:ax)=(a-b)^3
計算(a-b)^3
計算器沖突問題
將conversation
轉(zhuǎn)換為大寫, 需要將循環(huán)次數(shù)設(shè)置為cx,12
, 每次不固定, 可以寫為db 'conversation',0
做如下循環(huán)
capital:
mov cl,[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short capital
ok:
ret
有例子如下將下面字符串裝換為大寫
assume cs:code
data segment
db 'word',0
db 'unix',0
db 'wind',0
db 'goog',0
data ends
code segment
start:
mov ax,data
mov ds,ax
mov bx,0
mov cx,4
s:
mov si,bx
call capital
add bx,5
loop s
mov ax,4c00h
int 21h
capital:
push cx
push si
change:
mov cl,[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short change
ret
ok:
pop si
pop cx
ret
code ends
end start
在以上代碼中使用了棧來存儲參數(shù), 另一種方式是使用cx 來直接存儲循環(huán)次數(shù), 部分代碼如下
s:
mov si,bx
call capital
add bx,5
loop s
mov ax,4c00h
int 21h
capital:
mov cl,[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short capital
ret
ok:
ret
在內(nèi)循環(huán)中也同樣使用cx, 會造成沖突, 重復(fù)使用cx 一個寄存器
而使用棧來存儲, 就不用關(guān)心子程序使用了哪些寄存器, 也不會造成寄存器沖突
子程序標(biāo)準(zhǔn)框架如下
子程序開始:
子程序中使用的寄存器入棧
子程序內(nèi)容
子程序使用的寄存器出棧
返回
在子程序的開始, 將要用到的所有寄存器中的內(nèi)容都保存起來, 在子程序返回前再恢復(fù)
標(biāo)志寄存器
PSW/FLAGS
別稱, 程序狀態(tài)字
結(jié)構(gòu):
- flag 寄存器是按位起作用的, 就是說, 它的每一位都有專門的含義, 記錄特定信息
- 8086 中沒有使用flag 的1, 3, 5, 12~15 位, 這些位不具有任何含義
作用:
- 用來存儲相關(guān)指令的某些執(zhí)行結(jié)果
- 為cpu 執(zhí)行相關(guān)指令提供行為依據(jù)
- 控制cpu 相關(guān)工作方式
直接訪問標(biāo)志寄存器的方法
- pushf: 將標(biāo)志寄存器的值壓棧
- popf: 棧中彈出數(shù)據(jù), 送入到標(biāo)志寄存器
ZF 零標(biāo)志(zero flag)
標(biāo)記相關(guān)指令計算結(jié)果是否為0
- zf=1, 表示結(jié)果為0, 1表示邏輯真
- zf=0, 表示結(jié)果不是0, 0 表示邏輯假
指令 | 結(jié)果 |
---|---|
mov ax,1 and ax,0 |
zf=1, 表示結(jié)果是0 |
mov ax,1 or ax,0 |
zf=0, 結(jié)果非0 |
- 在8086 指令集中, 有的指令執(zhí)行是影響標(biāo)志寄存器的, 比如:
and
,sub
,mul
,div
,inc
,or
,add
, 大都是運(yùn)算指令, 進(jìn)行邏輯或算術(shù)運(yùn)算 - 有的指令執(zhí)行對標(biāo)志寄存器沒有影響, 比如,
mov
,push
,pop
, 大都是傳送指令 - 使用一條指令的時候, 要注意指令的全部功能, 其中敖闊執(zhí)行結(jié)果對標(biāo)志寄存器的哪些標(biāo)志位造成影響
PF 奇偶標(biāo)志(parity flag)
指令執(zhí)行后, 結(jié)果的所有二進(jìn)制中1 的個數(shù)
- 1 的個數(shù)為偶數(shù), pf=1
- 1 的個數(shù)為奇數(shù), pf=0
指令 | 結(jié)果 |
---|---|
mov al,1 add al,10 |
結(jié)果為0000 1011B = 0000 0001B + 0000 1010B; 其中有3(奇數(shù))個1, 則PF=0 |
mov al,1 or al,2 |
結(jié)果為00000011B = 0000 0001B or 0000 0010B; 其中有2(偶數(shù))個1,則PF=1 |
SF 符號標(biāo)志(sign flag)
指令執(zhí)行后, 將結(jié)果視為有符號數(shù)
- 結(jié)果為負(fù), sf=1
- 結(jié)果為非負(fù), sf=0
指令 | 結(jié)果 |
---|---|
mov al,10000001B add al,1 |
al 為10000010B; 為負(fù)數(shù)浮庐,則SF=1 |
sub ax,ax | ax為0巴碗,為非負(fù)數(shù), sf=0 |
該標(biāo)志是cpu 對有符號數(shù)運(yùn)算結(jié)果的一種記錄, 將數(shù)據(jù)當(dāng)做有符號數(shù)來運(yùn)算的時候, 通過sf 可知結(jié)果的正負(fù), 將數(shù)據(jù)當(dāng)做無符號數(shù)來運(yùn)算, sf 的值則沒有意義, 雖然相關(guān)的指令影響了它的值
CF 進(jìn)位標(biāo)志(carry flag)
進(jìn)行無符號數(shù)運(yùn)算的時候, cf 記錄了運(yùn)算結(jié)果的最高有效位向更高位的進(jìn)位值, 或從更高位的借位值
執(zhí)行指令后
- 有進(jìn)位或借位, cf=1
- 無進(jìn)位或借位, cf=0
指令 | 結(jié)果 |
---|---|
mov al,98H add al,al |
(al)=30H, CF=1, CF記錄了最高有效位向更高位的進(jìn)位值 |
add al,al | (al)=60H,CF=0, CF記錄了最高有效位向更高位的進(jìn)位值 |
sub al,98H | (al)=C8H, CF=1, CF記錄了向更高位的借位值 |
OF 溢出標(biāo)志(overflow flag)
進(jìn)行有符號數(shù)運(yùn)算的時候, 如結(jié)果超過了機(jī)器所能表示的范圍稱為溢出
指令執(zhí)行后
- 有溢出, of=1
- 無溢出, of=0
指令 | 結(jié)果 |
---|---|
mov al,98 add al,99 |
(al)=197,超出了8位有符號數(shù)的范圍(-128~127), OF=1 |
mov al,0F0H add al,88H |
(al)=(-16)+(-120)=-136, 有溢出, OF=1 |
cf 和of 區(qū)別
- cf 是對無符號數(shù)運(yùn)算有意義的進(jìn)/借位標(biāo)志位
- of 是對有符號數(shù)運(yùn)算有意義的溢出標(biāo)志位
帶進(jìn)(借) 位加減法
adc 帶進(jìn)位加法指令
adc 利用cf 位上記錄的進(jìn)位值
格式: adc 操作對象1,操作對象2
功能: 操作對象1=操作對象1+操作對象2+cf
例如: adc ax,bx 實(shí)現(xiàn)的功能, (ax)=(ax)+(bx)+cf
指令 | mov al, 98h add al,al adc al,3 |
mov ax,1 add ax,ax adc ax,3 |
mov ax,2 mov bx,1 sub bx,ax adc ax,1 |
---|---|---|---|
結(jié)果 | (ax)=34h | (ax)=5 | (ax)=4 |
解釋 | adc 執(zhí)行后, 計算為(ax)+3+cf=30h+3+1=34h | (ax)+3+cf=2+3+0=4 | (ax)+1+cf=2+1+1=4) |
adc 大數(shù)相加
兩個128 位數(shù)據(jù)相加, 逆序相加
data segment
dw 0A452H,0A8F5H,78E6H,0A8EH,8B7AH,54F6H,0F04H,671EH
dw 0E71EH,0EF04H,54F6H,8B7AH,0A8EH,78E6H,58F5H,0452H
data ends
其中使用了sub ax,ax
, 因?yàn)榭梢詫?biāo)志寄存器的值置為默認(rèn), inc di
不影響進(jìn)位標(biāo)志位
sbb 帶借位減法指令
格式: sbb 操作對象1,操作對象2
功能: 操作對象1=操作對象1-操作對象2-cf
例如: sbb ax,bx; (ax)=(ax)-(bx)-cf
cmp 指令
格式: cmp 操作對象1,操作對象2
功能: 計算操作對象1–操作對象2
應(yīng)用: 其他相關(guān)指令通過識別這些被影響的標(biāo)志寄存器位來得知比較結(jié)果
指令 | cmp ax,ax | mov ax,8 mov bx,3 vmp ax,bx |
---|---|---|
功能 | 做(ax)–(ax)的運(yùn)算, 結(jié)果為0, 但并不在ax中保存, 僅影響flag的相關(guān)各位 | (ax)=8,(bx)=3 |
標(biāo)志寄存器 | ZF=1 PF=1 SF=0 CF=0 OF=0 | ZF=0 PF=1 SF=0 CF=0 OF=0 |
無符號數(shù)比較與標(biāo)志位取值
通過cmp 指令執(zhí)行后相關(guān)標(biāo)志位的值, 可以看出比較結(jié)果
cmp ax,bx
有符號數(shù)比較與標(biāo)志位取值
cmp ah,bh
條件轉(zhuǎn)移指令
舉例
jxxx 系列指令和cmp 指令配合, 構(gòu)造條件轉(zhuǎn)移指令
- 不必再考慮cmp 指令對相關(guān)標(biāo)志位的影響和jxxx 指令對相關(guān)標(biāo)志位的檢測
- 可以直接考慮cmp 和jxxx 配合使用表現(xiàn)出來的邏輯含義
配合使用實(shí)現(xiàn)高級語言中的if 語句功能
1 如果(ah)=(bh), 則(ah)=(ah)+(ah), 否則(ah)=(ah)+(bh)
cmp ah,bh
je s
add ah,bh
jmp short ok
s:
add ah,ah
ok:
ret
====================
if(a==b){
a=a+a
}
else{
a=a+b
}
2 如果(ax)=0, 則(ax)=(ax)+1
;ax 獲得值
add ax,0
jnz s
inc ax
s:...
====================
if(a==0){
a++;
}
條件轉(zhuǎn)移指令應(yīng)用
指令: jxxx--je/jna/jae..
可以根據(jù)某種條件, 決定是否轉(zhuǎn)移重新執(zhí)行流程, "轉(zhuǎn)移"=修改ip
如何檢測
- 通過檢測標(biāo)志位, 由標(biāo)志位體現(xiàn)條件
- 條件轉(zhuǎn)移指令通常都和cmp 相配合使用, cmp 指令改變標(biāo)志位
示例
data segment
db 8,11,8,1,8,5,63,38
data ends
統(tǒng)計數(shù)值為8 的字節(jié)個數(shù)
思路:
初始設(shè)置(ax)=0, 然后使用循環(huán)依次比較每個字節(jié)的值, 找到一個和8 相等的數(shù)將ax 的值加1
assume cs:code
data segment
db 8,11,8,1,8,5,63,38
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,0
mov bx,0
mov cx,8
s:
cmp byte ptr [bx],8
jne next
inc ax
next:
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start
DF 標(biāo)志和傳送指令
方向標(biāo)志位(Direction Flag)
功能
- 在串處理指令中, 控制每次操作后si, di的增減
- DF = 0: 每次操作后si, di遞增
- DF = 1: 每次操作后si, di遞減
對df 位進(jìn)行設(shè)置的指令
cld指令: 將標(biāo)志寄存器的DF位設(shè)為0(clear)
std指令: 將標(biāo)志寄存器的DF位設(shè)為1(setup)
轉(zhuǎn)送指令1: movsb
以字節(jié)為單位傳送
((es)×16 + (di)) = ((ds) ×16 + (si))
-
如果DF = 0則:
(si) = (si) + 1
(di) = (di) + 1
如果DF = 1則:
(si) = (si) - 1
(di) = (di) - 1
傳送指令2: movsw
功能, 以字為單位傳送
((es)×16 + (di)) = ((ds) ×16 + (si))
-
如果DF = 0則:
(si) = (si) + 2
(di) = (di) + 2
如果DF = 1則:
(si) = (si) - 2
(di) = (di) - 2
data segment
db 'Welcome to masm!'
db 16 dup(0)
start:
mov ax,data
mov ds,ax
mov si,0
mov es,ax
mov di,16
cld
mov cx,16
s:
movsb
loop s
mov ax,4c00h
int 21h
code ends
end start
rep指令
rep 指令常和串傳送指令搭配使用
功能: 根據(jù)cx 的值, 重復(fù)執(zhí)行后面的指令
rep movsb == s: movsb, loop s
rep movsw==s: movsw, loop s
例如
用串傳送指令, 將F000H 段中的最后16 個字符復(fù)制到data 段中, 最后一個字符位置: F000:FFFF
assume cs:code,ds:data
data segment
db 16 dup(0)
data ends
code segment
start:
mov ax,0f000h
mov ds,ax
mov si,0ffffh
mov ax,data
mov es,ax
mov di,15
mov cx,16
std
rep movsb
mov ax,4c00h
int 21h
code ends
end start