GCC Problem (Switch-Case)

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

GCC Problem (Switch-Case)

Post by Hornet »

Hello.
I've got a problem with gcc (DJGPP). The following Code works.

Code: Select all

char foo(char nFirstValue, char shiftstatus)
{
   switch(nFirstValue)
   {
   case SCANCODE_A:
      return 1;
      break;
   case SCANCODE_B:
      return 2;
      break;
   case SCANCODE_C:
      return 3;
      break;
   case SCANCODE_D:
      return 4;
      break;
   };
   return 0;
}

ASM Code:
:00001A90 55                      push ebp
:00001A91 89E5                    mov ebp, esp
:00001A93 83EC0C                  sub esp, 0000000C
:00001A96 8B4508                  mov eax, dword ptr [ebp+08]
:00001A99 8B550C                  mov edx, dword ptr [ebp+0C]
:00001A9C 8845FF                  mov byte ptr [ebp-01], al
:00001A9F 8855FE                  mov byte ptr [ebp-02], dl
:00001AA2 0FBE45FF                movsx eax, byte ptr [ebp-01]
:00001AA6 8945F4                  mov dword ptr [ebp-0C], eax
:00001AA9 837DF420                cmp dword ptr [ebp-0C], 00000020
:00001AAD 7437                    je 00001AE6
:00001AAF 837DF420                cmp dword ptr [ebp-0C], 00000020
:00001AB3 7F08                    jg 00001ABD
:00001AB5 837DF41E                cmp dword ptr [ebp-0C], 0000001E
:00001AB9 7410                    je 00001ACB
:00001ABB EB32                    jmp 00001AEF
:00001ABD 837DF42E                cmp dword ptr [ebp-0C], 0000002E
:00001AC1 741A                    je 00001ADD
:00001AC3 837DF430                cmp dword ptr [ebp-0C], 00000030
:00001AC7 740B                    je 00001AD4
:00001AC9 EB24                    jmp 00001AEF
:00001ACB C745F801000000          mov [ebp-08], 00000001
:00001AD2 EB22                    jmp 00001AF6
:00001AD4 C745F802000000          mov [ebp-08], 00000002
:00001ADB EB19                    jmp 00001AF6
:00001ADD C745F803000000          mov [ebp-08], 00000003
:00001AE4 EB10                    jmp 00001AF6
:00001AE6 C745F804000000          mov [ebp-08], 00000004
:00001AED EB07                    jmp 00001AF6
:00001AEF C745F800000000          mov [ebp-08], 00000000
:00001AF6 8B45F8                  mov eax, dword ptr [ebp-08]
:00001AF9 C9                      leave
:00001AFA C3                      ret
BUT this don't work:

Code: Select all

char foo(char nFirstValue, char shiftstatus)
{
   switch(nFirstValue)
   {
   case SCANCODE_A:
      return 1;
      break;
   case SCANCODE_B:
      return 2;
      break;
   case SCANCODE_C:
      return 3;
      break;
   case SCANCODE_D:
      return 4;
      break;
   case SCANCODE_F:
      return 5;
      break;
   };
   return 0;
}
ASM Code:
:00001A90 55                      push ebp
:00001A91 89E5                    mov ebp, esp
:00001A93 83EC0C                  sub esp, 0000000C
:00001A96 8B4508                  mov eax, dword ptr [ebp+08]
:00001A99 8B550C                  mov edx, dword ptr [ebp+0C]
:00001A9C 8845FF                  mov byte ptr [ebp-01], al
:00001A9F 8855FE                  mov byte ptr [ebp-02], dl
:00001AA2 0FBE45FF                movsx eax, byte ptr [ebp-01]
:00001AA6 83E81E                  sub eax, 0000001E
:00001AA9 8945F4                  mov dword ptr [ebp-0C], eax
:00001AAC 837DF412                cmp dword ptr [ebp-0C], 00000012
:00001AB0 0F8787000000            ja 00001B3D
:00001AB6 8B55F4                  mov edx, dword ptr [ebp-0C]
:00001AB9 8B0495C41A0000          mov eax, dword ptr [4*edx+00001AC4]
:00001AC0 FFE0                    jmp eax <-- BUG  Jump @0x00 ?!!
..
Has anyone an Idea how to use more than 4 case-instructions ?

Hornet (german)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:GCC Problem (Switch-Case)

Post by Pype.Clicker »

what do you have at 1AC4 ?
so far it doesn't look like a bug for me, but rather an optimization of the compiler ...
(however, you should use a lookup table rather than this huuge switch)
bkilgore

Re:GCC Problem (Switch-Case)

Post by bkilgore »

I'm not sure why that's not working for you, because this DOES work fine for me:

Code: Select all

char foo(unsigned char nFirstValue, char shiftstatus)
{
   switch(nFirstValue)
   {
   case 0xab:
      return 1;
      break;
   case 0xbc:
      return 2;
      break;
   case 0xcd:
      return 3;
      break;
   case 0xde:
      return 4;
      break;
   case 0xef:
      return 5;
      break;
   };
   return 6;
}



void main()
{
   char ret = foo(0xcd, 0);
   printf("ret = %d\n", ret);
}
And it works no matter what value I pass to foo, it prints what I expect to return.

One thing I did have to do is change the first parameter type to unsigned char, otherwise it wasn't working at all (no matter how many case labels) if what i was switching on was > 127. Is it possible SCANCODE_A through SCANCODE_D are all < 127, but SCANCODE_E > 127?

- Brandon
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GCC Problem (Switch-Case)

Post by Solar »

I think it is safe to assume that switch() is not broken in *any* compiler that's being around that long. ;-)

bkilgore might be on the right path here. You *do* know that:

* you must not assume char being *either* signed or unsigned;
* thus, for value passing purposes, the only safe bet for char is 0 to 127;
* it is virtually always better to pass such values as int / unsigned int?
Every good solution is obvious once you've found it.
Post Reply