[英]Mixing syscall write with printf on linux
我在汇编调用c函数时做了一些测试,当我使用ansi转义代码并调用使用printf的ac函数时,我得到了我认为的奇怪行为。
这是装配部分:
section .data
red db 27,"[31;1m",0
redlen equ $ - red
cyan db 27,"[36;1m",0
cyanlen equ $ - cyan
colorReset db 27,"[0m",0
colorResetLen equ $ - colorReset
section .text
extern printLetter
extern letter
global main
main:
mov BYTE [letter], 'H'
call ansiSetRed
call printLetter
mov BYTE [letter], 'e'
call ansiSetCyan
call printLetter
mov BYTE [letter], 'l'
call ansiReset
call printLetter
mov BYTE [letter], 'l'
call ansiSetRed
call printLetter
mov BYTE [letter], 'o'
call ansiSetCyan
call printLetter
mov BYTE [letter], '!'
call ansiReset
call printLetter
mov BYTE [letter], 10
call printLetter
ret
ansiSetRed:
mov rax, 1
mov rdi, 1
mov rsi, red
mov rdx, redlen
syscall
ret
ansiSetCyan:
mov rax, 1
mov rdi, 1
mov rsi, cyan
mov rdx, cyanlen
syscall
ret
ansiReset:
mov rax, 1
mov rdi, 1
mov rsi, colorReset
mov rdx, colorResetLen
syscall
ret
看起来很长,但我所做的只是在开头用ansi代码定义一些字符串,一个用于将前景色设置为红色,一个用于青色,一个用于重置颜色。
然后我有使用syscall write打印这个ansi字符串的函数。
主要功能是打印“你好!” 通过首先调用打印相应ansi字符串的汇编函数,然后调用extern c函数来打印存储在全局变量中的字符,来交替每个字母的颜色。
这里是c部分:
#include <stdio.h>
char letter;
void printLetter(void) {
printf("%c", letter);
}
当我运行它时,消息“你好!” 如果装配零件没有打印ansi代码,则显示全白色
但如果我改变c部分只是在每个字符后面打印一个新行:
#include <stdio.h>
char letter;
void printLetter(void) {
printf("%c\n", letter);
}
然后这些字母显示我开始时预期的每种颜色中的一种颜色。
这种行为的原因是什么?
那是因为如果stdout进入终端,stdio(C标准I / O包)对stdout使用行缓冲。 这意味着您编写的数据不会立即发送到终端,而是缓冲直到整行可用。 你在第一个程序中观察到的(你好,在一行上)是在用一个换行符调用printLetter
之前,实际上没有写入Hello
字符,导致stdout的缓冲区被刷新到终端。
我看到了以下解决问题的方法(其中任何一个都可以解决问题,但只使用一种方法):
ansiSetRed
等来调用fwrite
而不是直接执行write
系统调用。 这应该使缓冲按预期工作。 setbuf(stdout, NULL)
来关闭缓冲。 stderr
而不是stdout
因为stderr
是无缓冲的 printf
之后执行fflush(stdout)
以手动刷新stdout
。 printLetter
以使用系统调用write
而不是printf
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.