How to Open Existing File and Write to File (Overwrite contents) in assembly language MASM , irvine32 bits - file

the problem focuses on MASM and using Irvine 32 bits only. I don't plan to use macro or etc unless really needed.
.386
.model flat, stdcall
INCLUDE Irvine32.inc
.stack 4096
.Data
inputFilename byte "Enter filename : ",0
errorMssg byte "Unable to open file !",0
newAmount byte "2021",0 ;updated from dword to byte
fileHandle HANDLE ?
buffer dword 200 DUP(?)
.Code
main PROC
I would like to prompt user enter a filename. Then Open the file if it exist, if not error message is display. Lets assume the file is created and therefore exist. In the file contains just a number which is 2020.
OPEN_EXISTING_FILE:
mov edx,offset inputFilename ;ask user enter the existing filename
;currently in existing file content is 2020
call WriteString
call Crlf
mov ecx, SIZEOF inputFilename
call ReadString
call OpenInputFile
mov fileHandle,eax
;file error check
cmp eax, INVALID_HANDLE_VALUE
jne OVERWRITE_FILE
mov edx, offset errorMssg
call WriteString
call Crlf
jmp OPEN_EXISTING_FILE
It seems my Write to File is not working. Am i missing some codes? Can anyone guide me on how can i replace the "2020" to "2021", in the file.
OVERWRITE_FILE:
mov eax,fileHandle
mov edx, OFFSET newAmount ;i want to overwrite 2020 to 2021 in the existing file
mov ecx, LENGTHOF newAmount
call WriteToFile
call CloseFile
call crlf
call waitMsg
END main

Related

Assembly x86 read from any file and escape all special characters and get size of file in Bytes

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!

Reading text file line by line NASM

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.

My asm code writes trash bytes when I use int 21h function

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.

Reading from a txt file in assembly MASM?

In the code below, buffer is my buffer read, fileName is the name of the file, bytesRead is supposed to be the returned string.
I try to read from it, but it tells me that the buffer size is 6.
INCLUDE Irvine32.inc
INCLUDE macros.inc
.data
MAX = 5000
fileName BYTE 80 DUP (?)
fileHandle HANDLE ?
bytesRead DWORD ?
buffer BYTE MAX DUP(?)
.code
main PROC
mov EDX,OFFSET fileName
call ReadString
mov EDX,OFFSET fileName
call OpenInputFile
mov fileHandle, EAX
mov eax,fileHandle
mov ecx,MAX
call ReadFromFile
mov bytesRead,eax
mov edx, offset bytesRead
call WriteString
call crlf
call WriteDec
call crlf
exit
main ENDP
END main
RTFM:
ReadFromFile PROC
Reads an input file into a buffer.
Call args:
EAX = an open file handle
EDX = offset of the input buffer
ECX = maximum number of bytes to read
Return arg:
If CF = 0, EAX contains the number of bytes read.
If CF = 1, EAX contains a system error code. Call WriteWindowsMsg
to get a text representation of the error.
Example:
.data
BUFSIZE = 5000
buffer BYTE BUFSIZE DUP(?)
bytesRead DWORD ?
.code
mov eax,fileHandle
mov edx,OFFSET buffer
mov ecx,BUFSIZE
call ReadFromFile
jc show_error_message
mov bytesRead,eax
You need OFFSET buffer in there. bytesRead is the number of bytes read, not a string, your text should be in buffer.

open file and read form it to buffer in assembly

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.

Resources