8086汇编:猜数游戏

代码以及详细注释:

;=================================================================
;						猜数游戏
;=================================================================
;本程序采用数字比较的方式来实现,区别于使用字符串比较的猜数程序
;实现5位数字的比较,事实上,可以支持小于655350的正整数比较
;=================================================================
.model small
.stack
.data
		mod_sel_str 	db		'Please select the seed generating mod(1/2): ', 0dh, 0ah, ''
						db		'(1) Auto random seed', 0dh, 0ah, ''
						db		'(2) Input seed', 0dh, 0ah, '$'
		wrong_input_str	db		'Input wrong! Please input again: ', '$'
		string 			db		'Please input a number(0-99999): ', '$'	
		big_str			db		'It is bigger!', 0dh, 0ah, '$'	
		small_str 		db		'It is smaller!', 0dh, 0ah, '$'		
		correct_str		db		'Correct, congratulations! The num is: ', '$'
		num_str			db		'The rand num is: ', '$'
		press_str		db		'Press any key to continue....', 0dh, 0ah, '$'	
		try_again		db		'Do you want to try again?(y/n)', 0dh, 0ah, '$'	
		seed_in_str		db		'Please input an initial num to guess: ', 0dh, 0ah, '$'	
		times_str1		db		'You have tried ', '$'
		times_str2		db		' times.', 0dh, 0ah, '$'	
		exit_str		db		0dh, 0ah, 'Bye~                  ', '$'	
		buf 			db		8	dup(?)
		cnt				dw		?
		num				dd		?
		tmp				dw		?
.code
start:
;=================================================================
;						入口函数
;=================================================================
main proc
		mov 	ax, @data
		mov 	ds, ax

		mov		ah, 9
		lea		dx, mod_sel_str
		int		21h
select_mod:								;选择随机数产生方式
		mov		ah, 1
		int 	21h
		call 	print_crlf
		cmp		al, '1'
		je		sel_time_seed
		cmp		al, '2'
		je		sel_input_seed

		mov		ah, 9
		lea		dx, wrong_input_str		;输入错误,重新输入
		int		21h
		jmp		select_mod
sel_time_seed:
		call	time_seed				;使用时间种子
		jmp		sel_end
sel_input_seed:
		call    input_seed				;手动输入种子
sel_end:
		;将初始生成的随机种子存到num中:dx(16bit),ax(16bit) -> num(32bit)
		mov		word ptr num[0], dx
		mov		word ptr num[2], ax
again:
		call 	guess
		call 	rand			;利用种子(num)产生随机数
		mov		ah, 9
		lea		dx, try_again
		int		21h
		
		mov		ah, 1
		int 	21h
		call 	print_crlf
		cmp		al, 'y'
		mov		ax, word ptr num[2]
		je		again

exit:	
		mov		ah, 9			;输出结束
		lea		dx, exit_str
		int		21h
		mov 	ah, 4ch			;程序返回
		int 	21h

main endp
;=================================================================

;=================================================================
;					封装输入函数,接收一串无符号数字
;=================================================================
input proc 				
		push 	ax
		push 	si
		push	bx
		
		mov		bl, '0'
		xor		si, si
		mov 	ah, 01h
in1:
check_input1:
		int 	21h			
		cmp		al, 27		;用户键入ESC,退出
		jne		check_input2
		call	back
		jmp		exit
check_input2:
		cmp		al, 0dh
		je		end_input	;接收到换行,结束

check_input3:
		cmp		al, 08H
		jne		valid_input
		or		si, 0
		je		valid_input
		dec		si
		call 	delete
		jmp		in1
valid_input:
		cmp		al, '0'		;只接受'0'-'9'
		jae		valid_input1
		call	back
		jmp		in1
valid_input1:
		cmp		al, '9'
		jbe		check_zero
		call	back
		jmp		in1

;==================================================================================
;                            处理开头是0的情况
;==================================================================================
check_zero:					;已经读取到一个0,又输入一个0,则只保留一个0
		cmp		si, 1		;读到一个字符
		jne		in2
		cmp		buf[0], bl	;且该字符是'0'
		jne		in2
		cmp		al, bl		;输入的也是'0'
		jne		check_zero2
		call	back		
		jmp		in1			;那么直接跳回,重新输入
