Kip Irvine 汇编语言 基于x86处理器 Chapter06 代码(含习题)

案例代码

01.AND指令及其应用

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	;原理:把任何一个字符与二进制数 1101 1111进行与运算 ,则除5位以外的所有位都不变,就相当于
	;	   把ASCII码加上了100000也就是64

.code
	main PROC
		
		mov al,01100001b
		and al,11011111b
		call WriteChar
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

02.OR指令及其应用

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	;原理:把任何一个字符与二进制数 0010 0000进行或运算 ,则除5位以外的所有位都不变,就相当于
	;	   把ASCII码减去·1100000也就是64

.code
	main PROC
		;大写转小写
		mov al,01000001b
		or  al,61h
		call WriteChar
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

03.位映射集

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	SetX DWORD 10000000000000000000000000000111b
	SetY DWORD 01101010101010101010111110000001b

.code
	main PROC
		
		;测试操作①
		mov eax,SetX
		and eax,10000b	;元素[4]是SetX的成员吗?
		call WriteBin	;输出结果  如果结果为0则不是
		call Crlf

		;测试操作②
		not	eax			;求解eax的补集
		call WriteBin
		call Crlf

		;测试操作③
		or eax,SetX		;测试并集
		call WriteBin
		call Crlf
		or eax,SetY
		call WriteBin
		call Crlf

		call WaitMsg

		invoke ExitProcess,0
	main ENDP
	END main

04.检查奇偶标志位

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		and eax,0;将与本例子无关的0 1 屏蔽掉
		;如果奇偶标志位置1,那么就是偶校验 反之就是奇校验
		mov al,10110101b	;五个一 奇校验
		xor al,0			;奇校验 奇偶标志位清零
		mov al,11001100b	;四个一 偶校验
		xor al,0			;偶校验 奇偶标志位清零
		call WriteBin

		invoke ExitProcess,0
	main ENDP
END main

05.16bit奇偶性


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;对于十六位整数来说,可以通过将其高位字节和低位字节进行异或运算来监测数据的奇偶性
		;奇偶性检测的结果可以再奇偶校验位里面查看
		mov ax,100
		xor al,ah


		invoke ExitProcess,0
	main ENDP
END main

06.NOT指令


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov al,11111111b
		not al
		invoke ExitProcess,0
	main ENDP
END main

07.TEST指令

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;test指令用来测试指定的bit是否为1
		; test al,pattern  指的是只有当al里面所有的bit满足pattern
		; 的要求之后ZF标志位才置一 实际上就是al与pattern进行与运算
		; 但是test指令总是优先清除溢出 和 进位标志  如果ZF=0则测试
		; 失败 反之则测试成功

		mov  al,11111110b
		test al,11110000b
		call DumpRegs
		call Crlf


		invoke ExitProcess,0
	main ENDP
END main

08.cmp指令对0标志位的影响


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		

		;01
		mov ax,5
		cmp ax,10		;ZF=0  CF=1

		;02
		mov ax,1000
		mov cx,1000
		cmp ax,cx		;ZF=1  CF=0

		;03
		mov si,105
		cmp si,0		;ZF=0  CF=0  

		invoke ExitProcess,0
	main ENDP
END main

09.0标志位的置位和清零


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		test al,0		;零标志位置1
		and	 al,0		;零标志位置1
		or	 al,1		;零标志位清0

		invoke ExitProcess,0
	main ENDP
END main

10.符号标志位的置位与清零


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		or al,80h	;80h==1000 0000b  符号位置1
		and al,7fh	;7fh==0111 1111b  符号位清0

		invoke ExitProcess,0
	main ENDP
END main

11.进位标志位的置位和清零


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		stc	;进位标志位置一
		clc	;进位标志位清零

		invoke ExitProcess,0
	main ENDP
END main

12.溢出标志位的置位和清零


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov  al,7fh		
		inc al			;溢出标志位置位
		or eax,0		;溢出标志位清零

		invoke ExitProcess,0
	main ENDP
END main

13.求解两个数中较大的数

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
	;本程序输出两个数字比较大的那一个数字
		mov eax,10
		mov ebx,20

		mov edx,eax	;假设eax存放了较大的数
		cmp eax,ebx	;如果eax>=ebx
		jae L1		;则跳转到L1
		mov edx,ebx	;否则将ebx的数值送入edx
		L1:
			mov eax,edx
			call WriteInt
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

14.求解三个数中比较小的数

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	V1	WORD 1
	V2  WORD 2
	V3  WORD 3

.code
	main PROC
		;本程序求解三个数字中比较小的数字并输出
		mov ax,V1	;假设V1是最小值
		cmp	ax,V2	;如果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:
		movzx eax,ax
		call WriteInt
		call WaitMsg
		
		invoke ExitProcess,0
	main ENDP
END main

15.循环直到按下键

include irvine32.inc


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	char	BYTE	0	;保存按下键盘的ASCII	

.code
	main PROC
		
		L1:	
			mov eax,10
			call Delay

			call ReadKey
			jz	L1
			mov char,AL		;读取的键的ASCII码保存在al中

			movzx eax,al
			call WriteInt	;输出按下键的ASCII码
			call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

16.顺序搜索数组

;扫描数组			(ArrayScan.asm)
;扫描数组寻找第一个非零数值

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	intArray	SWORD	0,0,0,0,1,20,35,-12,66,4,0
	;intArray	SWORD	1,0,0,0								;候补测试数据
	;intArray	SWORD	0,0,0,0								;候补测试数据
	;intArray	SWORD	0,0,0,1								;候补测试数据
	nonMsg		BYTE	"A non-zero value was not found!",0
.code
	main PROC
		mov ebx,offset intArray								;指向数组
		mov ecx,LENGTHOF intArray							;循环计数器

	L1:
		cmp WORD ptr [ebx],0								;将数值与0比较
		jnz found											;寻找数值
		add ebx,2											;指向下一个元素
		loop L1												;继续循环
		jmp notFound										;没有发现非零数值

	found:
		movsx eax,word ptr[ebx]								;送入eax并进行符号扩展
		call  WriteInt										
		jmp   quit

	notfound:
		mov edx,offset nonMsg								;显示没有发现消息
		call WriteString

	quit:
		call Crlf
		call WaitMsg
		exit


		invoke ExitProcess,0
	main ENDP
