▶ 书中第六章的程序,使用了条件判断和跳转来实现一些功能
● 代码,查找数组首个非零值
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