ead*_*ead 4 linux assembly printf glibc x86-64
我尝试printf从我的汇编代码中使用,这是一个应该打印hello到标准输出的最小示例:
.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
Run Code Online (Sandbox Code Playgroud)
我用
gcc -nostdlib try_printf.s -o try_printf -lc
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它似乎工作:字符串hello被打印出来,退出状态是0:
XXX$ ./try_printf
hello
XXX$ echo $?
0
XXX$
Run Code Online (Sandbox Code Playgroud)
但是当我尝试捕获文本时,很明显,某些内容无法正常工作:
XXX$ output=$(./try_printf)
XXX$ echo $output
XXX$
Run Code Online (Sandbox Code Playgroud)
该变量output应具有 value hello,但为空。
我的用法有printf什么问题?
在使用 stdio 函数(如 printf)后使用call exit而不是原始_exit系统调用。 这会write在进行exit_group系统调用之前刷新 stdio 缓冲区(系统调用)。
(或者,如果您的程序定义了一个main而不是_start,则返回 frommain等效于调用exit。您不能ret从_start。)调用fflush(NULL)也应该有效。
正如迈克尔解释的那样,动态链接 C 库是可以的。这也是“自下而上编程”一书中的介绍(见第 8 章)。
然而,重要的是exit从 C 库调用以结束程序而不是绕过它,这是我错误地调用exit-syscall. 正如迈克尔所暗示的那样,退出会像冲洗流一样进行大量清理。
这就是发生的事情:正如这里所解释的,C 库按如下方式缓冲标准流:
哪种情况适用取决于printf第一次为流调用时。
因此,如果printf_try在终端直接调用,该程序的输出可以看出,因为hello具有\n在端部(其触发在行缓冲模式冲洗),并且它是一个终端,也2.情况。
printf_try通过调用$(./printf_try)意味着标准输出不再是终端(实际上我不知道它是临时文件还是内存文件),因此 3. 情况有效 - 需要显式刷新,即调用 C - exit.
| 归档时间: |
|
| 查看次数: |
1359 次 |
| 最近记录: |