學習筆記分享之彙編---2.彙編指令/語法

Tibbors發表於2020-04-18

學習內容:彙編指令/語法:

  1. 拷貝源運算元到目標運算元:

    mov 目標運算元,源運算元

    • 源運算元可以是任意單元(r/m/sr/imm) (sr:Segment Register)

    • 目標運算元可以是除了立即數之外的任意單元(r/m/sr)

    • 運算元的寬度必須前後一致

    • 源運算元和目標運算元不能同時為記憶體單元

  2. 加/減/與/或/異或:

    ? add/sub/and/or/xor 目標運算元,源運算元

    • 源運算元可以是r/m/imm

    • 目標運算元可以是r/m

    • 運算元的寬度除了源運算元是立即數的情況之外(即:立即數可以是任意位)必須前後一致

    ? 非:

    • not r/m8   not r/m16   not r/m32
  3. 從指定記憶體中寫入/讀取資料:

    mov dword ptr ds:[m],imm   //寫

    mov r,dword ptr ds:[r]      //讀

    ptr: Point 代表後面是一個指標 (指標即裡面存的不是普通的值,而是個地址)
    
    在8086中設定4個16位的段暫存器,用於管理4種段:
    ①資料段---ds(Data Segment):資料段暫存器
    ②程式碼段---cs(Code Segment):程式碼段暫存器
    ③堆疊段---ss(Stack Segment):堆疊段暫存器
    ④附加段---es(Extra Segment):附加段暫存器
    
    BYTE 位元組 = 8(BIT)
    
    WORD 字  =  16(BIT)
    
    DWORD 雙字 =  32(BIT)
    
    1KB = 1024 BYTE
    
  4. 定址公式

    (LEA與MOV的區別在於MOV是取地址中的值,而LEA是取地址)

    ①[imm]形式

    讀取記憶體的值 向記憶體中寫資料 讀取記憶體編號
    mov r,dword ptr ds:[m] mov dword ptr ds:[m],r/imm lea r,dword ptr ds:[m]

    ②[r]形式

    讀取記憶體的值 向記憶體中寫資料 讀取記憶體編號
    mov r',imm
    mov r'',dword ptr ds:[r']
    mov r,imm
    mov dword ptr ds:[r],imm
    lea r',dword ptr ds:[r'']
    mov r',dword ptr ds:[r'']

    ③[r+imm]形式

    讀取記憶體的值 向記憶體中寫資料 讀取記憶體編號
    mov r',imm 
    mov r'',dword ptr ds:[r'+imm]
    mov r,imm 
    mov dword ptr ds:[r+imm],imm
    lea r,dword ptr ds:[r+imm] 
    mov r,dword ptr ds:[r+imm]

    ④[r+r*(1/2/4/8)]形式

    讀取記憶體的值 向記憶體中寫資料 讀取記憶體編號
    mov r',imm
    mov r'',imm 
    mov r''',dword ptr ds:[r'+r''*4]
    mov r',imm
    mov r'',imm
    mov dword ptr ds:[r'+r''*4],imm
    lea r',dword ptr ds:[r'+r''*4]

    ⑤[r+r*(1/2/4/8)+imm]

    讀取記憶體的值 向記憶體中寫資料 讀取記憶體編號
    mov r',imm
    mov r'',imm
    mov r''',dword ptr ds:[r'+r''*4+8]
    mov r',imm
    mov r'',imm
    mov dword ptr ds:[r'+r''*4+8],imm
    lea r',dword ptr ds:[r'+r''*4+8]
  5. 壓棧與出棧
    PUSH與POP的語法:

    PUSH:

    • PUSH r16/32
    • PUSH m16/32
    • PUSH imm8/16/32

    POP:

    • POP r16/32
    • POP m16/32

    ? 注意:
      PUSH/POP加減2/4是看它PUSH/POP的是16/32位的單元

    ? 附:
    PUSHAD可將八個通用暫存器中的資料寫入記憶體中,然後即可對八個通用暫存器中的資料進行隨意更改
      而更改完之後需要恢復現場,就可以用POPAD再將剛剛PUSHAD出去的八個通用暫存器中的值原封不動的還原回去

  6. 帶進/借位加/減法
    ADC/SBB:帶 進位/借位 加/減法

    格式:
      ADC/SBB r/m , r/m/imm    兩邊不能同時為記憶體,寬度要一樣
    計算過程:
      當使用ADC/SBB指令後,在執行加/減法時會先看C位暫存器的值:
      ①C位暫存器值為1----執行加/減法時自動多加/減1
      ②C位暫存器值位0----正常執行加/減法

    e.g.
    ①C位暫存器值為1

    MOV EAX,3
    MOV ECX,1

    將C位暫存器值置為1
    ADC EAX,ECX
    ADC-C位為1

    將C位暫存器值置為1
    SBB EAX,ECX
    SBB-C位為1

    ②C位暫存器值為0

    MOV EAX,3
    MOV ECX,1

    將C位暫存器值置為0
    ADC EAX,ECX
    ADC-C位為0

    將C位暫存器值置為0
    SBB EAX,ECX
    SBB-C位為0

  7. 交換資料:
    XCHG:
      格式:
     XCHG r/m , r/m    兩邊都必須為容器且不能同時為記憶體,寬度要一樣

    e.g.
    XCHG AL,CL
    XCHG DWORD PTR DS:[12FFC4],EAX
    XCHG BYTE PTR DS:[12FFC4],AL

  8. 移動資料:
    MOVS:
    即:把一塊記憶體中的資料移動到另一塊記憶體中
    記憶體--記憶體(注意寬度) (唯一可以兩邊同時為記憶體單元的指令)
     此指令預設操作[EDI]和[ESI]暫存器
    格式:
     MOVSB == MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
     MOVSW == MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
     MOVSD == MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
    // 注意:[EDI]搭配的是PTR ES,而不是PTR DS
    計算過程:
      ①將[ESI]中儲存的地址 對應的 記憶體中的值 賦給[EDI] 指定的記憶體
      ②[ESI]和[EDI]中儲存的地址同時 加/減 1/2/4
    注意:
      [ESI]和[EDI]中儲存地址 加/減 取決於D位暫存器的值為 0/1

  9. 串儲存指令
    STOS(Store inTO String):
     功能:
    將[EAX/AX/AL]中的值存入[EDI]指定的記憶體單元(注意:不是存入[EDI]) 中 (存入的值的位數由BYTE/WORD/DWORD決定,存入後[EDI]的值加/減 由 D位暫存器的值是0/1 決定)
     格式:
     STOSB == STOS BYTE PTR ES:[EDI]
     STOSW == STOS WORD PTR ES:[EDI]
     STOSD == STOS DWORD PTR ES:[EDI]

  10. 重複指令
    REP:
     功能:
    按計數暫存器(ECX)中指定的次數重複執行字串指令
    每執行一次,就根據D位暫存器中的值(0/1)把記憶體地址加/減1/2/4

    MOV ECX,10
       //注意,ECX,10 中的10為十六進位制,即十進位制的16
    REP MOVSD
    REP STOSD
    
  11. 修改[EIP]暫存器
    補充[關於[EIP]]:
    [EIP]中儲存的是一個地址,這個地址就是CPU下一步要去的地方,即決定了CPU即將要執行的程式碼是什麼
    想要修改CPU的行為就要修改[EIP]的值


    ? JMP:
     功能:
    只修改[EIP]的值,相當於專用於[EIP]的MOV指令
     格式:
    JMP r/imm
    注: JMP隻影響[EIP]。
    完整操作簡述為:
    MOV EIP,r/imm


    ? CALL:
     功能:
    修改[EIP]的值,和JMP一樣,但是CALL會修改[ESP]的值,會把下一行指令的地址壓棧,而下一行指令的地址的計算是根據CALL這一行儲存的位元組數相加得到的,然後[ESP]中的值移動到[ESP-4]的記憶體地址中,相當於把CALL的下一個地址進行一個PUSH。
     格式:
    CALL r/addr
    注:函式的返回地址就是此處CALL壓入棧中的地址值
    完整操作簡述為:
    PUSH [CALL的地址+CALL行儲存的位元組數]
    MOV EIP,m/addr


    ? RET:
     功能:
    回到剛剛CALL的位置,出棧,相當於一個POP,然後把CALL的下一個地址寫入[EIP]。
     格式:
    RET
    完整操作簡述為:

    • LEA ESP,[ESP+4]
    • MOV EIP,[ESP-4]
      (=POP EIP)
  12. 比較指令:
    ? CMP:
     功能:
    該指令是比較兩個運算元,實際上,它相當於SUB指令,但是相減的結構並不儲存到第一個運算元中。即:在不改變任何資料的情況下,比較兩個運算元的大小,比較結果可以通過Z位、S位暫存器得到。

    • Z = 0 : 運算元1 ≠ 運算元2
    • Z = 1 : 運算元1 = 運算元2
    • S = 0 : 運算元1 > 運算元2
    • S = 1 : 運算元1 < 運算元2
       0001 0000            0010 0000
      -0010 0000           -0001 0000
      =1111 0000           =0001 0000
      
      S=1                  S=0
      

     格式:
    CMP r/m,r/m/imm

    ? TEST:
     功能:
    兩個數值進行與操作,該指令在一定程式上和CMP指令類似,結果不儲存,但是會改變相應標誌位。
     格式:
    TEST r/m,r/m/imm
     常見用法:
    用TEST指令判斷某個單元是否為0,通過Z位暫存器即可得到結果。
    TEST EAX,EAX

    • Z = 1 : 空
    • Z = 0 :非空

    e.g.
    標準用法

    MOV EAX,3
    TEST EAX,3
    TEST標準用法
    常見用法
    MOV EAX,3
    TEST EAX,EAX
    TEST常見用法(非空)
    MOV EAX,0
    TEST EAX,EAX
    TEST常見用法(空)

相關文章