END main

17.简单字符串加密

;加密程序			(Encrypt.asm)

include irvine32.inc

KEY = 239										;1-255之间的任何一个数值
BUFMAX = 128									;缓冲区的最大容量

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	sPrompt		BYTE	"Enter the plain text:",0
	sEncrypt	BYTE	"Cipher text:         ",0
	sDecrypt	BYTE	"Decrypted:           ",0
	buffer      BYTE	BUFMAX+1	DUP(0)
	bufSize		DWORD	0

.code
		main PROC

			call	InputTheString
			call	TranslateBuffer
			mov		edx,offset sEncrypt
			call	DisplayMessage
			call	TranslateBuffer
			mov		edx,offset sDecrypt
			call	DisplayMessage
			call	WaitMsg
			exit
			invoke ExitProcess,0
		main ENDP

		;-------------------------------
		InputTheString PROC
		;
		;提示用户输入一个纯文本字符串
		;保存字符串和它的长度
		;接收:;返回:;-------------------------------
			pushad								;保存32位寄存器
			mov	edx,offset sPrompt				;显示提示
			call WriteString
			mov ecx,BUFMAX						;字符计数器最大值
			mov edx,offset buffer				;指向缓冲区
			call ReadString						;输入字符串
			mov bufSize,eax						;保存长度
			call Crlf
			popad
			ret
		InputTheString ENDP



		;-------------------------------
		DisplayMessage PROC
		;
		;显示加密或者解密消息
		;接收:EDX指向消息
		;返回:无
		;-------------------------------
			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,0						;缓冲区索引初赋值0

		L1:
			xor buffer[esi],KEY				;转换一个字节
			inc esi							;指向下一个字节
			loop L1

			popad
			ret
		TranslateBuffer ENDP
END main

18.寻找数组中第一个正数并输出

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	array		SWORD	-3,-6,-1,210,10,30,40,4
	sentinel	SWORD	0

.code
	main PROC

		mov	esi,offset array
		mov ecx,lengthof array

	L1:
		test	word ptr [esi],8000h	;测试符号位
		pushfd							;标志位入栈
		add		esi,type array			;移动到下一个位置
		popfd
		loopnz L1						;继续循环
		jnz		quit1					;没有发现正数
		sub		esi,TYPE array			;esi指向数值
		jmp		quit2					;结束并输出第一个正数
	quit1:
		ret
	quit2:
		movzx	eax,word ptr[esi]
		call	WriteInt
		call	WaitMsg


		invoke ExitProcess,0
	main ENDP
END main

19.Flowchart

; Flowchart Example              (Flowchart.asm)

; Implements the flowchart in Figure 6-2,
; Calculates the sum of all array elements larger than
; a given value (sample).

INCLUDE Irvine32.inc

.data
		sum DWORD 0
		sample DWORD 50

		array DWORD 10,60,20,33,72,89,45,65,72,18
		ArraySize = ($ - Array) / TYPE array

.code
		main PROC
			mov	eax,0					; sum
			mov	edx,sample
			mov	esi,0					; index
			mov	ecx,ArraySize

		L1:	cmp	esi,ecx
			jl	L2
			jmp	L5

		L2:	cmp	array[esi*4], edx
			jg	L3
			jmp	L4
		L3:	add	eax,array[esi*4]

		L4:	inc	esi
			jmp	L1

		L5:	mov	sum,eax

			call	Writeint
			call	Crlf

			exit
		main ENDP

END main

20.表驱动选择

;过程量偏移表		ProcTable.asm
;本程序包含了过程量偏移的表格
;它用这个表格执行间接过程调用

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	CaseTable			BYTE	'A'								;查询值
						DWORD	Process_A						;过程地址

	EntrySize			=		($-CaseTable)	
						BYTE	'B'		
						DWORD	Process_B
						BYTE	'C'
						DWORD	Process_C
						BYTE	'D'
						DWORD	Process_D

	NumberOfEntries		=		($-CaseTable)/EntrySize
	prompt				BYTE	"Press capital A B C or D:",0

	;为每一个过程定义独立的消息字符串
	msgA				BYTE	"Process_A",0
	msgB				BYTE	"Process_B",0
	msgC				BYTE	"Process_C",0
	msgD				BYTE	"Process_D",0


.code
	main PROC
		
		mov		edx,offset prompt			;请求用户输入
		call	WriteString
		call	ReadChar					;读取字符到AL
		mov		ebx,offset CaseTable		;设置EBX为表指针
		mov		ecx,NumberOfEntries			;循环计数器

	L1:
		cmp		al,[ebx]					;发现匹配项?
		jne		L2							;否,继续
		call	near PTR [ebx+1]			;是,调用过程  间接调用需要使用near ptr来指定函数的名字

		call	WriteString					;显示消息
		call	Crlf
		jmp		L3							;退出搜索
	L2:
		add		ebx,EntrySize				;指向下一个表项
		loop	L1							;重复查询直到ECX=0

	L3:
		call	WaitMsg
		exit

		invoke ExitProcess,0
	main ENDP

	;下面的每一个过程向edx加载不同的字符串偏移量
	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

21.有限状态机的应用 判断输入字符串是否为数字

;有限状态机		Finite.asm
include irvine32.inc

ENTER_KEY=13					;Enter键的ASCII码

.data
	InvalidInputMsg		BYTE	"Invalid input",13,10,0

