为什么写系统调用会在 linux x86_64 (nasm) 的末尾打印 `%`? [英] Why do write syscalls print `%` at end on linux x86_64 (nasm)?

查看:27
本文介绍了为什么写系统调用会在 linux x86_64 (nasm) 的末尾打印 `%`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下 hello-world 程序在打印字符串的末尾显示一个 % 符号.这是为什么,我该如何删除它?

The following hello-world program displays a % sign at the end of the printed string. Why is this and how can I remove it?

这是我的程序:

section .data
    msg db  "hello, world!"

section .text
    global _start
_start:
    mov rax, 1      ; syscall 1 (write)
    mov rdi, 1      ; arg 1 = 1 (stdout)
    mov rsi, msg    ; arg 2 = msg ("hello, world!")
    mov rdx, 13     ; arg 3 = 13 (char count)
    syscall         ; call write
    mov rax, 60     ; syscall 60 (exit)
    mov rdi, 0      ; arg 1 = 0 (OK)
    syscall         ; call exit

这是我运行可执行文件时的输出:hello, world!%

And here is the output when I run the executable: hello, world!%

提前致谢.

这似乎是由 zsh 引起的(无法在 bash 中重现).问题是为什么会发生这种情况以及如何解决.

It seems to be caused by zsh (not reproducible in bash). The question is why this happens and how to fix it.

推荐答案

发生这种情况是因为程序的输出没有以换行符结尾.

This happens because your program's output doesn't end with a newline.

您的程序没有打印%.您可以通过将其输出通过管道传输到 hexdump -C 或类似内容来验证这一点.

Your program isn't printing the %. You can verify this by piping its output into hexdump -C or similar.

你也可以使用strace来追踪系统调用它的产生,但这不会显示输出,所以不排除内核神奇地添加一个 %.(但您可以确定内核不会这样做.唯一可能的调整是 write 在没有写入完整缓冲区的情况下提前返回.这仅适用于大缓冲区大小,尤其是写入缓冲区大于管道缓冲区(可能为 64kiB)的管道时.

You can also use strace to trace what system calls its making, but that doesn't show the output, so it doesn't rule out the kernel magically adding a %. (But you can be sure the kernel doesn't do that. The only munging that's possible is for write to return early, without having written the full buffer. This is only likely with large buffer sizes, especially when writing to a pipe with a buffer larger than the pipe-buffer (maybe 64kiB).

这是部分行的 ZSH 功能:为什么 ZSH 以突出显示的百分比符号结束一行?.你没有说它是一个突出显示的 % 符号.准确/完整的描述很重要.

This is a ZSH feature for partial lines: Why ZSH ends a line with a highlighted percent symbol?. You didn't say it was a highlighted % symbol. Accurate / complete descriptions are important.

(此答案的早期版本假设您在 ZSH 中使用 % 作为提示.% 有时用作提示,但在 C-shell 中更常见像 tcsh,而不是 Bourne 派生的 shell,如 bash 和 zsh.)

(An earlier version of this answer assumed you were using % as your prompt in ZSH. % is sometimes used as a prompt, but more often in C-shells like tcsh, not Bourne-derived shells like bash and zsh.)

你会从 echo -n "hello, world!" 得到完全一样的东西.例如在 bash 中:

You'd get exactly the same thing from echo -n "hello, world!". e.g. in bash:

peter@volta:/tmp$ echo -n 'hello world!'
hello world!peter@volta:/tmp$ 

在 ZSH 中:

volta:/tmp$ echo -n 'hello world!' 
hello world!%
volta:/tmp$      # and the % on the previous line is in inverse-video

Bash 只在前台命令退出后打印 $PS1(或运行 $PROMPT_COMMAND),而不管光标位置如何.它无法直接检查程序的输出是否以换行符结尾.我猜 ZSH 使用 VT100 转义码来查询光标位置以检测程序将光标不在行首的情况.

Bash just prints $PS1 (or runs $PROMPT_COMMAND) after a foreground command exits, regardless of cursor position. It can't directly check that your program's output ended with a newline. I guess ZSH uses VT100 escape codes to query the cursor position to detect cases where programs leave the cursor not at the start of a line.

当你cat一个不以换行符结尾的文件或任何其他情况时,你也会得到这个.

You also get this when you cat a file that doesn't end with a newline, or any number of other cases.

要修复它,请在您的消息中包含一个换行符(ASCII 换行符,0xa):

section .rodata
    msg: db  "hello, world!", 0xa
    msglen equ $ - msg               ; use mov edx, msglen
    msgend:                          ; or  mov edx, msgend - msg

请参阅$ 在 NASM 中究竟是如何工作的?了解更多详情让汇编程序为您计算大小.

See How does $ work in NASM, exactly? for more details on getting the assembler to compute the size for you.

不要在 NASM 中省略数据标签上的 :;它的风格很好,避免了与指令助记符和汇编指令的名称冲突.

Don't omit the : on data labels in NASM; it's good style and avoids name conflicts with instruction mnemonics and assembler directives.

NASM(但不是 YASM)在反引号内接受 C 样式的转义符,因此您可以编写代替换行符的数字 ASCII 代码

NASM (but not YASM) accepts C-style esacapes inside backquotes, so instead of the numeric ASCII code for a newline, you could write

  msg: db  `hello, world!\n`

这篇关于为什么写系统调用会在 linux x86_64 (nasm) 的末尾打印 `%`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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