Пересчет физических адресов в логические

Тема в разделе "WASM.BEGINNERS", создана пользователем Aoizora, 25 июл 2017.

  1. Aoizora

    Aoizora Active Member

    Публикаций:
    0
    Регистрация:
    29 янв 2017
    Сообщения:
    351
    Изучаю курс про операционные системы, где в первую неделю уже пишут ядро. Непонятен механизм преобразования физических адресов в логические. В курсе загрузчик ядра писали на ассемблере - это очень простой язык для написания загрузчиков, но я захотел сделать то же самое на си, чтобы разобраться с адресацией.

    В загрузчике есть код, который пишет в видеобуфер:

    Код (Text):
    1.  
    2.     /* Set videobuffer as destination address for memcpy */
    3.     movw $0xB800, %ax
    4.     movw %ax, %es        /* es register points to video buffer */
    5.     movw $data, %si
    6.     movw $0, %di
    7.     movw $size, %cx
    8.     call memcpy
    Запись производится в видеобуфер по физическому адресу 0xB8000. Используя фомулу перевода физического адреса в логический [math]addr = (SEG \cdot 16 + offset) mod {2}^{20}[/math], можно нормализовать адрес видеобуфера: в регистре ES будет адрес 0xB800, так что если мы умножим его на 16, используя приведенную формулу, то получим исходный адрес 0xB8000.

    Далее, в коде ядра, написанного на си, мне непонятен пересчет адресов:

    Код (Text):
    1. #ifndef __MEMORY_H__
    2. #define __MEMORY_H__
    3.  
    4. /* Higher 2 GB of 64 bit logical address space start from this address */
    5. #define VIRTUAL_BASE    0xffffffff80000000
    6.  
    7. /* First address after "canonical hole", beginning of the middle mapping. */
    8. #define HIGHER_BASE    0xffff800000000000
    9.  
    10. /* Kernel 64 bit code and data segment selectors. */
    11. #define KERNEL_CS    0x08
    12. #define KERNEL_DS    0x10
    13.  
    14. #define PAGE_BITS    12
    15. #define PAGE_SIZE    (1 << PAGE_BITS)
    16. #define PAGE_MASK    (PAGE_SIZE - 1)
    17.  
    18.  
    19. #ifndef __ASM_FILE__
    20.  
    21. #include <stdint.h>
    22.  
    23.  
    24. #define VA(x) ((void *)((uintptr_t)x + HIGHER_BASE))
    25. #define PA(x) ((uintptr_t)x - HIGHER_BASE);
    26.  
    27. static inline void *va(uintptr_t phys)
    28. { return VA(phys); }
    29.  
    30. static inline uintptr_t pa(const void *virt)
    31. { return PA(virt); }
    32.  
    33. #endif /*__ASM_FILE__*/
    34.  
    35. #endif /*__MEMORY_H__*/
    Код (Text):
    1. #include <stddef.h>
    2. #include <memory.h>
    3. #include <vga.h>
    4.  
    5.  
    6. static char * const VBUF = VA(0xB8000);
    7. static const int ROWS = 25;
    8. static const int COLS = 80;
    9. static const int ATTR = 15;
    10.  
    11.  
    12. static char *__vga_at(int r, int c)
    13. {
    14.     return VBUF + (r * COLS * 2 + c);
    15. }
    16.  
    17. static void vga_set(int r, int c, char x)
    18. {
    19.     *__vga_at(r, 2 * c) = x;
    20.     *__vga_at(r, 2 * c + 1) = ATTR;
    21. }
    22.  
    23. static char vga_get(int r, int c)
    24. {
    25.     return *__vga_at(r, 2 * c);
    26. }
    27.  
    28. static void scroll(void)
    29. {
    30.     for (int r = 1; r != ROWS; ++r)
    31.         for (int c = 0; c != COLS; ++c)
    32.             vga_set(r - 1, c, vga_get(r, c));
    33. }
    34.  
    35. static void putchar(char x)
    36. {
    37.     static int r = 0;
    38.     static int c = 0;
    39.  
    40.     if (x == '\n') {
    41.         for (; c != COLS; ++c)
    42.             vga_set(r, c, ' ');
    43.         c = 0;
    44.         ++r;
    45.     } else {
    46.         vga_set(r, c, x);
    47.         if (++c == COLS) {
    48.             c = 0;
    49.             ++r;
    50.         }
    51.     }
    52.  
    53.     if (r == ROWS) {
    54.         scroll();
    55.         --r;
    56.     }
    57. }
    58.  
    59. void vga_write(const char *data, size_t size)
    60. {
    61.     for (size_t i = 0; i != size; ++i)
    62.         putchar(data[i]);
    63. }
    64.  
    65. void vga_clr(void)
    66. {
    67.     for (int r = 0; r != ROWS; ++r)
    68.         for (int c = 0; c != COLS; ++c)
    69.             vga_set(r, c, ' ');
    70. }
    Для чего используется строка
    Код (Text):
    1. static char * const VBUF = VA(0xB8000);
    ?

    А VA определен, как можно видеть, макросом
    Код (Text):
    1. #define VA(x) ((void *)((uintptr_t)x + HIGHER_BASE))
    , где #define HIGHER_BASE 0xffff800000000000

    Что это за магия? Почему, если записать по адресу 0xffff800000000000 + 0xB8000, мы попадем в видеобуфер по его физическому адресу?
     
    Последнее редактирование: 25 июл 2017
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
  3. ol.

    ol. Active Member

    Публикаций:
    0
    Регистрация:
    21 фев 2017
    Сообщения:
    118
    От себя добавлю, что ваша ассемблерная цитата относится к реальному режиму работы процессора, а сишная - к защищенному. Трансляция адресов памяти в этих режимах совершенно различна и ничего общего между собой не имеет.