使用cmp加密和解密时遇到问题

时间:2015-03-20 22:54:31

标签: assembly x86

我现在对cmp有疑问。我需要合并3个表来加密和解密。我可以使用代码来执行n_tab,l_tab或a_tab,但似乎无法将所有三个结合起来。任何帮助将不胜感激。谢谢

.model small

.stack 100h

.data


    prompt1 db "ENTER YOUR MESSAGE HERE: $" 
    prompt2 db "ENCRYPTED: $"
    prompt3 db "DECRYPTED: $"

    a_tab db "ZYXWVUTSRQPONMLKJIHGFEDCBA"



    buff  db 50 dup(0)  


    .code

    main:
    mov ax, @data
    mov ds, ax                      ; set up addressability
    mov si, offset buff             ; put into buff

    lea dx, prompt1                 ; load and print the string PROMPT
    mov ah, 9
    int 21h
    mov si, di

    mov ah, 3fH
    mov cx, 50
    int 21h
    mov si, di





    mov bx, offset a_tab
    mov si, di

    l1: lodsb
    push bx
    mov ah, 6
    mov dl, 0ffh
    int 21h
    pop bx
    mov dl, al
    mov al, 0
    sub al, 'A'

    xlat
    loop l1

    lea dx, prompt2                 ; load and print the string PROMPT
    mov ah, 9
    int 21h
    mov si, di

    mov ah, 4cH
    int 21h

end main

1 个答案:

答案 0 :(得分:2)

我看到的一些问题我将会描述。抱歉,我没有DOS或DOS模拟器或Windows设置来测试这个,所以我只是阅读你的代码。可能还有其他问题,但这些问题很重要:

    mov ah, 3fH
    mov bx, 0
    mov cx, 50
    mov dx, offset buff         ; put into buff
    int 21h

此段的开头设置文件I / O以从文件句柄0(标准输入)读取。当int 21h返回时,读取的实际字节数在ax,但最终似乎被忽略了。

然后循环开始......

l1:
    mov dl, al
    mov bx, offset a_tab

您现在正在开始加密循环。您已将用户读取的字节数的低字节移至dl,并将a_tab地址加载到bx以设置xlat期望表格地址位于ds:bx,并将该表格按al中的值编入索引,并将结果加载到al

    xlat

所以我们已经遇到了麻烦。首次执行此al时,xlat中的内容是什么?它具有从标准输入读入的字节数,这可能与您的意图不同。我假设mov dl, al在某种程度上是为了从缓冲区中获取下一个字符,我们需要在al调用之前进入xlat。但这意味着我们必须从缓冲区中读取它。循环中的缓冲区索引或前进缓冲区指针是什么?它似乎没有设置。

继续......

    mov ah, 6
    mov dl, 0ffh
    int 21h

这会将al中的字符输出到终端。因此,无论您使用从终端读取的字节数作为索引从a_tab检索到的是您应该看到的第一个字符输出。

请记住l1:以上mov dl, al处的说明吗?这似乎没有任何效果,因为dl还没有被使用,现在被0ffh覆盖了上述DOS中断。

    lea dx, prompt2               ; load and print the string PROMPT
    loop l1

这表示您正在加载并打印提示字符串,这似乎是您开始执行的操作(使用lea)但是您执行了{{{ 1}}到loop。我假设l1指令在 loop指令之前属于。如果结果不为零,lea将递减loop中的计数器并跳转到cx。但是,l1中的内容是什么?答案:不确定因为我们执行输出字符的最后一次DOS中断可能已经改变了cx,因为它不能保证保留寄存器。即使它确实cx的最后一个已知值来自设置最大缓冲区大小的cx(而不是实际缓冲区大小,由缓冲区读取返回但被代码忽略)。该中断也可能已被删除mov cx, 50

我假设您正在尝试使用输入字符索引转换表。您必须首先决定是否为输入做大写,小写或两者,然后在输出表中有足够的条目cx来解释它。您需要读入一个字符,减去可能的最低字符值(如果您使用大写字母,则为a_tab),然后使用该值索引表格。

您看到了乱码输出,因为在每次循环执行'A'指令时,al中的确无法解释。{ / p>

为了使代码正常工作,请执行以下步骤:

循环之前

  1. 读取输入字符串缓冲区,正如您所做的那样,并将实际读取的字节数保存到循环计数器xlat中。所有x86 cx指令都使用loop作为计数器。
  2. 设置备用寄存器,将cx称为当前缓冲输入字符的地址(将si设置为si以启动)。 buf寄存器非常适合缓冲区索引(查找silods等指令)。
  3. 循环期间

    1. 将输入缓冲区中的一个字节读入stos(您可以使用al指令执行此操作,然后自动递增lodsb以进行下一次加载)
    2. 如果您正在阅读所有大写输入,请从si中的字符中减去'A'。如果一切都是小写,则减去al。您需要将索引归零为'a'
    3. a_tab的地址放入a_tab
    4. 执行bx指令,将翻译结果加载到xlat
    5. 使用al将您关注的任何寄存器保存到堆栈中;这包括push寄存器,它是您当前的循环计数器和cx
    6. 使用DOS中断输出si
    7. 中的字符
    8. 使用al
    9. 恢复先前在步骤5中保存的寄存器
    10. 使用pop指令绕过循环,这将减少循环计数器loop
    11. 这些是整体步骤。您可能还想在此处做其他事情,但这应该有助于您走上正确的轨道。您还应该在线阅读文档,以获取cxxlat等特殊说明,以了解其行为。此外,无论何时调用DOS中断或函数,它都有如何传递参数的约定,以及如何在寄存器中返回信息。未提及的任何其他寄存器可能在您不知情的情况下被该中断或函数使用,因此您应该在执行此类调用之前保存这些寄存器,例如使用lodsb,然后还原他们使用push进行通话后。