2015年1月30日 星期五

Assembly 筆記 - Ch4 資料轉移、定址與算術

作者:alog
來源:http://ibf.tw/xqzCv
備註:如果作者不希望被轉帖到此處,請告知,小弟會馬上刪帖。
-------------------------------------------------------------------------------------

資料轉移指令 ( Data Transfer Instructions )     * mov 指令
          mov 目的 , 來源       
         ◆ 兩個運算元要一樣的大小
         ◆ 兩個運算元不能是記憶體單元
         ◆ CS , EIP 及 IP 不能是目的運算元
         ◆ 一個立即值不能移至區段暫存器
         ◆ 區段暫存器只能在 real-mode下執行
    * movzx 指令 (複製較小值到較大值,整數的補零) 
         movzx r32 , r/m8         movzx r32 , r/m16
         movzx r16 , r/m8    ; 8bit來源運算元補零擴展到16bit目的運算元
         ◆ 只能用在無號整數    * movsx 指令 (複製較小值到較大值,符號擴展) 
         movzx r32 , r/m8
         movzx r32 , r/m16
         movzx r16 , r/m8  ; 低八位元複製後,取出來源最高位元,複製到目的運算元高八位元
         ◆ 只能用在有號整數

    * Example : 移動
         ; movzx
                 mov          bx  , 0A69Bh
                 movzx      eax , bx                ; eax = 0000A69Bh
                 movzx      edx , bl                 ; edx = 0000009Bh
                 movzx      cx   , bl                 ; cx = 009Bh
         ; movsx
                 mov          bx  , 0A69Bh
                 movsx      eax , bx                ; eax = FFFFA69Bh
                 movsx      edx , bl                 ; edx = FFFFFF9Bh
                 movsx      cx   , bl                 ; cx = FF9Bh
         ; Memory-to-memory exchange
                 mov          ax  , val1             ; ax = 1000h
                 xchg         ax  , val2             ; ax = 2000h , val2 = 1000h
                 mov         val1, ax                ; val1 = 2000h
         ; Direct-Offset Addressing (byte array)
                 mov          al   , arrayB         ; al = 10h , arrayB Byte 10h,20h,30h,40h,50h
                 mov          al   , [arrayB+1]  ; al = 20h
                 mov          al   , [arrayB+2]  ; al = 30h
         ; Direct-Offset Addressing (word array)
                mov           ax  , arrayW         ; ax = 100h , arrayW WORD 100h,200h,300h
                mov           ax  , [arrayW+2]  ; ax = 200h
         ; Direct-Offset Addressing (doubleword array)
                mov          eax , arrayD         ; eax = 10000h , arrayD DWORD 10000h,20000h
                mov          eax , [arrayD+4]  ; eax = 20000h

● 加法與減法
   
