Inline assembly call problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
IanSeyler
Member
Member
Posts: 326
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Inline assembly call problem

Post 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?
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Inline assembly call problem

Post by gerryg400 »

You need a '$'.
If a trainstation is where trains stop, what is a workstation ?
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: Inline assembly call problem

Post 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".
User avatar
IanSeyler
Member
Member
Posts: 326
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Re: Inline assembly call problem

Post 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?
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Inline assembly call problem

Post by xenos »

I guess you need an indirect call:

Code: Select all

asm volatile ("call *%0" : : "r" (0x00100010), "S"(str));
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
IanSeyler
Member
Member
Posts: 326
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Re: Inline assembly call problem

Post 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
			);
}
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
fronty
Member
Member
Posts: 188
Joined: Mon Jan 14, 2008 5:53 am
Location: Helsinki

Re: Inline assembly call problem

Post 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.
Post Reply