在 TASM 中加密字符串时遇到问题
Trouble with encrypting a string in TASM
您好,我是汇编语言的新手,我正在为我的 .asm 文件使用 TASM。我想创建一个加密和解密程序,它接受一个 input.txt 文件并加密该文件中的消息。最多只有 30 个字符。 input.txt 文件包含此短语,"You can read this!" 这是到目前为止的样子。
.MODEL SMALL
.STACK
.386
.DATA
welcome_msg1 db "Welcome to the Encrypt/Decrypt program.",13,10,'$'
welcome_msg2 db "Here are your choices.",13,10,'$'
choice_msg1 db "E - Encrypt",13,10,'$'
choice_msg2 db "D - Decrypt",13,10,'$'
choice_msg3 db "Q - Quit",13,10,'$'
filename db 'c:\input.txt',0
file_error db "Error, file not found!",13,10,'$'
string db 30 dup(0) ; Only 30 characters!
len equ $ - string
endchar db '$'
handle dw 0
.CODE
.STARTUP
call instructions
call openfile
call readfile
call closefile
; encrypt Text
lea si, string
mov cl, len
call encrypt
; display string
mov ah,09h
lea dx, string
int 21h
; terminate program once finish
mov ax,4c00h
int 21h
;*************************************;
;**************FUNCTIONS**************;
;*************************************;
; print instructions
instructions proc near
mov ah, 09h
lea dx, welcome_msg1
int 21h
mov ah, 09h
lea dx, welcome_msg2
int 21h
mov ah, 09h
lea dx, choice_msg1
int 21h
mov ah, 09h
lea dx, choice_msg2
int 21h
mov ah, 09h
lea dx, choice_msg3
int 21h
ret
instructions endp
; open file
openfile proc near
mov ax,3d02h
lea dx,filename
int 21h
jc error
mov handle,ax
ret
openfile endp
; read from file
readfile proc near
mov ah,3fh
mov bx,handle
mov cx,30
lea dx,string
int 21h
jc error
ret
readfile endp
; close file
closefile proc near
mov ah,3eh
mov bx,handle
int 21h
ret
closefile endp
; encrypt the string
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
add [si],01
inc si
loop shift_char
ret
encrypt endp
done proc near
mov [si], "$"
ret
done endp
; terminate program if fails
error proc near
mov ah, 09h
lea dx, file_error
int 21h
mov ax,4c00h
int 21h
error endp
end
这是输出:
我创建了一个单独的文件,其中只包含像这样的特定部分
.MODEL SMALL
.STACK
.386
.DATA
filename db 'c:\input.txt',0
string db 30 dup(0) ; Only 30 characters!
len equ $ - string
endchar db '$'
handle dw 0
.CODE
.STARTUP
;open file
mov ax,3d02h
lea dx,filename
int 21h
jc error
mov handle,ax
;read file
mov ah,3fh
mov bx,handle
mov cx,30
lea dx,string
int 21h
jc error
;close file
mov ah,3eh
mov bx,handle
int 21h
;encrypt string
lea si, string
mov cl, len
call encrypt
;print string
mov ah,09h
lea dx, string
int 21h
;finishes if done
done proc near
mov [si], "$"
ret
done endp
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
add [si],01
inc si
loop shift_char
ret
encrypt endp
;terminate if error
error proc near
mov ax,4c00h
int 21h
error endp
end
当我 运行 裁剪的程序时,我得到了我想要的。这是为此的结果
这正是我想要的。原始代码末尾有额外的笑脸,这是我不想要的。所以我目前很困惑是什么问题。
您的问题是您正在加密缓冲区中的所有 0
。
string db 30 dup(0) ; Only 30 characters!
这个 string
的声明是 30 个字节,用零填充,无论读取多少个字符,你计算的长度都是 30。
你应该做的是根据文件的输入计算 len
或将 encrypt
更改为在读取 char 0
时停止。
第二种方法可能是这样的:
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
cmp byte ptr [si], 0 ; <-- added
je done ; <-- finish when reaching the 0
add [si],01
inc si
loop shift_char
ret
encrypt endp
此外,可以通过在内存访问中添加 byte ptr
来修复警告,就像我对 cmp byte ptr [si], 0
所做的那样。
string db 30 dup(0) ; Only 30 characters!
len equ $ - string
首先,考虑到硬编码数字 30,以这种方式定义 len 可能会被认为有点愚蠢!一个普通的 len equ 30
更有意义。
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
add [si],01
inc si
loop shift_char
ret
encrypt endp
其次,这是唯一真正的问题,因为加密逻辑在其他方面是合理的,你在比较无法比较的东西!
当您写 cmp si, len
时,您将地址 (si
) 与长度 (len
) 进行比较。那是不可能的。您可以比较的是 2 个地址或 2 个长度。
继续讨论如何解决这个问题。
PawelLukasik
他说的是对的
"What you should do is either calculate the len based on the input from file or change the encrypt to stop when char 0 is read."
第二种方案是他选的,我不喜欢。此外,它存在与您放入其中的相同问题的缺陷。巧妙地掩饰但仍然存在。
此外,这次您加密的是一个通常不存在 0 字节的文本文件,但下次您将要处理一个二进制文件,然后您将再次陷入困境。
解决方案必须在您读取文件的程序中更早开始。当读取成功时,DOS 在 AX
寄存器中返回有效读取的字节数。您应该将此数字放在 LENGTH 变量中:
LENGTH dw 0
...
readfile proc near
mov ah, 3Fh
mov bx, handle
mov cx, 30 ;Maximum number of bytes to read
lea dx, string
int 21h
jc error
mov [LENGTH], ax ;Actual number of bytes read
ret
readfile endp
然后 encrypt 过程变成一个简单的循环:
encrypt proc near
mov cx, [LENGTH] ;Any number from 0 to 30, gotten from DOS
jcxz done ;In case of 0 (file was empty)
shift_char:
add byte ptr [si], 1
inc si
loop shift_char
done:
mov byte ptr [si], "$"
ret
encrypt endp
您好,我是汇编语言的新手,我正在为我的 .asm 文件使用 TASM。我想创建一个加密和解密程序,它接受一个 input.txt 文件并加密该文件中的消息。最多只有 30 个字符。 input.txt 文件包含此短语,"You can read this!" 这是到目前为止的样子。
.MODEL SMALL
.STACK
.386
.DATA
welcome_msg1 db "Welcome to the Encrypt/Decrypt program.",13,10,'$'
welcome_msg2 db "Here are your choices.",13,10,'$'
choice_msg1 db "E - Encrypt",13,10,'$'
choice_msg2 db "D - Decrypt",13,10,'$'
choice_msg3 db "Q - Quit",13,10,'$'
filename db 'c:\input.txt',0
file_error db "Error, file not found!",13,10,'$'
string db 30 dup(0) ; Only 30 characters!
len equ $ - string
endchar db '$'
handle dw 0
.CODE
.STARTUP
call instructions
call openfile
call readfile
call closefile
; encrypt Text
lea si, string
mov cl, len
call encrypt
; display string
mov ah,09h
lea dx, string
int 21h
; terminate program once finish
mov ax,4c00h
int 21h
;*************************************;
;**************FUNCTIONS**************;
;*************************************;
; print instructions
instructions proc near
mov ah, 09h
lea dx, welcome_msg1
int 21h
mov ah, 09h
lea dx, welcome_msg2
int 21h
mov ah, 09h
lea dx, choice_msg1
int 21h
mov ah, 09h
lea dx, choice_msg2
int 21h
mov ah, 09h
lea dx, choice_msg3
int 21h
ret
instructions endp
; open file
openfile proc near
mov ax,3d02h
lea dx,filename
int 21h
jc error
mov handle,ax
ret
openfile endp
; read from file
readfile proc near
mov ah,3fh
mov bx,handle
mov cx,30
lea dx,string
int 21h
jc error
ret
readfile endp
; close file
closefile proc near
mov ah,3eh
mov bx,handle
int 21h
ret
closefile endp
; encrypt the string
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
add [si],01
inc si
loop shift_char
ret
encrypt endp
done proc near
mov [si], "$"
ret
done endp
; terminate program if fails
error proc near
mov ah, 09h
lea dx, file_error
int 21h
mov ax,4c00h
int 21h
error endp
end
这是输出:
我创建了一个单独的文件,其中只包含像这样的特定部分
.MODEL SMALL
.STACK
.386
.DATA
filename db 'c:\input.txt',0
string db 30 dup(0) ; Only 30 characters!
len equ $ - string
endchar db '$'
handle dw 0
.CODE
.STARTUP
;open file
mov ax,3d02h
lea dx,filename
int 21h
jc error
mov handle,ax
;read file
mov ah,3fh
mov bx,handle
mov cx,30
lea dx,string
int 21h
jc error
;close file
mov ah,3eh
mov bx,handle
int 21h
;encrypt string
lea si, string
mov cl, len
call encrypt
;print string
mov ah,09h
lea dx, string
int 21h
;finishes if done
done proc near
mov [si], "$"
ret
done endp
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
add [si],01
inc si
loop shift_char
ret
encrypt endp
;terminate if error
error proc near
mov ax,4c00h
int 21h
error endp
end
当我 运行 裁剪的程序时,我得到了我想要的。这是为此的结果
这正是我想要的。原始代码末尾有额外的笑脸,这是我不想要的。所以我目前很困惑是什么问题。
您的问题是您正在加密缓冲区中的所有 0
。
string db 30 dup(0) ; Only 30 characters!
这个 string
的声明是 30 个字节,用零填充,无论读取多少个字符,你计算的长度都是 30。
你应该做的是根据文件的输入计算 len
或将 encrypt
更改为在读取 char 0
时停止。
第二种方法可能是这样的:
encrypt proc near
mov ch, 0
shift_char:
cmp si, len
je done
cmp byte ptr [si], 0 ; <-- added
je done ; <-- finish when reaching the 0
add [si],01
inc si
loop shift_char
ret
encrypt endp
此外,可以通过在内存访问中添加 byte ptr
来修复警告,就像我对 cmp byte ptr [si], 0
所做的那样。
string db 30 dup(0) ; Only 30 characters! len equ $ - string
首先,考虑到硬编码数字 30,以这种方式定义 len 可能会被认为有点愚蠢!一个普通的 len equ 30
更有意义。
encrypt proc near mov ch, 0 shift_char: cmp si, len je done add [si],01 inc si loop shift_char ret encrypt endp
其次,这是唯一真正的问题,因为加密逻辑在其他方面是合理的,你在比较无法比较的东西!
当您写 cmp si, len
时,您将地址 (si
) 与长度 (len
) 进行比较。那是不可能的。您可以比较的是 2 个地址或 2 个长度。
继续讨论如何解决这个问题。
PawelLukasik 他说的是对的
"What you should do is either calculate the len based on the input from file or change the encrypt to stop when char 0 is read."
第二种方案是他选的,我不喜欢。此外,它存在与您放入其中的相同问题的缺陷。巧妙地掩饰但仍然存在。
此外,这次您加密的是一个通常不存在 0 字节的文本文件,但下次您将要处理一个二进制文件,然后您将再次陷入困境。
解决方案必须在您读取文件的程序中更早开始。当读取成功时,DOS 在 AX
寄存器中返回有效读取的字节数。您应该将此数字放在 LENGTH 变量中:
LENGTH dw 0
...
readfile proc near
mov ah, 3Fh
mov bx, handle
mov cx, 30 ;Maximum number of bytes to read
lea dx, string
int 21h
jc error
mov [LENGTH], ax ;Actual number of bytes read
ret
readfile endp
然后 encrypt 过程变成一个简单的循环:
encrypt proc near
mov cx, [LENGTH] ;Any number from 0 to 30, gotten from DOS
jcxz done ;In case of 0 (file was empty)
shift_char:
add byte ptr [si], 1
inc si
loop shift_char
done:
mov byte ptr [si], "$"
ret
encrypt endp