Во-первых, имейте в виду, что GCC пока не поддерживает 16-битный код, поэтому вы в конечном итоге скомпилируете 32-битный код в 16-битном режиме, что очень неэффективно, но выполнимо (например, используетсяLinux и SeaBIOS).Это можно сделать с помощью следующего в начале каждого файла:
__asm__ (".code16gcc");
Более новые версии GCC (начиная с 4.9 IIRC) поддерживают флаг -m16
, который делает то же самое.
Такжедрайвер мыши недоступен, пока вы не загрузите его до запуска ядра init_mouse
.
Вы, похоже, используете API, обычно доступный в нескольких ОС x86.
asm
может занятьзаботиться о назначениях регистров, поэтому код можно уменьшить до:
void set_video_mode(int mode)
{
mode &= 255;
__asm__ __volatile__ (
"int $0x10"
: "+a" (mode) /* %eax = mode & 255 => %ah = 0, %al = mode */
);
}
void init_mouse(void)
{
/* XXX it is really important to check the IDT entry isn't 0 */
int tmp = 0;
__asm__ __volatile__ (
"int $0x33"
: "+a" (tmp) /* %eax = 0*/
:: "ebx" /* %ebx is also clobbered by DOS mouse drivers */
);
}
Оператор asm
задокументирован в руководстве GCC, хотя, возможно, недостаточно подробно и в нем отсутствуют примеры x86.Выходные данные (после первого двоеточия) имеют явно неясный синтаксис, в то время как остальные гораздо проще понять (второе двоеточие определяет входы, а третье - засоренные регистры, флаги и / или память).
Выходные данныедолжен иметь префикс =
, означающий, что вам не важно предыдущее значение, которое он мог иметь, или +
, означающий, что вы также хотите использовать его в качестве ввода.В этом контексте мы используем это вместо ввода, потому что значение модифицируется прерыванием, и вам не разрешено указывать входные регистры в закрытом списке (потому что компилятору запрещено их использовать).