2016-11-14 19 views
1

Я делаю драйвер клавиатуры для моей OSDev OS и у меня есть проблема в моем 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. */ 
} 

Почему это происходит?

EDIT: У меня все еще есть то, что «топор» не определен, на этот раз, в другой функции.

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 */ 
} 
+1

Компилятор считает, что вы объявляете массив под названием «ScanCode». Честно говоря, я понятия не имею, что вы пытаетесь сделать в этом коде. – user3386109

+0

Комментарий: «Удалить последние 8 бит из значения ...» -> выглядит как «Удалить последние 8 _bytes_ ...» – chux

+0

Хммм, если 'strlen (ValEAX) <= 8', код, безусловно, будет иметь проблемы. – chux

ответ

1

Очень сложно сказать, чего вы пытались достичь. Эта процедура возвращает исходный scancode, возвращаемый с BIOS interrupt 16h/AH=0h. Он использует GCC extended assembler template с использованием input/output constraint для передачи AX со значением 0 в шаблон ассемблера и для получения значения в AX впоследствии. Сканкод находится в верхних 8 битах переменной ax, поэтому мы сдвигаем его на 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 работает только в реальном режиме.

+0

У меня есть uint16_t/uint8_t. Спасибо за ваш ответ. – KC104

+0

Но как я могу сделать ключ из него, используя что-то вроде 'int Key = kbdus [ax]'? Это дает мне, что топор не определен, хотя в той же функции он вызывает getchar_scancode() ;. – KC104

+0

'ax' - это переменное имя, как и любое другое. Вы должны иметь возможность сделать что-то вроде 'int Key = kbdus [getchar_scancode()]' или do 'uint8_t scancode = getchar_scancode(); int Key = kbdus [scancode]; ' –

1

Сообщение об ошибке достаточно ясна. Вы не можете инициализировать массив переменной длины. Написать вместо

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

Или вы можете использовать стандартную функцию C memset, заявленной в заголовке <string.h> установить все элементы вектора 0x00.

Например

memset(ScanCode, 0x00, sizeof(ScanCode)); 
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; 
}