CHAP T ER   05
                                        《 程式流程控制    比較兩個整數 》


  下列四個例題中,例一及例二是對於有號數的比較,例三及例四是對於無號數
的比較。

【例一】
             CMP RAX, 0           ; 暫存器 RAX 內含值與 0 比較
             JL   L2              ; 當 RAX 小於 0 時跳躍至 L2
             ; 當 RAX>=0 時所執行的指令
       L2:

【例二】
             MOV RAX, [total]    ; 將 total 內含值拷貝至 RAX
             CMP RAX, 0          ; 暫存器 RAX 內含值與 0 比較
             JGE L3              ; 當 RAX 大於或等於 0 時跳躍至 L3
             ; 當 total<0 時所執行的指令
       L3:

【例三】
             CMP DL, 'K'          ; 暫存器 DL 內含值與 'K' 比較
             JB   L4              ; 當 DL 低於 'K' 時跳躍至 L4
             ; 當 RAX 高於或等於 0 時所執行的指令
       L4:

【例四】
             CMP DL, '0'          ; 暫存器 DL 內含值與 '0' 比較
             JAE L5               ; 當 RAX 高於或等於 0 時跳躍至 L5
             ; 當 DL 低於 '0' 時所執行的指令
       L5:




                                                                     89
64 位元組合語言



     5.5 無條件跳躍指令 JMP
       無條件跳躍指令 JMP 與條件無關,它跳至指定的標籤後從該標籤位址處繼續
     往下執行。它的格式如下:

           JMP    label

       單純的使用 JMP label 產生的機器碼 E9 後面的運算元佔一個雙字組,因此
     跳躍的範圍可至三十二位元的最大距離,屬於短程跳躍。若產生的機器碼 FF 後面
     的運算元佔一個四字組,因此跳躍的範圍可至六十四位元的最大距離。

       無條件跳躍指令 JMP 用於下列兩種狀況:

     1. 往前跳過一些您不想執行或不能執行的指令。
     2. 往回跳躍構成一個迴圈。


     5.6 迴圈指令 LOOP
       一個迴圈是指一系列的指令重複執行指定的次數。LOOP 指令建立一個迴圈,
     該迴圈的指令重複執行指定的次數。例如有一個資料表,包含十個數值,想將每一
     個數值累積至變數 sum 中,那就要重複執行累積的計算十次。

       LOOP 指令的格式如下:

           LOOP   label

       就像條件跳躍指令一樣,label 的範圍必須在 128 個位元組之內。

       LOOP 指令使用 RCX 暫存器當迴圈的計數器,開始時存放迴圈重複執行的次
     數,每執行迴圈一次 RCX 的值就自動遞減一,然後測試 RCX 的值是否為零,若
     不為零則繼續下一次的迴圈,如此重複執行,一直到 RCX 的值遞減至零時為止,
     LOOP 的流程圖如下圖所示。




90
CHAP T ER   05
                                         《 程式流程控制   迴圈指令 LOOP 》




                      圖 5.3 LOOP 迴圈流程圖


  在上圖 LOOP 迴圈流程圖中,流程圖「區塊 1」中的回圈次數要設定,流程
圖「區塊 2」是您要重複執行的指令,當然也要設定。流程圖「區塊 3」及「區塊
4」則隱藏在 LOOP 指令中,它會自動執行,就不用掛慮了。這個流程圖寫成組合
語言的程式如下:

               MOV   RCX, 10      ; 流程圖區塊 1
      label:
               ; 您要重複執行的指令 ; 流程圖區塊 2
               LOOP label     ; 流程圖區塊 3 及 4

  程式 sum.asm 中首先宣告一個 table 陣列變數,它的內含值分別為 1 至 19
的奇數,每一個奇數均存於一個四字組裡。宣告變數 sum,要存放 table 中每一
個元素值的總和。設定迴圈次數 RCX=10,因為 table 中共有十個元素因此設為
10。

      label:
          ADD RAX, [RSI+table] ;RAX=RAX+(table 第 RSI 項 )
          ADD RSI, 8           ;RSI=RSI+8
          LOOP label           ; 繼續迴圈



                                                                       91
