Assembly 在TASM中加密字符串时遇到问题

Assembly 在TASM中加密字符串时遇到问题,assembly,tasm,Assembly,Tasm,嗨,我对汇编语言非常陌生,我正在使用TASM作为我的.asm文件。我想创建一个加密和解密程序,它接受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 you

嗨,我对汇编语言非常陌生,我正在使用TASM作为我的.asm文件。我想创建一个加密和解密程序,它接受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
当我运行裁剪程序时,我得到了我想要的。这是我们的理由


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

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

string db 30 dup(0)     ; Only 30 characters!
string
的声明是30个字节,用零填充,无论读取多少个字符,长度的计算都是30

您应该做的是根据文件的输入计算
len
,或者在读取char
0
时将
encrypt
更改为stop

第二种方法可能是这样的:

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
encrypt proc near
mov-ch,0
移位字符:
cmp硅透镜
我做完了
cmp字节ptr[si],0;
首先,考虑到硬编码的数字30,用这种方式定义len可能有点愚蠢!普通的
leneq 30
更有意义

其次,这是唯一真正的问题,因为加密逻辑在其他方面是合理的,您正在比较无法比较的东西
写入
cmp si,len
时,将地址(
si
)与长度(
len
)进行比较。那是不可能的。你可以比较的是两个地址或者两个长度

继续讨论如何解决这个问题。 他说得对

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

我不喜欢他的第二种解决方案。此外,它的缺陷与你放在那里的问题相同。聪明地戴上面具但仍然存在

此外,这次您加密的文本文件通常不存在0字节,但下次您将要处理二进制文件,然后您将再次卡滞

解决方案必须在读取文件的程序中更早地启动。当读取成功时,DOS在
AX
寄存器中返回有效读取的字节数。应将此数字放入长度变量中:

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

呵呵,你也帮我解决了我的警告问题,虽然没有提到。谢谢你的解释!很高兴我能帮上忙:)哦,我想知道如何获取输入字符串,找到字符串长度,然后像使用for循环一样使用它(I=0;Ilen eq$-string
是一种方便的表示法,因此我们不必计算文本字符串中的字符,例如
msg db',这对我来说太长了,无法轻松计算,因此我让编译器来计算“为我工作”
它对读取文件字符串和用户输入字符串都有用吗?除了我的例子,我给它一个静态字节量holdNo,因为$symbol是一个编译时值。它在读取/输入时不再存在(两者都发生在程序运行时)。
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