汇编中没有换行符的 Printf

发布于 2024-12-21 06:45:54 字数 1163 浏览 2 评论 0原文

我最近读过这篇关于在汇编中使用 printf 和 scanf 的文章:

汇编中 intfmt: db "%d", 10, 0 的含义

特别是它说 “在 printf 中,换行符打印一个换行符,然后(如果输出处于行缓冲模式,这可能是),刷新内部输出缓冲区,以便您实际上可以看到结果。因此,当您删除 10 时,没有刷新而且你看不到输出。”

但是,如果我不想在汇编文件中的输出后添加换行符,我不知道该怎么办。 这是我编写的一个简单的测试文件,用于尝试在没有换行符的情况下进行打印:

extern printf


LINUX        equ     80H      ; interupt number for entering Linux kernel
EXIT         equ     60       ; Linux system call 1 i.e. exit ()




section .data
    int_output_format: db "%ld", 0


segment .text
    global  main


main:
    mov r8, 10
    push rdi
    push rsi
    push r10
    push r9
    mov rsi, r8
    mov rdi, int_output_format
    xor rax, rax
    call printf
    pop r9
    pop r10
    pop rsi
    pop rdi
    call os_return      ; return to operating system


os_return:
    mov  rax, EXIT      ; Linux system call 1 i.e. exit ()
    mov  rdi, 0     ; Error code 0 i.e. no errors
    syscall     ; Interrupt Linux kernel 64-bit

但正如我读过的文章表明 stdout 没有被刷新。我在想也许我需要在输出数字后以某种方式刷新?但我真的不确定。

我正在使用 NASM 汇编语言。

提前致谢!

I've recently read this article on using printf and scanf in assembly:

Meaning of intfmt: db "%d", 10, 0 in assembly

In particular it says
"In printf, the newline prints a newline and then (if the output is in line buffered mode, which it probably is), flushes the internal output buffer so you can actually see the result. So when you remove the 10, there's no flush and you don't see the output."

However I do not know what to do if I do not want a newline after my output in my assembly file.
Here's a simple test file I've written to try printing without a newline:

extern printf


LINUX        equ     80H      ; interupt number for entering Linux kernel
EXIT         equ     60       ; Linux system call 1 i.e. exit ()




section .data
    int_output_format: db "%ld", 0


segment .text
    global  main


main:
    mov r8, 10
    push rdi
    push rsi
    push r10
    push r9
    mov rsi, r8
    mov rdi, int_output_format
    xor rax, rax
    call printf
    pop r9
    pop r10
    pop rsi
    pop rdi
    call os_return      ; return to operating system


os_return:
    mov  rax, EXIT      ; Linux system call 1 i.e. exit ()
    mov  rdi, 0     ; Error code 0 i.e. no errors
    syscall     ; Interrupt Linux kernel 64-bit

but as the article I've read suggests stdout isn't being flushed. I was thinking perhaps I need to somehow flush after I output the number? But I'm really not sure.

I am using the NASM assembly language.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无人问我粥可暖 2024-12-28 06:45:54

fflush() 刷新行缓冲或全缓冲的输出stdio 流:

extern fflush
...
xor  edi, edi          ; RDI = 0
call fflush            ; fflush(NULL) flushes all streams
...

或者,mov rdi, [stdout] / call fflush 也可以仅刷新该流。 (使用 default rel 来实现高效的 RIP 相对寻址,并且您还需要 extern stdout。)

fflush() flushes buffered output in line or full-buffered stdio streams:

extern fflush
...
xor  edi, edi          ; RDI = 0
call fflush            ; fflush(NULL) flushes all streams
...

Alternatively, mov rdi, [stdout] / call fflush also works to flush only that stream. (Use default rel for efficient RIP-relative addressing, and you'll need extern stdout as well.)

找回味觉 2024-12-28 06:45:54

调用 fflush(stdout); 来显示缓冲区中当前的内容。

Call fflush(stdout); to display what's currently sitting in the buffers.

厌味 2024-12-28 06:45:54

对于 Windows 32 位模式 (FASM):

push [_iob]
call [fflush]   ; call into DLL.  Callee-pops calling convention

GNU/Linux 32 位模式 (NASM)

extern fflush
extern stdout
...
push dword [stdout]
call fflush            ; linker takes care of PLT stub for dynamic linking (in a non-PIE executable)
add  esp, 4            ; caller-pops calling convention
etc...

For Windows 32-bit mode (FASM):

push [_iob]
call [fflush]   ; call into DLL.  Callee-pops calling convention

GNU/Linux 32-bit mode (NASM)

extern fflush
extern stdout
...
push dword [stdout]
call fflush            ; linker takes care of PLT stub for dynamic linking (in a non-PIE executable)
add  esp, 4            ; caller-pops calling convention
etc...
迎风吟唱 2024-12-28 06:45:54

另一种可能性是删除 stdout 流的默认行缓冲。这里 C 调用来做到这一点。翻译成汇编让作为练习,因为我认为在 ASM 中进行文件/流 I/O 甚至没有意义,成本/收益是非常错误的。

setvbuf(stdout, NULL, _IONBF, 0);

这样,每个 printf(以及 fputs、putc、puts 等)都会有一个隐式的 fflush

The other possibility would be to remove the default line buffering of the stdoutstream. Here the C call to do that. Translation to assembly let as exercice, as I don't think it makes even sense to do file/stream I/O in ASM, the cost/benefit is tremendously wrong.

setvbuf(stdout, NULL, _IONBF, 0);

This way every printf (and fputs, putc, puts etc...) would have an implicit fflush

苦笑流年记忆 2024-12-28 06:45:54

我的答案是针对那些寻求快速绕过问题而不是实际解决方案的人。

我试图一次输出一位数字 1234,并遇到了与此处相同的问题。在使用上述解决方案没有成功之后,并且不想在这方面花费超过几分钟的时间,我找到了一种显示数字的简单方法。

在输出字符串格式中,只需有一个空行的输出字符串(当然还有换行符)。

Digit_out: db "%u", 0
Number_end: db "", 10, 0

随心所欲地输出;就我而言,我有 4 次 digital_out 推送(其中 4 次数字本身推送)和 4 次 printf 调用。

完成后,按下 Number_end 并最后调用 printf。然后将显示整个数字:)

My answer is for those searching a fast bypass to the problem, not an actual fix.

I was attempting to output the number 1234 one digit at a time and encountered the same issue as those here. After having no success with the mentioned solutions, and not wanting to spend more than a few minutes on this, I have found an easy way to display the number.

In your output string formats, simply have an output string that is an empty line (with the newline ofcourse).

Digit_out: db "%u", 0
Number_end: db "", 10, 0

Output as you would; in my case I had 4 pushes of digit_out (with 4 pushes of the digits themselves) and 4 calls to printf.

Once this is done, push Number_end and do a final call to printf. The entire number will then show :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文