I want to call a write syscall from 32-bit assembly, the code i'm using right now:
.section    .rodata             # read-only data
msg:
    .ascii  "hello"             # char array called "msg" (no null character)
len:
    .long   5                   # length of "msg"
.section    .text               # actual runnable code
.globl      _start
.type       _start, @function
_start:
    movl    $4, %eax            # syscall number into eax (4 is write)
    movl    $1, %ebx            # argument number 1 into ebx (stdout)
    movl    $msg, %ecx          # argument number 2 into ecx
    movl    len, %edx           # argument number 3 into edx
    int     $0x80
    
    movl    $1, %eax            # syscall number into eax (1 is exit)
    movl    $0, %ebx            # argument number 1 into ebx (exit code)
    int     $0x80
To compile it i first invoke the GNU assembler and then the linker:
as --32 main.s -o main.o
ld -m elf_i386 main.o -o main
It compiles and works properly, printing the string "hello" to the console, but when i use strace to "see" the write happen, i get following output:
execve("./main", ["./main"], [/* 86 vars */]) = 0
strace: [ Process PID=22529 runs in 32 bit mode. ]
write(1, "hello", 5hello)                    = 5
exit(0)                                 = ?
+++ exited with 0 +++
I'd like to know what causes the third argument to be 5hello instead of 5.
                        
Nothing, the
helloin there is the actual output of your program. Here is what is happening:write(1, "hello", 5. Note this goes tostderr. For some reason it doesn't print the closing)yet.writesyscall gets executed, thushellois printed tostdout.) = 5.In your case both
stdoutandstderrrefer to the same terminal. Redirect the output of either strace or your code so they don't get interspersed.