Смешивание C и ассемблерного кода в простом 32-битном ядре - PullRequest
4 голосов
/ 23 января 2020

У меня есть простая реализация 32-битного ядра, которую я написал в C (это автономная реализация): (Экран VGA в цветном текстовом режиме 80 * 25)

#include<stdint.h>

#define COLOR 0x39
#define VIDEO_MEMORY 0xb8000

uint32_t get_cursor();
void set_cursor(uint32_t);

void puts(char* Message);
void kmain()
{
        puts("This is a test message..");
        return;
}

void puts(char* Message)
{
        uint32_t pointer = get_cursor();
        pointer <<= 1;
        char* VGA_CURSOR = (char*) VIDEO_MEMORY;
        VGA_CURSOR += pointer;
        while   (*Message)
        {
                *VGA_CURSOR = *Message;
                Message++;
                VGA_CURSOR ++;
                *VGA_CURSOR = COLOR;
                VGA_CURSOR ++;
        }
        VGA_CURSOR -= VIDEO_MEMORY;
        pointer = (uint32_t)VGA_CURSOR;
        pointer >>= 1;
        set_cursor(pointer);
}

Функции set_cursor и get_cursor определены в сборке следующим образом:

[bits 32]
[global set_cursor]
[global get_cursor]

set_cursor:   ;ebx is the location

        mov ebx,[esp+0x18]
        mov al, 0x0f ;Refer to the index register table port mapping for CRT (low byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al   ;Write 0x0f in port 0x3D4  --- note that the port registers are 1 byte in size
        mov dx,0x3d5 ;port number CRT data
        mov al,bl
        out dx,al

        mov al, 0x0e ;Refer to the index register table port mapping for CRT (high byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al
        mov dx,0x3d5 ;port number CRT data
        mov al,bh
        out dx,al

        ret

get_cursor:
        mov al, 0x0f ;Refer to the index register table port mapping for CRT (low byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al   ;Write 0x0f in port 0x3D4  --- note that the port registers are 1 byte in size
        mov dx,0x3d5 ;port number CRT data
        in al,dx   ;Store the low byte in al -- Hardware forced to use al
        mov bl,al

        mov al, 0x0e ;Refer to the index register table port mapping for CRT (high byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al   ;Write 0x0f in port 0x3D4  --- note that the port registers are 1 byte in size
        mov dx,0x3d5 ;port number CRT data
        in al,dx   ;Store the high byte in al -- Hardware forced to use al
        mov bh,al   ;Store the high byte in bh

        xor eax,eax
        mov ax,bx

        ret

Здесь функция getcursor, кажется, работает нормально (она получает значение курсора в диапазоне от 0 до 80 * 25). Я знаю, что реализация setcursor тоже правильная. (Я использовал это в чистых ассемблерных кодах). Я считаю, что произошла ошибка при передаче значений в стеке. Где я мог ошибаться?

1 Ответ

2 голосов
/ 23 января 2020

Похоже, место, где существовала ошибка, было при передаче параметров функции. Objdump кода c показывает это в том месте, где вызывается функция:

  73:   ff 75 f0                pushl  -0x10(%ebp)
  76:   e8 fc ff ff ff          call   77 <printf+0x5e>
  7b:   83 c4 10                add    $0x10,%esp

[ebp-0x10] - моя указатель переменная ... Место, где я запутался, вероятно, add esp, 0x10 . Несмотря на то, что я передал только 1 параметр (из 4 байтов), он, кажется, сохраняет 16 байтов в стеке?

Однако похоже, что [esp] был адресом возврата (4 байта = 32 бита), [esp + 4] является первым параметром .... Возможно, 16 байтов были для правильного выравнивания

Благодарю Майкла Петча: { ссылка } и Питера Кордеса: { ссылка } за их комментарии!

...