Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compile this program with inline asm?

I cannot compile this program taken from a tutorial. It should print "Hello World".

void main() 
{
    __asm__("jmp forward\n\t"
            "backward:\n\t"
            "popl   %esi\n\t"
            "movl   $4, %eax\n\t"
            "movl   $2, %ebx\n\t"
            "movl   %esi, %ecx\n\t"
            "movl   $12, %edx\n\t"
            "int    $0x80\n\t"
            "int3\n\t"
            "forward:\n\t"
            "call   backward\n\t"
            ".string \"Hello World\\n\""
           );
}

gcc 4.7 under Linux gives me the following error:

gcc hello.c -o hello
hello.c: Assembler messages:
hello.c:5: Error: invalid instruction suffix for `pop'

Is there also a way to avoid to specify double quotes for each line?

Also, I'd like to know how to modify the program to use libc call printf instead of the kernel service.

like image 237
Martin Avatar asked Aug 10 '13 03:08

Martin


1 Answers

Q:

hello.c: Assembler messages:
hello.c:5: Error: invalid instruction suffix for `pop'

A: popl is available on x86-32 but not on x86-64 (it has popq instead). You need to either adapt your assembly code to work on x86-64, or you need to invoke GCC to generate x86-32 binary output.

Assuming you want to generate x86-32, use the command-line option -m32.

Q:

Is there also a way to avoid to specify double quotes for each line?

A: Nope. This is because __asm__() is a pseudo-function that takes string arguments, so the string follows the C syntax. The contents of the string are passed to the assembler with little or no processing.

Note that in C, when strings are juxtaposed, they are concatenated. For example, "a" "b" is the same as "ab".

Note that in the assembly language syntax (GAS), you can separate statements by newline or by a semicolon, like this: "movl xxx; call yyy" or "movl xxx \n call yyy".

Q:

how to modify the program to use libc call printf

A: Follow the calling convention for C on x86. Push arguments from right to left, call the function, then clean up the stack. Example:

pushl $5678  /* Second number */
pushl $1234  /* First number */
pushl $fmtstr
call printf
addl $12, %esp  /* Pop 3 arguments of 4 bytes each */

/* Put this away from the code */
fmtstr: .string "Hello %d %d\n"  /* The \n needs to be double-backslashed in C */
like image 101
Nayuki Avatar answered Sep 20 '22 14:09

Nayuki