GCC Inline asm label BUG??
Re: GCC Inline asm label BUG??
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.
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.
Re: GCC Inline asm label BUG??
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:
And here is the optimised output, which has the special feature??:
And for completeness, the debug output, which returns the correct address, not special feature??:
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;
}
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
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
Re: GCC Inline asm label BUG??
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.
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.
Re: GCC Inline asm label BUG??
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.
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.
Re: GCC Inline asm label BUG??
Please remember this is just "I think"
Re: GCC Inline asm label BUG??
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.
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 );
}
- Combuster
- 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??
You taught yourself Unmaintainable Code. Congratulations.Great, so that is how it is done
Re: GCC Inline asm label BUG??
Awesome, cheers guys. LOL, good to learn.
Re: GCC Inline asm label BUG??
Hi guys, now, is this a mistake in the documentation?
I found that that the mov was wrong, it should be lea.
Here is my version for x64:
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 );
}
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 );
Re: GCC Inline asm label BUG??
This is not a good idea to tell compiler you have one function, while there are two.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;
}
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.
Re: GCC Inline asm label BUG??
Yes Many thanks, I agree, just want to remove a call or jump and possible cache miss.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.
Re: GCC Inline asm label BUG??
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:
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.
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");
}
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.
Re: GCC Inline asm label BUG??
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.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.
Re: GCC Inline asm label BUG??
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
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
Re: GCC Inline asm label BUG??
Yes thanks, I know this.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" )
I did not know the .global
Thanks.
Last edited by tsdnz on Tue Jun 24, 2014 4:55 pm, edited 1 time in total.