【问题标题】:Trouble with encrypting a string in TASM在 TASM 中加密字符串的问题
【发布时间】:2017-05-22 06:29:03
【问题描述】:

您好,我是汇编语言的新手,我正在为我的 .asm 文件使用 TASM。我想创建一个加密和解密程序,该程序采用 input.txt 文件并加密该文件中的消息。最多只有 30 个字符。 input.txt 文件包含这句话,“你可以阅读这个!”这是到目前为止的样子。

.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

当我运行那个裁剪后的程序时,我得到了我想要的。这是输出

这正是我想要的。原始代码末尾有额外的笑脸,这是我不想要的。所以我目前很困惑问题是什么。

【问题讨论】:

    标签: assembly tasm


    【解决方案1】:

    您的问题是您正在加密缓冲区中的所有0

    string db 30 dup(0)     ; Only 30 characters!
    

    string 的声明是 30 个字节,用零填充,无论读取多少个字符,您计算的长度都是 30。

    您应该做的是根据来自文件的输入计算len,或者将encrypt 更改为在读取字符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 所做的那样。

    【讨论】:

    • 呵呵,你也帮我解决了我的警告问题,虽然没有提到。谢谢你的解释!它完全按照我现在想要的方式工作。
    • 很高兴我能帮上忙 :)
    【解决方案2】:
    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 他说的没错

    “您应该做的是根据文件的输入计算 len,或者将加密更改为在读取 char 0 时停止。”

    我不喜欢的第二种解决方案是他选择的。此外,它存在与您在那里提出的相同问题的缺陷。巧妙地掩饰,但仍然存在。

    此外,这一次您正在加密一个通常不存在 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 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
    

    【讨论】:

    • ooo,我试图弄清楚如何获取输入字符串,找到字符串长度并将其用作 for 循环(i = 0; i
    • 你的意思是使用DOS功能0Ah从键盘输入,不再从文件中读取?
    • len equ $-string 是一种方便的表示法,因此我们不必计算 literal 字符串中的字符,例如 msg db 'This is too long for me to count it easily so I let the compiler do the work for me'
    • 对于读取文件的字符串和用户输入的字符串不是很有用吗?除了我给它一个静态字节数来保存的情况
    • 否,因为 $ 符号是编译时值。它在读取/输入时不再存在(两者都发生在程序运行时)。
    猜你喜欢
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多