零值旗標 : 當算術指令將目的運算元設為時就會設定 zero flag
                mov   cx , 1        
                sub     cx , 1                             ; cx = 0 , ZF = 1
                mov   ax , 0FFFFh                  
                inc     ax                                   ; ax = 0 , ZF = 1
                inc     ax                                   ; ax = 1 , ZF = 0            

     *符號旗標 : 算術結果為負數時,就會設定sign flag
                mov   cx , 0
                sub     cx , 1                             ; cx = -1 , SF = 1
                add     cx , 2                             ; cx = 1 ,  SF = 0

     *進位旗標 : 執行無號數運算時才會很重要,對目的運算元而言
                             無號數的加法結果太大(或太小),carry flag會被設定
                ◆ inc 與 dec指令不會影響進位旗標                mov   al , 0FFh            
                add    al , 1                               ; CF = 1 , al = 00
                mov   ax, 00FFh
                add    ax, 1                               ; CF = 0 , ax = 0100h 
                mov   ax, 0FFFFh
                add    ax, 1                               ; CF = 1 , ax = 0000h
                mov   al , 1
                sub    al , 2                               ; CF = 1
 
     *溢位旗標 : 只有在有號數算術時才會啟用 over flag
                mov   al , +127
                add    al , 1                              ; OF = 1
                mov   al, - 128
                sub    al , 1                              ; OF = 1

    * Example :
                Rval   SDWORD   ?
                Xval   SDWORD   26
                Yval   SDWORD   30
                Zval   SDWORD    40
                ;---------------------------------------------------------------------
                ; inc and dec
                mov   ax , 1000h
                inc     ax                                   ; 1001h
                dec    ax                                   ; 1000h
                ; Expression : Rval = -Xval + ( Yval - Zval )                mov   eax , Xval
                neg    eax                                 ; -26
                mov   ebx , Yval
                sub    ebx ,  Zval                      ; -10
                add    eax ,  ebx
                mov   Rval , eax                      ; -36
                ; Zero flag
                mov   cx , 1
                sub     cx , 1                             ; ZF = 1
                mov   ax , 0FFFFh               
                inc     ax , 1                              ; ZF = 1
                ; Sign flag
                mov   cx , 0
                sub     cx , 1                              ; SF = 1
                mov   ax , 7FFFh
                add    ax , 2                               ; SF = 1
                ; Carry flag 
                mov   al , 0FFh  
                add    al , 1                                ; CF = 1 , al = 00
                ; Overflow flag
                mov   al , +127
                add    al , 1                                ; OF = 1
                mov   al , -128
                sub    al  , 1                               ; OF = 1
                ;---------------------------------------------------------------------

● Data-Related Operators and Directives
   
OFFSET : 傳回變數從所在區段開始的偏移距離
         .data
         bVal   BYTE        ?
        wVal   WORD      ?
        dVal    DWORD   ?
       dVal2   DWORD   ?
       .code                                              ;  assume bVal's offset : 00404000 
        mov     esi , OFFSET bVal             ; ESI = 00404000
        mov     esi , OFFSET wVal            ; ESI = 00404001
        mov     esi , OFFSET dVal             ; ESI = 00404003
        mov     esi , OFFSET dVal2           ; ESI = 00404007

     *ALIGN : 將變數置於位元組、字組、雙字組或是段落的邊界            ALIGN   邊界   
         邊界 = 1 : 下一變數位址會置於一個位元組的邊界(預設)
                  = 2 :                                     雙數的位址
                  = 4 :                                      四的倍數
          bval      BYTE        ?                    ; 00404000
          ALIGN 2   
          wVal     DWORD   ?                    ; 00404002
          bVal2    BYTE       ?                    ; 00404004
          ALIGN 4
          dVal      DWORD   ?                    ; 原本是00404005,現為00404008
          dVal2    DWORD   ?                    ; 0040400C
  
      *PTR : 存取的變數大小與當初宣告的變數不同          .data
                   myDouble DWORD   12345678h 
          .code 
                   mov  ax , myDouble                              ; error
                   mov  ax , WORD PTR myDouble          ; ax = 5678h
                   mov  ax , WORD PTR [myDouble + 2]  ; ax = 1234h
                   mov  bl  , BYTE PTR myDouble            ; bl = 78h

       *TYPE : 傳回變數單一元件以 byte為單位的大小值           .data
                   var1   BYTE       ?
                   var2   WORD     ?   
                   var3   DWORD   ?
                   var4   QWORD   ?
                   TYPE var1          ; 1
                   TYPE var2          ; 2
                   TYPE var3          : 4
                   TYPE var4          ; 8

       *LENGTHOF : 計算陣列中的元件數           .data
                   byte1   BYTE        10,20,30
                   array1  WORD      30 DUP(?) , 0,0
                   array2  WORD       5  DUP( 3 DUP(?) )
                   array3  DWORD    1 ,2 ,3, 4
                   digitStr BYTE        "12345678" , 0

           LENGTHOF  byte1       ; 3        
           LENGTHOF  array1      ; 30+2
           LENGTHOF  array2      ;  5*3
           LENGTHOF  array3      ; 4
           LENGTHOF  digitStr     ; 9
 
           myArray       BYTE       10,20,30,40,50 
                                BYTE       60,70,80,90,100
           LENGTHOF myArray  ;只計算第一列定義的部分陣列,傳回 5
         
      *SIZEOF :  傳回的值等於LENGTHOF乘上TYPE的值
          intArray   WORD  32 DUP(0)     ; SIZEOF = 32 * 2

