Page 1 of 1

Inline assembly call problem

Posted: Fri Feb 11, 2011 2:58 pm
by IanSeyler
Its been a while since I've compiled a C program for BareMetal OS but something has changed with GCC I think.

Main Program

Code: Select all

#include "libBareMetal.h"

int main(void)
{
	b_print_string("Hello world, from C!\n");
	return 0;
}
libBareMetal

Code: Select all

void b_print_string(char *str)
{
	asm volatile ("call 0x00100010" : : "S"(str)); // Make sure source register (RSI) has the string address (str)
}
This used to compile properly under Arch Linux with GCC 4.5.0 but trying it today under Ubuntu 10.10 with GCC 4.4.5 doesn't produce the output I'm expecting.

Binary output with ndisasm shows this:

Code: Select all

0000002B  FF142510001000    call qword [0x100010]
How can I get GCC to treat it as a value instead of a pointer?

Re: Inline assembly call problem

Posted: Fri Feb 11, 2011 3:19 pm
by gerryg400
You need a '$'.

Re: Inline assembly call problem

Posted: Fri Feb 11, 2011 4:31 pm
by Tosi
In AT&T syntax a constant value without a $ prefix is treated as a dereferenced pointer. As gerryg400 pointed out you need a "call $0x00100010" instead of a "call 0x00100010".

Re: Inline assembly call problem

Posted: Fri Feb 11, 2011 8:49 pm
by IanSeyler
I tried that but got this error: Error: operand type mismatch for `call'

Code: Select all

void b_print_string(char *str)
{
	asm volatile ("call $0x00100010" : : "S"(str)); // Make sure source register (RSI) has the string address (str)
}
Could it be the GCC version?

Re: Inline assembly call problem

Posted: Sat Feb 12, 2011 2:19 am
by xenos
I guess you need an indirect call:

Code: Select all

asm volatile ("call *%0" : : "r" (0x00100010), "S"(str));

Re: Inline assembly call problem

Posted: Mon Feb 14, 2011 11:19 am
by IanSeyler
That didn't work either. It generates this: Error: operand type mismatch for `call'

This code generates a call that works:

Code: Select all

void b_print_string(char *str)
{
	asm volatile (
			"mov $0x00100010, %%r15\n\t"
			"call *%%r15"
			: // no output registers
			: "S"(str) // Place string address in RSI
			: "%r15" // Trashed
			);
}

Re: Inline assembly call problem

Posted: Mon Feb 14, 2011 11:41 am
by fronty

Code: Select all

asm volatile ("call *%0" : : "r" (0x00100010ULL), "S"(str));
I didn't try to compile that and I don't know x86(_64)? very well, but I guess your problem could be that the compiler uses 32-bit register when you use 32-bit value, and it thinks the programmer is wise enough to do correct wizardry with inline assembly and doesn't convert your 32-bit to 64-bit which would be correct in this spot.