I have a Linux x86-32 GAS assembly program terminating like this:
movl $1, %eax
movl $0, %ebx # argument for _exit
int $0x80
When I exit like this, the program functions like normally, but if I try to read the stdout output, I get nothing (using i.e. less or wc).
I tried compiling a minimal C program and comparing the strace outputs. The only difference I found was, that GCC made the C program (int main() { printf("donkey\n"); }) implicitely exit with exit_group(0) in the strace output.
I tried modifying my ASM program to exit with call exit instead of the raw syscall. The stdout was now readable as normal.
Test case
.data
douout: .string "monkey\n"
.text
.globl main
main:
pushl $douout
call printf
# Exit
movl $1, %eax
movl $0, %ebx
int $0x80
Compile and run:
$ yasm -g dwarf2 -f elf -p gas t.asm && gcc -g -melf_i386 -o t t.o && ./t | wc -c
0
Expected:
7
EDIT:
I tried calling both tcflush and fflush, and I still have the problem. With fflush I even get a segfault.
0xb7e9e7c9 in _IO_fflush (fp=0x804a018) at iofflush.c:42
42 iofflush.c: No such file or directory.
in iofflush.c
(gdb) bt
#0 0xb7e9e7c9 in _IO_fflush (fp=0x804a018) at iofflush.c:42
#1 0x08048434 in main () at t.asm:12
(gdb) frame 1
#1 0x08048434 in main () at t.asm:12
12 call fflush
(gdb) list
7
8 pushl $douout
9 call printf
10 # Exit
11 movl $0, %eax
12 call fflush
13 movl $1, %eax
14 movl $0, %ebx
15 int $0x80
EDIT2:
Okay, it works now everyone. I was using the wrong calling convention that I copied from here: Printf without newline in assembly
The argument for fflush should be on the stack, as usual.
$ cat t.asm
.data
douout: .string "monkey\n"
.text
.globl main
main:
pushl $douout
call printf
# Exit
pushl $0
call fflush
movl $1, %eax
movl $0, %ebx
int $0x80
$ yasm -g dwarf2 -f elf -p gas t.asm && gcc -g -melf_i386 -o t t.o && ./t | wc -c
7
$
Thanks everyone, especially nos.
when you pipe stdout to wc, stdout becomes fully buffered.
_exit terminates the process immediately and does not run atexit() and other cleanup handlers. The runtime will register such handlers to be run on exit that flushes open FILE*, such as stdout. When those handlers does not get executed on exit, buffered data will be lost.
You should see output if you call
fflush(stdout)after the printf call, or if you just run the program in a consol without piping the output to another program – in which case stdout will normally be line buffered, so stdout is flushed whenever you write a \n