KC104 KC104 - 20 days ago 8
C Question

Error: variable-sized object may not be initialized?

I am making a keyboard driver for my OSDev OS and i have a problem in my kbd.c:

kbd.c: In function 'scancoderec':
kbd.c:56:2: error: variable-sized object may not be initialized
register int (ScanCode[strlen(ValEAX)-8]) = 0x00; /* Remove last 8 bits from the value we gathered from EAX to get AH and make that the scancode. */


Here is the function that contains the failing line of code:

int scancoderec() {
__asm__ volatile( "movl $0, %eax" ); /* Moving 00 to EAX. */
__asm__ volatile( "int $0x16 "); /*int 0x16 */
register int ValEAX asm("eax"); /* Let's get eax */
register int (ScanCode[strlen(ValEAX)-8]) = 0x00; /* Remove last 8 bits from the value we gathered from EAX to get AH and make that the scancode. */
}


Why is this happening?

Answer

Very hard to tell what you were trying to achieve. This routine returns the raw scancode returned from BIOS interrupt 16h/AH=0h. It uses GCC extended assembler template using an input/output constraint to pass AX with value 0 into the assembler template and to retrieve the value in AX afterwards. The scancode is in the upper 8 bits of the ax variable so we shift it right by 8 bits.

#include <stdint.h>
uint8_t getchar_scancode()
{
   uint16_t ax = 0;    /* int 0x16, AH=0 is get keystroke */
   __asm__ __volatile__ ("int $0x16\n\t"
                         : "+a"(ax)); 
                       /* +a is an input and output constraint using EAX register */
   ax = ax >> 8;       /* Shift top 8 bits of ax to lower 8 bits */
                       /* ax now is the scancode returned by BIOS */
   return (uint8_t)ax; /* Return the lower 8 bits */
}

If you don't have stdint.havailable to define uint16_t and uint8_t then you can use unsigned short and unsigned char respectively.


BIOS Interrupts will not work in protected mode and will likely fault the machine. INT 16h/AH=0 only works in real mode.

Comments