我尝试从我的汇编代码中使用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什么问题?
正如Michael解释的那样,动态链接C库是可以的。 这也是在“自下而上”的书中介绍的(见第8章)。
然而,为了结束程序而不是绕过它,调用C库的exit是非常重要的,这就是我通过调用exit-syscall所做的错误。 正如迈克尔所暗示的那样,出口像清理溪流一样清理了很多。
这就是发生了什么事情:正如这里所解释的,C库缓冲标准流如下:
当第一次调用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 。