64 位元組合語言


       上列是要重複執行的指令,將 [table+RSI] 所指的元素值累加至 RAX 暫存
     器後,RSI 的值加 8,指到 table 的下一個元素,預備下一迴圈累積之用,LOOP
     指令跳至 label 處繼續迴圈。

           MOV    QWORD [sum], RAX   ;sum=RAX
           prnvar format, sum        ; 以 format 格式列印 sum 值

       上列指令將累積的結果存入 sum 變數中,然後透過 prnvar 巨集將累積總和
     sum 依指定的 format 格式輸出。

           ;********************** sum.asm *********************
           %include "..binnasm64io.mac"
           SECTION .data
           table   DQ    1,3,5,7,9,11,13,15,17,19
           sum     DQ    0
           format DB     'sum up all elements in table = %I64d '
                   DB    13, 10, 0
           start:
               MOV    RSI, 0            ;RSI=0
               MOV    RAX, 0            ;RAX=0
               MOV    RCX, 10           ;RCX=10
           L2: ADD    RAX, [RSI+table] ;RAX=RAX+(table 第 RSI 項 )
               ADD    RSI, 8            ;RSI=RSI+8
               LOOP   L2                ; 繼續迴圈
               MOV    QWORD [sum], RAX ;sum=RAX
               prnvar format, sum       ; 以 format 格式列印 sum 值
               RET

       執行 sum.bat 結果如下:

           C:asm64ch05>sum.exe
           sum up all elements in table = 100

       LOOP 指令建立重複執行 RCX 次的迴圈,但有時也需建立依比較結果而重複執
     行的迴圈,LOOPE 及 LOOPNE 指令將這兩種功能結合在一起,它的格式與 LOOP
     並沒有兩樣,這兩個指令在 LOOP 迴圈之前直接放入一個比較的指令,是否需迴圈
     不但要檢查 RCX 是否為 0,同時也要檢查指定的條件是否滿足,才決定是否繼續迴
     圈。LOOPE 的條件為相等(Equal),LOOPNE 的條件為不相等(Not Equal)。


92
CHAP T ER   05
                                         《 程式流程控制    迴圈指令 LOOP 》


  程式 pos.asm 宣告一個變數 pos,用於存放在 table 中第一個出現其值為
9 元素的位置,本例中它的位置為第五個(從 0 算起)。

     label:
           MOV      RAX, [RSI+table]   ;RAX=table 第 RSI 元素值
           ADD      RSI, 8             ;RSI=RSI+8
           INC      QWORD [pos]        ;pos 內含值 +1
           CMP      RAX, 9             ;RAX:9?
           LOOPNE   label              ; 不相等或 RCX>0 時繼續迴圈

  在 LOOPNE 的結構裡放著要重複執行的指令,要處理 table 的下一元素的
同時將位置變數的值增加 1,然後比較下一個元素是否為 9,若不是 9,且暫存器
RCX 的值不為 0 時,則繼續迴圈。table 的下一個元素值若為 9,則跳出迴圈,
繼續執行 LOOPNE 的下一個指令。

  請考慮若 table 中沒有您要找尋的元素 9 時,pos 的值是多少呢,請將它當
一個練習題目做做看。

     ;*********************** pos.asm **********************
     %include "..binnasm64io.mac"
     SECTION .data
     table   DQ 1,3,5,7,9,11,13,15,17,19
     pos     DQ -1
     format DB 'element 9 at position (from 0) = %I64d',0
     SECTION .text
     start:
         MOV     RSI, 0           ;RSI=0
         MOV     RCX, 10          ;RCX=10
     L2: MOV     RAX, [RSI+table] ;RAX=table 第 RSI 元素值
         ADD     RSI, 8           ;RSI=RSI+8
         INC     QWORD [pos]      ;pos 內含值 +1
         CMP     RAX, 9           ;RAX:9?
         LOOPNE L2                ; 不相等或 RCX>0 時繼續迴圈
         prnvar format, [pos]     ; 以 format 格式列印 pos 值
         RET




                                                                       93
