程序集的Printf调用不打印到标准输出

时间:2019-02-03 21:52:25

标签: assembly

我正在 x86_64 Linux 上的 NASM 中构建和运行代码。

程序从我的程序中调用 GNU libc printf函数。

该程序只需在标准输出上打印一个句子即可。

; comment
section .data
fmt: db "Hello %s %c", 0
name: db "Jane Doe", 0

section .text
global _start
extern printf

func:
lea rdi, [fmt]
lea rsi, [name]
mov rcx, 0x0A
xor rax, rax
call printf
ret

_start:
call func
; exit
mov rax, 1
mov rbx, 0
int 80h
ret

这是我编译它的方式:

nasm -f elf64 Program.s -o Program.o -Werror 
ld -m elf_x86_64 Program.o -o Program -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2

当我运行程序时,它输出到终端Hello Jane Doe。好的,那是我所期望的。

但是当我将输出重定向如下时:

./Program > output.txt

文件output.txt

-rw-rw-r-- 1 me me    0 output.txt

有什么主意吗?看来libc printf在这种情况下正在打印到stdout以外的另一个文件描述符中,但也许我错了。

解决方案

用户已在评论中找到了解决方案。

切换

; exit
mov rax, 1
mov rbx, 0
int 80h
{p> by call exit做到了。

1 个答案:

答案 0 :(得分:2)

如果要使用C库函数,则不应使用_start,而应使用旧的main。如果您从libc盗用_start,它将无法执行多项设置和清除操作,例如刷新打开的C文件。

在这种情况下,仅当写入文件时才可见,因为写入tty stdout默认情况下是行缓冲的,因此会立即刷新。重定向到文件时,数据只是复制到一个临时缓冲区中,当数据已满或终止时将被刷新-但是在您的情况下从未调用过C运行时清理函数,因此,数据实际上从未被调用过传递给操作系统。

另一种可能性是使用exit libc函数退出,该函数应该处理清除操作,但是我不确定libc的内容是否即使没有机会被要求工作也可以正常工作首先初始化。