assembly - 来自程序集的 Printf 调用不打印到标准输出
问题描述
我正在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
成功了call exit
。
解决方案
如果你想使用你不应该使用的 C 库函数_start
,但是很好main
。如果您_start
从 libc 中窃取,它将无法执行多个设置和清理操作,例如刷新打开的 C 文件。
在这种情况下,这仅在写入文件时可见,因为默认情况下写入 tty 标准输出是行缓冲的,因此它会立即刷新。相反,当重定向到文件时,数据只是被复制到一个临时缓冲区中,当它足够满时被刷新,或者在终止时被刷新 - 但在你的情况下从未调用过 C 运行时清理函数,因此数据实际上永远不会传递给操作系统。
另一种可能性是使用exit
libc 函数退出(extern exit
在执行开始和call exit
结束时),它应该处理清理,但我不确定如果没有机会首先初始化 libc 中的东西是否需要正常工作在 Linux 上应该是安全的,请参阅@PeterCordes评论并感谢@Kirill_Zaitsev尝试它。
推荐阅读
- mysql - 如何在 MySQL 中回滚到 django 默认创建的事务?
- java - 将超类方法返回的超类实例转换为子类实例
- php - 数据库播种 laravel 创建 50 个用户并为每个用户附加一个关系
- vhdl - Shift left register with load and enable signals
- apl - APL 中的重复函数应用
- java - 在构建容器时,为什么使用 Java 泛型比使用对象类更好?(Java 泛型和数据结构)
- homebrew - Xdebug install on macOS
- django - 我对 app.py 中使用的 ready 函数感到困惑
- airflow - 气流 - 在重试中保留状态
- ffmpeg - 如何使用 ffMpeg 缓存 AVI 文件