Character counting from big files in assembly - file

This should be counting every character in file but its working only for smaller files and i need it to work for files containing more than 32768 characters
fn DB strsize DUP ('$');
bsize equ 32768
buff db bsize dup ('$')
read proc
mov ah,3dh ;open
mov al,0 ; read only mode
mov dx,offset fn ; offset of file name
int 21h ; file handle
jc jmpchyba
ret
endp
BITY proc
mov full,00
mov actual,00
jmpback:
call read
mov actual,00
mov bx,ax;offset buff
mov ah,3fh
mov cx,bsize ; count bytes
mov dx,offset buff
int 21h ;
mov actual,ax
mov bx,actual
add full,bx
cmp actual,bsize
je jmpback
vypis kolko
mov ax,full
call convasci;this is working convert from binary to asci
ret
endp

Firstly define full as a dword. Then use this code
mov actual,ax
mov bx,actual
add full,bx
adc full+2,0
Obviously the conversion routine convasci should also be changed to deal with a dword.
The proc read actually opens the file! You should certainly not keep calling it from the BITY proc.
Rename read as open and place call open before the label jmpback:
Open proc
mov ah,3dh ;open
mov al,0 ; read only mode
mov dx,offset fn ; offset of file name
int 21h ; file handle
jc jmpchyba
ret
endp
BITY proc
mov full,0
mov full+2,0
call Open
mov bx,ax ;Handle!!!
jmpback:
mov actual,00
mov ah,3fh
mov cx,bsize ; count bytes
mov dx,offset buff
int 21h ;
mov actual,ax
add full,ax
adc full+2,0
cmp ax,bsize
je jmpback

Related

How to scan symbols from file with 16-bit DOS calls

I have a task to calculate how many characters are in a .txt file whose name the user enters and edit characters if needed. I am new at Assembly x86 so I need some help with file reading and symbols reading in a file.
As my code below shows I use int 21,3d to open the file and int 21,3f to read the file. But I don't understand how to read symbols from file correctly, because if I have 100 random symbols in my txt file, how to read one by one and count them all?
My code:
.data
fname_input db 255,?,255 dup("$")
buff db 255,?,255 dup("$")
endl db 13,10,"$"
handle dw ?
.code
start:
mov dx, #data
mov ds, dx
mov ah, 0Ah
mov dx, offset fname_input ;input put in to buffer
int 21h
mov ah, 3fh
mov al, 00 ;only read
mov dx, offset fname_input ; name of the file to open
int 21h
mov ah,3fh
mov bx,[handle]
mov cx,4
mov dx,offset buff
int 21h
mov ax, 4c00h ;exit
int 21h
end start
Corrections to the code.
mov ah, 3fh
mov al, 00 ;only read
mov dx, offset fname_input ; name of the file to open
int 21h
mov ah,3fh
mov bx,[handle]
mov cx,4
mov dx,offset buff
int 21h
It's maybe a typo, but the DOS.OpenFile function is 3Dh (so not 3fh)
The filename is not at the address of offset fname_input. That's where you defined the input structure for the DOS.BufferedInput function 0Ah.
The actual filename starts 2 bytes higher up in memory, and for now is terminated by the code 13. You must change this code to 0 before you can present this to the DOS.OpenFile function.
You must never omit checking for any errors reported by DOS!
Your DOS.ReadFile function 3Fh uses the handle variable even before you initialized it!
Way to solve the task
The simplest(1) solution will read the file one byte at a time, until the read function reports it could not fulfil the request. That will happen at file's end.
For every byte you receive, you can increment a counter for establishing the file length, and if you find that the byte needs changing, then you can set the file pointer one position back and write the new character code to the file. Because you not only need read access to the file, you'll have to ask DOS for read/write access when you open the file.
mov si, offset TheBuffer
mov word ptr [si], 0050h ; Set both lengths for DOS.BufferedInput
mov dx, si
mov ah, 0Ah ; DOS.BufferedInput
int 21h
xor bx, bx
mov bl, [si + 1] ; Length of the filename
mov [si + 2 + bx], bh ; Changing carriage return 13 into zero-terminator 0
lea dx, [si + 2] ; ASCIIZ Filename
mov ax, 3D02h ; DOS.OpenFile for read/write
int 21h ; -> AX CF
jc ERROR
mov [handle], ax
MainLoop:
mov dx, offset TheBuffer
mov cx, 1
mov bx, [handle]
mov ah, 3Fh ; DOS.ReadFile
int 21h ; -> AX CF
jc ERROR
cmp ax, cx
jb EOF
...
jmp MainLoop
EOF:
mov bx, [handle]
mov ah, 3Eh ; DOS.CloseFile
int 21h ; -> AX CF
mov ax, 4C00h ; DOS.Terminate
int 21h
TheBuffer db 512 dup (0)
At the ellipsis in the above code snippet, you can do anything you need to do with that one byte that you received.
In order to set the filepointer one position back so you can update the file with the new character that you prepared in TheBuffer, you need to use the DOS.MoveFilepointer function 42h. Use it with a 32-bit offset of -1 in CX:DX.
mov dx, -1
mov cx, -1
mov bx, [handle]
mov ax, 4201h ; DOS.MoveFilepointer from current position
int 21h ; -> DX:AX CF
jc ERROR
mov dx, offset TheBuffer
mov cx, 1
mov bx, [handle]
mov ah, 40h ; DOS.WriteFile
int 21h ; -> AX CF
jc ERROR
(1) A solution that reads more than 1 byte at a time will be more efficient, albeit somewhat more involved. In such case defining a buffer of 512 bytes is best. It nicely matches the disk sector size and the buffers that DOS maintains.