check_zero2:				;如果输入的不是0,则为大于零的数,去掉第一位的0
		call	back
		call	back
		dec		si			;指针前移,覆盖第一位的0

		push	ax
		push	dx
		mov		ah, 02h
		mov		dl, al
		int		21h			;输出去除0后的数

		pop		dx
		pop		ax
;==================================================================================
in2:
		cmp		si, 5		;最多输入5个字符
		jne		store_asci
		call	back
		jmp		in1
store_asci:
		mov 	buf[si], al
		inc 	si			;输入字符数加1
		jmp		in1
end_input:
		or		si, 0		;只接收到换行
		je		in1			;重新输入
		mov 	cnt, si		;字符个数存cnt
		
		pop		bx
		pop		si
		pop		ax
		ret
input endp
;=================================================================

;=================================================================
;					封装输出函数,打印buf中的数字
;=================================================================
output proc 		 		
		push	cx
		push	si
		push	ax
		push	dx
		
		mov 	cx, cnt
		xor 	si, si
		mov 	ah, 02h
out1:	
		mov 	dl, buf[si]
		inc		si
		int 	21h
		loop 	out1
		
		pop		dx
		pop		ax
		pop		si
		pop		cx	
		ret
output endp
;=================================================================

;=================================================================
;			平方取中法(产生小于100000的随机数,存于num)
;=================================================================
rand proc 			
		push	ax
		push	bx
begin_rand:
		mul 	ax		
		
		mov 	al, ah
		mov 	ah, dl 
		cmp		ax, 0
		jne		rand_next
		call 	time_seed
		jmp		begin_rand
rand_next:
		xor		dl, dl
		and		dh, 1
		jz		over_rand
		mov		bx, 34464
		div		bx
		mov		ax, dx
		mov		dx, 1
		
over_rand:	
		mov		word ptr num[2], ax
		mov		word ptr num[0], dx
		
		pop		bx
		pop		ax
		ret
rand endp
;=================================================================

;=================================================================
;			打印num中存储的32位数字(0 - 2^32-1)
;=================================================================
printNum proc 			
		push	ax
		push	bx
		push	cx
		push	dx
		
begin_print:
		xor		bx, bx
		xor 	cx, cx
		mov		bx, 10
		mov 	ax, word ptr num[2]
		mov		dx, word ptr num[0]
one:
		div		bx
		
		push	dx		;存储余数
		inc		cx		;位数加一
		
		xor		dx, dx
		cmp		ax, 0
		jne		one
		
		mov 	ah, 02h
two:
		pop		dx
		add		dx, 30h
		int 	21h
		loop	two
		
		pop		dx
		pop		cx
		pop		bx
		pop		ax

		ret
printNum endp
;=================================================================

;=================================================================
;							输出换行
;=================================================================
print_crlf proc
		push 	ax
		push	bx
		push	dx
		
		mov 	ah, 02h
		mov		dx, 0dh
		int 	21h
		mov		dx, 0ah
		int 	21h
		
		pop		dx
		pop		bx
		pop		ax
		ret
print_crlf endp
;=================================================================

;=================================================================
;					把buf中的字符转为数字存到dx, ax
;=================================================================
readNum proc				
		push	bx
		push	cx
		push	si
		push	di
		
		mov		cx, cnt
		xor		bx, bx
		xor		ax, ax
		xor		si, si
		xor		dx, dx
		mov		tmp, bx
		mov		di, 10
read_next:
		mov		al, buf[bx]	;从buf中读取一位数字,从高向低读
		sub		al, 30h
		xor		ah, ah
		inc		bx
		
		push	cx			;各位数乘以相应的10的次幂
		dec		cx			;乘10的次数是当前cx的计数值减1
		cmp		cx, 0
		jle		skip_mul_10
mul_10:
		mul		di			;结果不会超过16位
		loop	mul_10
skip_mul_10:
		pop		cx
		add		si, ax
		jnc		if_c
		inc		dx
if_c:		
		cmp		dx, 0
		je		start_loop
		mov		tmp, dx
