是否可以在Linux上没有链接libc的情况下将C转换为asm?

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软件中断.

可能吗?如果是这样,这个问题上有什么工具吗?

谢谢!

dus*_*uff 7

不是来自那个源代码.的呼叫到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之间是不同的.以这种方式编写代码将使维护变得非常困难.


chb*_*er0 6

您当然可以将C代码编译为汇编而无需链接到libc,但您不能使用C库函数.Libc的全部目的是提供从C库函数到Linux系统调用(或Windows,或者您正在使用的任何系统)的接口.因此,如果您不想使用libc,则必须将自己的包装器写入系统调用.