hey im a beginner in assembly ,, i wont to open a file and read value " integer "
from it and save the integer in buffer to print on the screen this is my code it doesn't work
include inout.asm
.model small,c
.486
.stack
.data
org 100h ; .com memory layout
buf db ?
file db "c:\rtasm\bin\file.txt";the file name in bin
.code
mov dx, offset file ; address of file to dx
mov al,0 ; open file (read-only)
mov ah,3dh
int 21h ; call the interupt
mov bx,ax ; put handler to file in bx
mov ah,40h
mov bx,ax
mov cx,2h ;; how many bytes you want to read
mov dx,offset buf ;; where you want to store that data (see note on Offset above)
int 21h
call putchar,offset buf; print char on the screen
mov ah,3eh
mov bx,ax
int 21h
.exit
END
Int 21h function 3Dh ("OPEN EXISTING FILE") expects a zero-terminated string in ds:dx. The string you're supplying doesn't have a zero terminator. The filename should be declared as file db "c:\rtasm\bin\file.txt",0.
Both function 3Dh and 40h return error codes if they fail. You should check for these and inform the user (yourself in this case) if an error has occurred, rather than assuming that the operations always will succeed.
Another problem is the following code:
mov bx,ax ; put handler to file in bx
mov ah,40h
mov bx,ax <-- gives you a nonsense file handle since ah now is 40h
mov cx,2h ;; how many bytes you want to read
mov dx,offset buf ;; where you want to store that data (see note on Offset above)
int 21h
The second mov bx,ax is unnecessary since bx already contains the file handle. In fact, it's not only unnecessary but also incorrect since you've overwritten the high part of ax (ah) with the value 40h.
There's also the fact that you're reading two bytes into a buffer that only has room for one byte.
Related
I've been tasked to create a very basic text editor as a project. I'm currently trying to take an argument on the command line, open the file, read it, etc. The issue I'm having is either I'm not understanding where in memory the contents of the text file are being put, or I do understand but for some reason it's not being put there.
This is my code so far
org 100h
jmp start
inHandle dw ?
charAmount dw ?
buff db 100 dup (?)
start :
xor bx, bx
mov bl, [80h] ; length of string from command line
cmp bl, 126 ; check length
ja exit ; if above the length, exit
mov [bx+81h], 0 ; add 0 to the end of the string
;*** open file***
mov ah, 3Dh ; open existing file
mov al, 0 ; read only
mov dx, 82h ; offset of string
int 21h
mov inHandle, ax ; save the handle
jc err ; carry flag set, jump to error block
;**Note i wont include the err code block, it just displays an icon on a video window to tell me it went wrong;
jmp continue
;***I know this continue is probably redundant since it will go here on its own
continue: nop
mov ah, 42h ; Seek end of file
mov bx, inHandle ; Bx takes the handle
mov al, 2 ; end of file plus offset
mov cx, 0 ; Upper order of bytes to move
mov dx, 0 ; Lower order of bytes to move
int 21h
mov charAmount, ax ; store the length in charAmount (My file has 13 for example, so this returned 13 after seeking the end of file)
;*******READ FILE******
mov ah, 3Fh ; Read file
mov bx, inHandle ; Takes the handle
xor cx, cx
mov cx, charAmount ; Counter set to the length
mov dx, offset buff ; set to buffer I defined
int 21h
exit: nop ; (was used for the error code I didnt include)
end start
So I'm confused about the read file. I'm a bit unsure what passing something called buffer to dx does. Is it an offset to give? I'm reading in documentation it says DS:DX is the pointer to read buffer. After I run my code, DS is 0700, and DX is 0112. So I look in the memory at 0700:0112 but I don't see the string from my file. It's just all 0's.
Did I do something wrong? Am I forgetting something? Or am I not understanding at all where in memory this should be and I'm just looking at the wrong address. This is very frustrating and I'd appreciate the help. Thanks. I'm doing this in emu8086 by the way.
I'm trying to use a user inputted string to create a file. I'm using 0Ah function to get the user input. I think the error occurs once I use 3Ch to create the file. The code I'm using to create the file is:
mov ah, 3Ch ; create file
mov cx, 0
mov dx, offset filename + 2 ; where the characters start
since user input string
starts 3 bytes over
int 21h
mov handle, ax ; save file handle
Then I have a loop that basically writes a string to the file using 40h
WRITE:
mov ah, 40h ; write
mov bx, handle
mov cx, lstring ; length of string
mov dx, offset string
int 21h
loop WRITE ; I know it's a infinite loop, just an example
The error is "Phase error between passes" points to the "WRITE:" line, but it seems that if I remove the WRITE label it will put the error on the next label. From what I can google, there's something wrong with the variables in that the second pass as it sees them as a different size? How do I fix this error?
Here's my code before I hit the first label
.code
main:
mov ax, #data
mov ds, ax
mov ax, 4000h ; set up display string
mov bx, 1 ; to monitor
mov cx, lstring1 ; length of string1
mov dx, OFFSET string1
int 21h
mov ah, 0Ah ; set up service to capture buffered input
mov dx, offset filename ; where to find the input
int 21h
mov ah, 3Ch ; dos service to create file
mov cx, 0
mov dx, offset filename + 2 ; I still to need add NULL to the end of filename
int 21h
mov handle, ax ; save file handle
On further messing around, it seems if I deleted the code that outputs to monitor with the 4000h, the error disappears.
You say that you get the user input via DOS function 0Ah. This function delivers you a CR-terminated string. But the subsequent DOS function 3Ch to create a file expects a ZERO-terminated string. There's no knowing what could have been created!
You don't actually save the handle. Better use
mov handle, ax ; save file handle
Phase error comes up when a label is assumed in data segment and not present in code segment. To fix it you can assume ds:code-seg OR by mov ax,cs:label. Qualify the label that gives phase error
I have an assignment from school. I have to read any file in size to 128KB and write its content on screen.
I use function 3Dh for opening specific file and then function 3Fh to read a file. I use 32KB buffer for it.
I face few problems now.
Have 59KB .txt file with some text from book and also some of my codes.
When I want to get size of file in Bytes, it runs fine and result is correct.
When I want to print content of file It, prints everything to the point where occurs '$' character in file. So I need somehow escape all special characters as '$' is to print whole and any file.
Have 380KB .csv file
When I print it, it is printed fine, whole file, all 380KB.
But, when I want to get size, it returns just 2186 B. When I don't close file at the end of procedure and call this procedure again and again, it returns always size in bytes as multiple of 2186 B (4372, 6558, etc.).
I copied 126KB from previous .csv to another
Again print is ok (there are no '$' chars).
When I get size it returns 64063 B so again wrong result.
Here are my procedures.
buffsiz equ 32768 ;buffer size =32KB
fnsize equ 255 ;filename size =255
data segment
maxlen db fnsize ;max length of file name
len db ? ;length of filename
file db fnsize dup (?) ;file name
filesiz dd ? ;dword variable of file size
buffer db buffsiz dup ('$') ;32KB buffer
;...
data ends
getcont proc ;get content of file procedure
mov ah,3dh ;open file function
mov al,0 ;read-access bit
call forout ;just bring 0 char on the end of filename
mov dx,offset file ;"move filename" to dx
int 21h
mov bx,ax ;move filehandler from ax to bx
buffIn: prntstr buffer ;print content of buffer (in first iteration it is whole set to '$'
mov ah,3fh ;read from file
mov cx,buffsiz ;how much bytes it should read from file (32768)
mov dx,offset buffer
int 21h
output: xchg ax,bx ;exchange values in ax and bx
mov buffer[bx],'$' ;after last read byte put '$' into buffer
xchg ax,bx ;exchange registers back for next iteration
cmp ax,0 ;if there was no read byte stop loop
jnz buffIn ;if was go to next iteration
mov ah,3Eh ;close file
int 21h
ret
getcont endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
getsize proc
mov word ptr[filesiz],0 ;put zero into filesize variable (dword)
mov word ptr[filesiz]+2,0
mov ah,3dh ;same as in getcont procedure
mov al,0
call forout
mov dx,offset file
int 21h
mov bx,ax
bufflp: mov ah,3fh
mov cx,buffsiz
mov dx,offset buffer
int 21h
add word ptr[filesiz],ax ;add number of bytes read into filesiz variable - not certain in this
cmp ax,0 ;if there was no byte read end loop
jnz bufflp ;if was go to next iteration
prntstr nl ;new line
prntstr velkost ;print string about file size operation
xor dx,dx ;clear ax and dx registers
xor ax,ax
mov ax,word ptr[filesiz] ;move low word from filesiz(dword) variable to ax
mov dx,word ptr[filesiz]+2 ;move high word from filesiz to dx to get filesiz=dx:ax
call prntint ;call procedure to print decimal number on output
prntchr ' ' ;print space
prntchr 'B' ; print Byte unit char
mov ah,3Eh ;close file
int 21h
ret
getsize endp
Working with TASM assembly x86.
I found these problems in the code you presented:
mov buffer[bx],'$' ;after last read byte put '$' into buffer
You should enlarge the buffer by 1 byte. Now you are writing this $ past the buffer when 32768 bytes were read!
add word ptr[filesiz],ax ;add number of bytes read into filesiz variable
The previous line will not update the dword variable filesiz! Use the following
add word ptr[filesiz],ax
adc word ptr[filesiz]+2,0
ps. You don't ever check if DOS reports an error. You should not neglect this when accessing files!
I'm new in assembly programming and I have an assignment in which I have to read a text file line by line and use what is written in the file and pass it to another function. My problem is that I'm not sure of how to read the text this way because from what I have discovered for reading a text file first I have to create a buffer reserving certain quantity of bytes for storing what is in the file. Howerver in this case I want to read line by line (like a loop) until the end of file so I dont know how much bytes I have to reserve. Thanks.
Btw here is the code I'm trying to use:
SECTION .data
file_name db 'instruct.txt',0
SECTION .bss
fd_out resb 1
fd_in resb 1
info resb 20
SECTION .text
global main
main: ;tell linker entry point
push ebp
mov ebp, esp
push ebx
;open the file for reading
mov eax, 5
mov ebx, file_name
mov ecx, 2
mov edx, 0777 ;read, write and execute by all
int 0x80
mov [fd_in], eax
loop:
;read from file
mov eax, 3
mov ebx, [fd_in]
mov ecx, info
mov edx, 5
int 0x80
cmp eax, 0
;check EOF
je exit
; print the info
mov eax, 4
mov ebx, 1
mov ecx, info
mov edx, 5
int 0x80
;
jmp loop
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
exit:
; close the file
mov eax, 6
mov ebx, [fd_in]
pop ebx
mov esp, ebp
pop ebp
ret
use mmap syscall, read entire file to memory and search for 0x0A sequence. This is the ASCII code for end of line. Perhaps usefull too to check for 0x0D (in case you are dealing with windows text files. There the sequence 0x0A,0x0D indicates an new line and thus an end of line.
mmap will try to allocate memory for you without the overhead of administration for you. Otherwise determine the file length and reserve memory with syscall sbrk. Works also but you have to program a bit more. My suggestion is that mmap is the best way.
I did a search on Stack Overflow, and I have not found anything similar to my problem. My problem is this: I have a code that opens a file and writes a message at the end. When I use int 21h to write to the file in the first time, it writes well if the file is empty, but if the file has content, the program adds to the end many trash bytes (characters like 畂 or another japanese or chinese characters).
I have checked that the program don't write more bytes than the message length. Please, help me. Here is my source code:
.model tiny
.code
main:
call delta
delta:
pop bp
sub bp, offset delta
mov ax, #code ;Get the address of code segment and store it in ax
mov ds, ax ;Put that value in Data segment pointer.
;Now, we can reference any data stored in the code segment
;without fail.
;Subroutines
open:
mov ax, 3D02H ;Opens a file
lea dx, [bp+filename];Filename
int 21h ;Call DOS interrupt
mov handle, ax ;Save the handle in variable
move_pointer_to_end:
mov bx, handle
mov ax,4202h ; Move file pointer
xor cx,cx ; to end of file
cwd ; xor dx,dx
int 21h
write:
mov ax, 4000H
mov bx, handle
lea dx, [bp+sign]
mov cx, 16
int 21H
exit:
mov ah,4Ch ;Terminate process
mov al,0 ;Return code
int 21h
datazone:
handle dw ?
filename db 'C:\A.txt', 0
sign db 'Bush was here!!', 0
end main
Please help me!!
That's because the file to which you're appending the data is encoded in unicode. If you write a file out from Notepad or another text editor and save it, you have to pick ANSI as the encoding. Then if you point your program at the ANSI encoded text file, it should append the string indicated with the expected result.
Unicode allocates two bytes for every character so in a hex editor you might see s.o.m.e.t.h.i.n.g. .l.i.k.e. .t.h.i.s. rather than something like this that you might expect for ANSI or UTF-8.