在assembly中使用printf会导致空的输出

我尝试从我的汇编代码中使用printf ,这是一个最简单的例子,它应该打印hello到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 

我用它来构build它

 gcc -nostdlib try_printf.s -o try_printf -lc 

当我运行它,似乎工作:stringhello打印出来,退出状态是0

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

但是,当我尝试捕捉文本时,很明显,有些东西不能正常工作:

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

variablesoutput的值应该是hello ,但是是空的。

我使用printf什么问题?

Solutions Collecting From Web of "在assembly中使用printf会导致空的输出"

正如Michael解释的那样,动态链接C库是可以的。 这也是在“自下而上”的书中介绍的(见第8章)。

然而,为了结束程序而不是绕过它,调用C库的exit是非常重要的,这就是我通过调用exit-syscall所做的错误。 正如迈克尔所暗示的那样,出口像清理溪流一样清理了很多。

这就是发生了什么事情:正如这里所解释的,C库缓冲标准流如下:

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

当第一次调用printf时,决定使用哪种情况。

所以如果在终端直接调用printf_try ,程序的输出就可以看出来了,因为hello在结尾处有\n (在线路缓冲模式下触发刷新),它是一个终端,也是2.情况。

通过$(./printf_try)调用printf_try意味着stdout不再是一个终端(实际上我不知道是一个临时文件还是一个内存文件),因此3. case就是有效的 -一个明确的同花顺即呼叫C- exit

C标准库通常包含标准I / O流的初始化代码 – 通过定义自己的入口点来绕过初始化代码。 尝试定义main而不是_start

  .globl main main: # _start code here. 

然后使用gcc try_printf.s -o try_printf不带-nostdlib-nostdlib