GCC Inline asm label BUG??

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.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Good morning, this was never meant to end or start an argument or offend anyone, So I apologize.
This is a great site and the only one I use or have any interest in.
I think gcc is great, awesome in-fact.

As gcc optimizes out the code unless I write it this way I could not find an easy way to show you guys what I think was happening.
So the code displayed was broken, stack, void, inline, etc...
It is not production code.
I was just trying to show the value in rax was different even when the code was not optimized out.
I will try some more code to get a cleaner example, but the cleaner I go, the more gcc removes code, as it should, and it is then pointless.

Thanks all.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Ok, I hope this serves me well, what do you of this Feature, LOL?

It aligns correctly, it calls DoThis with the correct address.
BUT, the value returned points to before the ".align 16" instead of TSD_SpecialCode
If I remove the ".align 16" it works, I was hoping it would work with ".align"

Here is the source:

Code: Select all

	QWORD ReturnASpecialPointerToInlinedASMCode()
	{
		asm goto("jmp %l0" : : : : DoThis);

asm volatile (	".align 16 \t\n");
TSD_SpecialCode:
		// The issue is the value returned by this function
		// To use this I have just inserted a mov and a ret so it can be called as a normal function, BUT it will crash.
		asm volatile (	"mov $0x1234, %rax \t\n"		\
						"retq \t\n");

DoThis:

		QWORD Addr = (QWORD)&&TSD_SpecialCode;
		return Addr;
	}
And here is the optimised output, which has the special feature??:

Code: Select all

000000000030fe10 <_ZN6Kernel37ReturnASpecialPointerToInlinedASMCodeEv>:
  30fe10:	eb 16                	jmp    30fe28 <_ZN6Kernel37ReturnASpecialPointerToInlinedASMCodeEv+0x18>
  30fe12:	66 66 66 66 66 2e 0f 	data32 data32 data32 data32 nop WORD PTR cs:[rax+rax*1+0x0]
  30fe19:	1f 84 00 00 00 00 00 
  30fe20:	48 c7 c0 34 12 00 00 	mov    rax,0x1234
  30fe27:	c3                   	ret    
  30fe28:	48 b8 12 fe 30 00 00 	movabs rax,0x30fe12
  30fe2f:	00 00 00 
  30fe32:	c3                   	ret    
  30fe33:	90                   	nop
  30fe34:	66 66 66 2e 0f 1f 84 	data32 data32 nop WORD PTR cs:[rax+rax*1+0x0]
  30fe3b:	00 00 00 00 00
And for completeness, the debug output, which returns the correct address, not special feature??:

Code: Select all

00000000003074dd <_ZN6Kernel37ReturnASpecialPointerToInlinedASMCodeEv>:
  3074dd:	55                   	push   rbp
  3074de:	48 89 e5             	mov    rbp,rsp
  3074e1:	48 83 ec 10          	sub    rsp,0x10
  3074e5:	eb 11                	jmp    3074f8 <_ZN6Kernel37ReturnASpecialPointerToInlinedASMCodeEv+0x1b>
  3074e7:	66 0f 1f 84 00 00 00 	nop    WORD PTR [rax+rax*1+0x0]
  3074ee:	00 00 
  3074f0:	48 c7 c0 34 12 00 00 	mov    rax,0x1234
  3074f7:	c3                   	ret    
  3074f8:	48 c7 45 f8 f0 74 30 	mov    QWORD PTR [rbp-0x8],0x3074f0
  3074ff:	00 
  307500:	48 8b 45 f8          	mov    rax,QWORD PTR [rbp-0x8]
  307504:	c9                   	leave  
  307505:	c3                   	ret    
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: GCC Inline asm label BUG??

Post by sortie »

Never write interrupt handlers in C.

It doesn't work. Write your interrupt handlers in assembly and then safely call C from them.

End of story. Trust us on this. Never claim there is a compiler bug when osdev members claim your code is broken: Fix your code and then we can potentially talk. You are not able to write correct inline assembly, it's very hard and even I have trouble doing so - you must be an expert in inline assembly to correctly do it. It's not a bug that your inline assembly generates incorrect code when your inline assembly is incorrectly written.

Btw: Your original post is very confusing for people reading the topic for the first time, please use a more sane style of editing your posts.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Ok, cheers guys!
I think it can be done using gcc if the above approach is taken to return a pointer to the "SpecialCode" label instead of the function.
It will save one call and a possible cache miss.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Please remember this is just "I think"
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Just read the interrupt service routine supplied and it has code like mine at the bottom, so I will copy and paste to see what it returns, and it returns the correct address!!

Great, so that is how it is done, using asm volatile goto !!

Here is the function for those interested.

Code: Select all

	void * interrupt_handler( )
	{
		asm volatile goto( "jmp %l[endOfISR]" : : : "memory" : endOfISR );
		asm volatile( ".align 16\t\n" : : : "memory" );  // align by 16 for efficiency - could be even higher, depending on CPU
startOfISR:
		asm volatile( "push %%rax\t\n" : : : "memory" );

		asm volatile( "pop %%rax\t\niret\t\n" : : : "memory" );
endOfISR:
		asm volatile goto( "mov %l[startOfISR], %%eax" : : : "memory" : startOfISR );

	}
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: GCC Inline asm label BUG??

