《汇编语言 基于x86处理器》第六章条件处理部分的代码

时间:2022-01-30 01:20:57

▶ 书中第六章的程序,使用了条件判断和跳转来实现一些功能

● 代码,查找数组首个非零值

 1 INCLUDE Irvine32.inc
 2 
 3 .data
 4 intArray SWORD  0, 0, 0, 0, 1, 20, 35, -12, 66, 4, 0   ; 测试用的数组
 5 ;intArray SWORD  1, 0, 0, 0
 6 ;intArray SWORD  0, 0, 0, 0
 7 ;intArray SWORD  0, 0, 0, 1
 8 noneMsg  BYTE "Non-zero value not found", 0
 9 
10 .code
11 main PROC
12     mov   ebx, OFFSET intArray
13     mov   ecx, LENGTHOF intArray
14 
15 L1:
16     cmp   WORD PTR [ebx], 0     ; 与 0 作比较
17     jnz   found                 ; 结果非零即找到了                 
18     add   ebx, TYPE intArray
19     loop  L1
20     jmp   notFound
21 
22 found:
23     movsx eax, WORD PTR [ebx]
24     call  WriteInt
25     jmp   quit
26 
27 notFound:
28     mov   edx, OFFSET noneMsg
29     call  WriteString
30 
31 quit:
32     call  crlf
33     call WaitMsg
34 main ENDP
35 
36 END main

● 代码,简单的加密 / 解密

 1 INCLUDE Irvine32.inc
 2 KEY     = 239                       ; 用来异或的秘钥
 3 BUFMAX  = 128
 4 
 5 .data
 6 sPrompt  BYTE   "Plain text:    ", 0
 7 sEncrypt BYTE   "Cipher text:   ", 0
 8 sDecrypt BYTE   "Decrypted:     ", 0
 9 buffer   BYTE   BUFMAX + 1      DUP(0)
10 bufSize  DWORD  ?
11 
12 .code
13 main PROC
14     call    InputTheString          ; 输入
15 
16     call    TranslateBuffer         ; 加密并输出
17     mov     edx,    OFFSET sEncrypt
18     call    DisplayMessage
19 
20     call    TranslateBuffer         ; 解密并输出
21     mov     edx,    OFFSET sDecrypt
22     call    DisplayMessage
23 
24     call    WaitMsg
25     exit
26 main ENDP
27 
28 InputTheString PROC
29     pushad                          ; 寄存器全压栈
30     mov     edx,    OFFSET sPrompt
31     call    WriteString
32     mov     ecx,    BUFMAX
33     mov     edx,    OFFSET buffer
34     call    ReadString
35     mov     bufSize,eax
36     call    Crlf
37     popad                           ; 寄存器全恢复,返回值在 buffer 里
38     ret
39 InputTheString ENDP
40 
41 DisplayMessage PROC
42     pushad
43     call    WriteString
44     mov     edx,    OFFSET buffer
45     call    WriteString
46     call    Crlf
47     call    Crlf
48     popad
49     ret
50 DisplayMessage ENDP
51 
52 TranslateBuffer PROC
53     pushad
54     mov     ecx, bufSize
55     mov     esi, 0
56 L1:
57     xor     buffer[esi], KEY    ; 用一个循环来逐字节异或
58     inc     esi
59     loop    L1
60 
61     popad
62     ret
63 TranslateBuffer ENDP
64 END main

● 代码,表驱动选择

 1 INCLUDE Irvine32.inc
 2 .data
 3 CaseTable  BYTE   'A'           ; 驱动表,交替存储选项和分支
 4            DWORD   Process_A    
 5            BYTE   'B'
 6            DWORD   Process_B
 7            BYTE   'C'
 8            DWORD   Process_C
 9            BYTE   'D'
10            DWORD   Process_D
11 NumberOfEntries = 4
12 
13 prompt BYTE "Input A, B, C or D: ", 0
14 msgA BYTE "Process_A", 0
15 msgB BYTE "Process_B", 0
16 msgC BYTE "Process_C", 0
17 msgD BYTE "Process_D", 0
18 
19 .code
20 main PROC
21     mov  edx, OFFSET prompt     ; 输入字符
22     call WriteString
23     call ReadChar
24     mov  ebx, OFFSET CaseTable  ; ebx 指向表
25     mov  ecx, NumberOfEntries
26 L1:
27     cmp  al, [ebx]              ; 是否匹配 ebx 指向的项
28     jne  L2                     ; 否分支
29     call NEAR PTR [ebx + 1]     ; 是分支,调用对应的子过程(过程指针解引用,NEAR PTR)
30     call WriteString            ; 显示相应的信息并退出循环
31     call Crlf
32     jmp  L3
33 
34 L2:
35     add  ebx, 5                 ; 指向表中下一项
36     loop L1
37 
38 L3:
39     exit
40 
41     call WaitMsg
42 main ENDP
43 
44 Process_A PROC
45     mov  edx, OFFSET msgA
46     ret
47 Process_A ENDP
48 
49 Process_B PROC
50     mov  edx, OFFSET msgB
51     ret
52 Process_B ENDP
53 
54 Process_C PROC
55     mov  edx, OFFSET msgC
56     ret
57 Process_C ENDP
58 
59 Process_D PROC
60     mov  edx, OFFSET msgD
61     ret
62 Process_D ENDP
63 
64 END main

