流程轉(zhuǎn)移與子程序

綜述

一般情況下, 指令順序執(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
jmp根據(jù)位移轉(zhuǎn)移

執(zhí)行順序

  1. (ip)=0003, cs:ip 指向EB 05, jmp 的機(jī)器碼
  2. 讀取指令碼EB 05 進(jìn)入指令緩沖器
  3. (ip)=(ip)+多讀取指令長度=(ip)+2=0005, cs:ip 指向add ax,0001
  4. cpu 指向指令緩沖器里的指令EB 05
  5. 指令EB 05 執(zhí)行后, (ip)=(ip)+05=000AH, cs:ip 指向inc ax

兩種段內(nèi)轉(zhuǎn)移

短轉(zhuǎn)移

jmp short 標(biāo)號

功能: (ip)=(ip)+8 位位移

原理:

  1. 8 位位移="標(biāo)號" 處的地址-jmp指令后的第一個字節(jié)的地址
  2. short 指明此處的位移為8 位位移
  3. 8 位位移的范圍-128~127, 用補(bǔ)碼表示
  4. 8 位位移由編譯程序在編譯時算出

近轉(zhuǎn)移

jmp near ptr 標(biāo)號

功能: (ip)=(ip)+16位位移

原理:

  1. 16 位位移="標(biāo)號" 處的地址-jmp指令后的第一個字節(jié)的地址
  2. near ptr 指明此處的位移為16 位位移, 進(jìn)行的是段內(nèi)近轉(zhuǎn)移
  3. 16 位位移的范圍-32768~32767, 用補(bǔ)碼表示
  4. 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)號

操作:

  1. (cx)=(cx)-1

  2. 當(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 指令的原理類似

過程:

  1. 將當(dāng)前的ip 或cs 和ip 壓入棧中
  2. 轉(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)移

  1. (sp)=(sp)-2

    ((ss)*16+(sp))=(cs)

    (sp)=(sp)-2

    ((ss)*16+(sp))=(ip)

  2. (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
執(zhí)行過程1
執(zhí)行過程2

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é)果放在哪里?

方案

  1. 寄存器傳遞參數(shù)
  2. 內(nèi)存單元傳遞參數(shù)
  3. 用棧傳遞參數(shù)

寄存器來存儲參數(shù)和結(jié)果是最常用的方法

  • 參數(shù)存放到bx 中, (bx)=N
  • 子程序中用多個mul 指令計算N 的3 次方
  • 將結(jié)果放到dx 和ax 中, (dx:ax)={N^3}

遇到的問題, 如果傳遞更多參數(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
用棧傳遞參數(shù)

計算(a-b)^3

用棧傳遞參數(shù)執(zhí)行過程

計算器沖突問題

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)志寄存器
標(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ù)相加

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
128位數(shù)據(jù)相加

其中使用了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

比較關(guān)系和標(biāo)志寄存器結(jié)果

有符號數(shù)比較與標(biāo)志位取值

cmp ah,bh

有符號數(shù)比較和標(biāo)志位取值

條件轉(zhuǎn)移指令

條件轉(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é)為單位傳送

  1. ((es)×16 + (di)) = ((ds) ×16 + (si))

  2. 如果DF = 0則:

    (si) = (si) + 1

    (di) = (di) + 1

    如果DF = 1則:

    (si) = (si) - 1

    (di) = (di) - 1

傳送指令2: movsw

功能, 以字為單位傳送

  1. ((es)×16 + (di)) = ((ds) ×16 + (si))

  2. 如果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
移動最后16位字符到data段
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吓妆,一起剝皮案震驚了整個濱河市遏佣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌译秦,老刑警劉巖崇堵,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蠕啄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)戈锻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門歼跟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人舶沛,你說我怎么就攤上這事〈凹郏” “怎么了如庭?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長撼港。 經(jīng)常有香客問我坪它,道長,這世上最難降的妖魔是什么帝牡? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任往毡,我火速辦了婚禮,結(jié)果婚禮上靶溜,老公的妹妹穿的比我還像新娘开瞭。我一直安慰自己,他們只是感情好罩息,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布嗤详。 她就那樣靜靜地躺著,像睡著了一般瓷炮。 火紅的嫁衣襯著肌膚如雪葱色。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天娘香,我揣著相機(jī)與錄音苍狰,去河邊找鬼。 笑死烘绽,一個胖子當(dāng)著我的面吹牛淋昭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播安接,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼响牛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起呀打,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤矢赁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贬丛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撩银,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年豺憔,在試婚紗的時候發(fā)現(xiàn)自己被綠了额获。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡恭应,死狀恐怖抄邀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昼榛,我是刑警寧澤境肾,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站胆屿,受9級特大地震影響奥喻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜非迹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一环鲤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧憎兽,春花似錦冷离、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扎附,卻和暖如春蔫耽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背留夜。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工匙铡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碍粥。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓鳖眼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嚼摩。 傳聞我的和親對象是個殘疾皇子钦讳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容