Post by Combuster »

Great, so that is how it is done
You taught yourself Unmaintainable Code. Congratulations. :-({|=
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Awesome, cheers guys. LOL, good to learn.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Hi guys, now, is this a mistake in the documentation?

I found that that the mov was wrong, it should be lea.

Code: Select all

void * interrupt_handler( )
   {
      asm volatile goto( "jmp %l[endOfISR]" : : : "memory" : endOfISR );
      asm volatile( ".align 16\t\n" : : : "memory" );  // align by 16 for efficiency - could be even higher, depending on CPU
startOfISR:
      asm volatile( "push %%rax\t\n" : : : "memory" );

      asm volatile( "pop %%rax\t\niret\t\n" : : : "memory" );
endOfISR:
      asm volatile goto( "mov %l[startOfISR], %%eax" : : : "memory" : startOfISR );

   }
Here is my version for x64:

Code: Select all

		asm volatile goto( "jmp %l[endOfISR]" : : : "memory" : endOfISR );
		asm volatile( ".align 64\t\n" : : : "memory" );  // align by 64 for efficiency
startOfISR:
		asm volatile( "push %%rax\t\n" : : : "memory" );

		asm volatile( "pop %%rax\t\n" : : : "memory" );
		asm volatile( "iretq\t\n" : : : "memory" );
endOfISR:
		asm volatile goto( "lea %l[startOfISR], %%rax" : : : "memory" : startOfISR );
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: GCC Inline asm label BUG??

Post by bluemoon »

tsdnz wrote:QWORD ReturnASpecialPointerToInlinedASMCode()
{
asm goto("jmp %l0" : : : : DoThis);

asm volatile ( ".align 16 \t\n");
TSD_SpecialCode:
// The issue is the value returned by this function
// To use this I have just inserted a mov and a ret so it can be called as a normal function, BUT it will crash.
asm volatile ( "mov $0x1234, %rax \t\n" \
"retq \t\n");

DoThis:

QWORD Addr = (QWORD)&&TSD_SpecialCode;
return Addr;
}
This is not a good idea to tell compiler you have one function, while there are two.
You could have hundred ways to lie to the compiler and do something, but I won't call it good practice.

Also, as already pointed out, your inline assembly is broken, individual asm block can be re-ordered, things without side effect can be legally eliminated by the compiler.

In short, reordering the label to 0x30fe12, which is before "align 16", is totally legal output.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

This is not a good idea to tell compiler you have one function, while there are two.
You could have hundred ways to lie to the compiler and do something, but I won't call it good practice.

Also, as already pointed out, your inline assembly is broken, individual asm block can be re-ordered, things without side effect can be legally eliminated by the compiler.

In short, reordering the label to 0x30fe12, which is before "align 16", is totally legal output.
Yes Many thanks, I agree, just want to remove a call or jump and possible cache miss.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: GCC Inline asm label BUG??

Post by sortie »

Don't write interrupt handlers in C.

It doesn't work and it cannot possibly work except if you have absolute control over code generation. You don't have it here. It can be done with naked functions (not supported by gcc on x86 because it would be abused by crazy people like you), or using top-level asm() statements (but that would be effectively writing it in assembly as I recommended). For instance, look at this function:

Code: Select all

int foo() {
    asm("whatever");
}
How can we assure that nothing and absolutely nothing happens before whatever, that is, whatever is the first instruction executed when jumping to the foo symbol? We can't. The compiler might push the ebp register to register the function in the call stack linker list. It might push a few registers that are clobbered by later instructions. It might do a sanity check, or set up a stack canary if various security features are enabled. Quite simply, it cannot possibly be done reliably that way.

Don't write interrupt handlers in C. You don't have control over code generation to the level that you need. Write the interrupt handlers in assembly and call C from assembly when things are safe.
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

Don't write interrupt handlers in C. You don't have control over code generation to the level that you need. Write the interrupt handlers in assembly and call C from assembly when things are safe.
I did have them in assembly, thanks, I agree that it does not look the best and could cause me issues latter on, it is working in c++ now. I have the code commented out in my secondary loader if I need to resort back to it.
jbemmel
Member
Member
Posts: 53
Joined: Fri May 11, 2012 11:54 am

Re: GCC Inline asm label BUG??

Post by jbemmel »

All the obvious comments about preliminary optimizations and other bad practices aside, did you know you can actually have multiple asm statements in a single "asm volatile" block?

e.g. asm volatile(
".global irq_routine \t\n"
"irq_routine: \t\n"
"push %rax \t\n"
"pop %rbx \t\n"
"iret" )

gcc will pass this string to the assembler as-is. See https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html on how you could declare
extern "C" void irq_routine() asm("irq_routine");
to refer to this piece of code
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC Inline asm label BUG??

Post by tsdnz »

All the obvious comments about preliminary optimizations and other bad practices aside, did you know you can actually have multiple asm statements in a single "asm volatile" block?

e.g. asm volatile(
".global irq_routine \t\n"
"irq_routine: \t\n"
"push %rax \t\n"
"pop %rbx \t\n"
"iret" )
Yes thanks, I know this.

I did not know the .global
Thanks.
Last edited by tsdnz on Tue Jun 24, 2014 4:55 pm, edited 1 time in total.
Post Reply