.code
	main PROC
		call Clrscr

	StateA:
		call Getnext		;读取下一个字符,并送入AL
		cmp al,'+'			;前置+?
		je   StateB			;转移到状态B
		cmp al,'-'			;前置-?
		je   StateB			;转移到状态B
		call IsDigit		;如果AL包含数字,则ZF=1
		jz	StateC			;到状态C
		call DisplayErrorMsg;发现非法输入
		jmp Quit			;退出

	StateB:
		call Getnext		;读取下一个字符,并送入AL
		call IsDigit		;如果Al中包含数字,则ZF=1
		jz	StateC			;
		call DisplayErrorMsg;
		jmp Quit			;

	StateC:
		call Getnext		;读取下一个字符,并送入AL
		call IsDigit		;如果Al中包含数字,则ZF=1
		jz	StateC
		cmp al,ENTER_KEY	;按下enter键?
		je Quit				;是,退出
		call DisplayErrorMsg;否,发现非法输入
		jmp Quit			;
	Quit:
		call WaitMsg		;
		call Crlf			;
		exit				;
	main ENDP				;

	;--------------------------------------------------
	Getnext proc
	;
	;从标准输入中读入一个字符
	;接收:无
	;返回:字符保存在AL中
	;--------------------------------------------------
		call	ReadChar	;从键盘读入
		call	WriteChar	;显示在屏幕上
		ret					;
	Getnext ENDP


	;--------------------------------------------------
	DisplayErrorMsg PROC
	;
	;显示一个错误消息仪表示输入流中含有非法输入
	;接收:无
	;返回:无
	;--------------------------------------------------
	push edx
	mov edx,OFFSET InvalidInputMsg
	call WriteString
	pop edx
	ret
	DisplayErrorMsg ENDP
END main

22.SetCurPosition


include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
; Use the .IF and .ENDIF directives to perform
; run-time range checks on parameters passed to
; the SetCursorPosition procedure.
	main PROC

		mov	dl,79
		mov	dh,24
		call	SetCursorPosition

		call	WaitMsg
	main ENDP

	SetCursorPosition PROC
	;set the cursor position
	;receives:DL=X-coordinate,DH=Y-coordinate
	;checks the range of DL and DH
	.data
		BadXCoordMsg	BYTE	"X-Coordiante out of range!",0DH,0AH,0
		BadYCoordMsg	BYTE	"Y-Coordiante out of range!",0DH,0AH,0
	.code
		.IF(DL<0)||(DL>79)
			mov		edx,offset BadXCoordMsg
			call	WriteString
			jmp		quit
		.ENDIF

		.IF(DH<0)||(DH>24)
			mov		edx,offset BadYCoordMsg
			call	WriteString
			jmp		quit
		.ENDIF

		call		Gotoxy
	quit:
		ret
	SetCursorPosition ENDP

END main

23.大学生注册实例

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	TRUE=1
	FALSE=0
	gradeAverage	WORD	275	;要检查的数
	credits			WORD	12	;要检查的数
	OkToRegister	BYTE	0

.code
	main PROC
		
		;本程序监察一个学生是否有注册资格
		mov	OkToRegister,FALSE
		.IF gradeAverage > 350
			mov OkToRegister,TRUE
		.ELSEIF (gradeAverage > 250) && (credits <= 16)
			mov OkToRegister,TRUE
		.ELSEIF (credits <= 12)
			mov OkToRegister,TRUE
		.ENDIF

		movzx eax,OkToRegister
		call WriteInt
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

24.使用WHILE创建循环

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov eax,0
		.WHILE	eax<10
			inc		eax
			call	WriteDec
			call	Crlf
		.ENDW

		call	WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

25.使用REPEAT和UNTIL创建循环

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		mov	eax,0
		.REPEAT
			inc eax
			call WriteDec
			call Crlf
		.UNTIL eax == 10

		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

26.含有WHILE语句的循环

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	X		DWORD	0
	op1		DWORD	2
	op2		DWORD	4
	op3		DWORD	5


.code
	main PROC

		mov	eax,op1
		mov ebx,op2
		mov ecx,op3
		.WHILE eax<ebx
			inc eax
			.IF eax == ecx
				mov X,2
			.ELSE
				mov X,3
			.ENDIF
		.ENDW

		mov eax,X
		call WriteInt

		invoke ExitProcess,0
	main ENDP
END main

习题

6.10.01 (1~9)


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		;01
		mov		bx,0FFFFh
		and		bx,6Bh			;bx=

		;02
		mov		bx,91BAh
		and		bx,92h			;bx=

		;03
		mov		bx,0649Bh		
		or		bx,3Ah			;bx=

		;04
		mov		bx,029D6h
		xor		bx,8181h		;bx=


		;05
		mov		ebx,0AFAF649Bh
		or		ebx,3A219604h	;ebx=

		;06
		;mov		rbx,0AFAF6949Bh	
		;xor		rbx,0FFFFFFFFFh	;rbx=

		;07
		mov		al,01101111b	
		and		al,00101101b	;AL=
		mov		al,6Dh
		and		al,4Ah			;AL=
		mov		al,00001111b
		or		al,61h			;AL=
		mov		al,94h
		xor		al,37h			;AL=

		;08
		mov		al,7Ah
		not		al				;AL=
		mov		al,3Dh
		and		al,74h			;AL=
		mov		al,9Bh
		or		al,35h			;AL=
		mov		al,72h
		xor		al,0DCh			;AL=

		;09
		mov		al,00001111b
		test	al,00000010b	;CF=	ZF=		SF=
		mov		al,00000110b
		cmp		al,00000101b	;CF=	ZF=		SF=
		mov		al,00000101b
		cmp		al,00000111b	;CF=	ZF=		SF=

		invoke ExitProcess,0
	main ENDP
END main

6.10.02.01

include irvine32.inc
.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		mov al,10
		and al,11111111b
		movzx eax, al
		call WriteBin
		call WaitMsg
		invoke ExitProcess,0
	main ENDP
END main

6.10.02.02

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	oPrompt	BYTE	"ODD",0
	ePrompt	BYTE	"EVEN",0

.code
	main PROC
		
		mov eax,1
		and	eax,0001H

		.IF eax==0
			mov edx,offset ePrompt
		.ELSE
			mov edx,offset oPrompt
		.ENDIF
		call WriteString

		call	WaitMsg
		invoke ExitProcess,0
	main ENDP
END main

6.10.02.03

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	SetX DWORD 10000000000000000000000000000111b
	SetY DWORD 01101010101010101010111110000001b

.code
	main PROC
		
		mov eax,SetX
		mov ebx,SetY
		not ebx
		and eax,ebx
		call WriteBin
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main

6.10.02.04


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		mov dx,10
		mov cx,11
		cmp dx,cx
		jb L1

		L1:


		invoke ExitProcess,0
	main ENDP
END main

6.10.02.05


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov ax,+10
		mov cx,-10
		cmp ax,cx
		jg L2
			;do something here
		L2:
			

		invoke ExitProcess,0
	main ENDP
END main

