2015年1月30日 星期五

Assembly 筆記 - Ch6 條件處理


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

布林和比較指令 ( Boolean and Comparsion Instructions )
     * CPU旗標
          ◆ 運算的結果為,則設定 zero flag
          ◆ 運算結果所產生的目的運算元結果太大太小(容器不夠裝)carry flag 會被設定
          ◆ Sign flag是目的運算元高位元的複製,被設定表示為負,被清除為正
          ◆ 指令產生無效的有號結果(al=+127, al+1爆 , al = -128 , al-1爆),over flag會被設定
          ◆ 運算結果造成目的運算元低位元裡其值為 1 的位元為偶數時parity flag會被設定

    * AND指令 : 兩運算元中每對相對應位元間的 and布林運算,結果存放目的運算元
                              AND  目的運算元 , 來源運算元
                              AND   reg , reg
                              AND   reg , mem
                              AND   reg , imm
                              AND   mem , reg
                              AND   mem , imm
        ◆FLAGS : 總是清除 overcarry flag , 根據目的運算元的值修改 sign、zero、parity flags
        ◆常用來清除選定的位元並保持其它未被選擇位元不變
                            0  0  1  1  1  0  1  1
             AND        0  0  0  0  1  1  1  1
                         ----------------------------  
                           0   0  0  0  1  0  1  1             ; 高四位元被清除,較低四位元保持不變
        ◆將字元轉換成大寫字母
                   01100001 = 61h('a')
           and   11011111 = DFh           將字元與11011111作 and 運算轉成大寫
           -----------------------------------
                   01000001 = 41h('A') 



     * OR指令 : 兩運算元中每對相對應位元間的 or 布林運算,結果存放目的運算元                              OR 目的運算元 , 來源運算元
                              OR   reg , reg
                              OR   reg , mem
                              OR   reg , imm
                              OR   mem , reg
                              OR   mem , imm
         ◆FLAGS : 同 and 指令
         ◆常用來設定被選擇位元並且保持其它未被選擇位元不變
                           0  0  1  1  1  0  1  1
             OR         0  0  0  0  1  1  1  1
                         ----------------------------  
                           0   0  1  1  1  1  1  1             ; 高四位元不變,較低四位元被設定
         ◆0~9整數位元組轉換成ASCII
                   00000101 = 05h
             or   00110000 = 30h           將字元與00110000作 or 運算轉成ascii
           -----------------------------------
                   00110101 = 35h('5')

     * XOR指令 : 兩運算元中每對相對應位元間的 互斥 布林運算,結果存放目的運算元                              XOR 目的運算元 , 來源運算元         ◆FLAGS : 同 and 指令
         ◆檢查同位旗標 : 按位元運算或算數運算結果的最低位元組其值為1的個數
                                   偶數 => 偶同位,parity flag被設定
                                   奇數 => 奇同位,parity flag被清除
                                   將待測數全和零值作互斥能不改變待測數值,並完成同位檢查
             mov  al , 10110101b        ; 5個1 => 奇同位    
             xor    al , 0                        ; 清除parity flag (PO)
             mov   al , 11001100b       ; 4個1 => 偶同位
             xor    al , 0                        ; 設定parity flag (PE)

     * NOT指令 : 兩所有位元 0 變 1 ,1 變0,結果為 1 的補數
                              NOT reg
                              NOT mem
         ◆FLAGS : 不影響任何旗標

     * TEST指令 : 兩運算元間每對相對應位元中 and 運算,依其結果設定旗標
                      and 唯一不同是不會修改目的運算元的值 
                      常被用於「發現運算元個別的各個位元是否被設定
           00100101       ; 輸入值          
           00001001       ; test值,測試位元0和位元3
           00000001       ; 結果 : ZF = 0
           ---------------------------------------------------
           00100100       ; 輸入值
           00001001       ; test值,測試位元0和位元3
           00000000       ; 結果 : ZF = 1
         ◆FLAGS : 同 and 指令

     * CMP指令 : 完成來源運算元和目的運算元間的減法,但不修改運算元的值
         ◆FLAGS : 同 sub 指令
CMP結果
ZF
CF
目的<來源
0
1
目的>來源
0
0
目的=來源
1
0
          帶正負號的整數比較
