汇编实现凯撒加密和解密

发布于 2020-07-24  543 次阅读


1.题目:
设计一个凯撒密码加密器,输入一串字符串(长度不超过20)以回车结束,之后再输入一个-8到8之间的整数X。
(1)如果输入非数字,则通过输出提示;
(2)如X=0,则输出该字符串本身;
(3)如果08或者X<-8,则退出到DOS系统。

2.分析
2.1凯撒密码加密解密器的原理
凯撒加密法的替换方法是通过排列明文和密文字母表,密文字母表示通过将明文字母表向左或向右移动一个固定数目的位置。例如,当偏移量是左移3的时候(解密时的密钥就是3):
明文字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZ
密文字母表:DEFGHIJKLMNOPQRSTUVWXYZABC
使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。需要解密的人则根据事先已知的密钥反过来操作,得到原来的明文。例如:
明文:THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
密文:WKH TXLFN EURZQ IRA MXPSV RYHU WKH ODCB GRJ
凯撒加密法的加密、解密方法还能够通过同余的数学方法进行计算。首先将字母用数字代替,A=0,B=1,…,Z=25。此时偏移量为n的加密方法即为:
En(x)=(x+n)mod26
解密就是:  Dn(x)=(x−n)mod 26
2.2题目分析
根据题目可知,需要设计一个汇编程序满足题目给的条件,其核心难点是在于实现凯撒加密和解密的过程。
(1)当输入的数字为-8<= X < 0时,我们需要对输入的字符串进行解密操作,这个输入的数字就是解密时的偏移量,比如:
当我们输入字符串 :abcdA
输入数字: -1
则解密后的结果是:zabZ
(2)当我们输入的数字为 X = 0时直接显示出输入的字符串即可。
(3)当我们输入的数字为 0< X <=8时,需要进行凯撒加密,这个输的数字X就是加密时的偏移量,比如:
当我们输入字符串 :abcdA
输入数字: 1
则解密后的结果是:bcdB
(4)在本次程序中,若输入的字符串中含有不是字母的字符则该字符不进行处理,比如:字符串“abcd123”,假设加密偏移量X=1,则进行加密后变为:“bcde123”,解密也是如此。
3.软件设计
3.1该程序的算法步骤
1.输入字符串codeStr;
2.输入凯撒加密或解密的偏移量X;
2.1如果X<-8或者 X < 8,直接结束程序返回dos系统;
2.2否则继续第3步;
3.判断X>=0是否成立
3.1如果不成立,则进行解密操作,并输出解密后字符串;
3.2如果成立,则继续第4步;
4.判断X > 0是否成立
4.1如果成立,则进行加密操作,并输出加密后字符串;
4.2如果不成立,则直接输出字符串codeStr;
5.结束程序返回dos界面。
3.2该程序的程序框图

3.3程序关键代码说明

3.3.1关键变量说明
(1)X DB ‘0’ :定义凯撒加密或解密的偏移量;
(2)XBuffer DB 4:预定义4字节的空间用于存储输入的凯撒解密或解密的偏移量,然后再将其转化为数字X;
(3)BUFFER DB 20:预定义20字节的空间,用于存储输入的字符串;
(4)codeStr DB 20 DUP(’$’) :20字节的空间,用于存储加密或解密后的字符串;
3.3.2关键代码说明
(1)InputCodeStr:使用dos的中断函数进行接收字符串存放到BUFFER 中去,并进行一定的处理使得BUFFER是完整的字符串数组。
(2)inputX:使用dos的中断函数进行接收输入的数字并存放到XBuffer中去,方便之后进行相应的操作使其转化为数字偏移量X。
(3)NegativeXber:处理输入的数字是负数的情况。
(4)PoSItiveXber:处理输入的数字是正数的情况,包括X = 0或者0<x <="8的情况."

(5)erroinput:处理错误输入,中断程序回到dos系统界面。