6.10.02.06


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		and AL,11111100b
		.IF AL==0
			jmp L3
		.ELSE
			jmp L4
		.ENDIF

		L3:
			;do something
		L4:
			;do something
		invoke ExitProcess,0
	main ENDP
END main

6.10.02.07


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	DWORD	1
	X		DWORD	0

.code
	main PROC
		mov ecx,2
		mov edx,3

		.IF (val1>ecx) && (ecx>edx)
			mov X,1
		.ELSE
			mov X,2
		.ENDIF

		invoke ExitProcess,0
	main ENDP
	END main

6.10.02.08


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	DWORD	1
	X		DWORD	0

.code
	main PROC
		mov ecx,2
		mov ebx,3

		.IF (ebx>ecx) && (ebx>val1)
			mov X,1
		.ELSE
			mov X,2
		.ENDIF

		invoke ExitProcess,0
	main ENDP
END main

6.10.02.09


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	DWORD	1
	X		DWORD	0

.code
	main PROC
		mov ecx,2
		mov edx,3
		mov ebx,4

		.IF (ebx>ecx && ebx>edx) || (edx>eax)
			mov X,1
		.ELSE
			mov X,2
		.ENDIF

		invoke ExitProcess,0
	main ENDP
END main

6.10.02.10


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	A	DWORD 1
	B	DWORD 2

.code
	main PROC
		
		mov eax,10

		.WHILE eax>0
			.IF eax != 3 && (eax<A || eax>B)
				sub eax,3
			.ENDIF
		.ENDW
			

		invoke ExitProcess,0
	main ENDP
END main

6.11.2.01

; Exercise 1: Filling an Array

Comment !
Create a procedure that fills an array of doubleword with N random integers, making 
sure the values fall within the range j..k. When calling the procedure, pass a 
pointer to the array that will hold the data, pass N, and pass the values of j 
and k. Write a test program that calls the procedure twice, using different 
values for N, j, and k.
!

INCLUDE Irvine32.inc

.data
	intArray	sdword	50 DUP(?)
	count		DWORD	0

.code
	main PROC
		call Randomize
	
		mov  esi,OFFSET intArray 		; point to the array
		mov  ecx,LENGTHOF intArray 		; N
		mov	 ebx,10						; lower limit (j)
		mov  eax,20						; upper limit (k)
		call FillRandom

		mov  ebx,5
		mov  eax,50						; upper limit (k)
		call FillRandom
	
		exit
	main ENDP

	FillRandom proc
	; Input parameters:
	; ESI points to the array, ECX is the size
	; EBX = lower base, EAX = upper limit	
		pushad

		sub		eax,ebx			; calculate interval size
		inc		eax

	L1:	push	eax				; save the interval size
		call	RandomRange		; generates value (0 to EAX-1)
		add	    eax,ebx			; add it to the base
		mov		[esi],eax
		pop		eax
		add		esi,4
		loop	L1

		popad
		ret
	FillRandom endp

END main

6.11.2.02

; Exercise 2: Summing Array Elements in a Range

COMMENT !
    Create a procedure that returns the sum of all array elements falling 
    within the range j..k (inclusive) . Write a test program that calls 
    the procedure twice, passing a pointer to a signed doubleword array, the 
    size of the array, and the values of j and k. Return the sum in 
    the EAX register.
!

.386

.model flat,stdcall

.stack 4096

ExitProcess proto,dwExitCode:dword

.data
    lowerLimit  dword   20
    upperLimit  dword   40
    array_1     sdword  10,30,25,15,17,19,40,41,43       ; sum: 5Fh (95)
    count_1     =       LENGTHOF array_1
    array_2     sdword  10,-30,25,15,-17,55,40,41,43     ; sum: 41h (65)
    count_2     =       LENGTHOF array_2

.code
    main proc
	    mov     ebx,lowerLimit
	    mov     edx,upperLimit
	    mov     esi,OFFSET array_1
	    mov     ecx,count_1
	    call    CalcSumRange        ; returns sum in EAX
	    call    CalcSumRange        ; call second time to see if registers are preserved
    
	    mov     esi,OFFSET array_2
	    mov     ecx,count_2
	    call    CalcSumRange        ; returns sum in EAX
    
	    invoke  ExitProcess,0
    main endp

    CalcSumRange proc
    .data
        sum sdword ?
    .code
    ; Input parameters: 
    ;	[EBX,EDX] = inclusive range
    ;	ESI = points to the array
    ;	ECX = array size
    ; Returns: EAX = sum
        push esi
        push ecx
        mov  sum,0

    L1: mov  eax,[esi]    ; get next value
        cmp  eax,ebx      ; check lower limit
        jl   next
        cmp  eax,edx      ; check upper limit
        jg   next
        add  sum,eax      ; must be in range
    next:
        add  esi,4        ; move to next element
        loop L1           ; continue loop

        mov  eax,sum      ; return value in EAX
        pop  ecx
        pop  esi
	    ret
    CalcSumRange endp

end main

6.11.2.03

; Exercise 3: Test Score Evaluation

Comment !
	Create a procedure named CalcGrade that receives an integer value 
	between 0 and 100, and returns a single capital letter in the AL 
	register. Preserve all other register values between calls to the 
	procedure. The letter returned by the procedure should be according 
	to the following ranges:

	Score Range  Letter Grade
	-------------------------
	90 to 100        A
	80 to  89        B
	70 to  79        C
	60 to  69        D
	 0 to  59        F

	Write a test program that generates 10 random integers between 50 and 100, 
	inclusive. Each time an integer is generated, pass it to the CalcGrade 
	procedure.  You can test your program using a debugger, or if you prefer 
	to use the book's library, you can display each integer and its corresponding 
	letter grade.
!

include Irvine32.inc

.data
	str1	BYTE	": The letter grade is ",0
	grade	BYTE	?

