execvp usage on nasm - linux

I'm learning NASM now, linux system calls probably. I'm trying to copy a process and call linux utility, but have same troubles with execvp, I don't know how to pass arguments into it. How I can do this right?
SECTION .data
cmd_cat: db '/bin/cat', 0
arg_cat: db 'log.txt', 0
cat: dd cmd_cat, arg_cat, 0
fd1: dw 0, 0
pipe_error_message: db 'pipe error occured', 0xa
pipe_error_message_length: equ $ - pipe_error_message
fork_error_message: db 'fork error occured', 0xa
fork_error_message_length: equ $ - fork_error_message
SECTION .text
GLOBAL _start:
_start:
;call pipe(fd1)
;42 - pipe system call number
mov eax, 42
mov ebx, fd1
;call kernel to execute
int 080h
cmp eax, 0
jne pipe_error
;call pipe(fd2)
mov eax, 42
mov ebx, fd1
int 080h
cmp eax, 0
jne pipe_error
;fork()
mov eax, 2
int 080h
cmp eax, -1
je fork_error
jnz child_cat
call exit
;displays error message and finishes the programm when something is wrong with pipe
pipe_error:
mov edx, pipe_error_message_length
mov ecx, pipe_error_message
call sys_write
call exit
;displays error message and finishes the programm when something is wrong with fork
fork_error:
mov edx, fork_error_message_length
mov ecx, fork_error_message
call sys_write
call exit
;sys_write(unsigned int fd, const char __user *buf, size_t count);
sys_write:
mov ebx, 1
mov eax, 4
int 080h
;exit(0)
exit:
mov eax,1
mov ebx,0
int 080h
child_cat:
mov ebx, [fd1]
mov eax, 6
int 080h
;dup2(fds[1],1)
mov ecx, 1
mov ebx, [fds + 4]
mov eax, 63
int 080h
mov eax, 11
mov ebx, cmd_cat
mov ecx, cat
int 080h

The following code works for me in the gas assembler. I have explained what it does, so hopefully someone else can provide the nasm translation.
.text
.global _start
_start:
movl $0xb, %eax # system call 0xb (execve) goes in eax
movl $arg0, %ebx # put the _address_ of the command string
# in ebx (we are providing a pointer)
movl $ptrarray, %ecx # put the _address_ of the array of pointers
# to arguments in ecx (again, a pointer)
movl $0, %edx # put a literal zero in edx (we don't have
# environment variables to pass, so we give
# a null pointer)
int $0x80 # run the system call
.data
ptrarray: # This is the array of pointers to command line
# arguments
.long arg0, arg1, 0 # The first element is a _pointer_ to the command
# The second element is a _pointer_ to an argument
# The third is a null pointer to indicate no more
arg0: # This is the command string
.asciz "/bin/cat"
arg1: # This is the argument string
.asciz "file.txt"

Related

assembly doesn't print empty line

I just started to learn x86 assembly and I tried to write a simple program that prints all the ascii characters and a line break to the standard output.
It prints everything as expected except the line break and I can't figure out why.
I compiled it with nasm on a 64 bit ubuntu operating system.
Here is the code:
section .data
curr db ' '
section .text
global _start
_start:
next:
;print current character
mov eax,4
mov ebx,1
mov ecx,curr
mov edx,1
int 0x80
;check condition and increment curr
inc byte [curr]
cmp byte [curr],126
jle next
;new line and exit <--- doesn't work ???
mov eax,4
mov ebx,1
mov ecx,10
mov edx,1
int 0x80
mov eax,1
mov ebx,1
int 0x80
The problem is that in that system call, ECX is a pointer, not the character you want to print. Perhaps modifying it like so?
MOV byte [curr], 10
MOV ECX, curr
MOV EAX, 4
MOV EDX, 1
INT 0x80

NASM: SegFault on MOV ECX

