The problem in my program is when I try to take a character from a buffer which contains a string of characters, assign one character to AL
register and call a procedure, which converts the character in AL
to HEX, I get an infinite loop. Here is my code:
.model small
.stack 100H
.data
about db 'example.exe [/?] [sourceFile2]]',13,10,13,10,9,'/? - help',13,10,'$'
err_s db 'Unable to open source file',13,10,'$'
str_term db '$'
sourceF db 12 dup (0)
sourceFHandle dw ?
buffer db 500 dup (?)
.code
START:
mov ax, @data
mov es, ax ; es so we can use stosb function: Store AL at address ES:(E)DI
mov si, 81h
call skip_spaces
mov al, byte ptr ds:[si] ; read first symbol of program parameter
cmp al, 13 ; if there's no parameters
jne _1
jmp help ; then jump to help
_1:
;; do we need to print out help
mov ax, word ptr ds:[si]
cmp ax, 3F2Fh ; if input is "/?" - 3F = '?'; 2F = '/'
jne _2
jmp help ; if "/?" is found, print out help
_2:
;; source file name
lea di, sourceF
call read_filename ; move from parameter to line
push ds
push si
mov ax, @data
mov ds, ax
jmp startConverting
readSourceFile:
pop si
pop ds
;; source file name
lea di, sourceF
call read_filename ; move from parameter to line
push ds
push si
mov ax, @data
mov ds, ax
cmp byte ptr ds:[sourceF], '$' ; if there was nothing to read
jne startConverting
jmp closeF
startConverting:
;; open
cmp byte ptr ds:[sourceF], '$' ; if there was nothing to read
jne source_from_file
mov sourceFHandle, 0
jmp read
source_from_file:
mov dx, offset sourceF ; file name
mov ah, 3dh ; open file command
mov al, 0 ; 0 - reading, 1-writing
int 21h ; INT 21h / AH= 3Dh - open existing file
jc err_source ; CF set on error AX = error code.
mov sourceFHandle, ax ; save filehandle
read:
mov bx, sourceFHandle
mov dx, offset buffer ; address of buffer in dx
mov cx, 500 ; how many bytes to read
mov ah, 3fh ; function 3Fh - read from file
int 21h
mov cx, ax ; bytes actually read
cmp ax, 0 ; if there was nothing to read
jne _6 ; not the end of file
mov bx, sourceFHandle ; end of the file being read
mov ah, 3eh ; close the file
int 21h
jmp readSourceFile ; open another file to read if it was specified in the parameters
_6:
mov si, offset buffer ; read from buffer
cmp sourceFHandle, 0
jne _7
cmp byte ptr ds:[si], 13
je closeF
_7:
push cx ; save big loop CX
sort_out:
lodsb ; Load byte at address DS:(E)SI into AL
push cx ; place cx
mov ah, 40h ; INT 21h / AH= 40h - write to file
int 21h
pop cx
loop sort_out
pop cx
loop read
help:
mov ax, @data
mov ds, ax
mov dx, offset about
mov ah, 09h
int 21h
jmp _end
closeF:
;; close the destination file
mov ah, 3eh ; close
int 21h
result:
MOV si, offset buffer ; source index = buffer coordinates
INC si ; add 1 to si
MOV bh, [si] ; let bh know how many symbols in total
INC si ; go to the symbol itself
mov bl, 0 ; initialize bl counter to 0
jmp char
; print out the text in buffer
mov dx, offset buffer
mov ah, 09h
int 21h
_end:
; add a string terminator to avoid static output
db '$'
mov ax, @data
mov ax, 4c00h
int 21h
char:
LODSB ; take a character from es:si and add it to al
; increment bl
INC bl
MOV dl, al ; add a symbol from al to dl
mov ah,2
int 21h
; try to convert the current symbol in al to HEX and print it out
; =======INFINITE LOOP PROBLEM HERE========
call char_to_hex
DEC bh ; subtract 1 from total amount of symbols
JZ _end ; if bh = 0, end program
JMP char ; if not, jump to other symbol
err_source:
mov ax, @data
mov ds, ax
mov dx, offset err_s
mov ah, 09h
int 21h
mov dx, offset sourceF
int 21h
mov ax, 4c01h
int 21h
;; procedures
skip_spaces PROC near
skip_spaces_loop:
cmp byte ptr ds:[si], ' '
jne skip_spaces_end
inc si
jmp skip_spaces_loop
skip_spaces_end:
ret
skip_spaces ENDP
read_filename PROC near
push ax
call skip_spaces
read_filename_start:
cmp byte ptr ds:[si], 13 ; if there is no parameters
je read_filename_end ; if yes, its the end of the filename
cmp byte ptr ds:[si], ' ' ; if space
jne read_filename_next ; then skip it and jump to the next parameter
read_filename_end:
mov al, '$' ; add '$' to the end
stosb ; Store AL at address ES:(E)DI, di = di + 1
pop ax
ret
read_filename_next:
lodsb ; loads other symbol
stosb ; Store AL at address ES:(E)DI, di = di + 1
jmp read_filename_start
read_filename ENDP
; Char to Hex converting
char_to_hex PROC ; Accept a character, print it's ascii value in hex.
MOV DX, OFFSET AskChar ; Display prompt
MOV AH, 09H
INT 21H
MOV AH, 07H ; Get keyboard input w/ no echo (AL)
INT 21H
MOV CL, AL ; Copy user input (AL) to CL
MOV AX, 0 ; Clear AX (get rid of HO bits)
MOV AL, CL ; Copy user input back into AL
MOV BX, 16 ; Set up the divisor (base 16)
MOV CX, 0 ; Initialize the counter
MOV DX, 0 ; Clear DX
Div2:
; Dividend (what's being divided) in DX/AX pair, Quotient in AX, Remainder in DX.
DIV BX ; Divide (will be word sized).
PUSH DX ; Save DX (the remainder) to stack.
ADD CX, 1 ; Add one to counter
MOV DX, 0 ; Clear Remainder (DX)
CMP AX, 0 ; Compare Quotient (AX) to zero
JNE Div2 ; If AX not 0, go to "Div2:"
getHex2:
MOV DX, 0 ; Clear DX.
POP DX ; Put top of stack into DX.
ADD DL, 30h ; Conv to character.
CMP DL, 39h
JG MoreHex2
HexRet2:
MOV AH, 02h ; 02h to display AH (DL)
INT 21H ; Send to DOS
LOOP getHex2 ; If more to do, getHex2 again
; LOOP subtracts 1 from CX. If non-zero, loop.
JMP Skip2
MoreHex2:
ADD DL, 7h
JMP HexRet2 ; Return to where it left off before adding 7h.
Skip2:
RET
char_to_hex ENDP
end START
My assigment is to get an output like this:
00000000 4d 61 6e 6f 20 62 61 74 61 69 20 62 75 76 6f 20 |Mano batai buvo |
00000010 64 75 2c 0a 56 69 65 6e 61 73 20 64 69 6e 67 6f |du,.Vienas dingo |
00000020 20 2d 20 6e 65 72 61 6e 64 75 2e 0a 41 f0 20 73 | - nerandu..A? s |
00000030 75 20 76 69 65 6e 75 20 62 61 74 75 6b 75 0a 4e |u vienu batuku.N|
00000040 69 65 6b 75 72 20 65 69 74 69 20 6e 65 67 61 6c |iekur eiti negal |
00000050 69 75 2e 0a |iu..|
00000054
Even though my program needs more work to get such a result, I at least would like to get the converting chars to hex part right.
See Question&Answers more detail:
os