lll*_*lll 1 c compiler-construction assembly assemblies
测试平台在Linux 32位上.(但也欢迎Windows 32位上的某些解决方案)
这是交响代码段:
int a = 0;
printf("%d\n", a);
Run Code Online (Sandbox Code Playgroud)
如果我使用gcc生成汇编代码
gcc -S test.c
Run Code Online (Sandbox Code Playgroud)
然后我会得到:
movl $0, 28(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
leave
ret
Run Code Online (Sandbox Code Playgroud)
而这个汇编代码需要链接到libc才能工作(因为调用printf)
我的问题是:
是否可以将C转换为asm,只使用显式使用系统调用,而不使用libc?
像这样:
pop ecx
add ecx,host_msg-host_reloc
mov eax,4
mov ebx,1
mov edx,host_msg_len
int 80h
mov eax,1
xor ebx,ebx
int 80h
Run Code Online (Sandbox Code Playgroud)
直接调用int 80h软件中断.
可能吗?如果是这样,这个问题上有什么工具吗?
谢谢!
不是来自那个源代码.的呼叫到printf()不能由编译器变换为对一个呼叫write系统调用-的printf()库函数包含逻辑的显著量中不存在系统中的呼叫(如处理格式字符串和转换整数和浮点数到字符串).
可以直接生成系统调用,但只能使用内联汇编.例如,要生成一个调用_exit(0)(与exit()!不完全相同),您可以编写:
#include <asm/unistd.h>
...
int retval;
asm("int $0x80" : "=a" (retval) : "a" (__NR_exit), "b" (0));
Run Code Online (Sandbox Code Playgroud)
有关GCC内联汇编的更多信息,特别是我在这里用于将变量映射到寄存器的约束,请阅读GCC内联汇编HOWTO.它相当古老,但仍然完全相关.
请注意,建议不要这样做.系统调用的确切调用约定(例如,哪些寄存器用于调用号和参数,如何返回错误等)在不同的体系结构,操作系统甚至32位和64位x86之间是不同的.以这种方式编写代码将使维护变得非常困难.
您当然可以将C代码编译为汇编而无需链接到libc,但您不能使用C库函数.Libc的全部目的是提供从C库函数到Linux系统调用(或Windows,或者您正在使用的任何系统)的接口.因此,如果您不想使用libc,则必须将自己的包装器写入系统调用.