Assembly: trying to write to file, but text is appending to filename - linux

I'm trying to study assembly, while trying out the example in the tutorials I get stuck. I am compiling this using an ubuntu virtual machine.
Here is the code:
SYS_READ equ 3
SYS_WRITE equ 4
SYS_OPEN equ 5
SYS_CLOSE equ 6
SYS_CREATE equ 8
SYS_EXIT equ 1
section .text
global _start
_start:
mov eax, SYS_CREATE
mov ebx, filename
mov ecx, 0777
int 0x80
mov [fd_out],ebx
mov eax,SYS_WRITE
mov edx,len
mov ecx,msg
mov ebx,[fd_out]
int 0x80
mov eax,SYS_CLOSE
mov ebx,[fd_out]
int 80h
mov eax,SYS_OPEN
mov ebx,filename
mov ecx,0
mov edx,0777
int 0x80
mov [fd_in],eax
mov eax, SYS_READ
mov ebx,[fd_in]
mov ecx,info
mov edx,26
int 0x80
mov eax,SYS_WRITE
mov ebx,1
mov ecx,info
mov edx,26
int 0x80
mov eax,SYS_EXIT
mov ebx,0
int 0x80
section .data
filename db 'test.txt'
msg db 'Hello world file'
len equ $-msg
section .bss
fd_out resb 1
fd_in resb 1
info resb 26
after executing the compiled output, I get a file named test.txtHello world file.

While SYS_WRITE accepts the length of the information in EDX, the function SYS_CREATE needs a pointer to NULL terminated string for the filename.
Your filename, defined as
filename db 'test.txt'
is not NULL terminated and that is why it concatenates with the next string:
msg db 'Hello world file'
The terminating NULL in this case is the next defined:
fd_out resb 1
In order to fix it, simply define the filename with zero terminating byte:
filename db 'test.txt', 0

Related

Assembly: Syscall is being skipped

