【发布时间】:2021-01-19 18:05:22
【问题描述】:
我想知道为什么汇编版本在通过管道传输到 hexdump 时没有显示任何输出?
源代码(printf.c):
#include <stdio.h>
// gcc -o printf printf.c && ./printf
int main() {
const char *frmt = "%s\n";
char *msg = "TEST";
printf(frmt, msg);
return 0;
}
输出到 STDOUT:
$ ./printf
TEST
管道到hexdump:
$ ./printf | hexdump -v -C
00000000 54 45 53 54 0a |TEST.|
00000005
追踪:
$ strace -ttT -f -e trace="write" ./printf
17:44:33.841789 write(1, "TEST\n", 5TEST
) = 5 <0.000050>
17:44:33.842320 +++ exited with 0 +++
源代码(printf.nasm):
; nasm -g -f elf64 printf.nasm && ld printf.o -o printf && ./printf
extern printf
global main
section .text
main:
mov rdi, frmt
mov rsi, msg
xor rax, rax
call printf
jmp exit
exit:
mov rax, 60
xor rdi, rdi
syscall
section .data
frmt db "%s", 0xa, 0x0
msg: db "TEST"
len: equ $ - msg
输出到 STDOUT:
$ ./printf
TEST
管道到hexdump(无输出):
$ ./printf | hexdump -v -C
追踪:
$ strace -ttT -f -e trace="write" ./printf
17:46:00.828887 write(1, "TEST\n", 5TEST
) = 5 <0.000050>
17:46:00.829282 +++ exited with 0 +++
【问题讨论】:
-
您在
msg上缺少尾随空值? -
所有 C 字符串都以
0x0结尾。您在frmt中有它,但在程序集中没有msg。 -
可能是因为您对 printf 的调用正在被缓冲,并且因为您使用 syscall 退出程序,缓冲区没有被刷新并且输出丢失。不要使用 syscall 退出,而是调用
exit以确保正确刷新缓冲区并终止进程。 -
@Michael Petch:我同意,我也认为输出是缓冲的。但是,我认为从
main返回(很像 C 示例所做的那样)同样最终会按预期刷新缓冲区。 -
@ecm: 是的,一个简单的
ret就可以完成,缓冲区将被刷新,进程也将以这种方式终止。 C 运行时两种方式都会在终止进程之前刷新任何缓冲区并进行任何必要的拆除。