Page 1 of 2
GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 11:27 am
by Ch4ozz
So this is like the 500th time GCC fucks with my inline asm and I have no idea why.
This is my small little function in C:
Code: Select all
int i;
for(i = 0; i < vfs_drive_cnt; i++)
{
char szPath[64];
sprintf(szPath, "%c:\\DATA\\APPS\\CMD.BIN", vfs_drive[i].letter);
asm volatile("push %eax; push %ebx");
asm volatile("int $0x30" : : "a"(14), "b"(szPath));
asm volatile("pop %ebx; pop %eax");
}
But GCC ends up with this:
Code: Select all
.text:020223B4 push eax
.text:020223B5 push ebx
.text:020223B6 mov eax, [ebp+var_268]
.text:020223BC int 30h ; (NOT A VECTOR!) FAR JMP instruction for CP/M-style calls
.text:020223BE pop ebx
.text:020223BF pop eax
Is there something I forgot?
Im compiling on O3
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 11:35 am
by Octacone
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 11:36 am
by Ch4ozz
I have a define which replaces asm and volatile with those.
It makes no difference sadly.
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 11:37 am
by Octacone
Ch4ozz wrote:
I have a define which replaces asm and volatile with those.
It makes no difference sadly.
Could it be your linker?
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 11:40 am
by Ch4ozz
octacone wrote: Could it be your linker?
This has nothing todo with the linker.
The object file looks the exact same
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 11:50 am
by Octocontrabass
Please read the wiki page on
inline assembly.
Each block of inline assembly is an independent piece, and GCC has no idea what they do. It will freely reorder them (or remove them!) if it thinks it's safe to do so. If you want some instructions to be a single block of code, you must put them in a single asm statement. Since GCC can't parse inline assembly, you must tell it about anything you clobber that GCC might expect to use later (e.g. registers, memory, condition codes).
Edit:
Oh, and one more thing: you don't need to push registers onto the stack to save them. If your asm statement is correct, GCC will do that for you. (It's also clever enough to avoid wasting time saving things it won't use again.)
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 12:02 pm
by Rusky
Ch4ozz wrote:Code: Select all
asm volatile("push %eax; push %ebx");
asm volatile("int $0x30" : : "a"(14), "b"(szPath));
asm volatile("pop %ebx; pop %eax");
There's no need to push/pop those registers yourself, since you're already telling GCC that you're using them on the second line. And in the general case, there's still no need to push/pop anything yourself- just mark anything you change as clobbered and let the compiler's register allocator handle it.
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 12:18 pm
by Ch4ozz
Well the first thing I tried was this:
Code: Select all
asm volatile("int $0x30" :: "a"(14), "b"(szPath));
I didnt directly look at the produced asm thats why I added push and pops.
Anyways, thanks for the replies, I understood that I have to inform the compiler about changes of the registers using clobbers.
I never used much GCC inline asm because I dont like its syntax (intel syntax is better imo)
So this is what I tried:
Code: Select all
asm volatile("int $0x30" :: "a"(14), "b"(szPath) : "eax", "ebx");
But it doesnt compile and I really dont see why.
I already got it to work by putting everything into one asm statement:
Code: Select all
asm volatile(
"push %%eax;"
"push %%ebx;"
"int $0x30;"
"pop %%ebx;"
"pop %%eax;"
: :
"a" (14),
"b" (szPath)
);
But I try to learn how to use the clobber list properly.
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 12:48 pm
by Rusky
You're already telling GCC which registers you're using, so there's no need for you to use the clobber list or push/pop in this case. The clobber list is only necessary when e.g. the instruction you use implicitly modifies some registers that aren't marked as outputs.
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 1:03 pm
by Ch4ozz
Rusky wrote:You're already telling GCC which registers you're using, so there's no need for you to use the clobber list or push/pop in this case. The clobber list is only necessary when e.g. the instruction you use implicitly modifies some registers that aren't marked as outputs.
Ahhh okay understood this.
Anyways, why this code is still having the wrong result then?
Code: Select all
asm volatile("int $0x30" :: "a"(14), "b"(szPath));
Code: Select all
.text:020223AF call sprintf
.text:020223B4 mov eax, [ebp+var_268]
.text:020223BA int 30h ; (NOT A VECTOR!) FAR JMP instruction for CP/M-style calls
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 1:29 pm
by Rusky
Without more context it's impossible to say- the correct values should be in eax and ebx at the point of the `int` instruction- might be good to confirm that in a debugger, though. It's also possible this part is working fine but you have an unrelated issue somewhere else.
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 1:33 pm
by Ch4ozz
Rusky wrote:Without more context it's impossible to say- the correct values should be in eax and ebx at the point of the `int` instruction- might be good to confirm that in a debugger, though. It's also possible this part is working fine but you have an unrelated issue somewhere else.
Well if you look at the IDA output I posted above, you will see that it moves the string into eax and nothing into ebx.
This is indeed wrong but I dont see a single reason for this.
It works well with -O0
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 1:42 pm
by mikegonta
Ch4ozz wrote:Well the first thing I tried was this:
Code: Select all
asm volatile("int $0x30" :: "a"(14), "b"(szPath));
Works fine for me.
Ch4ozz wrote:I never used much GCC inline asm because I dont like its syntax (intel syntax is better imo)
Use the GCC command-line option -masm=intel for intel syntax.
Ch4ozz wrote:So this is what I tried:
Code: Select all
asm volatile("int $0x30" :: "a"(14), "b"(szPath) : "eax", "ebx");
But it doesnt compile and I really dont see why.
Code: Select all
error: 'asm' operand has impossible constraints
GCC doesn't like to be told what it already knows.
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 2:03 pm
by tsdnz
Ch4ozz wrote:So this is like the 500th time GCC xxxx
with my inline asm and I have no idea why.
This is my small little function in C:
Code: Select all
int i;
for(i = 0; i < vfs_drive_cnt; i++)
{
char szPath[64];
sprintf(szPath, "%c:\\DATA\\APPS\\CMD.BIN", vfs_drive[i].letter);
asm volatile("push %eax; push %ebx");
asm volatile("int $0x30" : : "a"(14), "b"(szPath));
asm volatile("pop %ebx; pop %eax");
}
But GCC ends up with this:
Code: Select all
.text:020223B4 push eax
.text:020223B5 push ebx
.text:020223B6 mov eax, [ebp+var_268]
.text:020223BC int 30h ; (NOT A VECTOR!) FAR JMP instruction for CP/M-style calls
.text:020223BE pop ebx
.text:020223BF pop eax
Is there something I forgot?
Im compiling on O3
This first example should show you how to set and get.
Code: Select all
QWORD setAndGetRAX = 14;
QWORD setAndGetRBX = 0x12345678;
BYTE N = 0x30;
asm volatile("int %2;" : "+a"(setAndGetRAX), "+b"(setAndGetRBX) : "N"((N)) : "cc", "memory");
if (setAndGetRAX == setAndGetRBX) Util.Loop();
Code: Select all
302011: b8 0e 00 00 00 mov eax,0xe
302016: bb 78 56 34 12 mov ebx,0x12345678
30201b: cd 30 int 0x30
30201d: 48 39 d8 cmp rax,rbx
302020: 74 5c je 30207e <ss+0x34>
.....
30207e: eb fe jmp 30207e <ss+0x34>
This will set.
Code: Select all
QWORD setRAX = 14;
QWORD setRBX = 0x12345678;
BYTE N = 0x30;
asm volatile("int %2;" : : "a"(setRAX), "b"(setRBX), "N"((N)) : "cc", "memory");
Code: Select all
302011: b8 0e 00 00 00 mov eax,0xe
302016: bb 78 56 34 12 mov ebx,0x12345678
30201b: cd 30 int 0x30
Re: GCC "optimizing" wrong (again)
Posted: Fri Aug 12, 2016 2:15 pm
by tsdnz
Ch4ozz wrote:But GCC ends up with this:
Code: Select all
.text:020223B4 push eax
.text:020223B5 push ebx
.text:020223B6 mov eax, [ebp+var_268]
.text:020223BC int 30h ; (NOT A VECTOR!) FAR JMP instruction for CP/M-style calls
.text:020223BE pop ebx
.text:020223BF pop eax
Is there something I forgot?
Im compiling on O3
The reason ebx is not set in your snippet is it must have been set when sfprint was called.