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.
Related
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.
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 !
I'm trying to test my code on emu, but the problem is that I get errors.
open_files:
lea dx, filename_asm
mov ah, 3Dh ; 3Dh - opening the file
mov al, 00h ; 00h - reading
int 21h
mov handle_asm, ax
jc fopen_error
lea dx, filename_htm
xor ax, ax
mov ah, 3Ch ; 3dh - making of the file or clearing it
mov cx, 00h ; 00h - normal
int 21h
mov handle_htm, ax
jc fopen_error
jmp html_1
fopen_error:
lea dx, show_error_msg
mov ah, 09h
int 21h
call exit_pro
html_1:
call write_html_1
I get error "interrupt error: 21h/3Dh : cannot open file.".
What I've been reading is that I need to put the code txt file in the emu8086 vdrive C folder, which I've done. I'm trying to set command line arguments as " c:\ antra.exe antra.asm antra.htm". Should I specify the path or something?
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
I am trying to read a string from a file and print it on the screen, but I always get an error at opening the file. Why is this happening? What is wrong with the code or with the file? PS: the file is in the same folder as the .asm file.
ASSUME cs: code, ds:data
data SEGMENT
inputFile db "D:\AC\input.txt", 0
openingError db 'An error has occured at opening the file!$'
readingError db 'An error has occured at reading the file!$'
s1 db 10 dup(?)
ls db 0
handle dw ?
data ENDS
code SEGMENT
start:
mov ax,data
mov ds,ax
;open the file
mov ah, 3dh
mov al, 0
mov dx, offset inputFile
int 21h
mov handle, ax
jc openError
;read 10 bytes from the file into s1
mov ah, 3fh
mov bx, handle
mov cx, 10
mov dx, offset s1
int 21h
jc readError
openError:
mov ah, 09h
mov dx, offset openingError
int 21h
jmp the_end
readError:
mov ah, 09h
mov dx, offset readingError
int 21h
jmp the_end
;close file
mov ah, 3eh
mov bx, handle
int 21h
;print string on the screen
lea dx, s1
mov ah, 09h
int 21h
the_end:
mov ax,4C00h
int 21h
code ENDS
END start
Did youi forget to actually open the file? Where is the int 21?
mov ah, 3dh
mov al, 0
lea dx, inputFile
int 21h
jc openingError
mov handle, ax