6)showInputStr:打印输入的字符串,当X =0时调用该代码块。
(7)ENCODE:进行凯撒加密操作,通过调用相关的函数不断循环逐个将字符串里面的字符按照凯撒加密的原则进行操作,然后将操作后的字符存储到codeStr中。
(8)DECODE:进行凯撒解密操作。通过调用相关的函数不断循环逐个将字符串里面的字符按照凯撒解密的原则进行操作,然后将操作后的字符存储到codeStr中。

PS:具体代码请看源程序代码。.
4.源代码

DATA   SEGMENT                               
    inputStrMsg  DB  "PLEAse input a string: ",'$' 															;	提示输入一个字符串
    inputNumMsg db "    Input a number in  -8 to 8: ",13,10,"$"             ;提示输入一个数字
   showCodeStrMsg  DB  "Your input is: ",'$'																		;提示输出的字符串
	RepeatInputMsg DB "Input is erro ,exit !"																		;提示重新输入
	encodeMsg  DB   "You chose encryption,after encode:    ",'$'					;提示加密后
	deCodeMsg  DB  "You chose   decryption,after deconde:    ",'$'			;提示解密后

 	num  DB    '0'						;定义用于存储输入的数字加密或解密偏移量
	NumBuffer DB  20			;预定义4字节的空间用于存储输入的凯撒解密期待偏移量
       DB  ?				  		  ;待输入完成后,自动获得输入的字符个数
       DB  20  DUP(0) 	;初始化全为0
       
  BUFFER DB  20			  ;预定义20字节的空间
       DB  ?				  			 ;待输入完成后,自动获得输入的字符个数
       DB  20  DUP(0)          
  CRLF   DB  0AH, 0DH,'$'             
 	codeStr   DB  20 DUP('$')    ;20字节的空间,加密后的字符串
DATA   ENDS                                  
CODE   SEGMENT                              
				ASSUME CS:CODE, DS:DATA    	;建立段bai寄存器和段名之间关系