64 位元組合語言


       執行 sum.bat 結果如下:

           C:asm64ch05>sum.exe
           element 9 at position (from 0) = 4



     5.7 選擇結構
       選擇結構從一個或多個情況中選擇您所要的,然後執行指定的指令。例如您的
     程式中可以檢查某一個變數 ch2 值,當它的值是 'a' 時就將 'A' 存入 ch2 變數
     中。程式片段如下:

                 ; if ch2='a' then ch2='A'
                       MOV AL, [ch2]      ; 變數 ch2 內含值拷貝至 AL
                       CMP AL, 'a'        ;AL 內含值與 'a' 比較
                       JNE next           ; 不相等時跳至 next
                       MOV BYTE[ch2],'A' ; 相等時將 'A' 存入 ch2 變數中
                 next:

       使用組合語言時,您必須將條件的建立與檢查比較的結果分開成兩個指令,條
     件的建立可以使用 CMP 指令,兩個運算元比較的結果會設定相對應的狀態旗標值,
     檢查比較的結果可使用條件跳躍指令,直接測試狀態旗標值,滿足指定的條件才跳
     躍至指定的標籤位址。上例中比較變數 ch2 的內含值及 'a' 立即值,滿足相等條
     件時才將 'A' 存入 ch2 變數中,否則跳至 next 標籤處繼續執行。這種結構稱為
     單選的 if 結構。




                            圖 5.4 單選的 if 結構


94
CHAP T ER   05
                                             《 程式流程控制     選擇結構 》


   在 上 一 個 例 題 中, 條 件 是「CMP AL,'a'」 指 令, 條 件 跳 躍 指 令「JNE
next」判斷不為 'a' 時才跳至 next,否則就執行「MOV BYTE[ch2],'A'」指
令,這個指令就是當條件成立時您所要執行的指令。

   在本章後面的幾個例子都會用到有關字元的處理,字元在電腦記憶體裡面是以
二進位的方式儲存的,個人電腦一般使用 ASCII 碼以一個位元組來表示一個字元,
例如字元 'A' 以「0100 0001」二進位的方式儲存,以十六進位表示為 41H,以
十進位表示為 65,您要從鍵盤輸入 'A' 字元,可以透過巨集 scanvar,其使用
方法如下列程式所示。

       ;*************** hexval.asm ***************
       %include "..binnasm64io.mac"
       SECTION .data
       msg      DB 'please keyin a character: ',0
       format   DB '%c',0
       format2 DB '%c = %02I64xH',0
       SECTION .bss
       char     RESB   2
       SECTION .text
       start:
           prnstr   msg
           scanvar format, char
           prn2vars format2, [char], [char]
           RET

   執行 hexval.bat 結果如下:

      C:asm64ch05>hexval.exe
      please keyin a character: C <Enter>
      C = 43H




                                                                      95
64 位元組合語言


       程式 compchar.asm 說明單選 if 結構的用法。從鍵盤輸入一字元至 ch2 記
     憶體位址。變數 ch2 的內含值與字元 'a' 比較,不相等時跳至 L2 標籤,將 ch2
     的值顯示出來,若 ch2 的值等於 'a' 時設定值為 'A' 後才將 ch2 的值列印出來。

           ;****************** compchar.asm *****************
           %include "..binnasm64io.mac"
           SECTION .data
           msg      DB 'please keyin a character: ',0
           format   DB '%c',0
           format2 DB 'the result character = %c',0
           SECTION .bss
           ch2      RESB 2
           SECTION .text
           start:
               prnstr   msg             ; 印出 msg 字串
               scanvar format, ch2      ; 鍵入字元至 ch2
               MOV      AL, [ch2]       ; 拷貝 ch2 變數值至 AL
               CMP      AL, 'a'         ;AL 內含值與 'a' 比較
               JNE      L2              ; 不相等時跳至 L2
               MOV      AL, 'A'
               MOV      BYTE [ch2], AL ; 相等時將 [ch2] 換為 'A'
           L2: prnvar   format2, [ch2]   ; 輸出結果
               RET

       執行 compchar.bat 結果如下:

           C:asm64ch05>compchar.exe
           please keyin a character: a <Enter>
           the result character = A
           C:asm64ch05>compchar.exe
           please keyin a character: c <Enter>
           the result character = c

       有時測試條件成立時要執行這些指令,條件不成立時要執行那些指令,也就是
     說測試之前程式是一條主流,測試後不是執行這個支流的指令,就是執行那個支流
     的指令,不管是這支或那支,最後又合流成一個主流。