● 間接定址 : 暫存器當作指標     *間接運算元 : 可是任一個 32 bit通用暫存器(eax ebx ecx edx esi edi ebp esp) 
         ◆在real-mode,若暫存器作間接運算元,僅可能是 si di bxbp,避免用bp
             它通常用來定址堆疊區段
         ◆在間接運算元中使用PTR
             inc  [esi]         ; 錯誤,運算元必須標示大小
             inc  BYTE PTR [esi]
    *陣列        .data
        arrayD   DWORD   10000h , 20000h , 30000h
        .code
        mov    esi  , OFFSET arrayD
        mov    eax , [esi]                         ; first number
        add     esi  ,  4
        add     eax , [esi]                         ; second number
        add     esi  ,  4                          
        add     eax , [esi]                         ; third number

   *索引運算元 : 加一個常數到暫存器上,產生一個有效位址
        ◆在real-mode,若暫存器作間接運算元,僅可能是 si di bxbp,避免用bp
             它通常用來定址堆疊區段  
        常數[暫存器]        [ 常數 + 暫存器 ]        .data
        arrayB   BYTE   10h,20h,30h
        .code
        mov   esi , 0
        mov   al  , [ arrayB + esi ]             ; al = 10h    
   *指標 : 變數中有另一個變數的位址時,稱為指標變數指標 
       在 16 及 32 位元模式下的指標

16位元模式32位元模式
NEAR
指標
從資料區段開始的
16位元位移值
從資料區段開始的
32位元位移值
FAR
指標
32位元區段位移位址48位元區段位移位址

保護模式
使用NEAR指標,所以儲存在雙字組變•¸
         arrayB     BYTE       10h , 20h , 30h , 40h
         arrayW    WORD     1000h , 2000h , 3000h
         ptr           DWORD   arrayB
         ptrW        DWORD  arrayW
         ptrB         DWORD  OFFSET arrayB
         ptrW        DWORD  OFFSET arrayW

  *TYPEDEF :  定義變數時,建立使用者定義型態
        PBYTE     TYPEDEF   PTR BYTE
        .data
         arrayB     BYTE   10h , 20h , 30h , 40h
         ptr1         PBYTE  ?                                    ;未初始化
         ptr2         PBYTE  arrayB                        ; 指向一個陣列


● JMP及LOOP指令    * JMP指令
       JMP 目的標籤         top :
                 ...
                 jmp top                  ;重覆無止盡迴圈

     * LOOP指令 : 指定次數(ecx),重覆執行特定區段的指令
                           迴圈的目的必須在現在位置-128+127之間             mov   ax  , 0
            mov  ecx , 5
      L1:   
            inc     ax
           loop    L1                                         ;迴圈中止後,ax=5 , ecx = 0

     * Example : SumArray
           intarray    WORD   100h , 200h , 300h , 400h
           mov     edi , OFFSET intarray           ; intarray位址
           mov     ecx , LENGTHOF intarray    ; 迴圈次數
           mov      ax , 0                                   ; 歸零
        L1:
           add        ax , [edi]                              ; 加上一整數
           add        edi , TYPE intarray              ; 指向下一個整數
           loop       L1                                       ; 重複直到 ecx = 0
   * Example : 字串複製
      
source     BYTE    "This is the source string" , 0
         target      BYTE     SIZEOF   source DUP(0) , 0
         mov        esi  , 0                                   ; 索引暫存器
         mov        ecx , SIZEOF source             ; 迴圈次數
       L1:
         mov        al , source[esi]                       ; 從來源取得字元                   
         mov        target[esi] , al                         ; 儲存在目標
         inc          esi                                          ; 移到下一個字元
         loop        L1                                          ; 重複整個字串

沒有留言:

張貼留言