Page 1 of 1

gcc inline assembler syntax for ljmp seg:offset

Posted: Tue Jul 16, 2024 12:02 pm
by sebihepp
Dear OSDev Community,

I am currently hanging with my inline assembler line for the long jump. I tried many thinks and googled for hours, but I am still not able to produce something that will compile.

I am in 32bit PMode and setup a new GDT. Now I want to do a far jump to update the CS. Here is what I use:

Code: Select all

#define GDT_CODE32_SEL 0x08
#define GDT_DATA32_SEL 0x10
(...)
	asm volatile (
		"lgdt %0;"
		"ljmp $%1, $1f;"
		"1:"
		"movw %%ax, %%ds;"
		"movw %%ax, %%es;"
		"movw %%ax, %%fs;"
		"movw %%ax, %%gs;"
		"movw %%ax, %%ss;"
		:  
		: "m" (GlobalDescriptorTableDescriptor), "i" (GDT_CODE32_SEL), "ax" (GDT_DATA32_SEL)
		: 
	);
(...)
The compiler error is that there is an undefined reference to "$8" - But the $ should indicate an immediate value. If I try without the $ I get an error "operand mismatch".

Why does GCC think the $8 is a symbol and not an immediate value?

Best regards
Sebi

Re: gcc inline assembler syntax for ljmp seg:offset

Posted: Tue Jul 16, 2024 12:07 pm
by sebihepp
And as soon as I tried one more thing I solved it: The $ sign is too much for the segment. But why?

Re: gcc inline assembler syntax for ljmp seg:offset

Posted: Tue Jul 16, 2024 9:02 pm
by Octocontrabass
Tokens in the assembler template are replaced with operands formatted according to the constraint you've chosen. You used "i" as the constraint for the code segment selector, so GCC replaces the "%1" token with "$8". Since you wrote "$%1" in the template, you got "$$8", which the assembler interprets as a reference to a symbol called "$8" and not the literal value 8.

The constraint you used for the data segment descriptor is wrong. You used "ax", but GCC interprets that as "a" and "x" separately. The "a" constraint tells GCC it can use EAX, and the "x" constraint tells GCC it can use any SSE register. You probably wanted to use "a" by itself. (Alternatively, use "r" as the constraint and use "%2" instead of "%%ax" so GCC can choose the register.)