96
CHAP T ER   05
                                           《 程式流程控制         選擇結構 》




                    圖 5.5 二選一的 if 結構


  以程式 if.asm 為例,比較輸入的字元是否高於 'D',若是高於 'D' 則跳至
標籤 L4 處執行,顯示不及格訊息。若是低於或等於 'D' 則顯示及格訊息後跳至
L2 處結束程式之執行。稱為二選一的 if 結構,流程圖如上圖所示。

     ;******************* if.asm *******************
     %include "..binnasm64io.mac"
     SECTION .data
     msg      DB 'keyin a character (A-F): ',0
     format   DB '%c',0
     pass     DB 'pass',13,10,0
     fail     DB 'fail',13,10,0
     SECTION .bss
     ch2      RESB 2
     SECTION .text
     start:
         prnstr   msg           ; 列印 msg 字串
         scanvar format, ch2    ; 依 format 格式輸出 ch2
         MOV      AL, [ch2]     ; 拷貝 ch2 變數值至 AL
         CMP      AL, 'D'       ;AL 內含值與 'D' 比較

                                                                        97
64 位元組合語言


               JA       L4           ; 高於 'D' 時跳至 L4
           L2: prnstr   pass         ;A/B/C/D 顯示 pass 及格
               RET
           L4: prnstr   fail         ;E/F 顯示 fail 不及格
               RET

       執行 if.bat 結果如下:

           C:asm64ch05>if.exe
           keyin a character (A-F): B <Enter>
           pass
           C:asm64ch05>if.exe
           keyin a character (A-F): E <Enter>
           fail

       有時測試的條件不只兩種情形,這時您要一個條件一個條件逐一測試,滿足第
     一種條件就跳至第一標籤執行,滿足第二種條件就跳至第二標籤執行,滿足第三種
     條件就跳至第三標籤執行,等等,最後又合流至主流。




                        圖 5.6 多選一的 switch 結構
98