START:     
     																																														   
        MOV AX, DATA      	 ;初始化数据
        MOV DS, AX             
        CALL  InputCodeStr     	;调用输入需要加密内容的代码块进行输入
        CALL   inputNum					;调用输入加密或解密偏移量的代码块进行输入
        LEA DX, CRLF            ;回车换行,另取一行                  
        MOV AH, 09H							 
        INT 21H  
        ;-------判断输入的数字是否是两位,大于零时是一位数,是负数是两位数,如果不符合直接结束程序-------
       LEA SI,NumBuffer+1	
       MOV AL,[SI]
       CMP AL,0
       JBE   erroInput
       CMP AL,2
       JA     erroInput
       ;------------结束判断输入的数字是否合法------------------
       
       LEA SI , NumBuffer +2																																									
       MOV  AL , [SI ]										    ;获取 符号用于判读表示是否是负数
       CMP  AL,'-'
    	 JE  NegativeNumber  					;相等,是负数
    	 CMP AL,'-'
  	   jne  PoSItiveNumber				 ;不相等,不是负数,表示大于或等于0
 	   JMP   exit
     
           ;-------------输入字符串-----------------------
 InputCodeStr:      
        LEA DX, inputStrMsg           ;打印提示输入信息    
        MOV AH, 09H							 
        INT 21H
        LEA DX,BUFFER     ;接收字符串
        MOV AH, 0AH				;调用dos系统中断函数进行输入
        INT 21H
        MOV AL, BUFFER+1      ;对字符串进行处理
        ADD AL, 2
        MOV AH, 0
        MOV SI, AX
        MOV BUFFER[SI], '$'				;给字符串末尾添加一个'$'结束符号
        
        LEA DX, CRLF       ;另取一行                   
        MOV AH, 09H							 
        INT 21H
        RET	
  ; ---------------结束输入字符串-------------------------
     
     
     
     ;-----------输入数字作为凯撒加密器的偏移量------------------
 inputNum:
      LEA DX, inputNumMsg       ;打印提示输入信息    
        MOV AH, 09H							 
        INT 21H
        LEA DX,NumBuffer     ;接收字符串
        MOV AH, 0AH					;调用dos系统中断函数进行输入
        INT 21H
        MOV  AL, NumBuffer+1        ;对字符串进行处理
        ADD AL, 2
        MOV AH, 0
        MOV SI, AX
        MOV NumBuffer[SI], '$'			;给字符串末尾添加一个'$'结束符号
        RET
      ;-----------结束输入数字作为凯撒加密器的偏移量------------------ 
     
      
      
      
 ;-------------输入的整数为负数的情况------------------
  NegativeNumber:
    LEA DX, CRLF          	   ;另取一行                   
    MOV AH, 09H						
    int  21h
    LEA dx,deCodeMsg		;打印提示信息
    MOV ah,09h
    int  21h
     LEA DX, CRLF        	 ;回车换行           
    MOV AH, 09H				
    int  21h																																										 
     inc SI 						 ;输入的数为负数需要读取第四个数为偏移量
	  MOV  AL,[SI] 				 ;读取输入的正整数
 	 MOV num,AL					;获取输入的正整数偏移量保存到num中
 	  sub num,48						;将获取到的ASCII码转化为实际的数字要减去48
 	 CMP  num,0
 	 JB   erroInput			;小于0跳转到输入有误
 	 CMP num,8
 	 JG   erroInput						;大于8跳转跳转到输入错误
 	  JMP  decode						 ;-8<=num<0,跳转到加密
    JMP exit
     
    ;----------输入的整数是非负数的情况---------------------
  PoSItiveNumber:
   LEA DX, CRLF        	    ;回车换行              
    MOV AH, 09H				
    int  21h
  MOV  AL,[SI] 				 ;读取输入的正整数,位于第三个位置
   MOV num,AL			;获取输入的正整数偏移量保存到num中
   sub num,48				;将获取到的ASCII码转化为实际的数字要减去48
     CMP num,0
   JE   showInputStr 					;输入的偏移量num = 0则直接显示输入的字符串
    LEA DX, CRLF              ;回车换行                 
    MOV AH, 09H				
    int  21h
  CMP  num,0
  JB   erroInput		 ;小于0跳转到输入有误
  CMP num,8
  JG   erroInput						;大于8跳转跳转到输入错误
    LEA dx,encodeMsg					;提示加密信息
    MOV ah,09h
    int  21h
   JMP  ENCODE							;0 <num<=8,跳转到加密
   
   
  ;----------------错误输入处理----------------------
  erroInput:
   LEA dx,RepeatInputMsg
   MOV ah,09h
   int 21h
   JMP exit
  ;-------------结束错误处理-----------------------
  
  ;---------------直接显式输出输入的字符串----------------
  showInputStr:
       LEA dx ,showCodeStrMsg 				 ;显示提示信息
       MOV ah,09h
       int 21h
       LEA DX, BUFFER+2             ;输出输入的字符串
        MOV AH, 09H							 
        INT 21H
        JMP exit
  ;-------------------加密处理-----------------
  
   ENCODE:    
       LEA  SI ,BUFFER+2				 ;键入字符串的起始地址
       LEA  DI,codeStr  						  ;键入加密后字符串的起始地址
      MOV  cl,BUFFER+2 					;初始化开始循环的起始地址
      MOV ch,0