x86 Array not printing out to screen [duplicate]

This question already has answers here:
why does the interruption int 21h ignore all strings after writing a string filled durring the execution of the program?
(2 answers)
Weird garbage in output
(1 answer)
Assembly, printing ascii number
(4 answers)
Displaying Time in Assembly
(3 answers)
How to index arrays properly in x86 assembly
(4 answers)
Closed 1 year ago.
I am working on an assembly assignment for school. The objective is to take two numbers from user input, add them and then output the result on screen. However, the array, output, that holds the results of the operations to be outputted will not print out to the screen whatsoever. I am really not sure exactly what is wrong here. My print_output function works as a whole since it will print out other strings and arrays if I tell it to do so. Due to this I think I might have an indexing issue with accessing the input array for the data need for the operations that causes issues later or maybe something with my arithmetic but that is really my only hunch. Thanks for any help with this. Note: In response to Michael's comment I edited the program back for the array to terminate in a $ but the problem was still occuring past that.
.model small
.stack 64
.data
Prompt DB 'Enter a number between 10 and 49 number: ', '$'
Prompt2 DB 'Enter another number between 10 and 49 number: ', '$'
StrPar LABEL BYTE
StrPar2 LABEL BYTE
Actual_Len DB 4
Chars DB 4 DUP('$')
output DB 4 DUP('$')
.code
MAIN proc FAR
mov AX,#data
mov DS,AX
call Clear
call Set_Cursor
call Request_Input
call Get_Input
call Add_Input
call Clear
call Set_Cursor
call Request_Input2
call Get_Input
call Clear
call Set_Cursor
call Add_Input2
call Prep_Output
call Print_Output
mov AX,4C00h
int 21h
MAIN endp
;________________________
Clear proc NEAR
mov AX, 06H
mov AL, 00H
mov BH, 71H
mov CX, 0000H
mov DX, 184FH
int 10H
ret
Clear endp
;__________________________
Set_Cursor proc NEAR
mov AH, 02H
mov BH, 0
mov DH, 10
mov DL, 5
int 10H
ret
Set_Cursor endp
;___________________________
Request_Input proc NEAR
mov AH, 09H
lea DX,Prompt
int 21H
ret
Request_Input endp
;___________________________
Request_Input2 proc NEAR
mov AH, 09H
lea DX,Prompt2
int 21H
ret
Request_Input2 endp
;__________________________
Get_Input proc NEAR
mov AH, 0AH
lea DX, StrPar
int 21H
mov BH,00
mov BL,Actual_Len
mov Chars[BX],'$'
ret
Get_Input endp
;__________________________
;_________________________
Add_Input proc NEAR
mov AH, 00
mov DX, 00
mov BX,1
mov DL, Chars[BX]
sub DL,48
mov AX,10
mul DX
mov DX,AX
mov BX,2
mov CX,00
mov CL, Chars[BX]
sub CX,48
add DX,CX
ret
Add_Input endp
;______________________
Add_Input2 proc Near
mov AX,00
mov BX,1
mov CL, Chars[BX]
sub CX, 48
mov AX,10
mul CX
mov CX,AX
mov BX,2
mov BL, Chars[BX]
sub BL,48
mov BH,00
add CX,BX
ret
Add_Input2 endp
;______________________
Prep_Output proc NEAR
mov AX,00
add DX,CX
mov AX,DX
mov BX,10
div BL
add AL,48
add AH,48
mov BX, 1
mov output[BX],AL
mov BX, 2
mov output[BX],AH
ret
Prep_Output endp
;________________________
Print_Output proc NEAR
mov AH, 09H
lea DX, output
int 21H
ret
Print_Output endp
end MAIN