9789572239940 試閱章節

  • 1.
    CHAP T ER 05 《 程式流程控制 比較兩個整數 》 下列四個例題中,例一及例二是對於有號數的比較,例三及例四是對於無號數 的比較。 【例一】 CMP RAX, 0 ; 暫存器 RAX 內含值與 0 比較 JL L2 ; 當 RAX 小於 0 時跳躍至 L2 ; 當 RAX>=0 時所執行的指令 L2: 【例二】 MOV RAX, [total] ; 將 total 內含值拷貝至 RAX CMP RAX, 0 ; 暫存器 RAX 內含值與 0 比較 JGE L3 ; 當 RAX 大於或等於 0 時跳躍至 L3 ; 當 total<0 時所執行的指令 L3: 【例三】 CMP DL, 'K' ; 暫存器 DL 內含值與 'K' 比較 JB L4 ; 當 DL 低於 'K' 時跳躍至 L4 ; 當 RAX 高於或等於 0 時所執行的指令 L4: 【例四】 CMP DL, '0' ; 暫存器 DL 內含值與 '0' 比較 JAE L5 ; 當 RAX 高於或等於 0 時跳躍至 L5 ; 當 DL 低於 '0' 時所執行的指令 L5: 89
  • 2.
    64 位元組合語言 5.5 無條件跳躍指令 JMP 無條件跳躍指令 JMP 與條件無關,它跳至指定的標籤後從該標籤位址處繼續 往下執行。它的格式如下: JMP label 單純的使用 JMP label 產生的機器碼 E9 後面的運算元佔一個雙字組,因此 跳躍的範圍可至三十二位元的最大距離,屬於短程跳躍。若產生的機器碼 FF 後面 的運算元佔一個四字組,因此跳躍的範圍可至六十四位元的最大距離。 無條件跳躍指令 JMP 用於下列兩種狀況: 1. 往前跳過一些您不想執行或不能執行的指令。 2. 往回跳躍構成一個迴圈。 5.6 迴圈指令 LOOP 一個迴圈是指一系列的指令重複執行指定的次數。LOOP 指令建立一個迴圈, 該迴圈的指令重複執行指定的次數。例如有一個資料表,包含十個數值,想將每一 個數值累積至變數 sum 中,那就要重複執行累積的計算十次。 LOOP 指令的格式如下: LOOP label 就像條件跳躍指令一樣,label 的範圍必須在 128 個位元組之內。 LOOP 指令使用 RCX 暫存器當迴圈的計數器,開始時存放迴圈重複執行的次 數,每執行迴圈一次 RCX 的值就自動遞減一,然後測試 RCX 的值是否為零,若 不為零則繼續下一次的迴圈,如此重複執行,一直到 RCX 的值遞減至零時為止, LOOP 的流程圖如下圖所示。 90
  • 3.
    CHAP T ER 05 《 程式流程控制 迴圈指令 LOOP 》 圖 5.3 LOOP 迴圈流程圖 在上圖 LOOP 迴圈流程圖中,流程圖「區塊 1」中的回圈次數要設定,流程 圖「區塊 2」是您要重複執行的指令,當然也要設定。流程圖「區塊 3」及「區塊 4」則隱藏在 LOOP 指令中,它會自動執行,就不用掛慮了。這個流程圖寫成組合 語言的程式如下: MOV RCX, 10 ; 流程圖區塊 1 label: ; 您要重複執行的指令 ; 流程圖區塊 2 LOOP label ; 流程圖區塊 3 及 4 程式 sum.asm 中首先宣告一個 table 陣列變數,它的內含值分別為 1 至 19 的奇數,每一個奇數均存於一個四字組裡。宣告變數 sum,要存放 table 中每一 個元素值的總和。設定迴圈次數 RCX=10,因為 table 中共有十個元素因此設為 10。 label: ADD RAX, [RSI+table] ;RAX=RAX+(table 第 RSI 項 ) ADD RSI, 8 ;RSI=RSI+8 LOOP label ; 繼續迴圈 91
  • 4.
    64 位元組合語言 上列是要重複執行的指令,將 [table+RSI] 所指的元素值累加至 RAX 暫存 器後,RSI 的值加 8,指到 table 的下一個元素,預備下一迴圈累積之用,LOOP 指令跳至 label 處繼續迴圈。 MOV QWORD [sum], RAX ;sum=RAX prnvar format, sum ; 以 format 格式列印 sum 值 上列指令將累積的結果存入 sum 變數中,然後透過 prnvar 巨集將累積總和 sum 依指定的 format 格式輸出。 ;********************** sum.asm ********************* %include "..binnasm64io.mac" SECTION .data table DQ 1,3,5,7,9,11,13,15,17,19 sum DQ 0 format DB 'sum up all elements in table = %I64d ' DB 13, 10, 0 start: MOV RSI, 0 ;RSI=0 MOV RAX, 0 ;RAX=0 MOV RCX, 10 ;RCX=10 L2: ADD RAX, [RSI+table] ;RAX=RAX+(table 第 RSI 項 ) ADD RSI, 8 ;RSI=RSI+8 LOOP L2 ; 繼續迴圈 MOV QWORD [sum], RAX ;sum=RAX prnvar format, sum ; 以 format 格式列印 sum 值 RET 執行 sum.bat 結果如下: C:asm64ch05>sum.exe sum up all elements in table = 100 LOOP 指令建立重複執行 RCX 次的迴圈,但有時也需建立依比較結果而重複執 行的迴圈,LOOPE 及 LOOPNE 指令將這兩種功能結合在一起,它的格式與 LOOP 並沒有兩樣,這兩個指令在 LOOP 迴圈之前直接放入一個比較的指令,是否需迴圈 不但要檢查 RCX 是否為 0,同時也要檢查指定的條件是否滿足,才決定是否繼續迴 圈。LOOPE 的條件為相等(Equal),LOOPNE 的條件為不相等(Not Equal)。 92
  • 5.
    CHAP T ER 05 《 程式流程控制 迴圈指令 LOOP 》 程式 pos.asm 宣告一個變數 pos,用於存放在 table 中第一個出現其值為 9 元素的位置,本例中它的位置為第五個(從 0 算起)。 label: MOV RAX, [RSI+table] ;RAX=table 第 RSI 元素值 ADD RSI, 8 ;RSI=RSI+8 INC QWORD [pos] ;pos 內含值 +1 CMP RAX, 9 ;RAX:9? LOOPNE label ; 不相等或 RCX>0 時繼續迴圈 在 LOOPNE 的結構裡放著要重複執行的指令,要處理 table 的下一元素的 同時將位置變數的值增加 1,然後比較下一個元素是否為 9,若不是 9,且暫存器 RCX 的值不為 0 時,則繼續迴圈。table 的下一個元素值若為 9,則跳出迴圈, 繼續執行 LOOPNE 的下一個指令。 請考慮若 table 中沒有您要找尋的元素 9 時,pos 的值是多少呢,請將它當 一個練習題目做做看。 ;*********************** pos.asm ********************** %include "..binnasm64io.mac" SECTION .data table DQ 1,3,5,7,9,11,13,15,17,19 pos DQ -1 format DB 'element 9 at position (from 0) = %I64d',0 SECTION .text start: MOV RSI, 0 ;RSI=0 MOV RCX, 10 ;RCX=10 L2: MOV RAX, [RSI+table] ;RAX=table 第 RSI 元素值 ADD RSI, 8 ;RSI=RSI+8 INC QWORD [pos] ;pos 內含值 +1 CMP RAX, 9 ;RAX:9? LOOPNE L2 ; 不相等或 RCX>0 時繼續迴圈 prnvar format, [pos] ; 以 format 格式列印 pos 值 RET 93
  • 6.
    64 位元組合語言 執行 sum.bat 結果如下: C:asm64ch05>sum.exe element 9 at position (from 0) = 4 5.7 選擇結構 選擇結構從一個或多個情況中選擇您所要的,然後執行指定的指令。例如您的 程式中可以檢查某一個變數 ch2 值,當它的值是 'a' 時就將 'A' 存入 ch2 變數 中。程式片段如下: ; if ch2='a' then ch2='A' MOV AL, [ch2] ; 變數 ch2 內含值拷貝至 AL CMP AL, 'a' ;AL 內含值與 'a' 比較 JNE next ; 不相等時跳至 next MOV BYTE[ch2],'A' ; 相等時將 'A' 存入 ch2 變數中 next: 使用組合語言時,您必須將條件的建立與檢查比較的結果分開成兩個指令,條 件的建立可以使用 CMP 指令,兩個運算元比較的結果會設定相對應的狀態旗標值, 檢查比較的結果可使用條件跳躍指令,直接測試狀態旗標值,滿足指定的條件才跳 躍至指定的標籤位址。上例中比較變數 ch2 的內含值及 'a' 立即值,滿足相等條 件時才將 'A' 存入 ch2 變數中,否則跳至 next 標籤處繼續執行。這種結構稱為 單選的 if 結構。 圖 5.4 單選的 if 結構 94
  • 7.
    CHAP T ER 05 《 程式流程控制 選擇結構 》 在 上 一 個 例 題 中, 條 件 是「CMP AL,'a'」 指 令, 條 件 跳 躍 指 令「JNE next」判斷不為 'a' 時才跳至 next,否則就執行「MOV BYTE[ch2],'A'」指 令,這個指令就是當條件成立時您所要執行的指令。 在本章後面的幾個例子都會用到有關字元的處理,字元在電腦記憶體裡面是以 二進位的方式儲存的,個人電腦一般使用 ASCII 碼以一個位元組來表示一個字元, 例如字元 'A' 以「0100 0001」二進位的方式儲存,以十六進位表示為 41H,以 十進位表示為 65,您要從鍵盤輸入 'A' 字元,可以透過巨集 scanvar,其使用 方法如下列程式所示。 ;*************** hexval.asm *************** %include "..binnasm64io.mac" SECTION .data msg DB 'please keyin a character: ',0 format DB '%c',0 format2 DB '%c = %02I64xH',0 SECTION .bss char RESB 2 SECTION .text start: prnstr msg scanvar format, char prn2vars format2, [char], [char] RET 執行 hexval.bat 結果如下: C:asm64ch05>hexval.exe please keyin a character: C <Enter> C = 43H 95
  • 8.
    64 位元組合語言 程式 compchar.asm 說明單選 if 結構的用法。從鍵盤輸入一字元至 ch2 記 憶體位址。變數 ch2 的內含值與字元 'a' 比較,不相等時跳至 L2 標籤,將 ch2 的值顯示出來,若 ch2 的值等於 'a' 時設定值為 'A' 後才將 ch2 的值列印出來。 ;****************** compchar.asm ***************** %include "..binnasm64io.mac" SECTION .data msg DB 'please keyin a character: ',0 format DB '%c',0 format2 DB 'the result character = %c',0 SECTION .bss ch2 RESB 2 SECTION .text start: prnstr msg ; 印出 msg 字串 scanvar format, ch2 ; 鍵入字元至 ch2 MOV AL, [ch2] ; 拷貝 ch2 變數值至 AL CMP AL, 'a' ;AL 內含值與 'a' 比較 JNE L2 ; 不相等時跳至 L2 MOV AL, 'A' MOV BYTE [ch2], AL ; 相等時將 [ch2] 換為 'A' L2: prnvar format2, [ch2] ; 輸出結果 RET 執行 compchar.bat 結果如下: C:asm64ch05>compchar.exe please keyin a character: a <Enter> the result character = A C:asm64ch05>compchar.exe please keyin a character: c <Enter> the result character = c 有時測試條件成立時要執行這些指令,條件不成立時要執行那些指令,也就是 說測試之前程式是一條主流,測試後不是執行這個支流的指令,就是執行那個支流 的指令,不管是這支或那支,最後又合流成一個主流。 96
  • 9.
    CHAP T ER 05 《 程式流程控制 選擇結構 》 圖 5.5 二選一的 if 結構 以程式 if.asm 為例,比較輸入的字元是否高於 'D',若是高於 'D' 則跳至 標籤 L4 處執行,顯示不及格訊息。若是低於或等於 'D' 則顯示及格訊息後跳至 L2 處結束程式之執行。稱為二選一的 if 結構,流程圖如上圖所示。 ;******************* if.asm ******************* %include "..binnasm64io.mac" SECTION .data msg DB 'keyin a character (A-F): ',0 format DB '%c',0 pass DB 'pass',13,10,0 fail DB 'fail',13,10,0 SECTION .bss ch2 RESB 2 SECTION .text start: prnstr msg ; 列印 msg 字串 scanvar format, ch2 ; 依 format 格式輸出 ch2 MOV AL, [ch2] ; 拷貝 ch2 變數值至 AL CMP AL, 'D' ;AL 內含值與 'D' 比較 97
  • 10.
    64 位元組合語言 JA L4 ; 高於 'D' 時跳至 L4 L2: prnstr pass ;A/B/C/D 顯示 pass 及格 RET L4: prnstr fail ;E/F 顯示 fail 不及格 RET 執行 if.bat 結果如下: C:asm64ch05>if.exe keyin a character (A-F): B <Enter> pass C:asm64ch05>if.exe keyin a character (A-F): E <Enter> fail 有時測試的條件不只兩種情形,這時您要一個條件一個條件逐一測試,滿足第 一種條件就跳至第一標籤執行,滿足第二種條件就跳至第二標籤執行,滿足第三種 條件就跳至第三標籤執行,等等,最後又合流至主流。 圖 5.6 多選一的 switch 結構 98