程序集的Printf调用不打印到标准输出 [英] Printf call from assembly do not print to stdout

查看:82
本文介绍了程序集的Printf调用不打印到标准输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

i am building and running a code in NASM on a x86_64 Linux.

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

The program calls the GNU libc printf function from my program.

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

The program only must print a sentence to stdout.

; 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.好的,那是我所期望的.

When i run the program, it outputs to the terminal Hello Jane Doe. Ok, that is what i am expecting.

但是当我按照以下方式重定向输出时:

But when i redirect the out as following :

./Program > output.txt

文件output.txt.

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

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

Any idea ? It seems that the libc printf is in this case printing into another file descriptor than stdout but maybe i am wrong.

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

The solution has been found by a user in the comments.

切换

; exit
mov rax, 1
mov rbx, 0
int 80h

by call exit做到了.

推荐答案

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

If you want to use C library functions you shouldn't use _start, but good old main. If you steal _start from libc, it won't be able to perform several setup and cleanup operations, such as flushing the open C files.

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

This is visible in this case only when writing to file, as when writing to a tty stdout is line-buffered by default, so it's flushed immediately. When redirecting to file, instead, the data is just copied in a temporary buffer, to be flushed when it's full enough, or at termination - but the C runtime cleanup functions aren't ever called in your case, so the data is never actually passed to the OS.

另一种可能性是使用exit libc函数(执行开始时为extern exit并在执行结束时为call exit)退出,该函数应进行清理,,但我不确定是否如果libc的东西没有机会被初始化,甚至还要求它能正常工作在Linux上应该是安全的,请参见 @PeterCordes 评论,并感谢 @Kirill_Zaitsev 进行尝试.

Another possibility is to exit using the exit libc function (extern exit at the beginning and call exit at the end of the execution), which should handle the cleanup, but I'm not sure if stuff from libc is even required to work fine if it doesn't get the chance to be initialized in first place should be safe on Linux, see @PeterCordes comment and thanks to @Kirill_Zaitsev for trying it.

这篇关于程序集的Printf调用不打印到标准输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