首页 > 解决方案 > 为什么这个汇编程序两次输出相同的字符串?

问题描述

这个凯撒密码程序生成解密字符串(长度始终为 10),输出为 output.txt 文件。例如下面的代码生成 .txt 文件,

ILIKEASSEM

HOWAREYOUU

但是当我运行这段代码时,文件是

ILIKEASSEM

ILIKEASSEM

即使通过 Visual Studio 2017 (MASM) 调试器 (TT) 进行调试,我也不知道出了什么问题

怎么了...?

INCLUDE Irvine32.inc

.data
Num_Str DWORD 2
;;key = 10
Cipher_Str BYTE "SVSUOKCCOW",0 
        BYTE "RYGKBOIYEE",0
filename    BYTE"output.txt", 0
fileHandle  DWORD ?
BUFFER_SIZE = 12
buffer  BYTE BUFFER_SIZE DUP(?)
L   BYTE "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0
Decipher    BYTE "QRSTUVWXYZABCDEFGHIJKLMNOP", 0
count       DWORD ?

.code
main PROC

    mov     edx, OFFSET filename
    call    CreateOutputFile        
    mov     fileHandle, eax         



    mov     ecx, Num_Str
    mov     esi, 0                  

    L1:
        push    ecx                 
        mov     ecx, 11                 

    L2: 
        mov     al, Cipher_Str[esi]     
        sub     al, 65                  


        movzx   ax, al                  
        movzx   eax, ax                 

        mov     edi, eax                



        mov     al, Decipher[edi]       

        mov     buffer[esi], al     
        inc     esi

    loop    L2


        mov     bl, 13
        mov     buffer[esi], bl

        inc     esi
        mov     bl, 10
        mov     buffer[esi], bl


        mov     eax,fileHandle
        mov     edx,OFFSET buffer
        mov     ecx, BUFFER_SIZE
        call    WriteToFile



        pop     ecx



    loop    L1




    mov     eax, fileHandle 
    call    CloseFile


exit
main ENDP
END main

标签: assemblyx86masmirvine32

解决方案


甚至在开始外循环L1的第二次迭代之前,您就溢出了 12 字节缓冲区 。您破译这 10 个字符,还破译终止的零(您应该忽略它),然后添加回车和换行。总共有 13 个字节! 您进一步溢出它,因为您没有重置寄存器。
ESI

一种可能的解决方案是在外循环的每次迭代中将索引输出缓冲区的偏移寄存器重置为零,并使用不同的索引寄存器来引用相隔 11 个字节的密码字符串。

    BUFFER_SIZE = 12
    ...
    mov     esi, offset Cipher_Str            
L1:
    xor     edi, edi            ; EDI=0
L2: 
    movzx   eax, byte ptr [esi+edi]
    mov     al, Decipher[eax-65]
    mov     buffer[edi], al 
    inc     edi
    cmp     edi, 10
    jb      L2
    mov     word ptr buffer[edi], 0A0Dh

    mov     eax, fileHandle
    mov     edx, OFFSET buffer
    mov     ecx, BUFFER_SIZE
    call    WriteToFile

    add     esi, 11             ; Move to the 2nd input string (or after it)
    cmp     esi, offset Cipher_Str + 22
    jb      L1

推荐阅读