错误:可能无法初始化可变大小的对象?

时间:2016-11-14 21:27:45

标签: c gcc keyboard keyboard-events osdev

我正在为我的OSDev操作系统制作一个键盘驱动程序,我的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. */

这是包含失败代码行的函数:

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. */
}

为什么会这样?

编辑:我仍然认为“ax”未定义,这次是在另一个函数中。

kbd.c:65:27: error: 'ax' undeclared (first use in this function)
register int Key = kbdus[ax];

扫描码功能代码和getkey功能:

    unsigned short scancodeget()
    {
       unsigned char ax = 0;    /* int 0x16, AH=0 is get keystroke */
       __asm__ __volatile__ ("int $0x16\n\t"
                             : "+a"(ax)); 
       ax = ax >> 8;       /* Shift top 8 bits of ax to lower 8 bits */
                       /* ax now is the scancode returned by BIOS */
       return (unsigned short)ax; /* Return the lower 8 bits */
}

int getkey() { /*This could be used as a keyboard driver. */
       scancoderec(); /*Get our scancode! */
       int Key = kbdus[ax]; /*Use our kbdus array which i copied from a website since i seriously don't want to make an gigantic array */
}

3 个答案:

答案 0 :(得分:1)

错误消息足够清楚。您可能无法初始化可变长度数组。改为写

register int (ScanCode[strlen(ValEAX)-8]);
ScanCode[0] = 0x00;

或者您可以使用在标头memset中声明的标准C函数<string.h>将向量的所有元素设置为0x00

例如

memset( ScanCode, 0x00, sizeof( ScanCode ) );

答案 1 :(得分:1)

很难说出你想要实现的目标。此例程返回从BIOS interrupt 16h/AH=0h返回的原始扫描码。它使用GCC extended assembler template使用input/output constraint将值为0的 AX 传递到汇编程序模板中,然后检索 AX 中的值。扫描码位于ax变量的高8位,因此我们将其右移8位。

#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 */
                       /* The contents of the 'ax' variable will be transferred */
                       /* into EAX register upon entry, and the value of EAX register */
                       /* will be transferred into variable 'ax' when finished */ 
   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 */
}

如果您没有stdint.h可用于定义uint16_t,则可以将其替换为unsigned short,并将uint8_t替换为unsigned char

如果您需要将扫描码转换为ASCII字符,可以使用其他功能来提供该功能:

unsigned char kbdus[128] =
{
    0,  27, '1', '2', '3', '4', '5', '6', '7', '8',   /* 9 */
    '9', '0', '-', '=', '\b',                         /* Backspace */
    '\t',                                             /* Tab */
    'q', 'w', 'e', 'r',                               /* 19 */
    't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',     /* Enter key */
    0,                                                /* 29   - Control */
    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
    '\'', '`',   0,                                   /* Left shift */
    '\\', 'z', 'x', 'c', 'v', 'b', 'n',               /* 49 */
    'm', ',', '.', '/',   0,                          /* Right shift */
    '*',
    0,                                                /* Alt */
    ' ',                                              /* Space bar */
    0,                                                /* Caps lock */
    0,                                                /* 59 - F1 key ... > */
    0,   0,   0,   0,   0,   0,   0,   0,
    0,                                                /* < ... F10 */
    0,                                                /* 69 - Num lock*/
    0,                                                /* Scroll Lock */
    0,                                                /* Home key */
    0,                                                /* Up Arrow */
    0,                                                /* Page Up */
    '-',
    0,                                                /* Left Arrow */
    0,
    0,                                                /* Right Arrow */
    '+',
    0,                                                /* 79 - End key*/
    0,                                                /* Down Arrow */
    0,                                                /* Page Down */
    0,                                                /* Insert Key */
    0,                                                /* Delete Key */
    0,   0,   0,
    0,                                                /* F11 Key */
    0,                                                /* F12 Key */
    0, /* All other keys are undefined */
};

uint8_t getchar()
{
    return (kbdus[getchar_scancode()]);
}

BIOS中断在保护模式下无效,可能会导致机器故障。 INT 16h / AH = 0 仅适用于实模式。

答案 2 :(得分:0)

该行

register int (ScanCode[strlen(ValEAX)-8]) = 0x00;

声明一个VLA并尝试初始化它,这是不允许的。将其更改为:

// Declare
int size = strlen(ValEAX)-8
register int ScanCode[size];

// Set values.
for ( int i = 0; i < size; ++i )
{
   ScanCode[i] = 0x00;
}