7
votes

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.

1
well it should be int main for one, asm is pretty system dependent so it could definitely crash depending on which computer your using - aaronman
It looks like you're compiling x86-32 code to output to an x86-64 binary. - Nayuki
You could remove the ls and change %e* to %r*, which gets somewhere. Don’t trust my opinion on it, however. - Ry-
@NayukiMinase maybe you should post an answer so we can upvote it - Homer6
Don't fall into the trap thinking that using call instructions from within GCC inline assembly is a simple thing to do. Unless you're very very careful, there's a lot of cornercases (especially in 64bit) where doing so will break things. Not always ... just sometimes ... and if so not usually right at the place where your inline asm ends up. A clobber list is mandatory if you do this. - FrankH.

1 Answers

10
votes

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 */