OSDev
http://osdev.su/

Определение адресов ОЗУ в адресной памяти
http://osdev.su/viewtopic.php?f=6&t=347
Страница 1 из 1

Автор:  s3dworld [ 27 окт 2010, 11:09 ]
Заголовок сообщения:  Определение адресов ОЗУ в адресной памяти

Всем доброго дня!

Среди 4 ГБ адресной памяти я хочу получить те адреса, которые являются оперативной памятью (ОЗУ). На основании полученных сведений я смогу построить таблицу страниц (по 4 МБ на страницу), где у меня будет задействована именно оперативная память (ОЗУ).

Для достижения своих целей решил я использовать функция 0xE820 прерывания 0x15 (http://ru.osdev.wikia.com/wiki/%D0%9E%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BE%D0%B1%D1%8A%D1%91%D0%BC%D0%B0_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8). Это BIOS прерывание и естественно получать информацию я буду из режима реальных адресов (R-Mode).

Написал модуль для определения объёма и карты распределения памяти:

Код:
; Имя:         test_memory
; Описание:      Определение карты памяти
; Автор:      Дубровкин Сергей
; Начало:      26.10.2010 - 13:19
; Завершение:   ??.??.???? - ??:??
; *******************************************************************************

use16

; *******************************************************************************
;                                П Р О Ц Е Д У Р Ы
; *******************************************************************************

; ------------------------------------------------------------------------------{
; Название:   Test_Memory__Main()
; Описание:   Определение карты памяти
; Вход:      Нет
; Выход:   Нет
; -------------------------------------------------------------------------------
Test_Memory__Main:
   mov EAX,0x0000E820
   xor EBX,EBX
   mov EDI,test_memory__item
   mov ECX,24
   mov EDX,"SMAP"
   int 0x15
   
   cmp EAX,"SMAP"
   jnz Test_Memory__Main_Label_1
   
   push EDI
   mov EAX,[EDI]
   call UnsignedNumberToString
   
   mov ESI,EDI
   mov BL,00001111b
   mov DH,0
   mov DL,0
   call Boot__DrawText
   
   pop EDI
   add EDI,4
   
   push EDI
   mov EAX,[EDI]
   call UnsignedNumberToString
   
   mov ESI,EDI
   mov BL,00001111b
   mov DH,1
   mov DL,0
   call Boot__DrawText
   
   pop EDI
   add EDI,4
   
   push EDI
   mov EAX,[EDI]
   call UnsignedNumberToString
   
   mov ESI,EDI
   mov BL,00001111b
   mov DH,2
   mov DL,0
   call Boot__DrawText
   
   pop EDI
   add EDI,4
   
   push EDI
   mov EAX,[EDI]
   call UnsignedNumberToString
   
   mov ESI,EDI
   mov BL,00001111b
   mov DH,3
   mov DL,0
   call Boot__DrawText
   
   pop EDI
   add EDI,4
   
   push EDI
   mov EAX,[EDI]
   call UnsignedNumberToString
   
   mov ESI,EDI
   mov BL,00001111b
   mov DH,4
   mov DL,0
   call Boot__DrawText
   
   pop EDI
   add EDI,4
   
   mov EAX,[EDI]
   call UnsignedNumberToString
   
   mov ESI,EDI
   mov BL,00001111b
   mov DH,5
   mov DL,0
   call Boot__DrawText
   
   jmp Test_Memory__Main_Label_End
   
   Test_Memory__Main_Label_1:
      mov ESI,test_memory__end
      mov BL,00001111b
      mov DH,0
      mov DL,0
      call Boot__DrawText
   
   Test_Memory__Main_Label_End:
ret
; ------------------------------------------------------------------------------}
   
; *******************************************************************************
;                                   Д А Н Н Ы Е
; *******************************************************************************

test_memory__Data16:
   test_memory__itemSize   db   24
   test_memory__item      db    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
   test_memory__end      db "Function no complete!",0



После вызова данной процедуры, у меня значение двадцати четырёх байт, на начало которых указывает переменная test_memory__item, так и остаётся нулевым. И регистр EAX не содержит сигнатуру SMAP.

О чём это может говорить: либо я что-то не так делаю, либо BIOS моего Bochs не совместим с ACPI?

Как же мне тогда узнать адреса в адресной памяти в 4 ГБ, где у меня располагается оперативная память (ОЗУ)?

Автор:  s3dworld [ 27 окт 2010, 12:24 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

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

Код:
mov EDX,"SMAP"
int 0x15
   
cmp EAX,"SMAP"


Нужно было заменить на:

Код:
mov EDX,0x534d4150
int 0x15
   
cmp EAX,0x534d4150

Автор:  s3dworld [ 27 окт 2010, 12:42 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Ребят, вызываю функцию 0x0000E820 прерывания 0x15. В ответ получаю следующее:

Начальный адрес диапазона, младшие 32 бита: 0
Начальный адрес диапазона, старшие 32 бита: 0
Длина диапазона, младшие 32 бита: 651264
Длина диапазона, старшие 32 бита: 062156
Тип диапазона: 162156
Расширенные атрибуты диапазона: 062156

И что это значит? Откуда такая длина? У меня всего 2 ГБ оперативной памяти (ОЗУ). Да и что-то значение в Длина диапазона, старшие 32 бита равно значению в Расширенные атрибуты диапазона.

Сначала я подумал что возможно тупит моя функция перевода числа в строку, но я её тестировал (подсовывал ей значения и смотрел на результат) и она работала правильно. Хотя интересно, что в тексте впереди стоит 0, так ведь не должно быть. В чём может быть дело?

Вот код перевода:

Код:

; ********************************************************
;                   П Р О Ц Е Д У Р А
; ********************************************************

; -------------------------------------------------------{
; Название:   UnsignedNumberToString()
; Описание:   Преобразование 32-битного числа в строку
; Вход:      EAX - 32-битное число
; Выход:   EDI - указатель на строку
;         ECX - количество символов в строке
; --------------------------------------------------------
UnsignedNumberToString:
      mov EDI,string1
      mov ECX,0
      mov EBX,10
   
   UnsignedNumberToString__Label_Div:
      mov EDX,0
      div EBX
   
      add EDX,48
      mov [EDI],byte DL
      inc EDI
      inc ECX
   
      cmp EAX,0
      jz UnsignedNumberToString__Label_NoDiv
      jmp UnsignedNumberToString__Label_Div
   
   UnsignedNumberToString__Label_NoDiv:
      cmp ECX,1
      jz UnsignedNumberToString__Label_NoBuild
      jmp UnsignedNumberToString__Label_Build
   
   UnsignedNumberToString__Label_Build:
      ;mov ESI,string1
      ;mov EDI,string2
      mov EBX,0
      
      UnsignedNumberToString__Label_Build_Copy:
         mov EDX,ECX
         sub EDX,EBX
         sub EDX,1
         
         ;add ESI,EBX
         ;add EDI,EDX
         
         ;mov AL,byte [ESI]
         ;mov [EDI],byte AL
         
         mov EDI,string1
         add EDI,EBX
         mov AL,byte [EDI]
         mov EDI,string2
         add EDI,EDX
         mov [EDI],byte AL
         
         inc EBX

      cmp ECX,EBX
      jz UnsignedNumberToString__Label_BuildComplete
      jmp UnsignedNumberToString__Label_Build_Copy
   
   UnsignedNumberToString__Label_BuildComplete:
      mov EDI,string2
      jmp UnsignedNumberToString__Label_End
   
   UnsignedNumberToString__Label_NoBuild:
      mov EDI,string1
   
   UnsignedNumberToString__Label_End:
ret
; -------------------------------------------------------}

; ********************************************************
;                     Д А Н Н Ы Е
; ********************************************************

UnsignedNumberToString__Data:
   string1 db 0,0,0,0,0,0,0,0,0,0,0
   string2 db 0,0,0,0,0,0,0,0,0,0,0


Автор:  phantom-84 [ 27 окт 2010, 13:44 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Сделай вывод в 16-ричной системе. Так будет более понятно.

Адрес буфера для структуры вроде бы должен передаваться в es : di. Может, у тебя es не проинициализирован.

Автор:  s3dworld [ 27 окт 2010, 14:25 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

У меня все регистры установлены на 0, так же как и CS. В чём может быть дело?

Автор:  s3dworld [ 27 окт 2010, 15:34 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Ошибка найдена (не мной) и исправлена (мной). Заключалась она в обнулении значения строк:

Код:

; ********************************************************
;                   П Р О Ц Е Д У Р А
; ********************************************************

; -------------------------------------------------------{
; Название:   UnsignedNumberToString()
; Описание:   Преобразование 32-битного числа в строку
; Вход:      EAX - 32-битное число
; Выход:   EDI - указатель на строку
;         ECX - количество символов в строке
; --------------------------------------------------------
UnsignedNumberToString:
      mov EDI,string1
      mov ECX,0
      mov EBX,10
      
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      
      mov EDI,string2
      
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      inc EDI
      mov [EDI],byte 0
      
      mov EDI,string1
   
   UnsignedNumberToString__Label_Div:
      mov EDX,0
      div EBX
   
      add EDX,48
      mov [EDI],byte DL
      inc EDI
      inc ECX
   
      cmp EAX,0
      jz UnsignedNumberToString__Label_NoDiv
      jmp UnsignedNumberToString__Label_Div
   
   UnsignedNumberToString__Label_NoDiv:
      cmp ECX,1
      jz UnsignedNumberToString__Label_NoBuild
      jmp UnsignedNumberToString__Label_Build
   
   UnsignedNumberToString__Label_Build:
      ;mov ESI,string1
      ;mov EDI,string2
      mov EBX,0
      
      UnsignedNumberToString__Label_Build_Copy:
         mov EDX,ECX
         sub EDX,EBX
         sub EDX,1
         
         ;add ESI,EBX
         ;add EDI,EDX
         
         ;mov AL,byte [ESI]
         ;mov [EDI],byte AL
         
         mov EDI,string1
         add EDI,EBX
         mov AL,byte [EDI]
         mov EDI,string2
         add EDI,EDX
         mov [EDI],byte AL
         
         inc EBX

      cmp ECX,EBX
      jz UnsignedNumberToString__Label_BuildComplete
      jmp UnsignedNumberToString__Label_Build_Copy
   
   UnsignedNumberToString__Label_BuildComplete:
      mov EDI,string2
      jmp UnsignedNumberToString__Label_End
   
   UnsignedNumberToString__Label_NoBuild:
      mov EDI,string1
   
   UnsignedNumberToString__Label_End:
ret
; -------------------------------------------------------}

; ********************************************************
;                     Д А Н Н Ы Е
; ********************************************************

UnsignedNumberToString__Data:
   string1 db 0,0,0,0,0,0,0,0,0,0,0
   string2 db 0,0,0,0,0,0,0,0,0,0,0



Результат такой:

Изображение

Первое значение на рисунке - это значение для регистра EBX (нужно для обработки следующих диапазонов). То что у меня идёт строка в обратном порядке, это точно. Но всё же получается что адрес с 0x00000000 (0) по 0x0009F000 (651264) у меня будет принадлежать именно к оперативной памяти (ОЗУ)? А значение 1 будет определять что память доступна для использования. Так? Но есть очень интересный момент: последнее значение равно 0. А в статье написано следующее:

Цитата:
Если содержит 0, ОС должна игнорировать этот описатель диапазона адресов (он содержит недействительную информацию)

То есть данный диапазон использовать мне не стоит и продолжать дальше искать адреса. Так?

Автор:  Himik [ 27 окт 2010, 16:16 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Адреса с 0x00000000 (0) по 0x0009F000 использовать не запрещается. Но первый килобайт занимает таблица BIOS прерываний, а второй килобайт занимают данные BIOS.

Автор:  s3dworld [ 27 окт 2010, 16:20 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Ага, только я же всё это хочу для защищённого режима. Пока вот наберусь данных, а уже в защищённом режиме составлю каталог страниц.

Автор:  s3dworld [ 27 окт 2010, 16:23 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Решил я вызвать большее количество раз функцию, передавая ей то в EBX, что она сама вернула. Вот что у меня получилось:

Изображение

Но не понимаю, почему два раза значение 5. Кто-нибудь вообще объяснит?

Напомню, что самым первым в каждой группе цифр отображается то значение, которое оказалось в регистре EBX после вызова прерывания 0x15.

Автор:  SII [ 27 окт 2010, 21:23 ]
Заголовок сообщения:  Re: Определение адресов ОЗУ в адресной памяти

Что возвращается в ЕБХ, никого волновать не должно, нужно лишь соблюдать все требования системного вызова.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/