I am trying to encrypt binary file. But program does not encrypt anything and it gets errors when writing file on disk. So I dont get encrypted file on disk and program stucks with infinite loop printing unknown symbols. Can you help me out and fix code, please.
.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
I was trying to just read file but it stuck at infinite loop without writing anything back.
How program works:
a) reads from console to buffer keyword
b) try to open input.doc
, but there is no such file in folder. After ah = 3dh
, ax = 2
, file not found
c) writes to output.doc
from fileContent
buffer, which contains only zeros.
First problem occurs in ReadFileGetReadMsgLen MACRO
. bx
contains filename offset, but after that there is inc bx
. So file name will be (I)NPUT.DOC
. This code just puts 0
inside messages. So only part of text will appear on screen, because 0
marks end of string. Can't creat
and Can't wri
. Same code is in 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
Program can't open INPUT.DOC
, because there is no file. Program should use service 5bh
at the begining of ReadFileGetReadMsgLen MACRO
to create file or open existing file.
Service 3dh
works fine now because file was created with 5bh
dx
contains (IN)PUT.DOC
. No such file exists.
lea dx, filename ; dx = 0202h
add dx, 2 ; dx = 0204h
mov ah, 3dh
xor al, al
int 21h
Service 3fh
reads 0 bytes because there is no data in file input.doc
. Maybe idea was to read from console to keyword
buffer and save this to file input.doc
. I added proc which does that Keyword2InputFile
.
And then read from INPUT.DOC
to fileContent
buffer. Well, program could just copy keyword
to fileContent
.
WriteFileGetWriteMsgLen MACRO
. Same problems as above.
Encrypt MACRO
, mov al, encryptedMessage
, mov message, al
, it's just insertion of one byte 4b
, I think code should
return offset to encryptedMessage
in dx
, because we use dx service 40h
after encyption.
Inside GetStrLen str_chunk, cx
, cx = 6
but popa
restores old value. So only 2 bytes will be saved to OUTPUT.DOC
. I used di
here to store str_chunk
length.
Code:
.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