I am working on an assignment and I got stuck somehow. This is the part of the code, that must be wrong. And what is actually wrong is that when the program should print the number (thtough procedure convertNumber, which works fine!), it doesn't do anything, neither it returns. It just doesn't react, I must close it manually.
read:
mov ah, 3fh ; function for reading from file
mov bx, handle ; moving file handle to BX
mov cx, 10000 ; how many bytes will be read
mov dx, buffer ; where the string will be saved
int 21h ; system call ready
mov bytesRead, 0 ; nulling my variable bytesRead, which represents how many bytes have been read
mov bytesRead, ax ; now moving the real value from AX
cmp ax, 0 ; if it is equal to 0, then there is nothing left to read
je closeFile ; close file
mov cx, 0 ; starting position
cycle:
cmp cx, bytesRead ; if I need to reload buffer
jge read
mov bx, 0 ; nulling position counter
mov bx, cx ; moving CX to BX -> mov ax, buffer[cx] was an illegal operation, so I did it this way
mov ax, buffer[bx] ; getting a character from BX. position from buffer
cmp ax, 'a'
jb next ; below 'a', skip
cmp ax, 'z'
ja next ; above 'z', skip
inc count_task ; if it passed, it is between 'a' and 'z'
jmp next ; and moving on
next:
inc cx ; increase position counter (always!)
jmp cycle ; and repeat
finally:
mov ax, count_task ; move the final count to AX (needed by the procedure convertNumber)
call convertNumber ; convert number to its ASCII value (+48)
ret
error_fopen:
print fopenErr
ret
error_fclose:
print fcloseErr
ret
closeFile:
mov ah, 3eh
mov bx, handle
int 21h
jc error_fclose
jmp finally
convertNumber proc near
push si
mov buff, '$'
lea si, buff
mov cx, 10
conv:
mov dx, 0
div cx ; AX is being divided by CX, where value 10 is stored (direct dividing by 10 is not legal)
add dx, 48 ; getting ASCII value of the number (from 0 to '0')
dec si ; going backwards
mov [si], dl
cmp ax, 0
jz printNumber ; if AX is empty (0), print the number
jmp conv ; else loop
printNumber:
mov ah, 9 ; service to print string
mov dx, si ; position of my string (number)
int 21h
pop si
ret
convertNumber endp
I hope you can understand what is going on in this code, if not, I can explain you. I would be very grateful for any help!
A version using lodsb
and loop
shown below, with a couple of other things tidied up. I added a little extra to print the index of each small letter found. I didn't check this for silly errors as I'm not set up to run DOS interrupts.
This code will handle files longer than 65535 bytes long, but the "convertNumber" subroutine would need to be updated to print long integers.
EDIT: The format below assumes the NASM assembler (the actual assembler used isn't mentioned in the problem statemet).
mov [count_task], 0
mov [count_task+2], 0
mov [index], 0
mov [index+2], 0
read:
mov ah, 3fh ; function for reading from file
mov bx, [handle] ; moving file handle to BX
mov cx, 10000 ; how many bytes will be read
mov dx, buffer ; where the string will be saved
int 21h ; system call ready
jc error_read
cmp ax, 0 ; if it is equal to 0, then there is nothing left to read
je finally ; print result and close
; This code assumes your ds segment register already points to your data
lea si, [buffer]
mov cx, ax ; starting loop counter
cld ; clear direction flag (increment)
cycle:
lodsb
cmp al, 'a'
jb next
cmp al, 'z'
ja next
add [count_task], 1
adc [count_task+2], 0
; Print the current index of the found small letter.
; Note it's assumed that convertNumber saves certain registers
; according to calling conventions. For example, if it uses "si"
; then it should save "si". AX, CX, and DX are fair game.
;
push cx
mov ax, [index]
mov dx, [index+2]
call convertNumber ; print the index of the found small letter
pop cx
next:
add [index], 1 ; increment overall index
adc [index+2], 0
loop cycle ; and repeat
jmp read ; read another buffer full
finally:
mov ah, 3eh
mov bx, [handle]
int 21h
jc error_fclose
mov ax, [count_task] ; move the final count to DX:AX (needed by the procedure convertNumber)
mov dx, [count_task+2]
call convertNumber ; convert number to its ASCII value (+48)
ret
error_read:
print freadErr
ret
error_fopen:
print fopenErr
ret
error_fclose:
print fcloseErr
ret