● 代码,简单反汇编输出

 1 INCLUDE Irvine32.inc
 2 
 3 .data
 4 TRUE = 1
 5 FALSE = 0
 6 gradeAverage  WORD 275
 7 credits       WORD 12
 8 OkToRegister  BYTE ?
 9 
10 .code
11 main PROC
12     mov OkToRegister,FALSE
13 
14     .IF gradeAverage > 350
15        mov OkToRegister,TRUE
16     .ELSEIF (gradeAverage > 250) && (credits <= 16)
17        mov OkToRegister,TRUE
18     .ELSEIF (credits <= 12)
19        mov OkToRegister,TRUE
20     .ENDIF
21 
22     exit
23 main ENDP
24 
25 END main

■ 反汇编后,

 1 _main@0:
 2 002E1005  jmp         main (02E1010h)
 3 002E100A  int         3
 4 002E100B  int         3
 5 002E100C  int         3
 6 002E100D  int         3
 7 002E100E  int         3
 8 002E100F  int         3
 9 --- D:\Code\assembler\project6\asm6\asm6\haha.asm ------------------------------
10 
11     mov OkToRegister,FALSE
12 002E1010  mov         byte ptr [OkToRegister (02E4004h)],0
13 
14     .IF gradeAverage > 350
15 002E1017  cmp         word ptr [gradeAverage (02E4000h)],15Eh
16 002E1020  jbe         @C0001 (02E102Bh)
17        mov OkToRegister,TRUE
18 002E1022  mov         byte ptr [OkToRegister (02E4004h)],1
19     .ELSEIF (gradeAverage > 250) && (credits <= 16)
20 002E1029  jmp         @C0001+2Fh (02E105Ah)
21 @C0001:
22 002E102B  cmp         word ptr [gradeAverage (02E4000h)],0FAh
23 002E1034  jbe         @C0001+1Eh (02E1049h)
24 002E1036  cmp         word ptr [credits (02E4002h)],10h
25 002E103E  ja          @C0001+1Eh (02E1049h)
26        mov OkToRegister,TRUE
27 002E1040  mov         byte ptr [OkToRegister (02E4004h)],1
28     .ELSEIF (credits <= 12)
29 002E1047  jmp         @C0001+2Fh (02E105Ah)
30 @C0004:
31 002E1049  cmp         word ptr [credits (02E4002h)],0Ch
32 002E1051  ja          @C0001+2Fh (02E105Ah)
33        mov OkToRegister,TRUE
34 002E1053  mov         byte ptr [OkToRegister (02E4004h)],1
35     .ENDIF
36 
37     exit
38 002E105A  push        0
39 002E105C  call        _ExitProcess@4 (02E1075h)

● 代码,有限自动机判断输入的是否是一个合法的数字。注意每输入一个字符就进行状态跳转,而不是输入一行后回车才开始分析

 1 INCLUDE Irvine32.inc
 2 
 3 ENTER_KEY = 13              ; 回车键作为停止输入的标志
 4 .data
 5 InvalidInputMsg BYTE "Invalid input", 13, 10, 0
 6 
 7 .code
 8 main PROC
 9     call    Clrscr
10 
11 StateA:
12     call    Getnext         ; 读取下一个字符
13     cmp     al,'+'          ; 前导 +,前往状态 B
14     je      StateB
15     cmp     al,'-'          ; 前导 -,前往状态 B
16     je      StateB
17     call    IsDigit         ; 数字,置 ZF = 1,前往状态 C
18     jz      StateC
19     call    DisplayErrorMsg ; 错误状态
20     jmp     Quit
21 
22 StateB:
23     call    Getnext
24     call    IsDigit
25     jz      StateC
26     call    DisplayErrorMsg
27     jmp    Quit
28 
29 StateC:
30     call    Getnext
31     call    IsDigit
32     jz      StateC
33     cmp     al, ENTER_KEY
34     je      Quit
35     call    DisplayErrorMsg
36     jmp     Quit
37 
38 Quit:
39     call    Crlf
40     call    WaitMsg
41     exit
42 main ENDP
43 
44 Getnext PROC
45      call ReadChar
46      call WriteChar
47      ret
48 Getnext ENDP
49 
50 DisplayErrorMsg PROC
51      push   edx
52      mov    edx, OFFSET InvalidInputMsg
53      call   WriteString
54      pop    edx
55      ret
56 DisplayErrorMsg ENDP
57 END main