.code
	main PROC
		call    Randomize

		mov     ecx,10             ; repeat loop 10 times
	again:
		push    ecx                ; save loop counter
		mov     eax,51
		call    RandomRange        ; value [0..50]
		add     eax,50             ; becomes [50..100]
		call    WriteDec           ; optional print statement

		call    CalcGrade          ; returns the grade in AL
		mov     grade,al

		; Print the grade (optional)

		mov	    edx,OFFSET str1	; ": The letter grade is "
		call	WriteString		
		mov     al,grade
		call	WriteChar			; display grade letter (AL)
		call	Crlf

		pop     ecx                 ; restore the loop counter
		loop    again

		exit
	main ENDP

	CalcGrade proc
	; Calculates a letter grade
	; Receives: EAX = numeric grade
	; Returns:  AL = letter grade

	Grade_A:
		cmp	eax,90
		jb	Grade_B
		mov	al,'A'
		jmp	finished

	Grade_B:
		cmp	eax,80
		jb	Grade_C
		mov	al,'B'
		jmp	finished
	
	Grade_C:
		cmp	eax,70
		jb	Grade_D
		mov	al,'C'
		jmp	finished

	Grade_D:
		cmp	eax,60
		jb	Grade_F
		mov	al,'D'
		jmp	finished

	Grade_F:
		mov	al,'F'

	finished:
		ret
	CalcGrade endp

END main

6.11.2.04

在这里插入代码片; Exercise 4: College Registration

Comment !
Using the College Registration example from
Section 6.7.2.2 as a starting point, do the following:
  Recode the logic using CMP and conditional jump
instructions (instead of the .IF and .ELSEIF directives).
 Perform range checking on the credits value; it cannot
be less than 1 or greater than 30. If an invalid entry
is discovered, display an appropriate error message.
!
include Irvine32.inc

TRUE		=		1
FALSE		=		0

.data
	gradeAverage  DWORD ?
	credits       DWORD ?
	OkToRegister  DWORD ?
	str1		BYTE	"Error: Credits must be between 1 and 30",0dh,0ah,0
	str2		BYTE	"Enter the grade average [0 - 400]: ",0
	str3		BYTE	"Enter the requested number of credits: ",0
	str4		BYTE	"The student can register",0dh,0ah,0
	str5		BYTE	"The student cannot register",0dh,0ah,0

.code
	main PROC

		call GetUserInput
		call CheckRegistration
		call ShowResults

		exit
	main ENDP

	;-----------------------------------------------
	GetUserInput PROC
	;-----------------------------------------------
		pushad

		; ask for the grade average

		mov	edx,OFFSET str2
		call	WriteString
		call	Crlf
		call	ReadInt
		mov	gradeAverage,eax
	
		; ask for the number of credits

		mov	edx,OFFSET str3
		call	WriteString
		call	Crlf
		call	ReadInt
		mov	credits,eax
	
		popad
		ret
	GetUserInput ENDP

;-----------------------------------------------
	ShowResults PROC
	;-----------------------------------------------
		pushad

		cmp   OkToRegister,TRUE
		jne   L2

	L1:	mov   edx,offset str4		; can register
		call  WriteString
		jmp   L3

	L2:	mov   edx,offset str5		; cannot register
		call  WriteString

	L3:	popad
		ret
	ShowResults ENDP

	;-----------------------------------------------
	CheckRegistration PROC
	;
	; Evaluates the gradeAverage and number of
	; credits, and sets the value of OkToRegister.
	; Displays an error message if credits are
	; not in the range 1-30.
	; Receives: nothing
	; Returns: sets boolean value of OkToRegister
	;-----------------------------------------------
		push	edx
		mov	OkToRegister,FALSE

	; Check credits for valid range 1-30
		cmp	credits,1				; credits < 1?
		jb	E1
		cmp	credits,30			; credits > 30?
		ja	E1
		jmp	L1					; credits are ok

	; Display error message: credits out of range
	E1:	mov	edx,OFFSET str1
		call	WriteString
		jmp	L4

	; Evaluate gradeAverage and credits, using the logic
	; found in Section 6.7.2.2
	L1:	cmp gradeAverage,350		; if gradeAverage > 350
		jna	L2
		mov	OkToRegister,TRUE		; OkToRegister = TRUE
		jmp	L4

	L2:	cmp gradeAverage,250		; elseif gradeAverage > 250
		jna	L3
		cmp	credits,16			;   && credits <= 16
		jnbe	L3
		mov	OkToRegister,TRUE		; OKToRegister = TRUE
		jmp	L4

	L3:	cmp credits,12				; elseif credits <= 12
		ja	L4
		mov	OkToRegister,TRUE		; OKToRegister = TRUE

	L4:	pop	edx					; endif
		ret
	CheckRegistration ENDP

END main

6.11.2.05

; Exercise 5: Boolean Calculator, Part 1

Comment !
Description: Create a program that functions as a
simple boolean calculator for 32-bit integers. It
should display a menu that asks the user to make a
selection from the following list:

1. x AND y
2. x OR y
3. NOT x
4. x XOR y
5. Exit program

When the user makes a choice, call a procedure that displays the name of the 
operation about to be performed. You must implement this procedure using the 
Table-Driven Selection technique, shown in Section 6.5.4. (We will implement 
the operations in the exercise following this one.)
!

include Irvine32.inc

.data
	msgMenu BYTE "---- Boolean Calculator ----",0dh,0ah
		BYTE 0dh,0ah
		BYTE "1. x AND y"     ,0dh,0ah
		BYTE "2. x OR y"      ,0dh,0ah
		BYTE "3. NOT x"       ,0dh,0ah
		BYTE "4. x XOR y"     ,0dh,0ah
		BYTE "5. Exit program",0

	msgAND BYTE "Boolean AND",0
	msgOR  BYTE "Boolean OR",0
	msgNOT BYTE "Boolean NOT",0
	msgXOR BYTE "Boolean XOR",0

	caseTable BYTE '1'				; lookup value
		DWORD AND_op				; addres of procedure
	EntrySize = ($ - caseTable )
		BYTE '2'
		DWORD OR_op
		BYTE '3'
		DWORD NOT_op
		BYTE '4'
		DWORD XOR_op
		BYTE '5'
		DWORD ExitProgram
	NumberOfEntries = ($ - caseTable) / EntrySize