I have the following assembly code down here. Basically I want to execute sys_write syscall twice to write something to stdout.
section .text
global _start
_start:
;write hello world
mov eax, 4
mov ebx, 1
mov edx, len_hello_world
mov ecx, hello_world
int 0x80
;write my name
mov eax, 4
mov ebx, 1
mov edx, len_my_name
mov ecx, my_name
int 0x80
;exit program
mov eax, 1 ; sys_exit
int 0x80
section .data
hello_world db "Hello, World!", 0xd
len_hello_world equ $ - hello_world
my_name db " My name is Moritz!", 0x13
len_my_name equ $ - my_name
Expected output:
Hello, World! My name is Moritz!
Actual output:
My name is Moritz!
My question is: Why is the first sys_call "skipped" (sorry for layman terms, i'm total noob)

NASM read file char by char

I am new to NASM and i have a project from school.
For start i need to know how to read char by char from .txt
after a long research this is my code:
section .text
global _start
_start:
;open the file
mov eax, 5 ;sys call open
mov ebx, file_name ;file name
mov ecx, 0 ;read only
mov edx, 0777 ; exe by all
int 0x80
mov [fd_in], eax
;read
loop:
mov eax, 3 ;sys call read
mov ebx, [fd_in] ;file descriptor
mov ecx, buff
mov edx, 1
int 0x80
cmp eax, 0 ;cmp EOF
je eof
;print
mov eax, 4 ;sys call write
mov ebx, 1 ;std out
mov ecx, buff
mov edx, 1
int 0x80
jmp loop
eof:
mov eax, 1
int 0x80
section .data
file_name db 'hey.txt'
section .bss
fd_in resb 1
buff resb 1
but it only print endlessly to fist char in my .txt file.
BTW in the .txt file it says "Hey my name is blah".
i would love any help or suggestions.
thanks.

Assembly on Linux: unexpected behaviour from Assembly [duplicate]

This question already has answers here:
In NASM labels next to each other in memory are printing both strings instead of first one
(1 answer)
How does $ work in NASM, exactly?
(2 answers)
Closed 4 years ago.
running the code below generates a file with Welcome to jj Shashwat as content. what i didn't get is why does it writes Shashwat at the end of the file, Shashwat is in a totally different variable. Any idea why does this happen?
section .text
global _start ;must be declared for using gcc
_start:
;create the file
mov eax, 8
mov ebx, file_name
mov ecx, 0777 ;read, write and execute by all
int 0x80 ;call kernel
mov [fd_out], eax
; close the file
mov eax, 6
mov ebx, [fd_out]
;open the file for reading
mov eax, 5
mov ebx, file_name
mov ecx, 2 ;for read/write access
mov edx, 0777 ;read, write and execute by all
int 0x80
mov [fd_out], eax
; write into the file
mov edx,len ;number of bytes
mov ecx, msg ;message to write
mov ebx, [fd_out] ;file descriptor
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
; close the file
mov eax, 6
mov ebx, [fd_out]
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
file_name db 'myfile.txt', 0
msg db 'Welcome to jj', 0
mgafter db ' Shashwat', 0
lntwo equ $-mgafter
len equ $-msg
section .bss
fd_out resb 1
fd_in resb 1
info resb 26
That's because you said len equ $-msg after defining both msg and msgafter, so len is set to the length of both msg and msgafter, making your write call write both strings. This is because len equ $-msg means “set len to be the difference between the current location ($) and the location of msg.”
To fix this, move the len equ $-msg line right after the definition of msg.

Read file in a loop in assembly

I am supposed to write a small assembly "program" that simply reads a file using a loop and outputs the contents to STDOUT.
Now, I made a program that can read the file and unfortunately only outputs the first line. I also can't figure out how to use the loop.
This is my very first time working with assembly and I do it because I have to, not because I want to.
Here's my code:
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
;open the file for reading
mov eax, 5
mov ebx, file_name
mov ecx, 0 ;for read only access
mov edx, 0777 ;read, write and execute by all
int 0x80
mov [fd_in], eax
;read from file
mov eax, 3
mov ebx, [fd_in]
mov ecx, info
mov edx, 26
int 0x80
; close the file
mov eax, 6
mov ebx, [fd_in]
; print the info
mov eax, 4
mov ebx, 1
mov ecx, info
mov edx, 26
int 0x80
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
file_name db './passwd'
section .bss
fd_out resb 1
fd_in resb 1
info resb 26

How do I use a BSS var to move string into register NASM

I'm trying to move a string into a BSS var, I've tried various methods but I have a feeling that unless I hardcode the string or use a read to grab the string I'm fighting a futile battle, the problem I'm having is although I can get the text data into the right register more data accompanies it which trashes the output and some how trashes the value of vdlen (if I directly assign a value to ecx in WriteFile the proper length is put however attempting to use vdlen causes it to way off radar)
How do I get the right results (ie "Hello!" in "text.txt") ?
section .bss
vdata resw 10
vdlen resb 3
vfd resb 1
vfn resb 15
err resb 2
section .text
mov eax,vfn
mov dword [eax],'test'
mov dword [eax+3], '.txt'
mov ebx,vdata
mov dword [ebx], 'Hell'
mov dword [ebx+3],'o!'
mov ecx,vdlen
mov [ecx], 0x03h
jmp WriteFile
ProgramEnd:
mov eax,1
mov ebx,[err]
int 80h
WriteFile:
mov eax,5 ;Syscall for open()
mov ebx,vfn
mov ecx, 65 ; mode Write-only Create
mov edx, 420 ; permissions rw-r-r
int 80h ; Linux Kernel Interrupt
mov [vfd],eax ; get file descriptor
mov eax,4 ;Syscall for write()
mov ebx,[vfd] ; FD argument
mov ecx,[vdata] ; this is where my issue is
mov edx,[vdlen] ; length of vdata
int 80h
mov [err],eax
jmp ProgramEnd
After the extremely helpful advice provided by rkbh and MikeCat to the OP, the OP got it working:
section .bss
vfd resb 5
vfn resb 15
vdlen resb 5
vdata resw 10
section .text
global _start
_start:
mov eax,vfn
mov dword [eax],'test'
mov dword [eax+4],'.txt'
mov ebx,vdata
mov dword [vdata], 'Hell'
mov dword [vdata+4],0 ;nullbyte ?
mov word [vdlen],4
jmp WriteFile
ProgramEnd:
mov eax,1
mov ebx,[err]
int 80h
WriteFile:
mov eax,5 ; open syscall
mov ebx,vfn
mov ecx, 65 ; Write Only, Create Only File Mode
mov edx, 420 ; ugo: RW-R-R
int 80h
mov [vfd],eax
mov eax,4
mov ebx,[vfd]
mov ecx,vdata
mov edx,[vdlen]
int 80h
mov byte [err],0 ;this essentially does nothing since write()
;returns the number of bytes written so I can't actually get an
;error code unless I want to check for err == 0 or
;err >= expectedWriteSize
jmp ProgramEnd
TL;DR: OP was trying to cram 6 bytes into 4 bytes using DWORD MOV's and had mis-specified the size for vdlen.

Resources