南京郵電大學組合——實驗二:使用者登陸驗證程式的設計

2020-10-23 12:00:34

南京郵電大學組合——實驗二:使用者登陸驗證程式的設計

兩個題目

  1. 從BUF單元開始存有一字串(長度<255),程式設計實現統計該字串中的ASCII在42H~45H之間的字元個數,並將統計結果以二進位制形式顯示在螢幕。
  2. 程式執行後,給出提示操作,請使用者鍵入使用者名稱和密碼;使用者在鍵入密碼時,程式不回顯鍵入字元;只有當使用者鍵入的使用者名稱,密碼字串和程式內定的字串相同時,顯示歡迎介面並返回DOS;否則給出提示資訊,使用者名稱或密碼錯誤,再次輸入。介面顏色自定(彩色或黑白)

原始碼

本來是想用rdrand指令來寫一段亂數生成程式碼的,但是發現rdrand這個指令是在Inter於Ivy Bridge微架構(2012年生產)後才定義到IA32架構中的,目前我們的電腦上基本上都支援這個指令,但是經過嘗試之後發現即使採用直接寫位元組碼dosbox也不支援這個指令,可能有以下兩個原因:

  1. DosBox的虛擬化環境採用了模擬而不是虛擬,這導致了只支援真真實模式下的指令集;
  2. 這個指令只能在保護模式下使用

第一題的原始碼

.586P
data segment use16
	Count_Number db 0
	String_1 db 'ABCDEFG',0
data ends



Code segment USE16
ASSUME CS: CODE, DS: DATA
	BEG:
		mov ax,data
		mov ds,ax
		mov di,offset String_1
		
	;得到在範圍內的數
	Get_Count:
		mov al,ds:[di]
		cmp al,0
		jz	Print_Result
		cmp al,42h
		jb	.1
		cmp	al,45h
		ja	.1
		inc Count_Number
	.1:	
		inc di
		jmp	Get_Count
	;得到在範圍內的數
	
	;列印資料
	Print_Result:
		mov bl,Count_Number
		mov cx,8
	.2:
		mov dl,0
		shl bl,1
		adc dl,30h
		mov ah,2
		int 21h
		loop .2
		mov dl,'h'
		int 21h
	;列印資料
	
		mov ah,4ch
		int 21h
code ends

end BEG 

第二題的原始碼

.586P
data segment use16
	;定義資料接受區
	UserName 			db 100 	dup(0)
	UserName_Recived_Number	dw 0
	Password			db 100	dup(0)
	Password_Recived_Number	dw 0
	;定義資料接受區
	
	UserName_Origin		db	'YourUserName',0
	Password_Origin		db	'YourPassword',0
	String_Tip 			db 'Please enter your username!',0ah,0dh,'$'
	String_Password_Tip 			db 'Please enter your password!',0ah,0dh,'$'
	String_Wrong_Tip 	db 'Wrong username or password!\n',0ah,0dh,'$'
	String_Hello_Tip	db 'You got it!',0ah,0dh,'$'
data ends



Code segment USE16
ASSUME CS: CODE, DS: DATA
	BEG:
		mov ax,data
		mov ds,ax
		mov dx,offset String_Tip
		mov ah,9
		int 21h
		
		mov UserName_Recived_Number,0
	GetUserName:
		mov ah,1
		int 21h
		mov di,offset UserName
		add di,UserName_Recived_Number
		mov	ds:[di],al
		inc	UserName_Recived_Number
		cmp al,0dh;當輸入回車時實際上是輸入了0x0a,0x0d兩個字元,此時系統呼叫實際上返回的是最後一個字元0x0d
		jnz GetUserName
		mov di,offset UserName
		add di,UserName_Recived_Number
		sub di,1
		mov [di],0
		
		mov dx,offset String_Password_Tip
		mov ah,9
		int 21h
		
		mov Password_Recived_Number,0
	GetPassword:
		mov ah,8
		int 21h
		mov di,offset Password
		add di,Password_Recived_Number
		mov	ds:[di],al
		inc	Password_Recived_Number
		cmp al,0dh;當輸入回車時實際上是輸入了0x0a,0x0d兩個字元,此時系統呼叫實際上返回的是最後一個字元0x0d
		jnz GetPassword
		mov di,offset Password
		add di,Password_Recived_Number
		sub di,1;將最後一個輸入的0x0d字元刪去
		mov [di],0
	
		cld;當df位為0時,採用大端方式
		mov ax,ds
		mov es,ax
		
	CheckUserName:
		mov si,offset UserName_Origin
		mov di,offset UserName
		mov cx,UserName_Recived_Number
		REPE cmpsb;採用串比較,源地址為ds:si,目的地址為es:di
		jnz Wrong
		
	CheckPassword:
		mov si,offset Password_Origin
		mov di,offset Password
		mov cx,Password_Recived_Number
		REPE cmpsb
		jnz Wrong
	
		mov dx,offset String_Hello_Tip
		mov ah,9
		int 21h
		mov ah,4ch
		int 21h
	Wrong:
		mov dx,offset String_Wrong_Tip
		mov ah,9
		int 21h
		jmp BEG
		
code ends

end BEG 

實際上這兩個題目都比較簡單,實際上編寫的時候只需要注意一下系統呼叫之後的引數改變就好了。
其中第二個原始碼由於比較懶…有以下缺陷:

  • 並沒有判斷輸入字元的個數,而是以回車作為結束迴圈條件,所以存在緩衝區溢位;
  • 並沒有考慮結束條件,這意味著如果不能輸入正確的使用者名稱和祕密將不能返回DOS系統

執行結果

第一個題目:
在這裡插入圖片描述

第二個題目:
在這裡插入圖片描述