GCC "optimizing" wrong (again)

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.
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

GCC "optimizing" wrong (again)

Post 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
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: GCC "optimizing" wrong (again)

Post by Octacone »

Try:

Code: Select all

__asm__ __volatile__
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: GCC "optimizing" wrong (again)

Post by Ch4ozz »

octacone wrote:Try:

Code: Select all

__asm__ __volatile__
I have a define which replaces asm and volatile with those.
It makes no difference sadly.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: GCC "optimizing" wrong (again)

Post by Octacone »

Ch4ozz wrote:
octacone wrote:Try:

Code: Select all

__asm__ __volatile__
I have a define which replaces asm and volatile with those.
It makes no difference sadly.
:| Could it be your linker?
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: GCC "optimizing" wrong (again)

Post by Ch4ozz »

octacone wrote::| Could it be your linker?
This has nothing todo with the linker.
The object file looks the exact same
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: GCC "optimizing" wrong (again)

Post 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.)
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Re: GCC "optimizing" wrong (again)

Post 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.
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: GCC "optimizing" wrong (again)

Post 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.
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Re: GCC "optimizing" wrong (again)

Post 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.
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: GCC "optimizing" wrong (again)

Post 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
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Re: GCC "optimizing" wrong (again)

Post 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.
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: GCC "optimizing" wrong (again)

Post 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
mikegonta
Member
Member
Posts: 229
Joined: Thu May 19, 2011 5:13 am
Contact:

Re: GCC "optimizing" wrong (again)

Post 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.
Mike Gonta
look and see - many look but few see

https://mikegonta.com
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: GCC "optimizing" wrong (again)

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

Re: GCC "optimizing" wrong (again)

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