.code
	main PROC
		call Clrscr

	Menu:
		mov	    edx, OFFSET msgMenu			; menu choices
		call	WriteString
		call	Crlf

	L1:	call	ReadChar
		cmp	    al,'5'						; is selection valid (1-5)?
		ja	    L1							; if above 5, go back
		cmp	    al,'1'
		jb	    L1							; if below 1, go back

		call	ChooseProcedure
		jc	    quit						; exit if CF=1

		call	Crlf
		call	WriteString					; display message
		call	Crlf
		call	Crlf

		jmp	Menu							; display menu again

	quit: exit

	main ENDP

	;------------------------------------------------
	ChooseProcedure PROC
	;
	; Selects a procedure from the caseTable
	; Receives: AL = number of procedure
	; Returns: nothing
	;-----------------------------------------------
		push ebx
		push ecx

		mov	ebx, OFFSET caseTable		; pointer to the table
		mov	ecx, NumberOfEntries		; loop counter

	L1:	cmp	al,[ebx]					; match found?
		jne	L2						    ; no: continue
		call NEAR PTR [ebx + 1]			; yes: call the procedure
		jmp	L3

	L2:	add ebx, EntrySize				; point to the next entry
		loop L1						    ; repeat until ECX = 0

	L3:	pop ecx
		pop ebx

		ret
	ChooseProcedure ENDP

	;------------------------------------------------
	AND_op PROC
	;
	; Receives: Nothing
	; Returns: EDX = offset of message
	;------------------------------------------------
		mov edx, OFFSET msgAND			; message to display

		ret

	AND_op ENDP

	;------------------------------------------------
	OR_op PROC
	;
	; Receives: Nothing
	; Returns: EDX = offset of message
	;------------------------------------------------
		mov edx, OFFSET msgOR			; message to display

		ret

	OR_op ENDP

	;------------------------------------------------
	NOT_op PROC
	;
	; Receives: Nothing
	; Returns: EDX = offset of message
	;------------------------------------------------
		mov edx, OFFSET msgNOT			; message to display

		ret

	NOT_op ENDP

	;------------------------------------------------
	XOR_op PROC
	;
	; Receives: Nothing
	; Returns: EDX = offset of message
	;------------------------------------------------

		mov edx, OFFSET msgXOR			; message to display

		ret

	XOR_op ENDP

	;------------------------------------------------
	ExitProgram PROC
	;
	; Receives: Nothing
	; Sets CF = 1 to signal end of program
	;------------------------------------------------

		stc							; CF = 1

		ret

	ExitProgram ENDP

END main

6.11.2.06

; Exercise 6: Boolean Calculator, Part 2

Comment !
Description: Continue the solution program from the preceding
exercise by implementing the following procedures:
  AND_op: Prompt the user for two hexadecimal integers. AND them
  together and display the result in hexadecimal.
  OR_op: Prompt the user for two hexadecimal integers. OR them
  together and display the result in hexadecimal.
  NOT_op: Prompt the user for a hexadecimal integer. NOT the
  integer and display the result in hexadecimal.
  XOR_op: Prompt the user for two hexadecimal integers. Exclusive-OR
  them together and display the result in hexadecimal.
!

include Irvine32.inc

.data
	msgMenu BYTE "---- Boolean Calculator ----------",0dh,0ah
		BYTE 0dh,0ah
		BYTE "1. x AND y"     ,0dh,0ah
		BYTE "2. x OR y"      ,0dh,0ah
		BYTE "3. NOT x"       ,0dh,0ah
		BYTE "4. x XOR y"     ,0dh,0ah
		BYTE "5. Exit program",0dh,0ah,0dh,0ah
		BYTE "Enter integer> ",0

	msgAND BYTE "Boolean AND",0
	msgOR  BYTE "Boolean OR",0
	msgNOT BYTE "Boolean NOT",0
	msgXOR BYTE "Boolean XOR",0

	msgOperand1 BYTE "Input the first 32-bit hexadecimal operand:  ",0
	msgOperand2 BYTE "Input the second 32-bit hexadecimal operand: ",0
	msgResult   BYTE "The 32-bit hexadecimal result is:            ",0

	caseTable BYTE '1'				; lookup value
		DWORD AND_op				; address of procedure
	EntrySize = ($ - caseTable )
		BYTE '2'
		DWORD OR_op
		BYTE '3'
		DWORD NOT_op
		BYTE '4'
		DWORD XOR_op
		BYTE '5'
		DWORD ExitProgram
	NumberOfEntries = ($ - caseTable) / EntrySize

