[SOLVED] GCC 6.3.0 bug ?
Posted: Sun Apr 09, 2017 10:48 am
Hello guys,
I just wanna share something with you that I discovered during my keyboard driver's debug phase.
Here is my function to write a byte to the keyboard :
In assembly, it gives this (as seen by IDA Pro) :
My keyboard ISR sets Keyboard_waitingForAck to false when the keyboard sends an ACK.
But as you can see in the assembly code, it is never going to check if Keyboard_waitingForAck's value has changed, even if in the C code, the while loop should exit if Keyboard_waitingForAck is false.
So I decided to change my C code :
In assembly, it gives that :
The call to Console_write() does absolutely nothing, but as GCC does not know what it can do, it checks for Keyboard_waitingForAck because Console_write() could have changed its value (logical).
And guess what, it works !
Do you guys have an idea why GCC is doing this and how I can fix it ?
PS : My compile line is
And my linking line is
I just wanna share something with you that I discovered during my keyboard driver's debug phase.
Here is my function to write a byte to the keyboard :
Code: Select all
void Keyboard_writeByte(uint8_t value) {
while(Keyboard_waitingForAck) {
hlt;
}
Keyboard_waitingForAck = true;
Keyboard_lastCommand = value;
PS2_data_write(Keyboard_port, value);
}
Code: Select all
.text:08000000 ; void __cdecl Keyboard_writeByte(uint8_t value)
.text:08000000 public Keyboard_writeByte
.text:08000000 Keyboard_writeByte proc near ; CODE XREF: Keyboard_init+11p
.text:08000000 ; Keyboard_init+1Dp ...
.text:08000000
.text:08000000 value = dword ptr 4
.text:08000000
.text:08000000 sub esp, 0Ch
.text:08000003 cmp ds:Keyboard_waitingForAck, 0
.text:0800000A mov eax, [esp+0Ch+value]
.text:0800000E jz short loc_8000013
.text:08000010
.text:08000010 loc_8000010: ; CODE XREF: Keyboard_writeByte+11j
.text:08000010 hlt
.text:08000011 ; ---------------------------------------------------------------------------
.text:08000011 jmp short loc_8000010
.text:08000013 ; ---------------------------------------------------------------------------
.text:08000013
.text:08000013 loc_8000013: ; CODE XREF: Keyboard_writeByte+Ej
.text:08000013 sub esp, 8
.text:08000016 mov ds:Keyboard_lastCommand, al
.text:0800001B movzx eax, al
.text:0800001E push eax
.text:0800001F push ds:Keyboard_port
.text:08000025 mov ds:Keyboard_waitingForAck, 1
.text:0800002C call PS2_data_write
.text:08000031 add esp, 1Ch
.text:08000034 retn
.text:08000034 Keyboard_writeByte endp
But as you can see in the assembly code, it is never going to check if Keyboard_waitingForAck's value has changed, even if in the C code, the while loop should exit if Keyboard_waitingForAck is false.
So I decided to change my C code :
Code: Select all
void Keyboard_writeByte(uint8_t value) {
while(Keyboard_waitingForAck) {
Console_write("\0");
hlt;
}
Keyboard_waitingForAck = true;
Keyboard_lastCommand = value;
PS2_data_write(Keyboard_port, value);
}
Code: Select all
.text:08000000 ; void __cdecl Keyboard_writeByte(uint8_t value)
.text:08000000 public Keyboard_writeByte
.text:08000000 Keyboard_writeByte proc near ; CODE XREF: Keyboard_init+11p
.text:08000000 ; Keyboard_init+1Dp ...
.text:08000000
.text:08000000 value = dword ptr 4
.text:08000000
.text:08000000 push ebx
.text:08000001 sub esp, 8
.text:08000004 cmp ds:Keyboard_waitingForAck, 0
.text:0800000B mov ebx, [esp+0Ch+value]
.text:0800000F jz short loc_800003A
.text:08000011 jmp short loc_8000020
.text:08000011 ; ---------------------------------------------------------------------------
.text:08000013 align 10h
.text:08000020
.text:08000020 loc_8000020: ; CODE XREF: Keyboard_writeByte+11j
.text:08000020 ; Keyboard_writeByte+38j
.text:08000020 sub esp, 0Ch
.text:08000023 push offset unk_80001A0
.text:08000028 call Console_write
.text:0800002D hlt
.text:0800002E ; ---------------------------------------------------------------------------
.text:0800002E add esp, 10h
.text:08000031 cmp ds:Keyboard_waitingForAck, 0
.text:08000038 jnz short loc_8000020
.text:0800003A
.text:0800003A loc_800003A: ; CODE XREF: Keyboard_writeByte+Fj
.text:0800003A sub esp, 8
.text:0800003D mov ds:Keyboard_lastCommand, bl
.text:08000043 movzx ebx, bl
.text:08000046 push ebx
.text:08000047 push ds:Keyboard_port
.text:0800004D mov ds:Keyboard_waitingForAck, 1
.text:08000054 call PS2_data_write
.text:08000059 add esp, 10h
.text:0800005C add esp, 8
.text:0800005F pop ebx
.text:08000060 retn
.text:08000060 Keyboard_writeByte endp
And guess what, it works !
Do you guys have an idea why GCC is doing this and how I can fix it ?
PS : My compile line is
Code: Select all
i686-elf-gcc -Wall -Wextra -O2 -ffreestanding -nostdlib -g -c -std=gnu99 $< -o $@
Code: Select all
i686-elf-gcc -T linker.ld -Wall -Wextra -O2 -ffreestanding -lgcc -nostdlib -g