I'm trying to make a very simple assembly program run, however I seem to get segfaults whatever I do.
Here is my code (should print 'a' on a linux machine)
section .data
buffer times 50 db 97
pointer db 0
section .text
global _start
_start:
mov ECX , pointer
mov EDX , [buffer + ECX]
mov EAX , 4
mov EBX , 1
mov ECX , EDX
mov EDX , 1
int 0x80
It causes a segfault on the first MOV but it seems obvious to me that it should work.
I reduced it to almost nothing and it still segfault.
section .data
msg db "hello"
section .text
global _start
_start:
mov EAX,1
I've run this succesfully:
section .text
global _start
_start:
mov ax, 0b
dec ax
sub ax, 11111111b
mov bx, 97
add ax, bx
mov [INVENTORY], ax ; put a in first inventory pos
mov eax, 4
mov ebx, 1
mov ecx, INVENTORY
mov edx, 1
int 0x80
mov ax, [INVENTORY]
add ax, 1
mov [INVENTORY + 1], ax ; put b in second inventory pos
mov [VAR], ax
mov eax, 4
mov ebx, 1
mov ecx, VAR
mov edx, 1
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, '\n'
mov edx, 1
int 0x80
mov eax,1
int 0x80
_newline:
section .data
VAR DW 0
INVENTORY TIMES 8 DW 0
Is it possible that it has to do with the symbols I use for newlines or tabs? I generate the assembly from java and I use \t for tabs and \n for new lines (and spaces so it doesn't look too bad.
I'm using NASM and I'm running it here:
https://www.tutorialspoint.com/compile_assembly_online.php
Thank you!
If you are just trying to print out a set of 'a's.
section .data
buffer times 50 db 97
len.buffer equ $-buffer
pointer db 0
section .text
global _start
_start:
; ssize_t write(int fd, const void *buf, size_t count);
; i386 ebx ecx edx esi edi ebp
mov EAX , 4 ; write syscall
mov EBX , 1 ; std out
lea ecx, [buffer] ; buffer
mov edx, len.buffer ; size
int 0x80
_exit:
mov eax, 1 ; exit syscall
int 0x80
output:
./yvon_001
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ndavid#ubuntuserver00A:~/asm$ ./yvon_001
In the end #MichealPetch was right, I needed to add an EXIT syscall at the end of the code. The sample I tried still did a SEGFAULT because I was moving pointer instead of [pointer] in a registry.
Thanks for comments and answers!

How to return of Called Functions multiple times/NASM

I am trying to return of a function, which also calls a function, but I get a SIGSEV.
MY ASSEMBLER: Linux, Unix nasm 64 +ld
sample:
;something
call myFunction
myFunction:
call func2
ret
func2:
;do sth
ret
One possibility is to push the Pointer to the stack, but the Stack is Limited, isn't it? And I need a solution for doing this n-times, whereas n should be able to stand for infinity.
Another possibility is to call the function and do a label for returning, but when I hava a function, which is called by different routines, I'm runnning into another problem :(
Is there an elegant way of doin' this?
Ox, so I got the suggestion, I should try it as it could work.
I tried it with this code:
section .data
test : db "test", 0x0a; length: 5
input: db "433", 0x00
blank: db 0xa
section .bss
section .text
global _start:
_start:
mov eax, 4
mov ebx, 1
mov ecx, input
mov edx, 4
int 80h
mov eax, input
call strToInt
mov [input], eax
mov eax, 4
mov ebx, 0
mov ecx, test
mov edx, 5
int 80h
ret
mov eax, 1
mov ebx, 0
int 80h;
strToInt:
mov ebx, 0; counter
mov ecx, 0; ecx is 4 the result
conversion_loop:
cmp BYTE[eax], 0
jz leave_loop
sub byte[eax], 48
inc eax
inc ebx
cmp ebx ,9
jge leave_loop
jmp conversion_loop
leave_loop:
call hey
ret
hey:
mov eax, 4
mov ebx, 0
mov ecx, test
mov edx, 5
int 80h
ret
(sorry for the code, this long -.-)
the result is:
433test
test
SEGFAULT
Does this clarify this a bit?
Look at this lines:
int 80h
ret
I think this ret is jump out of your code segment. You must remove ret to call sys_exit function to complete programm gracefully.

linux assembly: how to call syscall?

I want to call a syscall in assembly. The problem is I can't mov ecx,rsp. rsp is 64-bit register, ecx is a 32-bit register. I want to pass the buffer addr as a parameter of this syscall. What can I do? Thanks.
section .data
s0: db "Largest basic function number supported:%s\n",0
s0len: equ $-s0
section .text
global main
extern write
main:
sub rsp, 16
xor eax, eax
cpuid
mov [rsp], ebx
mov [rsp+4], edx
mov [rsp+8], ecx
mov [rsp+12], word 0x0
mov eax, 4
mov ebx, 1
mov ecx, rsp
mov edx, 4
int 80h
mov eax, 4
mov ebx, 1
mov ecx, s0
mov edx, s0len
int 80h
mov eax, 1
int 80h
To make a system call in 64-bit Linux, place the system call number in rax, and its arguments, in order, in rdi, rsi, rdx, r10, r8, and r9, then invoke syscall.
Note that 64-bit call numbers are different from 32-bit call numbers.
Here is an example in GAS syntax. NASM syntax for putting an address in a register is lea rsi, [rel message] using a RIP-relative LEA.
.global _start
.text
_start:
# write(1, message, 13)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
lea message(%rip), %rsi # address of string to output
mov $13, %rdx # number of bytes
syscall
# exit(0)
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # return code 0
syscall
.section .rodata # read-only data section
message:
.ascii "Hello, World\n"
See also What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?

NASM loop over bytes

Currently I'm trying to loop over every single byte in a buffer (read from a file) and compare it to see if any of them is a whitespace, and write them to STDOUT. For some reason the program compiles and runs fine, but produces zero output.
section .data
bufsize dw 1024
section .bss
buf resb 1024
section .text
global _start
_start:
; open the file provided form cli in read mode
mov edi, 0
pop ebx
pop ebx
pop ebx
mov eax, 5
mov ecx, 0
int 80h
; write the contents in to the buffer 'buf'
mov eax, 3
mov ebx, eax
mov ecx, buf
mov edx, bufsize
int 80h
; write the value at buf+edi to STDOUT
mov eax, 4
mov ebx, 1
mov ecx, [buf+edi]
mov edx, 1
int 80h
; if not equal to whitespace, jump to the loop
cmp byte [buf+edi], 0x20
jne loop
loop:
; increment the loop counter
add edi, 1
mov eax, 4
mov ebx, 1
mov ecx, [buf+edi]
int 80h
; compare the value at buf+edi with the HEX for whitespace
cmp byte [buf+edi], 0x20
jne loop
; exit the program
mov eax, 1
mov ebx, 0
int 80h
The main problem was that I didn't given the address of bufsize ([bufsize]), also the loops had some problems.
Here's the fixed version, thanks everyone for your input.
section .data
bufsize dd 1024
section .bss
buf: resb 1024
section .text
global _start
_start:
; open the file provided form cli in read mode
mov edi, 0
pop ebx
pop ebx
pop ebx
mov eax, 5
mov ecx, 0
int 80h
; write the contents in to the buffer 'buf'
mov eax, 3
mov ebx, eax
mov ecx, buf
mov edx, [bufsize]
int 80h
; write the value at buf+edi to STDOUT
; if equal to whitespace, done
loop:
cmp byte [buf+edi], 0x20
je done
mov eax, 4
mov ebx, 1
lea ecx, [buf+edi]
mov edx, 1
int 80h
; increment the loop counter
add edi, 1
jmp loop
done:
; exit the program
mov eax, 1
mov ebx, 0
int 80h

Resources