在汇编中使用printf会导致输出空 [英] Using printf in assembly leads to an empty ouput

查看:180
本文介绍了在汇编中使用printf会导致输出空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从我的汇编代码中使用printf,这是一个最小的示例,应该只将hello打印到stdout:

I try to use printf from my assembler code, this is a minimal example which should just print hello to stdout:

.section  .rodata
hello:
    .ascii  "hello\n\0"
.section .text
    .globl _start        
_start:
    movq $hello, %rdi #first parameter
    xorl %eax, %eax #0 - number of used vector registers
    call printf        
#exit   
    movq $60, %rax
    movq $0, %rdi
    syscall

我用

gcc -nostdlib try_printf.s -o try_printf -lc

,当我运行它时,它似乎可以正常工作:打印出字符串hello,退出状态为0:

and when I run it, it seems to work: the string hello is printed out and the exit status is 0:

XXX$ ./try_printf
hello
XXX$ echo $?
0
XXX$

但是当我尝试捕获文本时,很明显,某些功能无法正常工作:

But when I try to capture the text, it is obvious, that something is not working properly:

XXX$ output=$(./try_printf) 
XXX$ echo $output

XXX$ 

变量output的值应为hello,但为空.

The variable output should have the value hello, but is empty.

我使用printf有什么问题?

推荐答案

在使用诸如printf之类的stdio函数之后,使用call exit代替原始的_exit syscall.

Use call exit instead of a raw _exit syscall after using stdio functions like printf.

正如Michael所解释的,可以动态链接C库.这也是自下而上编程" 一本书(请参阅第8章).

As Michael explained, it is OK to link the C-library dynamically. This is also how it is introduced in the "Programming bottom up" book (see chapter 8).

但是,从C库中调用exit以结束程序而不是绕过程序很重要,这是我错误地通过调用exit-syscall所做的.正如Michael所暗示的,exit会做很多清理像冲洗溪流.

However it is important to call exit from the C-library in order to end the program and not to bypass it, which was what I wrongly did by calling exit-syscall. As hinted by Michael, exit does a lot of clean up like flushing streams.

发生的事情:如此处,C库将按以下方式缓冲标准流:

That is what happened: As explained here, the C-library buffers the the standard streams as follows:

  1. 不缓冲标准错误.
  2. 如果标准输出/输入是终端,则它是行缓冲的.
  3. 如果标准输出/输入不是终端,则它是完全缓冲的,因此在编写结束时需要刷新.

哪种情况是在第一次为流调用printf时决定的.

Which case applies is decided when printf is called for the first time for a stream.

因此,如果直接在终端中调用printf_try,则可以看到程序的输出,因为hello的末尾带有\n(在行缓冲模式下触发刷新),并且它是一个终端,也是2.情况.

So if printf_try is called directly in the terminal, the output of the program can be seen because hello has \n at the end (which triggers the flush in the line-buffered mode) and it is a terminal, also the 2. case.

通过$(./printf_try)调用printf_try意味着stdout不再是终端(实际上我不知道是临时文件还是内存文件),因此3.情况有效-存在需要显式刷新,即调用C- exit.

Calling printf_try via $(./printf_try) means that the stdout is no longer a terminal (actually I don't know whether is is a temp file or a memory file) and thus the 3. case is in effect - there is need for an explicit flush i.e. call to C-exit.

这篇关于在汇编中使用printf会导致输出空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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