Read a line from File and pass it to variable, then proceed to next line (Assembly 8086)

this is my first post so I'm sorry in advance if I did it wrongly (in any ways).
So what I am facing now is, I have a a file (name.txt) and I want to pass the first line to buffer1 , second line to buffer2 and so on.
Extra Info :
The maximum line of the file is going to be 10.
The maximum length of the string is 27(data)+1(dollar sign)+2(CR LF) or so I think.
I created 5 buffer for this example
The example of the string is "1washingmachine"
name.txt is already created
.
.model small
.stack 64
.data
filename db "name.txt",0
handler dw ?
strPrompt db 10,13,"enter:$"
strInput label byte
max db 28 ;max name is 20 , + 1 for index , 6 for time , 1 for $
act db ?
data db 28 dup ('$')
buffer1 db 30 dup ('$')
buffer2 db 30 dup ('$')
buffer3 db 30 dup ('$')
buffer4 db 30 dup ('$')
buffer5 db 30 dup ('$')
newLine db 10,13
.code
main proc far
;INITIALIZE DATA SEGMENT.
mov ax,#data
mov ds,ax
;CREATE FILE.
mov ah, 3dh
mov al, 2
lea dx, filename
int 21h
;PRESERVE FILE HANDLER RETURNED.
mov handler, ax
;READ STRING
MOV AH, 3FH ; read file
MOV BX, handler ; copy handle into BX
MOV CX,30 ; set count to read 28+2
lea dx,buffer1
INT 21H ; AX = bytes read
MOV AH, 3FH ; read file
MOV BX, handler ; copy handle into BX
MOV CX,30 ; set count to read 28+2
lea dx,buffer2
INT 21H
MOV AH, 3FH ; read file
MOV BX, handler ; copy handle into BX
MOV CX,30 ; set count to read 28+2
lea dx,buffer3
INT 21H
MOV AH, 3FH ; read file
MOV BX, handler ; copy handle into BX
MOV CX,30 ; set count to read 28+2
lea dx,buffer4
INT 21H
MOV AH, 3FH ; read file
MOV BX, handler ; copy handle into BX
MOV CX,30 ; set count to read 28+2
lea dx,buffer5
INT 21H
mov ah,09h
lea dx,buffer1
int 21h
mov ah,09h
lea dx,buffer2
int 21h
mov ah,09h
lea dx,buffer3
int 21h
mov ah,09h
lea dx,buffer4
int 21h
mov ah,09h
lea dx,buffer5
int 21h
;input string to write in file
mov ah,09h
lea dx,strPrompt
int 21h
mov ah,0ah
lea dx,strInput
int 21h
;WRITE STRING.
mov ah, 40h
mov bx, handler
mov ch,0
mov cl, act ;STRING LENGTH.
inc cx
mov dx, offset data
int 21h
lea dx,newLine
mov bx,handler
mov cx,2
mov ah,40h
int 21h
;CLOSE FILE (OR DATA WILL BE LOST).
mov ah, 3eh
mov bx, handler
int 21h
;FINISH THE PROGRAM.
mov ax,4c00h
int 21h
main endp
end main
Hopefully someone from StackOverflow can help me with this, either guidance or solution will do !

read and write from a txt file (assembly)

