Переписать ассемблерный код в стиле Intel в встроенную сборку GCC - PullRequest
3 голосов
/ 17 января 2012

Как написать этот ассемблерный код как встроенную сборку?Компилятор: gcc (i586-elf-gcc).Синтаксис GAS меня смущает. Пожалуйста, скажите мне, как записать это как встроенную сборку, которая работает для gcc.

.set_video_mode:
    mov ah,00h
    mov al,13h
    int 10h   

.init_mouse:
    mov ax,0
    int 33h

Подобный у меня в сборке.Я написал их отдельно как процедуры сборки, чтобы вызвать их из моей программы на Си.Мне нужно вызвать эти и некоторые другие прерывания от самого C.

Также мне нужно поместить некоторые значения в некоторые регистры в зависимости от того, какую процедуру прерывания я вызываю.Пожалуйста, скажите мне, как это сделать.

Все, что я хочу сделать, - это вызвать прерывания вызова из C. Это нормально для меня, даже сделать это с помощью int86 () , но я не делаюесть исходный код этой функции.Я хочу int86 (), чтобы я мог вызывать прерывания из C.

Я занимаюсь разработкой собственной крошечной ОС, поэтому у меня нет ограничений на вызов прерываний или на любой прямой аппаратный доступ.

Ответы [ 2 ]

2 голосов
/ 18 января 2012

Я не проверял это, но вам стоит начать:

void set_video_mode (int x, int y) {
  register int ah asm ("ah") = x;
  register int al asm ("al") = y;

  asm volatile ("int $0x10"
                : /* no outputs */
                : /* no inputs */
                : /* clobbers */ "ah", "al");
}

В качестве примера я поместил два 'clobbers', но вам нужно установить правильный список clobbers, чтобы компилятор знал, что вы перезаписали значения регистров (возможно, ни одного).

0 голосов
/ 26 сентября 2016

Во-первых, имейте в виду, что 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.Выходные данные (после первого двоеточия) имеют явно неясный синтаксис, в то время как остальные гораздо проще понять (второе двоеточие определяет входы, а третье - засоренные регистры, флаги и / или память).

Выходные данныедолжен иметь префикс =, означающий, что вам не важно предыдущее значение, которое он мог иметь, или +, означающий, что вы также хотите использовать его в качестве ввода.В этом контексте мы используем это вместо ввода, потому что значение модифицируется прерыванием, и вам не разрешено указывать входные регистры в закрытом списке (потому что компилятору запрещено их использовать).

...