CMP結果
旗標
目的<來源
SF≠OF
目的>來源
SF=OF
目的=來源
ZF=1


     * 清除或設定個別 CPU flag 
       ◆方法 : ① 設定或清除 zero flag
                    and  al , 0     ; 設定 zero flag,任何運算元和 0and 運算
                    or     al , 1     ; 清除 zero flag,.................. 1 .. or ........
            
                    ② 設定或清除 sign flag
                    or     al , 80h  ; 設定 sign flag,運算元的最高位元1or 運算
                    and  al , 7Fh   ; 清除 sign flag,..........................  0 .. and ....

                    ③ 設定或清除 carry flag
                    stc                  ; 設定 carry flag
                    clc                   ; 清除 carry flag

                    ④ 設定或清除 overflow flag
                    將兩個正位元組值相加產生的和為負便能設定溢位旗標
                    若要清除可將一運元和 0 作 or 運算
                    mov al , 7Fh       ; al = +127
                    inc   al                ; al = 80h(-128) , OF=1
                    or    eax , 0        ; 清除 overflow flag

 ● 條件跳越 ( Conditional Jmps )
     * 條件跳越指令的類型 
         跟據 ① 特殊的 flag 值
                ② 兩運算元是否相等或(E)AX的值
                ③ 無號運算元的比較
                ④ 帶正負號運算元間的比較
         ◆特殊的 flag 值      
助憶符說明旗標
JZ若為零則跳ZF=1
JNZ若為不零則跳ZF=0
JC若進位則跳CF=1
JNC若不進位則跳CF=0
JO若溢位則跳OF=1
JNO若不溢位則跳OF=0
JS若負號則跳SF=1
JNS若非負號則跳SF=0
JP同位(偶)則跳PF=1
JNP非同位(奇)則跳PF=0

         ◆兩運算元是否相等或(E)AX的值           
            等式比較CMP  leftOp , rightOp
助憶符說明
JE相等則跳(leftOp=rightOp)
JNE不相等則跳(leftOp≠rightOp)
JCXZ若 CX = 0 則跳
JECXZ若 ECX = 0 則跳

        ◆無號運算元的比較
助憶符說明
JA較大則跳
JNBE不是較小或相等則跳(=JA)
JAE較大或相等則跳
JNB不是較小則跳(=JAE)
JB較小則跳
JNAE不是較大或相等則跳(=JB)
JBE較小或相等則跳
JNA不是較大則跳(=JBE)
  
       ◆ 帶正負號運算元間的比較
助憶符說明
JG較大則跳
JNLE非較小或相等則跳(=JG)
JGE較大或相等則跳
JNL不是較小則跳(=JGE)
JL較小則跳
JNGE非較大或相等則跳(=JL)
JLE較小或相等則跳
JNG不是較大則跳(=JLE)

    * 條件跳越的應用
        ①測試狀態位元           ; 第 0、1、4 位元其中之一被設定時進行跳越
           mov  al , status
           test  al , 00010011b      ; 測試第0、1、4位元
           jnz    InputDataByte
           ; 第 2、3、7 位元全被設定時跳越,使用 and 和 cmp
           mov  al , status
           and  al , 10001100b      ; 保留第2、3、7位元
           cmp  al , 10001100b      ; 是否完全被設定
           je      ResetMachine       ; 是則跳至標號所在
      
        ②兩數中較大者
             mov  dx , ax                 ; 假設 ax 較大
             cmp  ax , bx                 ; if ax >= bx 則
             jae   L1                        ; 跳至L1
             mov  dx , bx                 ; 否則存 bx 值到 dx
         L1:                                   ; dx 包含較大的整數

         ③三整數中最小者
            .data
             V1     WORD    ?
             V2     WORD    ?
             V3     WORD    ?
            .code
                      mov   ax , V1        ; 若 V1 最小
                      cmp   ax , V2         ; if ax <= V2 則
                      jbe     L1               ; 跳至 L1
                      mov   ax , V2         ; 否則存 V2 值到 ax
               L1:  cmp   ax , V3         ; 如果 ax <= V3 則
                      jbe     L2                ; 跳至 L2
                      mov    ax , V3        ; 否則存 V3 值到 ax
               L2:

    * 位元測試指令 : BT、BTC、BTR、BTS
        ①BT : 選擇其第一個運算元的第 n 位元並複製到進位旗標
                  BT   bitBase , n
           允許的運算元      
                  BT   r/m16 , r16
                  BT   r/m32 , r32
                  BT   r/m16 , imm8
                  BT   r/m32 , imm8
           ; carry flag被指定為變數semaphore的第7位元
              semaphore  WORD  10001000b
              BT   semaphore , 7          ; CF = 1

        ②BTC選擇第一個運算元的第n位元複製到進位旗標並將第 n 位元反相
                   BTC  bitBase , n
              semaphore  WORD  10001000b    
              BTC   semaphore , 6       ; CF = 0 , semaphore = 11001000b

        ③BTR選擇第一個運算元的第n位元複製到進位旗標並清除第 n 位元
                   BTR  bitBase , n
              semaphore   WORD  10001000b
              BTR   semaphore , 7        ; CF = 1 , semaphore = 00001000b

        ④BTS選擇第一個運算元的第n位元複製到進位旗標並設定第 n 位元                   BTS  bitBase , n
               semaphore   WORD  10001000b    
               BTS   semaphore , 6        ; CF = 0 , semaphore = 11001000b

