I'm writing a program that converts digits into words and also writes every other character unchanged to output file. But for some reason the output buffer overwrites characters on top of each other.
Ex. input file looks like this: 0a
the output file should look like this: nulisa
Instead it looks like this: aulis
Here's what I have so far:
.model small
.stack 100h
.data
msgHelp DB "Usage: program.exe <input_file> <output_file>$"
msgFileError DB "Error: File not found or cannot be opened.$"
input db 200 dup (0)
output db 200 dup (0)
skBuf db 20 dup (?)
raBuf db 200 dup (?)
words db "nulis", 0, "vienas", 0, "du", 0, "trys", 0, "keturi", 0, "penki", 0, "sesi", 0, "septyni", 0, "astuoni", 0, "devyni", 0
wordOffsets dw 0, 6, 13, 16, 21, 28, 34, 39, 47, 55
dFail dw ?
rFail dw ?
raBufPos dw 0
.code
start:
MOV ax, @data
MOV ds, ax
MOV di, offset raBuf
MOV bx, 82h
MOV si, offset input
cmp byte ptr es:[80h], 0
je help
cmp es:[82h], '?/'
jne check_param
cmp byte ptr es:[84h], 13
je help
jmp check_param
help:
mov ah, 9
mov dx, offset msgHelp
int 21h
jmp programEnd
check_param:
cmp byte ptr es:[bx], 13
je next_filename
cmp byte ptr es:[bx], 32
je next_filename
mov dl, byte ptr es:[bx]
mov [si], dl
inc bx
inc si
jmp check_param
next_filename:
inc bx
mov si, offset output
output_filename_loop:
cmp byte ptr es:[bx], 13
je found
mov dl, byte ptr es:[bx]
mov [si], dl
inc bx
inc si
jmp output_filename_loop
found:
MOV ah, 3Dh
MOV al, 00
MOV dx, offset input
INT 21h
JC file_error
MOV dFail, ax
MOV ah, 3Ch
MOV cx, 0
MOV dx, offset output
INT 21h
JC file_error
MOV rFail, ax
read:
MOV bx, dFail
CALL ReadBuf
CMP ax, 0
JE closeInput
MOV cx, ax
MOV si, offset skBuf
processLoop:
MOV dl, [si]
CMP dl, '0'
JB notDigit
CMP dl, '9'
JA notDigit
PUSH cx
PUSH si
PUSH di
CALL ConvertDigitToWord
POP di
POP si
POP cx
JMP skip
notDigit:
MOV [di], dl
INC di
INC raBufPos
skip:
INC si
DEC cx
JNZ processLoop
writeOutput:
MOV cx, raBufPos
MOV bx, rFail
MOV dx, offset raBuf
CALL WriteBuf
MOV di, offset raBuf
MOV raBufPos, 0
JMP read
file_error:
MOV ah, 09h
MOV dx, offset msgFileError
INT 21h
jmp programEnd
closeOutput:
MOV ah, 3Eh
MOV bx, rFail
INT 21h
JC file_error
closeInput:
MOV ah, 3Eh
MOV bx, dFail
INT 21h
programEnd:
MOV ah, 4Ch
MOV al, 0
INT 21h
ConvertDigitToWord PROC
SUB dl, '0'
MOV cl, dl
MOV si, offset wordOffsets
MOV bx, cx
SHL bx, 1
ADD si, bx
MOV ax, [si]
ADD ax, offset words
MOV si, ax
copyWord:
MOV al, [si]
CMP al, 0
JE doneCopy
MOV [di], al
INC di
INC si
INC raBufPos
JMP copyWord
doneCopy:
RET
ConvertDigitToWord ENDP
ReadBuf PROC
MOV ah, 3Fh
MOV bx, dFail
MOV cx, 20
MOV dx, offset skBuf
INT 21h
RET
ReadBuf ENDP
WriteBuf PROC
MOV ah, 40h
MOV bx, rFail
MOV cx, raBufPos
MOV dx, offset raBuf
INT 21h
RET
WriteBuf ENDP
END start
PUSH cx PUSH si PUSH di CALL ConvertDigitToWord POP di POP si POP cx
The DI register is currently only input to the ConvertDigitToWord procedure. But for your program it should also be output from this procedure. Solve it quickly by removing the PUSH di
and POP di
instructions.
Both DI and raBufPos play a similar role. You don't need that raBufPos variable.
Just setup DI like you're already doing in mov di, offset raBuf
and where you need the output length you can replace MOV cx, raBufPos
by lea cx, [di - raBuf]
. If your assembler does not accept this, then write it as mov cx, di
sub cx, offset raBuf
.
ps. Please edit your post and enclose your whole program between tripple backtick characters.