ENCODE_AGAIN:
 		MOV AL, [SI ]							;取来一个
 		  CMP AL,'$'
       je  showCodeStr					;加密结束,打印解密后的字符串
 		CMP  AL, 'A'
 		JL    ENCODE_NEXT					 ;小于'A'不用处理,转移到下一个
 		CMP AL,'z' ;- {'
 		JG  ENCODE_NEXT				 ;大于'z'不用处理,转移到下一个
 		CMP AL, 'a'
 		JL   ENCODE_Uppercase 		;小于'a'可能是大写,转移
 		CMP AL,'a'
 		JAE   ENCODE_Lowercase
ENCODE_Lowercase:
		 ADD  AL, num;								;当前字符加上加密的偏移量
 		CMP  AL,'z'
 		JA  EncodeSub_26 			;大于'z',超过了最后的字母,应减去26
	 JMP  ENCODE_NEXT				;跳转到处理字符函数

ENCODE_Uppercase:
 	   	CMP AL, 'Z' 																																
		 JG  ENCODE_NEXT 		 ;大于'Z'不用处理,转移到下一个
		 ADD  AL, num
 		CMP  AL, 'Z'
		 JA  EncodeSub_26				 ;大于'Z',超过了最后的字母,应减去26
 		JMP ENCODE_NEXT		;跳转到处理字符函数

EncodeSub_26:
 		SUB AL, 26										;当前字符减去26
 		JMP ENCODE_NEXT			;跳转到处理字符函数
 		
ENCODE_NEXT:
 		MOV  [DI], AL								 ;将当前的字符保存到保存密码
 		INC SI															;SI指针自增1
		 INC DI															;DI指针自增1
 		LOOP   ENCODE_AGAIN         	  ;重新进行循环
;----------------------------加密结束--------------------------------------


;-----------解密处理--------------------------------------------
    DECODE:
 	  LEA  SI ,BUFFER+2				 ;键入字符串的起始地址
      LEA  DI,codeStr					    ;键入加密后字符串的起始地址
      MOV  cl,BUFFER+2 				;初始化开始循环的起始地址
      MOV ch,0
    
DECODE_AGAIN:
 		MOV AL, [SI ]					;取来一个
 		    CMP AL,'$' 	
       je  showCodeStr				;循环结束,打印解密后的字符串
 		CMP  AL, 'A'
 		JB DECODE_NEXT					 ;小于'A'不用处理,转移到下一个
 		CMP AL,'z' 
 		JA DECODE_NEXT					 ;大于'z'不用处理,转移到下一个
 		CMP AL, 'a'
 		JB DECODE_Uppercase	 ;小于'a'可能是大写,转移
DECODE_Lowercase:
		 SUB  AL, num									 ;向左偏移 num个位置
 		CMP  AL,'a'
 		JB  DecodeAdd_26				 ;大于'z',超过了最后的字母,应减去26
	 JMP  DECODE_NEXT

DECODE_Uppercase:
 	   	CMP AL, 'Z' 
		 JA DECODE_NEXT  			;大于'Z'不用处理,转移到下一个
		 SUB  AL, num 											  ;向左偏移 num个位置
 		CMP  AL, 'A'
		 JB   DecodeAdd_26				 ;小于A,应该加上26
 		JMP DECODE_NEXT
 		

DECODE_NEXT:
 		MOV  [DI], AL					 ;将当前的字符保存到保存密码
 		INC SI									;SI指针自增1
		 INC DI											;DI指针自增1
 		LOOP   DECODE_AGAIN          	  ;重新进行循环


 DecodeAdd_26:
  ADD  AL,26										;当前字符需要加上26
  JMP DECODE_NEXT            ;跳转到处理字符函数
 ;-------------------解密结束--------------------
 
;--------------输出加密或者解密后的字符串---------------
showCodeStr:
       LEA DX,codeStr
       MOV ah,09h
       int 21h
      JMP  exit
;---------------结束输出加密或者解密后的字符串--------------
 
 ;--------------结束程序--------------------------------------
  exit: 
        MOV AH, 4CH                      ;返回DOS系统
        INT 21H
CODE   ENDS                                  
END    START        

5.运行截图:

6.该程序的源代码以及可执行程序的链接为(注意,解压后可直接编译ASM文件然后运行,而可执行exe文件需要在dosbox下运行才能执行成功):http://moyisuiying.com/wp-content/uploads/2020/07/CaesarEncryption.rar


繁华落尽,雪花漫天飞舞。