● 條件迴圈指令 ( Conditional Loop Instructions )
    * LOOPZ和LOOPE指令
        ①LOOPZ : (loop if zero) zero flat 被設定ecx的無號值>0允許迴圈繼續
                          目的標號的範圍需在其後指令的 -128+127 bytes 之間
        ②LOOPE : 與LOOPZ同     
       
        ◆執行邏輯: ecx = ecx -1                           若 ecx > 0 且 ZF=1 ,則跳至目的 
                           否則不進行跳越而繼續下一個指令

    * LOOPNZ和LOOPNE指令
 
        ①LOOPNZ : (loop if not zero) 在ecx中的無號值>0zero flag被清除時讓
                             迴圈繼續進行         ②LOOPNE : 與LOOPNZ同       
        ◆執行邏輯: ecx = ecx -1                           若 ecx > 0 且 ZF=0 ,則跳至目的 
                           否則不進行跳越而繼續下一個指令


        ◆ 範例:掃描陣列中的每個元素直到發現一個正數(sign flag=0)
            array       SWORD   -3 , -6 , -1 , -10 , 10 , 30 , 40 , 4
           
sentinel   SWORD   0
                   mov   esi , OFFSET        array
                   mov   ecx , LENGTHOF  array
            next:
                   test      WORD PTR[esi] , 8000h          ; test sign flag
                   pushfd                                                ; 將flag放入堆疊
                   add       esi , TYPE array
                   popfd                                                  ; 將flag從堆疊中拿出
                   loopnz   next                                      ; 迴圈繼續
                   jnz         quit                                       ; not found
                   sub        esi , TYPE array                     ; esi 指向該值
             quit:


● 條件結構 ( Conditional Structures )
    * IF敘述
        ◆ 範例1 : if(op1 == op2)
                     mov  eax , op1  ; eax和op2作比較
                        {                                           cmp  eax , op2  ;相等跳至L1
                                X=1;                             je     L1             ;否則跳至L2
                                Y=2;                             jmp  L2
                         }                                     L1:
                                                                     mov X,1
                                                                     mov Y,2
                                                               L2:
                         -----------------------------------------------------------------------------
        ◆ 範例2 : 
clusterSize = 8192;                      mov clusterSize , 8192
                         if(gigabytes<8)                             cmp gigabytes , 8
                                 clusterSize = 4096;               jae  next
                                                                              mov clusterSize,4096
                                                                      next:

     * 複合運算式         高階                                      一般                                簡化
        ◆ 範例 : 
if(a1>b1) AND (b1>c1)         cmp al , bl   ;第一個運算式       cmp al,bl
                       
{                                            ja    L1                                  jbe  next
                                X = 1 ;                          jmp  next                              cmp bl , cl
                         }                                     L1:                                             jbe  next
                                                                     cmp bl , cl   ;第二個運算式      mov X,1
                                                                     ja    L2                             next:
                                                                     jmp next
                                                               L2:                   ; 皆為真
                                                                     mov  X,1    ; 將X設為1
                                                               next:
    --------------------------------------------------------------------------------------------------------
    *WHILE迴圈                                          
       ◆ 範例1 :    while(val1 < val2)              mov eax , val1       
                        {                               while:
                               val1++;                       cmp  eax , val2  ; val1<val2 ?
                               val2--;                         jnl    endwhile   ; 跳出迴圈
                        }                                        inc    eax           ; val1++
                                                                  dec   val2          ; val2--
                                                                  jmp   while
                                                    endwhile:
                                                                  mov   val1,eax   ; 新值存回val1
      
      ◆ 範例2: while(op1<op2)                  mov  eax , op1                     {                                           mov  ebx , op2
                            op1++;                        mov  ecx , op3
                            if( op2 == op3)       L1:cmp  eax , ebx      ; eax < ebx ?
                                   X = 2;                    jl       L2               ; 若成立
                            else                              jmp   L7               ; 不成立
                                   X = 3;              L2: inc    eax
                    }                                    L3 : cmp  ebx , ecx      ; ebx == ecx?
                                                                 je     L4               ; 成立
                                                                 jmp  L5                ;不成立
                                                          L4 : mov X , 2             ; X=2
                                                                 jmp  L6               
                                                          L5 : mov  X , 3             ; X=3
                                                          L6 : jmp   L1                ; 重複迴圈

沒有留言:

張貼留言