我现在对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
答案 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>
为了使代码正常工作,请执行以下步骤:
循环之前
xlat
中。所有x86 cx
指令都使用loop
作为计数器。cx
称为当前缓冲输入字符的地址(将si
设置为si
以启动)。 buf
寄存器非常适合缓冲区索引(查找si
,lods
等指令)。循环期间
stos
(您可以使用al
指令执行此操作,然后自动递增lodsb
以进行下一次加载)si
中的字符中减去'A'
。如果一切都是小写,则减去al
。您需要将索引归零为'a'
。a_tab
的地址放入a_tab
bx
指令,将翻译结果加载到xlat
。al
将您关注的任何寄存器保存到堆栈中;这包括push
寄存器,它是您当前的循环计数器和cx
si
al
pop
指令绕过循环,这将减少循环计数器loop
。这些是整体步骤。您可能还想在此处做其他事情,但这应该有助于您走上正确的轨道。您还应该在线阅读文档,以获取cx
和xlat
等特殊说明,以了解其行为。此外,无论何时调用DOS中断或函数,它都有如何传递参数的约定,以及如何在寄存器中返回信息。未提及的任何其他寄存器可能在您不知情的情况下被该中断或函数使用,因此您应该在执行此类调用之前保存这些寄存器,例如使用lodsb
,然后还原他们使用push
进行通话后。