start_loop:		
		loop	read_next
		
		mov		ax, si
		mov		dx, tmp
		pop		di
		pop		si
		pop		cx
		pop		bx
		ret
readNum endp
;=================================================================

;=================================================================
;						猜数函数主体
;=================================================================
guess proc
		push	ax
		push	dx
		push	bx

		xor		bx, bx
		mov		ah, 9
		lea		dx, num_str
		int 	21h

		call 	printNum
		call 	print_crlf
		
		mov		ah, 9
		lea		dx, press_str
		int		21h
		
		mov		ah, 1
		int		21h
		call	cls
		
start_guess:
		mov		ah, 9
		lea		dx, string
		int		21h

		call 	input
		call	readNum
		
		cmp		dx, word ptr num[0]		
		jb		smaller
		ja		bigger
		cmp		ax, word ptr num[2]
		jb		smaller
		ja		bigger
		je		correct
bigger:
		mov		ah, 9
		lea		dx, big_str
		int		21h
		inc		bx
		jmp		start_guess
smaller:
		mov		ah, 9
		lea		dx, small_str
		int		21h
		inc		bx
		jmp		start_guess
correct:
		mov		ah, 9
		lea		dx, correct_str
		int		21h
		inc		bx
		call 	printNum
		call 	print_crlf
		
		;=====================================
		;           输出总尝试次数
		;=====================================
		push	word ptr num[0]			
		push	word ptr num[2]
		
		mov		word ptr num[2], bx
		xor		bx, bx
		mov		word ptr num[0], bx
		
		lea		dx, times_str1
		int		21h
		call	printNum		;输出num中的数字
		;=====================================

		pop		word ptr num[2]
		pop		word ptr num[0]
		
		lea		dx, times_str2
		int		21h
		
		pop		bx
		pop		dx
		pop		ax
		ret
guess endp
;=================================================================

;=================================================================
;							清屏
;=================================================================
cls	proc
		mov 	ah, 15
		int 	10h
		mov 	ah, 0
		int 	10h
		ret
cls endp
;=================================================================

;=================================================================
;				获取系统时间产生种子放在dx, ax
;=================================================================
time_seed proc		
		push	cx
		;push	dx
		
		mov		ah, 02h		;ch→hours cl→minutes dh→seconds,均为BCD码格式
		int		1Ah

		mov		dl, dh
		add		cx, dx
		mov		ax, cx
		
		;=================================================
		;		调整dx,ax使之不超过100000即0001_86A0H	   
		;=================================================
		cmp 	dx, 01h		;如果dx>=1,则需要把dx设为1,而且对ax求模86A1H
		jb		time_end
		mov		cx, 086A1H
		div		cx
		mov		ax, dx
		mov		dx, 01h
		;=================================================
time_end:
		;pop		dx
		pop		cx
		ret
time_seed endp
;=================================================================

;=================================================================
;						手动输入随机数种子
;=================================================================
input_seed proc			
		mov		ah, 9
		lea		dx, seed_in_str
		int		21h
		call 	input
		; call    output
		call 	readNum
		ret
input_seed endp
;=================================================================

;=================================================================
;								退格
;=================================================================
;具体操作是先光标左移,再输出空格,再光标左移
back proc
		push	ax
		push	bx
		push	cx
		push	dx
		
		mov		ah, 03h		;读取光标位置
		int		10h
		
		dec		dl			;左移光标
		push	dx
		mov		ah, 02h		
		int		10h
		
		mov		dl, ' '		;输出空格
		int		21h
		
		pop		dx
		int		10h			;左移光标
		
		pop		dx
		pop		cx
		pop		bx
		pop		ax
		ret
back endp
;=================================================================

;=================================================================
;							删除
;=================================================================
;具体操作是先输出空格,再光标左移
delete proc
		push	ax
		push	bx
		push	cx
		push	dx

		mov		ah, 02h
		mov		dl, ' '		;输出空格
		int		21h
		
		mov		ah, 03h		;读取光标位置->dl
		int		10h

		mov		ah, 02h		;左移光标
		dec		dl
		int		10h			
		
		pop		dx
		pop		cx
		pop		bx
		pop		ax
		ret
delete endp
;=================================================================

		end start
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CCF小彤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值