我正在尝试加密二进制文件。但程序不会加密任何内容,并且在磁盘上写入文件时会出错。因此,我没有在磁盘上获得加密文件,并且程序因无限循环打印未知符号而卡住。您能帮我修复代码吗?
.286
.model small
.stack 100h
.DATA
bufferSize EQU 255
keyword db bufferSize DUP (0)
fileContent db bufferSize DUP (0)
fileNameIn db "INPUT.DOC", 0
fileNameOut db "OUTPUT.DOC", 0
fileNameDec db "DECRYPTED.DOC", 0
bytesCountReadWrite dw 0
inputms db "Please enter keyword", 0
emptyinputmsg db "Console input is empty", 0
cantCreateFileMsg db "Can't create file", 0
cantWriteFileMsg db "Can't write file", 0
cantReadFileMsg db "Can't read file", 0
cantOpenFileMsg db "Can't open file", 0
handler_input dw 0
handler_output dw 0
handler_decrypt dw 0
.CODE
InitSet MACRO
mov ax, @data ; Load the segment address of the data segment into AX
mov ds, ax ; Set the data segment register (DS) to the value in AX
mov es, ax ; Set the extra segment register (ES) to the value in AX
; xor ax, ax ; Clear the value in AX by performing an XOR operation with itself
ENDM
GetStrLen MACRO string, strlen
LOCAL count_bytes, end_count
pusha
push si ; Save SI register on the stack
mov si, OFFSET string ; SI = offset of the string
; Calculate the number of bytes to write
mov cx, 0 ; Initialize byte count to 0
count_bytes:
cmp byte ptr [si], 0 ; Check if end of string
je end_count ; If end of string, jump to end_count
add cx, 1 ; Increment byte count by 1
add si, 1 ; Move to the next byte
jmp count_bytes ; Jump back to count_bytes to process the next character
end_count:
mov strlen, cx ; Store the byte count in the memory location pointed by strlen
pop si ; Restore SI register from the stack
popa
ENDM
PrintString MACRO string
LOCAL strlen
.data
strlen dw 0
.code
GetStrLen string, strlen
pusha
mov dx, offset string ; Load the offset of the string to print into DX
mov cx, strlen ; Load the length of the string into CX
mov ah, 40h ; Set AH to 40h for writing to file or device
mov bx, 1 ; Set BX to 1 for standard output handle
int 21h ; Call MS-DOS interrupt 21h to write the string
popa
ENDM
ReadFileGetReadMsgLen MACRO filename, bytesRead, s, handler_input
LOCAL readcontent, rt, closeFile, exit_readingfile
pusha
; check opened file
mov ax, [handler_input]
test ax, ax
jnz readcontent
; getting filename
lea bx, filename
inc bx
mov al, [bx]
xor ah, ah
add bx, ax
inc bx
xor al, al
mov [bx], al
; open file
lea dx, filename
add dx, 2
mov ah, 3dh
xor al, al
int 21h
; ax - filehandler or error num
jnc readcontent ; check open error
PrintString cantOpenFileMsg
jmp exit_readingfile
readcontent:
mov [handler_input], ax
mov bx,ax ; read file
mov ah, 3fh
mov cx, bufferSize ; count
lea dx, s
int 21h
jnc rt ; - open,write,read
PrintString cantReadFileMsg
jmp exit_readingfile
rt: ; if we read less than buffersize we can close file
cmp ax, bufferSize
jne closeFile
closeFile:
mov bytesRead, ax
xor ax, ax
mov ah, 3eh ; closing file handle
int 21h
mov [handler_input], ax
exit_readingfile:
popa
ENDM
WriteFileGetWriteMsgLen MACRO keyword, filename, bytesWrote, str_chunk, handler_output
LOCAL writecontent, encodeContent, rtwrt, closeOutFile
pusha
push si
; Check opened file
mov ax, [handler_output]
test ax,ax
jnz writecontent
; Getting filename
lea bx, filename
inc bx
mov al, [bx]
xor ah,ah
add bx, ax
inc bx
xor al,al
mov [bx], al
; Create File
lea dx, filename
add dx, 2
mov ah, 3Ch
xor cx, cx
int 21h
jnc writecontent
PrintString cantCreateFileMsg
jmp closeOutFile
writecontent:
mov [handler_output], ax
lea si, str_chunk
;mov cx, word ptr [str_chunk]
encrypt keyword, str_chunk
mov bx, [handler_output] ; Write file
mov ah, 40h
;mov cx, [str_chunk]
GetStrLen str_chunk, cx
lea dx, str_chunk
int 21h
jnc rtwrt
PrintString cantWriteFileMsg
jmp closeOutFile
rtwrt:
cmp ax, bufferSize
jne closeOutFile
closeOutFile:
mov bytesWrote, ax
xor ax, ax
mov ah, 3eh ; Close file
mov bx, [handler_output]
int 21h
xor ax, ax
mov [handler_output], ax
popa
ENDM
findX0 MACRO keyword, key0
LOCAL search_loop, strlen
.data
strlen dw 0
.code
pusha
GetStrLen keyword, strlen
mov al, 0 ; Initialize AL register to 0
mov bl, 0 ; Initialize BL register to 0
mov cx, strlen ; Load the length of the keyword into CX
mov bx, offset keyword ; Load the offset of the keyword into BX
search_loop:
mov al, [bx] ; Move the byte at memory location pointed by BX into AL
add key0, ax ; Add the value of AX to key0
rol key0, 8 ; Rotate the bits of key0 to the left by 8 positions
inc bx ; Increment BX to point to the next character in the keyword
loop search_loop ; Decrement CX and repeat the loop until CX becomes 0
popa
ENDM
encrypt MACRO keyword, message
LOCAL encrypt_loop, X0, Xi, strlen, encryptedMessage, A, B, M ; Define local labels for the loop and Xi variable
.data
encryptedMessage db bufferSize DUP (0)
strlen dw 0
Xi dw ? ; Define a word-sized variable Xi
X0 dw 0
A EQU 12
B EQU 25
M EQU 56
.code
findX0 keyword, X0
GetStrLen message, strlen
pusha
push si ; Save SI register on the stack
push di ; Save DI register on the stack
mov ax, X0 ; Move the value of X0 into AX
mov Xi, ax ; Move the value of AX into Xi variable
mov cx, strlen
mov si, offset message ; Load the offset of the message into SI
mov di, offset encryptedMessage ; Load the offset of the encrypted message into DI
encrypt_loop:
mov ax, [si] ; Move the word at memory location pointed by SI into AX
xor ax, Xi ; XOR the word with Xi
mov [di], byte ptr ax ; Move the result byte by byte into the encrypted message
mov ax, Xi ; Move the value of Xi into AX
mov bl, A ; Move the value of Akey into BL
mul bl ; Multiply AX by BL
xor bx, bx ; Clear BX register
mov bl, B ; Move the value of Bkey into BL
add ax, bx ; Add BX to AX
xor bx, bx ; Clear BX register
mov bl, M ; Move the value of Mkey into BL
div bl ; Divide AX by BL
xor bx, bx ; Clear BX register
mov byte ptr Xi, ah ; Move the remainder into Xi
xor ax, ax ; Clear AX register
inc si ; Increment SI to point to the next word in the message
inc di ; Increment DI to point to the next byte in the encrypted message
loop encrypt_loop ; Decrement CX and repeat the loop until CX becomes 0
xor ax, ax
mov al, encryptedMessage ; Swap messages to return encrypted message
mov message, al ; Being stored into origin
pop di ; Restore DI register from the stack
pop si ; Restore SI register from the stack
popa
ENDM
ReadString MACRO str
LOCAL ReadStringLoop, EndReadString, RetryInput, EndInputLabel
RetryInput:
mov cx, bufferSize ;max input length for string limited to 255 due
mov dx, offset str ;place string itself
push cx ; save registers
push si
push cx ; save digit count again
mov si,dx ; point to input buffer
dec cx ; save room for null byte
ReadStringLoop:
mov ah, 1 ; function: keyboard input
int 21h ; DOS returns char in AL
cmp al, 0Dh ; end of line?
je EndReadString ; yes: exit
mov [si], al ; no: store the character
inc si ; increment buffer pointer
loop ReadStringLoop ; loop until CX=0
EndReadString:
mov byte ptr [si], 0 ; end with a null byte
pop ax ; original digit count
sub ax, cx ; AX = size of input string
dec ax
pop si ; restore registers
pop cx
; Check if zero length str
xor ch, ch
mov cl, [str+1]
test cl, cl
jnz EndInputLabel
PrintString emptyinputmsg
jmp RetryInput
EndInputLabel:
ENDM
ReadingFile PROC
ReadFileGetReadMsgLen fileNameIn, bytesCountReadWrite, fileContent, handler_input
RET
ENDP
WritingFile PROC
WriteFileGetWriteMsgLen keyword, fileNameOut, bytesCountReadWrite, fileContent, handler_output
RET
ENDP
start:
InitSet
PrintString inputms
ReadString keyword
encryptFileLoop:
CALL ReadingFile
CALL WritingFile
cmp bytesCountReadWrite, bufferSize
je encryptFileLoop
mov ah, 4Ch ; Exit program
int 21h
end start
我试图只读取文件,但它陷入无限循环而没有写回任何内容。
程序如何运作:
a) 从控制台读取到缓冲区
keyword
b) 尝试打开
input.doc
,但文件夹中没有该文件。 ah = 3dh
、ax = 2
之后,找不到文件
c) 从
output.doc
缓冲区写入 fileContent
,该缓冲区仅包含零。
第一个问题出现在
ReadFileGetReadMsgLen MACRO
。 bx
包含文件名偏移量,但之后有 inc bx
。所以文件名将是(I)NPUT.DOC
。此代码只是将 0
放入消息中。因此屏幕上只会显示部分文本,因为 0
标记字符串结尾。 Can't creat
和Can't wri
。相同的代码位于WriteFileGetWriteMsgLen MACRO
。
lea bx, filename ; 0202h
inc bx ; 0203h
mov al, [bx] ; al = 4eh = 'N'
xor ah, ah ; ah = 0
add bx, ax ; bx = 0203h + 004eh = 0251h
inc bx ; bx = 0252h
xor al,al ; al = 0
mov [bx], al ; [0251] = 0
程序无法打开
INPUT.DOC
,因为没有文件。程序应在 5bh
开头使用服务 ReadFileGetReadMsgLen MACRO
来创建文件或打开现有文件。
服务
3dh
现在工作正常,因为文件是用5bh
创建的
dx
包含 (IN)PUT.DOC
。不存在这样的文件。
lea dx, filename ; dx = 0202h
add dx, 2 ; dx = 0204h
mov ah, 3dh
xor al, al
int 21h
服务
3fh
读取0字节,因为文件input.doc
中没有数据。也许想法是从控制台读取到keyword
缓冲区并将其保存到文件input.doc
。我添加了 proc 来做到这一点Keyword2InputFile
。
然后从
INPUT.DOC
读取到fileContent
缓冲区。好吧,程序可以将 keyword
复制到 fileContent
。
WriteFileGetWriteMsgLen MACRO
。和上面一样的问题。
Encrypt MACRO
、mov al, encryptedMessage
、mov message, al
,只是插入一个字节4b
,我认为代码应该
返回encryptedMessage
中dx
的偏移量,因为我们在加密后使用dx服务40h
。
在
GetStrLen str_chunk, cx
内部,cx = 6
但popa
恢复旧值。所以只有 2 个字节会被保存到 OUTPUT.DOC
。我在这里使用 di
来存储 str_chunk
长度。
代码:
.286
.model small
.stack 100h
.DATA
bufferSize EQU 255
keyword db bufferSize DUP (0)
fileContent db bufferSize DUP (0)
fileNameIn db "INPUT.DOC", 0
fileNameOut db "OUTPUT.DOC", 0
fileNameDec db "DECRYPTED.DOC", 0
bytesCountReadWrite dw 0
inputms db "Please enter keyword: ", 0
emptyinputmsg db "Console input is empty", 0
cantCreateFileMsg db "Can't create file", 0
cantWriteFileMsg db "Can't write file", 0
cantReadFileMsg db "Can't read file", 0
cantOpenFileMsg db "Can't open file", 0
handler_input dw 0
handler_output dw 0
handler_decrypt dw 0
.CODE
InitSet MACRO
mov ax, @data ; Load the segment address of the data segment into AX
mov ds, ax ; Set the data segment register (DS) to the value in AX
mov es, ax ; Set the extra segment register (ES) to the value in AX
; xor ax, ax ; Clear the value in AX by performing an XOR operation with itself
ENDM
GetStrLen MACRO string, strlen
LOCAL count_bytes, end_count
; pusha
push si ; Save SI register on the stack
mov si, OFFSET string ; SI = offset of the string
; Calculate the number of bytes to write
mov cx, 0 ; Initialize byte count to 0
count_bytes:
cmp byte ptr [si], 0 ; Check if end of string
je end_count ; If end of string, jump to end_count
add cx, 1 ; Increment byte count by 1
add si, 1 ; Move to the next byte
jmp count_bytes ; Jump back to count_bytes to process the next character
end_count:
mov strlen, cx ; Store the byte count in the memory location pointed by strlen
pop si ; Restore SI register from the stack
; popa
ENDM
PrintString MACRO string
LOCAL strlen
.data
strlen dw 0
.code
GetStrLen string, strlen
pusha
mov dx, offset string ; Load the offset of the string to print into DX
mov cx, strlen ; Load the length of the string into CX
mov ah, 40h ; Set AH to 40h for writing to file or device
mov bx, 1 ; Set BX to 1 for standard output handle
int 21h ; Call MS-DOS interrupt 21h to write the string
popa
ENDM
ReadFileGetReadMsgLen MACRO filename, bytesRead, s, handler_input
LOCAL readcontent, rt, closeFile, exit_readingfile
;fileNameIn, bytesCountReadWrite, fileContent, handler_input
pusha
; check opened file
mov ax, [handler_input]
test ax, ax
jnz readcontent
mov ah, 5bh ; create file
lea dx, offset filename
mov cx,2
int 21h
cmp ax,50h ; file exists?
jne save_file_handle ; new file created
jmp file_exists
save_file_handle:
mov [handler_input], ax
mov bx,ax
mov ah, 3eh ; closing file handle
int 21h
file_exists:
; getting filename
; lea bx, filename ; INPUT.DOC
; inc bx ; NPUT.DOC
; mov al, [bx]
; xor ah, ah
; add bx, ax
; inc bx
; xor al, al
; mov [bx], al
; open file
lea dx, filename
; add dx, 2
mov ah, 3dh
xor al, al
int 21h
; ax - filehandler or error num
jnc readcontent ; check open error
PrintString cantOpenFileMsg
jmp exit_readingfile
readcontent:
mov [handler_input], ax
mov bx, ax ; read file
mov ah, 3fh
mov cx, bufferSize ; count
lea dx, s ; read to fileContent
int 21h
jnc closeFile ; data saved in input.doc, close file
PrintString cantReadFileMsg
jmp exit_readingfile
closeFile:
mov bytesRead, ax
mov bx,[handler_input]
xor ax, ax
mov ah, 3eh ; closing file handle
int 21h
; mov [handler_input], ax
exit_readingfile:
popa
ENDM
WriteFileGetWriteMsgLen MACRO keyword, filename, bytesWrote, str_chunk, handler_output
LOCAL writecontent, encodeContent, rtwrt, closeOutFile
;keyword, fileNameOut, bytesCountReadWrite, fileContent, handler_output
pusha
; check opened file
mov ax, [handler_output]
test ax, ax
jnz writecontent
mov ah, 5bh ; create file
lea dx, offset filename
mov cx, 2
int 21h
cmp ax,50h ; file exists?
jne save_file_handle ; new file created
jmp file_exists
save_file_handle:
mov [handler_output], ax
mov bx, ax
mov ah, 3eh ; closing file handle
int 21h
file_exists:
; getting filename
; lea bx, filename ; OUTPUT.DOC
; inc bx ; UTPUT.DOC
; mov al, [bx]
; xor ah, ah
; add bx, ax
; inc bx
; xor al, al
; mov [bx], al
; open file
lea dx, filename
; add dx, 2
mov ah, 3ch
mov cx, 2
int 21h
jnc writecontent
PrintString cantCreateFileMsg
jmp exit_writingfile
writecontent:
mov [handler_output],ax
lea si, str_chunk ;filecontent buffer
;mov cx, word ptr [str_chunk]
encrypt keyword, str_chunk
mov bx, [handler_output] ; Write file
mov ah, 40h
;mov cx, [str_chunk]
GetStrLen str_chunk, di
mov cx, di
;lea dx, str_chunk
int 21h
jnc rtwrt
PrintString cantWriteFileMsg
jmp closeOutFile
rtwrt:
cmp ax, bufferSize
jne closeOutFile
closeOutFile:
mov bytesWrote, ax
xor ax, ax
mov ah, 3eh ; Close file
mov bx, ax
int 21h
xor ax, ax
mov [handler_output], ax
exit_writingfile:
popa
ENDM
findX0 MACRO keyword, key0
LOCAL search_loop, strlen
.data
strlen dw 0
.code
pusha
GetStrLen keyword, strlen
mov al, 0 ; Initialize AL register to 0
mov bl, 0 ; Initialize BL register to 0
mov cx, strlen ; Load the length of the keyword into CX
mov bx, offset keyword ; Load the offset of the keyword into BX
search_loop:
mov al, [bx] ; Move the byte at memory location pointed by BX into AL
add key0, ax ; Add the value of AX to key0
rol key0, 8 ; Rotate the bits of key0 to the left by 8 positions
inc bx ; Increment BX to point to the next character in the keyword
loop search_loop ; Decrement CX and repeat the loop until CX becomes 0
popa
ENDM
encrypt MACRO keyword, message ;1
LOCAL encrypt_loop, X0, Xi, strlen, encryptedMessage, A, B, M ; Define local labels for the loop and Xi variable
.data
;keyword, str_chunk
encryptedMessage db bufferSize DUP (0)
strlen dw 0
Xi dw ? ; Define a word-sized variable Xi
X0 dw 0
A EQU 12
B EQU 25
M EQU 56
.code
findX0 keyword, X0
GetStrLen message, strlen
; pusha
; push si ; Save SI register on the stack
; push di ; Save DI register on the stack
mov ax, X0 ; Move the value of X0 into AX
mov Xi, ax ; Move the value of AX into Xi variable
mov cx, strlen
mov si, offset message ; Load the offset of the message into SI
mov di, offset encryptedMessage ; Load the offset of the encrypted message into DI
encrypt_loop:
mov ax, [si] ; Move the word at memory location pointed by SI into AX
xor ax, Xi ; XOR the word with Xi
mov [di], al ; or ax ah ?? byte ptr ax ; Move the result byte by byte into the encrypted message
mov ax, Xi ; Move the value of Xi into AX
mov bl, A ; Move the value of Akey into BL
mul bl ; Multiply AX by BL
xor bx, bx ; Clear BX register
mov bl, B ; Move the value of Bkey into BL
add ax, bx ; Add BX to AX
xor bx, bx ; Clear BX register
mov bl, M ; Move the value of Mkey into BL
div bl ; Divide AX by BL
xor bx, bx ; Clear BX register
mov byte ptr Xi, ah ; Move the remainder into Xi
xor ax, ax ; Clear AX register
inc si ; Increment SI to point to the next word in the message
inc di ; Increment DI to point to the next byte in the encrypted message
loop encrypt_loop ; Decrement CX and repeat the loop until CX becomes 0
xor ax, ax
mov dx, offset encryptedMessage ; Swap messages to return encrypted message
; mov msg_off, dx ; Being stored into origin
; pop di ; Restore DI register from the stack
; pop si ; Restore SI register from the stack
; popa
ENDM
ReadString MACRO str
LOCAL ReadStringLoop, EndReadString, RetryInput, EndInputLabel
RetryInput:
mov cx, bufferSize ;max input length for string limited to 255 due
mov dx, offset str ;place string itself
push cx ; save registers
push si
push cx ; save digit count again
mov si,dx ; point to input buffer
dec cx ; save room for null byte
ReadStringLoop:
mov ah, 1 ; function: keyboard input
int 21h ; DOS returns char in AL
cmp al, 0Dh ; end of line?
je EndReadString ; yes: exit
mov [si], al ; no: store the character
inc si ; increment buffer pointer
loop ReadStringLoop ; loop until CX=0
EndReadString:
mov byte ptr [si], 0 ; end with a null byte
pop ax ; original digit count
sub ax, cx ; AX = size of input string
dec ax
pop si ; restore registers
pop cx
; Check if zero length str
xor ch, ch ; First element of keyword is 0dh
mov cl, [str+1]
test cl, cl
jnz EndInputLabel
PrintString emptyinputmsg
jmp RetryInput
EndInputLabel:
ENDM
ReadingFile PROC
ReadFileGetReadMsgLen fileNameIn, bytesCountReadWrite, fileContent, handler_input
RET
ReadingFile ENDP
WritingFile PROC
WriteFileGetWriteMsgLen keyword, fileNameOut, bytesCountReadWrite, fileContent, handler_output
RET
WritingFile ENDP
start:
InitSet ; ok
PrintString inputms ; ok
ReadString keyword ; ok
call Keyword2InputFile
encryptFileLoop:
CALL ReadingFile
CALL WritingFile
cmp bytesCountReadWrite, bufferSize
je encryptFileLoop
mov ah, 4Ch ; Exit program
int 21h
Keyword2InputFile proc
pusha
mov ah, 5bh ; create file
lea dx, offset fileNameIn ; INPUT.DOC
mov cx, 2 ; attrib rw
int 21h
cmp ax,50h ; file exists?
jne new_file_created ; new file created
jmp open_input_file ; file already exits
new_file_created:
mov [handler_input], ax ; save handle
jmp copy_keyword_2_input_doc
open_input_file:
mov ah, 3dh ; open file
mov al, 2 ; attrib rw
lea dx, fileNameIn
int 21h
mov [handler_input], ax
copy_keyword_2_input_doc:
mov bx, ax
mov ah, 40h
mov cx, bufferSize
lea dx, keyword
int 21h
mov bx, [handler_input]
mov ah, 3eh ; close file
int 21h
xor ax,ax
mov [handler_input], ax
popa
ret
Keyword2InputFile endp
end start