[英]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.