1. 程式人生 > >一些轉移指令

一些轉移指令

轉移指令
# 8086cpu的轉移指令分為以下幾類:
* 無條件轉移指令(如:jmp)
* 條件轉移指令
* 迴圈指令(如:loop)
* 過程(相當於函式)
* 中斷

 # 操作符offset在組合語言中是由編譯器處理的符號,它的功能是取得標號的偏移地址


 a. 無條件轉移:
   # jmp為無條件轉移,可以只改變IP,也可以同時修改CS和IP
 jmp指令要提供兩條資訊:
    * 轉移的目的地址
    * 轉移的距離(段間距離,段內短轉移,段內近轉移)

 //==============================段內轉移====================================
    1)jmp short 標號 (轉到標號處執行指令)
        這種格式的jmp指令實現的是段內短轉移,它對IP的修改範圍為-128-127,即向前轉移最多                    可以越過128個位元組,向後轉移最多可以越過127個位元組

            assume cs:codesg
        codesg segment
         start: mov ax,0
            jmp short s
            add ax,1    //此處ax+1未執行,由jmp直接跳過了,所以最終ax為1
            s:inc ax
        codesg ends
        end start

        實際上,指令"jmp short 標號"的功能為ip=ip+8位位移
            * 8位位移="標號"處的地址->jmp指令後的第一個位元組的地址
            * short指令表明此處的位移為8位位移
            * 8位位移的範圍為-128-127,用補碼錶示
            * 8位位移由編譯程式在編譯時算出

    2) jmp near ptr 標號(和jmp short 標號類似,不過是段內近轉移)

            指令"jmp near ptr 標號"的功能為ip=ip+16位位移
            * 16位位移="標號"處的地址->jmp指令後的第一個位元組的地址
            * near指令表明此處的位移為16位位移
            * 16位位移的範圍為-32769-32768,用補碼錶示
            * 16位位移由編譯程式在編譯時算出

    3)jmp 16位暫存器
        功能:IP=16位暫存器

    4)jmp word ptr 記憶體單元地址
        功能:從記憶體單元地址處開始存放一個字,是轉移的目的的偏移地址

 //==============================段間轉移=======================================
     1)jmp far ptr 標號(實現的是段間轉移,又稱為遠轉移)
        功能:
            * cs=標號所在段的段地址
            * ip=標號所在段中的偏移地址    

    2)jmp dword ptr 記憶體單元地址
        功能:從記憶體單元地址處開始存放兩個字,高地址處的字是轉移目的的段地址,低地址處是                 偏移地址

b.有條件轉移

1)jcxz指令
    jcxz指令為有條件轉移指令,所有的有條件轉移指令都是短轉移,在對應的機器碼中包含轉移的位移
      而不是目的地址。對IP的修改範圍都為-128-127

    指令格式: jcxz 標號
           如果cx=0,則轉移到標號處執行,相當於(if(cx==0) jmp short 標號)

2)loop
    loop為迴圈指令,所有的迴圈指令都是短轉移,在對應的機器碼中包含轉移的位移,對ip的修改範圍
    為-128-127

    指令格式:loop 標號
         每次執行後cx=cx-1,如果cx!=0,則轉移到標號處執行,與jcxz相反,相當於
        if(--cx!=0)
            jmp short 標號

!!!注意使用轉移指令時,比如

assume cs:codesg

codesg segment
        mov ax,4c00h
        int 21h

start:  mov ax,0
s:      nop     //什麼也不做,佔一個位元組
        nop
        mov di,offset s   //di儲存s標誌所在的偏移地址
        mov si,offset s2  //si儲存s2標誌所在偏移地址
        mov ax,cs:[si]
        mov cs:[di],ax    //將s標誌處的機器碼改為s2標誌處的機器碼,

s0:
jmp short s //跳轉到標誌s處 s1: mov ax,0 int 21h mov ax,0 s2: jmp short s1 nop codesg ends end start

來分析一下上面程式,從程式碼段的start標誌開始執行:

1:mov ax,0
2:nop
3:nop
4:mov di,offset s
5:mov si,offset s2
6:mov ax,cs:[si]   
7:mov cs:[di],ax  /*這裡將cs:[di]處的機器碼改為cs:[si]的,看一                  
                  下cs:[si],si是標誌s2處的偏移地址,s2處指令    
                  為    jmp short s1
                        nop
                    由於轉移指令不是記錄偏移地址,而是轉移的距離,編譯器
                    算出地址,所以這裡機器碼中儲存s2到s1的距離,由於
                    向上轉移,所以是負的,大小為位元組數,看一下debug


                    */

這裡寫圖片描述
第8步跳到標誌s中(jmp short s),由於標誌s處機器碼已經改為s2處的機器碼,所以再次跳轉,注意不是跳轉到s1,而是向上跳轉10個位元組,之所以用nop就是為了使得跳轉的位元組大小相同,所以應該跳轉到

 mov ax,4c00h
 int 21h

這裡寫圖片描述
程式結束