.code
	main PROC
		call Clrscr

	Menu:
		mov	edx, OFFSET msgMenu		; menu choices
		call WriteString

	L1:	call ReadChar
		cmp  al,'5'				; is selection valid (1-5)?
		ja   L1					; if above 5, go back
		cmp  al,'1'
		jb   L1					; if below 1, go back

		call Crlf
		call ChooseProcedure
		jc   quit					; if CF = 1 exit

		call Crlf
		jmp  Menu					; display menu again

	quit:
		exit
	main ENDP

	;------------------------------------------------
	ChooseProcedure PROC
	;
	; Selects a procedure from the caseTable
	; Receives: AL = number of procedure
	; Returns: nothing
	;------------------------------------------------
		push ebx
		push ecx

		mov  ebx,OFFSET caseTable		; pointer to the table
		mov  ecx,NumberOfEntries			; loop counter

	L1:	cmp  al,[ebx]					; match found?
		jne  L2						; no: continue
		call NEAR PTR [ebx + 1]			; yes: call the procedure
		jmp  L3

	L2:	add  ebx,EntrySize				; point to the next entry
		loop L1						; repeat until ECX = 0

	L3:	pop  ecx
		pop  ebx

		ret
	ChooseProcedure ENDP

	;------------------------------------------------
	AND_op PROC
	;
	; Performs a boolean AND operation
	; Receives: Nothing
	; Returns: Nothing
	;------------------------------------------------
		pushad						; save registers

		mov	edx, OFFSET msgAND			; name of the operation
		call WriteString				; display message
		call Crlf
		call Crlf

		mov  edx, OFFSET msgOperand1		; ask for first operand
		call WriteString
		call ReadHex					; get hexadecimal integer
		mov  ebx, eax					; move first operand to EBX

		mov  edx, OFFSET msgOperand2		; ask for second operand
		call WriteString
		call ReadHex					; EAX = second operand

		and  eax, ebx					; operand1 AND operand2

		mov  edx, OFFSET msgResult		; result of operation
		call WriteString
		call WriteHex					; EAX = result
		call Crlf

		popad						; restore registers
		ret
	AND_op ENDP


	;------------------------------------------------
	OR_op PROC
	;
	; Performs a boolean OR operation
	; Receives: Nothing
	; Returns: Nothing
	;------------------------------------------------
		pushad						; save registers

		mov  edx, OFFSET msgOR			; name of the operation
		call WriteString				; display message
		call Crlf
		call Crlf

		mov  edx, OFFSET msgOperand1		; ask for first operand
		call WriteString
		call ReadHex					; get hexadecimal integer
		mov  ebx, eax					; move first operand to EBX

		mov  edx, OFFSET msgOperand2		; ask for second operand
		call WriteString
		call ReadHex					; EAX = second operand

		or   eax, ebx					; operand1 OR operand2

		mov  edx, OFFSET msgResult		; result of operation
		call WriteString
		call WriteHex					; EAX = result
		call Crlf		

		popad						; restore registers
		ret
	OR_op ENDP

	;------------------------------------------------
	NOT_op PROC
	;
	; Performs a boolean NOT operation.
	; Receives: Nothing
	; Returns: Nothing
	;------------------------------------------------
		pushad						; save registers

		mov  edx,OFFSET msgNOT			; name of the operation
		call WriteString				; display message
		call Crlf
		call Crlf

		mov  edx,OFFSET msgOperand1		; ask for operand
		call WriteString
		call ReadHex					; EAX = operand

		not  eax						; NOT operand

		mov  edx,OFFSET msgResult		; result of operation
		call WriteString
		call WriteHex					; EAX = result
		call Crlf

		popad						; restore registers
		ret
	NOT_op ENDP



	;------------------------------------------------
	XOR_op PROC
	;
	; Performs an Exclusive-OR operation
	; Receives: Nothing
	; Returns: Nothing
	;------------------------------------------------
		pushad						; save registers

		mov  edx,OFFSET msgXOR			; name of the operation
		call WriteString				; display message
		call Crlf
		call Crlf

		mov  edx, OFFSET msgOperand1		; ask for first operand
		call WriteString
		call ReadHex					; get hexadecimal integer
		mov  ebx, eax					; move first operand to EBX

		mov  edx,OFFSET msgOperand2		; ask for second operand
		call WriteString
		call ReadHex					; EAX = second operand

		xor  eax,ebx					; operand1 XOR operand2

		mov  edx, OFFSET msgResult		; result of operation
		call WriteString
		call WriteHex					; EAX = result
		call Crlf

		popad						; restore registers
		ret
	XOR_op ENDP

	;------------------------------------------------
	ExitProgram PROC
	;
	; Receives: Nothing
	; Returns: Sets CF = 1 to signal end of program
	;------------------------------------------------
		stc							; CF = 1
		ret
	ExitProgram ENDP

END main

6.11.2.07

; Exercise 7: Probabilities and Colors

Comment !
Write a program that randomly chooses between three
different colors for displaying text on the screen. Use a loop to
display twenty lines of text, each with a randomly chosen color.
The probabilities for each color are to be as follows: white = 30%,
blue = 10%, green = 60%. Hint: generate a random integer between
0 and 9. If the resulting integer is in the range 0-2, choose white.
If the integer equals 3, choose blue. If the integer is in the
range 4-9, choose green.
!

include Irvine32.inc

.data
	msg BYTE "Line of text with randomly chosen color",0

.code
	main PROC

		call ClrScr
		call Randomize				; seed the random number generator

		mov	edx, OFFSET msg		    ; line of text
		mov	ecx, 20				    ; counter (lines of text)

	L1:	call ChooseColor
		call SetTextColor
		call WriteString			; display line of text
		call Crlf
		loop L1

		exit

	main ENDP

	;------------------------------------------------
	ChooseColor PROC
	;
	; Selects a color with the following probabilities:
	; white = 30%, blue = 10%, green = 60%.
	; Receives: nothing
	; Returns: EAX = selected color
	;-----------------------------------------------

		mov	eax, 10		; generate random (0-9)
		call RandomRange	; EAX = random value
	
	L_Green:				; if N = 4-9, choose green
		cmp	eax,4
		jb	L_Blue
		mov	eax,green
		jmp	L_Finished

	L_Blue:				    ; if N = 3, choose blue
		cmp	eax,3
		jne	L_White
		mov	eax,blue
		jmp	L_Finished
	
	L_White:				; if N = 0-2, choose white
		mov	eax,white	

	L_Finished:
		ret

	ChooseColor ENDP

END main

6.11.2.08

; Exercise 8: Message Encryption

Comment !
This program demonstrates simple symmetric encryption using 
the XOR instruction.Let the user enter a multi-byte key. Use 
this key to encrypt and decrypt the plaintext.
!

include Irvine32.inc
	BUFMAX	= 128     	; maximum buffer size
	KEYMAX	= 128     	; maximum key size

.data
	prompt1  BYTE  "Enter the plain text: ",0
	prompt2  BYTE  "Enter the encryption key: ",0

	sEncrypt BYTE  "Cipher text:         ",0
	sDecrypt BYTE  "Decrypted:           ",0

	keyStr   BYTE   KEYMAX+1 DUP(0)
	keySize  DWORD  ?
	buffer   BYTE   BUFMAX+1 DUP(0)
	bufSize  DWORD  ?