I am writing a project in assembly language and I have a problem with read from a file and print on the screen what is written in it.
I took part of the code (which is the read and print part) and I tried to fix it and re write it and i still have a problem.
If someone can help me I'll be more then happy
this is the code :
org 100h
mov ah,0ah
mov dx,offset place
int 21h ; getting the place(directory) of the file
mov si,offset place
inc si
mov dx,[si]
inc dx
mov si,dx
mov [si],0
mov ah,02
mov dl,13
int 21h
mov ah,02
mov dl,10
int 21h
mov ah,0ah
mov dx,offset filename
int 21h ;getting the file name
mov si,offset filename
inc si
mov dx,[si]
inc dx
mov si,dx
mov [si],0
mov ah,02
mov dl,13
int 21h
mov ah,02
mov dl,10
int 21h
call gotoplace ;go to the place of the file
;------------------
call openfile ;open the file
;------------------
mov ah,3fh
mov si,offset filehandle
mov bx,[si] ;move file adress to bx
mov cx,40000 ;numbers of bytes to read
mov dx,offset buff ;pointer to read buffer
int 21h
mov si,offset filesize ;move si pointer to filesize
mov [si],ax ;move to filesize how many bytes read
;------------------
;writing on the screen ->
mov bx,offset buff ;move bx pointer of buffer
mov si,offset filesize
mov cx,[si] ;move cx how many to write
startwrite:
mov ah,2
mov dl,[bx] ;move dl letter in place [bx]
int 21h
inc bx
dec cx
jnz startwrite
proc gotoplace
mov ah,3bh
mov dx,offset place ;move offset place to dx
add dx,2
int 21h
ret
endp gotoplace
proc openfile
mov ah,3d
mov al,2 ;open for read / write
mov dx,offset filename ;move dx offset filename
add dx,2
int 21h
;--------------------------
mov si,offset filehandle ;move offset filehandle(location in the memory) to si
mov [si],ax ;move the file adress to the 'filehandle'(location in the meory'
ret
endp openfile
ret
filehandle dd ?
filename db 40
db 42 dup (0)
place db 40
db 42 dup (0)
buff db 40000 dup (0)
filesize dd ?
And this is the function that read and write :
proc readprint
call gotoplace ;go to the place of the file
;------------------
call openfile ;open the file
;------------------
mov ah,3fh
mov si,offset filehandle
mov bx,[si] ;move file adress to bx
mov cx,40000 ;numbers of bytes to read
mov dx,offset buff ;pointer to read buffer
int 21h
mov si,offset filesize ;move si pointer to filesize
mov [si],ax ;move to filesize how many bytes read
;------------------
mov ah,2
mov bh,0
mov dh,1
mov dl,1
int 10h ;Move the cursor to the start of the page
;writing on the screen ->
mov bx,offset buff ;move bx pointer of buffer
mov si,offset filesize
mov cx,[si] ;move cx how many to write
startwrite:
mov ah,2
mov dl,[bx] ;move dl letter in place [bx]
int 21h
inc bx
dec cx
jnz startwrite
;------------------
ret
endp readprint
These are the problems in your code :
In proc openfile you use the number 3d that should be 3dH.
After capturing "place" and "filename" you insert chr(0) at the end of both strings, but you are doing mov dx,[si], which is an error because the length of the string (pointed by [si]) is one byte, and you are moving two bytes to dx.
The file size type is DD but it should be DW, remember you will use this number in cx to write to screen, that's why it must be DW.
You forgot to finish the program properly.
There is another problem that it's not your fault. EMU8086 has an issue when opening files. EMU8086 runs programs in subdirectory c:\emu8086\mybuild, sometimes EMU8086 doesn't allow to open files outside the subdirectory mybuild. In order to work with files in EMU8086, store them in c:\emu8086\mybuild.
Next is your code. I fixed the problems and commented the code that changes the subdirectory, changes are pointed by arrows <========= :
org 100h
;mov ah,0ah
;mov dx,offset place
;int 21h ; getting the place(directory) of the file
;ADD 0 TO END OF STRING <==================================
;mov si,offset place
;inc si
;mov dl,[si] ;<== LENGTH OF STRING IS BYTE, NOT WORD
;mov dh,0 ;<================== CLEAR DH TO USE DX
;inc dx
;add si,dx ;<========= SI POINTS TO FINAL CHAR + 1
;mov [byte ptr si],0 ;<========= THE NUMBER ZERO HAS NO SIZE
;LINE BREAK.
;;mov ah,02
;mov dl,13
;int 21h
;mov ah,02
;mov dl,10
;int 21h
mov ah,0ah
mov dx,offset filename
int 21h ;getting the file name
;ADD 0 TO END OF STRING <==================================
mov si,offset filename
inc si
mov dl,[si] ;<== LENGTH OF STRING IS BYTE, NOT WORD
mov dh,0 ;<================== CLEAR DH TO USE DX
inc dx
add si,dx ;<========= SI POINTS TO FINAL CHAR + 1
mov [byte ptr si],0 ;<========= THE NUMBER ZERO HAS NO SIZE
;LINE BREAK.
mov ah,02
mov dl,13
int 21h
mov ah,02
mov dl,10
int 21h
;call gotoplace ;go to the place of the file
;------------------
call openfile ;open the file
;------------------
mov ah,3fh
mov si,offset filehandle
mov bx,[si] ;move file adress to bx
mov cx,40000 ;numbers of bytes to read
mov dx,offset buff ;pointer to read buffer
int 21h
mov si,offset filesize ;move si pointer to filesize
mov [si],ax ;move to filesize how many bytes read
;------------------
;writing on the screen ->
mov bx,offset buff ;move bx pointer of buffer
mov si,offset filesize
mov cx,[si] ;move cx how many to write
startwrite:
mov ah,2
mov dl,[bx] ;move dl letter in place [bx]
int 21h
inc bx
dec cx
jnz startwrite
;WAIT UNTIL USER PRESS ANY KEY <===========================
mov ah,7
int 21h
;FINISH PROGRAM <==========================================
mov ax, 4c00h
int 21h
proc gotoplace
mov ah,3bh
mov dx,offset place ;move offset place to dx
add dx,2
int 21h
ret
endp gotoplace
proc openfile
mov ah,3dH
mov al,2 ;open for read / write
mov dx,offset filename ;move dx offset filename
add dx,2
int 21h
;--------------------------
mov si,offset filehandle ;move offset filehandle(location in the memory) to si
mov [si],ax ;move the file adress to the 'filehandle'(location in the meory'
ret
endp openfile
ret
filehandle dd ?
filename db 40
db 42 dup (0)
place db 40
db 42 dup (0)
buff db 40000 dup (0)
filesize dw ? ;<========= IN 8086 WE CANNOT READ MORE THAN 64KB.

Cannot find error in this simple assembly program

I am working with the following 16-bit assembly code:
.model tiny
.code
ORG 100H
FILE_NAME EQU 9EH ;DTA Position after execution of search_first_file
START:
mov ah,9 ;Print start message
mov dx,OFFSET STR_START
int 21H
mov ah,4EH ;Search first file
mov dx,OFFSET PATH
int 21H
jc NO_FILE_FOUND
FILE_FOUND:
mov ah,9 ;Print file found message
mov dx,OFFSET STR_FILE_FOUND
int 21H
mov ah,3DH ;Open file to write
mov al,01H
mov dx,FILE_NAME
int 21H
mov ah,9 ;Print file opened message
mov dx,OFFSET STR_FILE_OPENED
int 21H
mov ah,40H ;Write code
mov bx,ax
mov dx,100H
mov cx,44
int 21H
mov ah,9 ;Print file written message
mov dx,OFFSET STR_FILE_WRITTEN
int 21H
mov ah,3EH ;Close file
int 21H
mov ah,4FH ;Search next
int 21H
jnc FILE_FOUND
NO_FILE_FOUND:
ret
PATH db 'C:\comfiles_folder\HOST.COM',0
STR_START db 'program started!',0
STR_FILE_FOUND db 'file found!',0
STR_FILE_OPENED db 'file opened!',0
STR_FILE_WRITTEN db 'code written!',0
END START
This program basically searches the folder comfiles_folder at the path C:\comfiles_folder\HOST.COM and writes its own code to the file that is found.
I debugged it using CodeView and found out that it is not able to find the HOST.COM file. Can someone please tell me what is wrong?
Find First File call needs one parameter more.
You didn't set file attributes in register cx before Int 21 0x4E (Find Fist File) call.

Resources