簡體   English   中英

將系統調用與linux上的printf混合使用

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM