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

时间:2024-01-03 13:42:56

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

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

 INCLUDE Irvine32.inc

 .data
intArray SWORD , , , , , , , -, , , ; 测试用的数组
;intArray SWORD 1, 0, 0, 0
;intArray SWORD 0, 0, 0, 0
;intArray SWORD 0, 0, 0, 1
noneMsg BYTE "Non-zero value not found", .code
main PROC
mov ebx, OFFSET intArray
mov ecx, LENGTHOF intArray L1:
cmp WORD PTR [ebx], ; 与 0 作比较
jnz found ; 结果非零即找到了
add ebx, TYPE intArray
loop L1
jmp notFound found:
movsx eax, WORD PTR [ebx]
call WriteInt
jmp quit notFound:
mov edx, OFFSET noneMsg
call WriteString quit:
call crlf
call WaitMsg
main ENDP END main

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

 INCLUDE Irvine32.inc
KEY = ; 用来异或的秘钥
BUFMAX = .data
sPrompt BYTE "Plain text: ",
sEncrypt BYTE "Cipher text: ",
sDecrypt BYTE "Decrypted: ",
buffer BYTE BUFMAX + DUP()
bufSize DWORD ? .code
main PROC
call InputTheString ; 输入 call TranslateBuffer ; 加密并输出
mov edx, OFFSET sEncrypt
call DisplayMessage call TranslateBuffer ; 解密并输出
mov edx, OFFSET sDecrypt
call DisplayMessage call WaitMsg
exit
main ENDP InputTheString PROC
pushad ; 寄存器全压栈
mov edx, OFFSET sPrompt
call WriteString
mov ecx, BUFMAX
mov edx, OFFSET buffer
call ReadString
mov bufSize,eax
call Crlf
popad ; 寄存器全恢复,返回值在 buffer 里
ret
InputTheString ENDP DisplayMessage PROC
pushad
call WriteString
mov edx, OFFSET buffer
call WriteString
call Crlf
call Crlf
popad
ret
DisplayMessage ENDP TranslateBuffer PROC
pushad
mov ecx, bufSize
mov esi,
L1:
xor buffer[esi], KEY ; 用一个循环来逐字节异或
inc esi
loop L1 popad
ret
TranslateBuffer ENDP
END main

● 代码,表驱动选择

 INCLUDE Irvine32.inc
.data
CaseTable BYTE 'A' ; 驱动表,交替存储选项和分支
DWORD Process_A
BYTE 'B'
DWORD Process_B
BYTE 'C'
DWORD Process_C
BYTE 'D'
DWORD Process_D
NumberOfEntries = prompt BYTE "Input A, B, C or D: ",
msgA BYTE "Process_A",
msgB BYTE "Process_B",
msgC BYTE "Process_C",
msgD BYTE "Process_D", .code
main PROC
mov edx, OFFSET prompt ; 输入字符
call WriteString
call ReadChar
mov ebx, OFFSET CaseTable ; ebx 指向表
mov ecx, NumberOfEntries
L1:
cmp al, [ebx] ; 是否匹配 ebx 指向的项
jne L2 ; 否分支
call NEAR PTR [ebx + ] ; 是分支,调用对应的子过程(过程指针解引用,NEAR PTR)
call WriteString ; 显示相应的信息并退出循环
call Crlf
jmp L3 L2:
add ebx, ; 指向表中下一项
loop L1 L3:
exit call WaitMsg
main ENDP Process_A PROC
mov edx, OFFSET msgA
ret
Process_A ENDP Process_B PROC
mov edx, OFFSET msgB
ret
Process_B ENDP Process_C PROC
mov edx, OFFSET msgC
ret
Process_C ENDP Process_D PROC
mov edx, OFFSET msgD
ret
Process_D ENDP END main

● 代码,简单反汇编输出

 INCLUDE Irvine32.inc

 .data
TRUE =
FALSE =
gradeAverage WORD
credits WORD
OkToRegister BYTE ? .code
main PROC
mov OkToRegister,FALSE .IF gradeAverage >
mov OkToRegister,TRUE
.ELSEIF (gradeAverage > ) && (credits <= )
mov OkToRegister,TRUE
.ELSEIF (credits <= )
mov OkToRegister,TRUE
.ENDIF exit
main ENDP END main

■ 反汇编后,

 _main@0:
002E1005 jmp main (02E1010h)
002E100A int
002E100B int
002E100C int
002E100D int
002E100E int
002E100F int
--- D:\Code\assembler\project6\asm6\asm6\haha.asm ------------------------------ mov OkToRegister,FALSE
002E1010 mov byte ptr [OkToRegister (02E4004h)], .IF gradeAverage >
002E1017 cmp word ptr [gradeAverage (02E4000h)],15Eh
002E1020 jbe @C0001 (02E102Bh)
mov OkToRegister,TRUE
002E1022 mov byte ptr [OkToRegister (02E4004h)],
.ELSEIF (gradeAverage > ) && (credits <= )
002E1029 jmp @C0001+2Fh (02E105Ah)
@C0001:
002E102B cmp word ptr [gradeAverage (02E4000h)],0FAh
002E1034 jbe @C0001+1Eh (02E1049h)
002E1036 cmp word ptr [credits (02E4002h)],10h
002E103E ja @C0001+1Eh (02E1049h)
mov OkToRegister,TRUE
002E1040 mov byte ptr [OkToRegister (02E4004h)],
.ELSEIF (credits <= )
002E1047 jmp @C0001+2Fh (02E105Ah)
@C0004:
002E1049 cmp word ptr [credits (02E4002h)],0Ch
002E1051 ja @C0001+2Fh (02E105Ah)
mov OkToRegister,TRUE
002E1053 mov byte ptr [OkToRegister (02E4004h)],
.ENDIF exit
002E105A push
002E105C call _ExitProcess@4 (02E1075h)

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

 INCLUDE Irvine32.inc

 ENTER_KEY =               ; 回车键作为停止输入的标志
.data
InvalidInputMsg BYTE "Invalid input", , , .code
main PROC
call Clrscr StateA:
call Getnext ; 读取下一个字符
cmp al,'+' ; 前导 +,前往状态 B
je StateB
cmp al,'-' ; 前导 -,前往状态 B
je StateB
call IsDigit ; 数字,置 ZF = 1,前往状态 C
jz StateC
call DisplayErrorMsg ; 错误状态
jmp Quit StateB:
call Getnext
call IsDigit
jz StateC
call DisplayErrorMsg
jmp Quit StateC:
call Getnext
call IsDigit
jz StateC
cmp al, ENTER_KEY
je Quit
call DisplayErrorMsg
jmp Quit Quit:
call Crlf
call WaitMsg
exit
main ENDP Getnext PROC
call ReadChar
call WriteChar
ret
Getnext ENDP DisplayErrorMsg PROC
push edx
mov edx, OFFSET InvalidInputMsg
call WriteString
pop edx
ret
DisplayErrorMsg ENDP
END main