1
votes

Test platform is on Linux 32 bit. (But certain solution on windows 32 bit is also welcome)

Here is a c code snippet:

int a = 0;
printf("%d\n", a);

And if I use gcc to generate assembly code

gcc -S test.c

Then I will get:

      movl    $0, 28(%esp)
      movl    28(%esp), %eax
      movl    %eax, 4(%esp)
      movl    $.LC0, (%esp)
      call    printf
      leave
      ret

And this assembly code needs linking to libc to work(because of the call printf)

My question is :

Is it possible to convert C to asm with only explicit using system call automatically, without using libc?

Like this:

    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

Directly call the int 80h software interrupt.

Is it possible? If so, is there any tool on this issue?

Thank you!

3
I don't understand the question. The gcc compiler is a good tool to convert C code to assembly (but there are others). And you might use gcc -O -fverbose-asm -S to get some better assembly code. Or is your question about how to make syscalls without any C code? Then read the Linux Assembler HowToBasile Starynkevitch
You haven't clearly explained what's wrong with the gcc method. Are you just talking about the difference in representation? see: stackoverflow.com/q/972602/10396AShelly
@BasileStarynkevitch Hi, I am sorry and I modified the questionlllllllllllll
Define what polymorphic engine means to you.Basile Starynkevitch
@computereasy: please edit your question to improve it. Add what you explained in comments back into the question!Basile Starynkevitch

3 Answers

7
votes

Not from that source code. A call to printf() cannot be converted by the compiler to a call to the write system call - the printf() library function contains a significant amount of logic which is not present in the system call (such as processing the format string and converting integer and floating-point numbers to strings).

It is possible to generate system calls directly, but only by using inline assembly. For instance, to generate a call to _exit(0) (not quite the same as exit()!), you would write:

#include <asm/unistd.h>
...
int retval;
asm("int $0x80" : "=a" (retval) : "a" (__NR_exit), "b" (0));

For more information on GCC inline assembly, particularly on the constraints I'm using here to map variables to registers, please read the GCC Inline Assembly HOWTO. It's rather old, but still perfectly relevant.

Note that doing this is not recommended. The exact calling conventions for system calls (e.g, which registers are used for the call number and arguments, how errors are returned, etc) are different on different architectures, operating systems, and even between 32-bit and 64-bit x86. Writing code this way will make it very difficult to maintain.

6
votes

You can certainly compile C code to assembly without linking to libc, but you can't use the C library functions. Libc's entire purpose IS to provide the interface from C library functions to Linux system calls (or Windows, or whatever system you're on). So, if you didn't want to use libc, you would have to write your own wrappers to the system calls.

2
votes

If you compile some C code which does not use any function from the C library (e.g. does not use printf or malloc etc etc....) in the free-standing mode of the GCC compiler (i.e. with -ffreestanding flag to gcc), you'll need either to call some assembler function (from some other object or library) or to use asm instruction (you won't be able to do any kind of input output without making a syscall).

Read also the Assembly HowTo, the x86 calling conventions and the ABI relevant to your kernel (probably x86-64 ABI) and understand quite well what are system calls, starting with syscalls(2) and what is the VDSO (int 80 is not the best way to make syscalls these days, SYSENTER is often better). Study the source code of some libc, in particular of MUSL libc (whose source code is very readable).

On Windows (which is not free software and which I don't know) the question could be much more difficult: I am not sure that the system call level is exactly and completely documented.

The libffi enables you to call arbitrary functions from C. You could also cast function pointers from dlsym(3). You could consider JIT techniques (e.g. libjit, GNU lightning, asmjit etc...).