.code
	main PROC
		call	InputPlaintext			; input the plain text
		call	InputKey				; input the key
		call	TranslateBuffer			; encrypt the buffer
		mov	    edx,OFFSET sEncrypt		; display encrypted message
		call	DisplayMessage
		call	TranslateBuffer  		; decrypt the buffer
		mov	    edx,OFFSET sDecrypt		; display decrypted message
		call	DisplayMessage

		exit
	main ENDP

	;-----------------------------------------------------
	InputPlaintext PROC
	;
	; Asks the user to enter a string from the
	; keyboard. Saves the string and its length
	; in variables.
	; Receives: nothing
	; Returns: nothing
	;-----------------------------------------------------
		pushad
		mov	    edx,OFFSET prompt1			; display a prompt
		call	WriteString
		mov	    ecx,BUFMAX				    ; maximum character count
		mov	    edx,OFFSET buffer   		; point to the buffer
		call	ReadString         			; input the string
		mov	    bufSize,eax        			; save the length
		call	Crlf
		popad
		ret
	InputPlaintext ENDP

	;-----------------------------------------------------
	InputKey PROC
	;
	; Asks the user to enter a string that will be used as 
	; the encryption key. 
	; Receives: nothing
	; Returns: nothing
	;-----------------------------------------------------
		pushad
		mov	    edx,OFFSET prompt2			; display a prompt
		call	WriteString
		mov	    ecx,KEYMAX				    ; maximum character count
		mov	    edx,OFFSET keyStr   		; point to the buffer
		call	ReadString         			; input the string
		mov	    keySize,eax        			; save the length
		call	Crlf
		popad
		ret
	InputKey ENDP

	;-----------------------------------------------------
	DisplayMessage PROC
	;
	; Displays the encrypted or decrypted message.
	; Receives: EDX points to the message
	; Returns:  nothing
	;-----------------------------------------------------
		pushad
		call	WriteString
		mov	    edx,OFFSET buffer		; display the buffer
		call	WriteString
		call	Crlf
		call	Crlf
		popad
		ret
	DisplayMessage ENDP

	;-----------------------------------------------------
	TranslateBuffer PROC
	;
	; Translates the string by exclusive-ORing each buffer
	; byte with a coresponding byte in the encryption key.
	; Receives: nothing
	; Returns: nothing
	;-----------------------------------------------------
		pushad
		mov	ecx,bufSize		; loop counter
		mov	esi,0			; index 0 in the buffer
		mov	edi,0			; index 0 in the key
		
	L1:	mov	al,keyStr[edi]	; get key byte
		xor	buffer[esi],al	; translate a byte
		inc	esi				; point to next byte in buffer
		inc	edi				; point to next key byte
		cmp	edi,keySize		; key index <= key size?
		jb	L2				; yes, skip to LOOP instruction
		mov	edi,0			; no: reset key index to 0
	L2:	loop L1				; repeat the loop

		popad
		ret
	TranslateBuffer ENDP
END main

6.11.2.09

; Exercise 9: PIN Validation

COMMENT !
	Your task is to create a procedure named Validate_PIN that receives a pointer to an 
	array of byte containing a 5-digit PIN. Declare two arrays to hold the minimum and
	maximum range values, and use these arrays to validate each digit of the PIN that 
	was passed to the procedure. If any digit is found to be outside its valid range, 
	immediatey return the digit's position (between 1 and 5) in the EAX register. If 
	the entire PIN is valid, return 0 in EAX. Preserve all other register values between
	calls to the procedure. Write a test program that calls Validate_PIN at least four 
	times, using both valid and invalid byte arrays. By running the program in a debugger, 
	verify that the return value in EAX after each procedure call is valid. Or, if you 
	prefer to use the book's library, you can display "Valid" or "Invalid" on the console 
	after each procedure call. Use this table to validate the ranges:

	Digit 
	Number	Range
	1	    5 to 9
	2	    2 to 5
	3	    4 to 8
	4	    1 to 4
	5	    3 to 6
!

.386

.model flat,stdcall

.stack 4096

ExitProcess proto,dwExitCode:dword

.data
	VALID_PIN	=		0
	PIN_SIZE	=		5
	minVals		byte	5,2,4,1,3			; globally visible
	maxVals		byte	9,5,8,4,6			; globally visible
	samplePin_1 byte	6,3,4,4,3			; valid PIN
	samplePin_2 byte	5,2,3,2,4			; digit 3 is invalid
	samplePin_3 byte	5,2,4,5,3			; digit 4 is invalid
	samplePin_4 byte	1,3,4,4,3			; digit 1 is invalid

.code
	main proc

		mov  esi,OFFSET samplePin_1
		call Validate_PIN			; EAX = VALID_PIN

		mov  esi,OFFSET samplePin_2
		call Validate_PIN			; EAX = 3

		mov  esi,OFFSET samplePin_3
		call Validate_PIN			; EAX = 4

		mov  esi,OFFSET samplePin_4
		call Validate_PIN			; EAX = 1

		invoke ExitProcess,0
	main endp

	Validate_PIN proc
		mov  edi,0
		mov  ecx,PIN_SIZE

	L1:	mov  al,[esi]
		cmp  al,minVals[edi]
		jb   error
		cmp  al,maxVals[edi]
		ja   error
		inc	 edi
		inc  esi
		loop L1
		mov  eax,VALID_PIN	
		ret

	error:
		mov eax,edi			; return position # of the bad digit
		inc eax
		ret
	Validate_PIN endp


end main

6.11.2.10

; Exercise 10: Parity Checking

COMMENT !
Data transmission systems and file subsystems often use a form of error detection 
that relies on calculating the parity (even or odd) of blocks of data. Your task 
is to create a procedure that returns True in the EAX register if the bytes in 
an array contain even parity, or False if the parity is odd. In other words, if 
you count all the bits in the entire array, their count will be even or odd. 
Preserve all other register values between calls to the procedure. Write a test 
program that calls your procedure twice, each time passing it a pointer to an 
array and the length of the array. The procedure's return value in EAX should 
be 1 (True) or 0 (False). For test data, create two arrays containing at least 
10 bytes, one having even parity, and another having odd parity. 
!

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword

True = 1
False = 0

.data
	array_1 byte 41h,53h,82h,63h,41h,53h,82h,63h,81h,11h     ; even parity
	array_1_size = $ - array_1

	array_2 byte 41h,83h,03h,93h,41h,84h,03h,93h,81h,11h    ; odd parity (83h)
	array_2_size = $ - array_2
.code
	main proc

		mov  ecx,array_1_size
		mov  esi,OFFSET array_1
		call CheckEvenParity			; returns EAX = True
		
		mov  ecx,array_2_size
		mov  esi,OFFSET array_2
		call CheckEvenParity			; returns EAX = False

		invoke ExitProcess,0
	main endp

	CheckEvenParity proc
	
		mov al,[esi]	; first character
		xor	al,al		; affects the Parity flag
		pushf			; push the flags
		inc esi			; affects PF
		dec ecx
		popf

	L1:	xor al,[esi]	; affects the Parity flag
		pushf
		inc	esi
		popf
		loop L1			; does not affect PF

		jp	return_true
		mov	eax,False		; return False
		ret

	return_true:
		mov	eax,True
		ret
	CheckEvenParity endp

end main
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值