А если даже предположить, что размер страничек на 4 Кб, а 20 байт и следовательно инструкция попадает на границу страницы то процессору все равно будет на это пофигу. Он эмитирует линейность виртуального пространства при условии наличия для этого памяти.
Tronix Спасибо! Просто я хочу разобраться. Прочитал в статье http://ru.osdev.wikia.com/wiki/Определение_объёма_памяти про определение адресов оперативной памяти. И вот мне стало интересно... Я вот не понимаю, что значит минимум в этом случае. А что, если я укажу 40 байт, мне придёт 40 байт данных в ответ? Есть таблица: Расширенные атрибуты диапазона представляют собой двойное слово, то есть 32-бита (4 байта). Тогда получается что нужно в регистр ECX, перед вызовом функции, заносить значение 24? Вернёмся всё к той же таблице... У нас есть Начальный адрес диапазона, младшие 32 бита и Начальный адрес диапазона, старшие 32 бита. То есть данная функция BIOS предназначена для определения карты памяти в общем (x86, x64)? И вот ещё что: По этому адресу данные придут в виде текста ("12345678") или в виде числовых значений (12345678)?
barmaley57 22 года мне. Программированием занимаюсь с 8 лет (тогда ещё был у меня ZX-Spectrum). Жалею только об одном, что когда мне было лет 10-11, продавец CD-дисков заговорил меня и вместо того чтобы привести мне диск с ассемблером (хотел я его тогда изучать), он меня направил на языки высокого уровня (Java). А лучше бы я тогда фундамент на ассемблере построил. Но ничего, у меня ещё всё впереди. А к чему был этот вопрос?
s3dworld Нет - вам придет не больше того, что рекомендовано во входном описателе (а там рекомендовано, что текущий стандарт требует 24 байта). Только это не определение адресов. А определение объемов ОП. Внимательнее будьте. А вы кстати никогда не узнаете из программы, какую же именно реальную физическую память (какой банк памяти и какая ячейка) занял ваш код. За адресацию внутри ОП отвечает контроллер памяти. Вы же можете тока использовать то, что предоставляет процессор. А он вам предоставляет страничную, сегментную модели памяти и их комбинацию. Больше ничего использовать вам не дано. Это говорит о том, что есть еще 1 уровень трансляции: физический для процессора - в "честный физический" для ОП. Вот этим и занимается контроллер.
Да так, просто интересно стало. Если бы у меня в 22 года появился бы такой жгучий интерес, то я бы сейчас ух.... А так просто офисный планктон Так что удачи тебе в изысканиях.
TermoSINteZ Минутку, как не определяет адресов? А табличка: Тут же Начальный адрес диапазона и Длина диапазона. Это по Вашему что?
barmaley57 Спасибо! TermoSINteZ Если это не определяет адресов, тогда как их определить? Подскажите статьи или возможно теорию.
s3dworld Что вы хотите определить? Я не понимаю вас немного. Расшифруйте ваше "Определить адрес". Покажите пример , типа что дано, а что надо найти.
TermoSINteZ Адресное пространство в 4 ГБ занимает всё подряд (ОЗУ, память устройств, регистры устройств и прочее). Мне из всего адресного пространства в 4 ГБ нужно определить следующее: 1. Объём оперативной памяти (ОЗУ). У меня это 2048 МБ (2 097 152 байта). Вот мне нужно для галочки научиться определять этот объём (хотя фактически цифра может различаться, не верю я что производители байт в байт всё делают). Чтобы определив объём, я мог принять решение запускать операционную систему или нет. 2. Составить таблицу, которая содержала бы следующие поля: Например, будет так: То есть я хочу получить адреса участков адресной памяти, которые принадлежат к оперативной памяти (ОЗУ). Конечно по этой таблице я смогу и решить свой первый вопрос (просто просуммировав все длины). Собственно на основании такой таблицы я составлю таблицу для страничек.
Разве для этой цели мне не подходит функция, описанная выше, прерывания 0x15 системы BIOS? Что самое интересное: объём и адреса оперативной памяти (ОЗУ) и для 2^32 адресного пространства и для 2^64, определяются в реальном режиме (R-Mode) работы процессора (ну это и понятно, ведь прерывания BIOS доступны нам только тут). Так всё таки функцию для определения я правильную подметил? Ещё бы мне хотелось разную информацию (особенно числовую) выводить на экран монитора. Для начала мне подойдёт запись значений по адресу 0x0000B800. Но как быть с числовыми данными (пока интересуют только целые числа, да и пока пускай будут положительные). Придётся писать самому функцию конвертирования данных в текст или же есть какая-то хитрость? Просто тот же объём оперативной памяти вывести на экран.
s3dworld Чтобы получить объем памяти - да. Можно юзать. И все. А страничная адресация в защищенном режиме никак не связана с этой функцией. Ничего там хитрого и сложного. И обсуждалось 100500 раз на форуме. Ищите по ключевым словам ASCII, вывод чисел на экран и тп.
TermoSINteZ Я Вас не понимаю. Ведь написано в статье что она используется для определения адресов. Я лишь хотел узнать эффективный ли это способ или есть что-то лучше. Разве через эту функцию я не получу начало адреса для ОЗУ и длину? Разве не получу через несколько вызовов этой функцию всё карту адресов ОЗУ?
TermoSINteZ Понятное дело что страничная адресация не зависит от этой функции. Я же хочу определить где у меня ОЗУ и странички описать именно на ОЗУ, а не описывать все 1024 элемента на всю адресную память.
Я тут так подумал то про страничную адресацию... Предположим что мы имеем дело со страницами, размером по 4 МБ. Вот у нас 32-битное значение: В данном случае мы будем ссылаться на страничку с индексом 0 и смещение в ней в 0 байт. Пускай мы дошли до предела странички 4194304 байт (от 0 до 4194303) - то есть 4 МБ. И если мы дальше куда-то соберёмся идти по адресу: То это у нас уже будет страничка с индексом 1 и со смещением в 0 байт. Таким образом, в коде можно обращаться, скакать и прочие операции проводить, как угодно. Всё само собой будет переведено правильно (новая страничка, смещение с начала). Важно лишь чтобы для каждой программы странички начинались с индекса 0 (либо чтобы операционная система сама индекс понижала). А то программа пользователя захочет получить данные по адресу: Code (Text): mov EAX,dword [00000000000000000000000000000011b] Это будет интерпретировано как получить данные со странички с индексом 0 по смещение в 3 байта. А возможно что туда доступа программе пользователя и нет. Так что получается что лучше коды и данные текущей программы держать в первых страничках. Так? Например, как обычно и делается: первая страничка с данными, вторая страничка с кодом. Какие будут комментарии?
Что касается перевода целого положительного числа в строку... Алгоритм такой: 1. Разделим число на 10 (0x0000000A, 00000000000000000000000000001010b). 2. Остаток от деления на 10 (0x0000000A, 00000000000000000000000000001010b) записать куда-нибудь в память и прибавить к нему значение 48 (0x00000030, 00000000000000000000000000110000b). Если полученное число (не остаток от деления и не число, полученное при добавлении числа 48) равнялся нулю, то переходим к шагу 4, иначе к шагу 3. 3. Полученное число (не остаток) от деления на 10 (0x0000000A, 00000000000000000000000000001010b) передаём в шаг 1. 4. Если в строке получился всего один символ, то можем его вывести на экран. А если в строке больше одного символа, то выстраиваем символы в строке в обратном порядке. Давайте в месте всё проверим... Пусть у нас есть число 123 (0x0000007B, 00000000000000000000000001111011b). 1. 123 mod 10 = 3 2. 3 + 48 = 51 (записываем в строку - символ с индексом 0) 3. 12 mod 10 = 2 4. 2 + 48 = 50 (записываем в строку - символ с индексом 1) 5. 1 mod 10 = 1 6. 1 + 48 = 49 (записываем в строку - символ с индексом 2) 7. Так как у нас больше одного символа в строке (51, 50, 49), то мы их записываем в обратном порядке: 49, 50, 51. А числа 49, 50 и 51 представляют ASCII-коды следующих символов: '1', '2' и '3' - то есть будет у нас строка "123". Всё верно?
Вот даже кое что сообразил (надеюсь кому-то это будет в пользу): Code (Text): ; ******************************************************** ; П Р О Ц Е Д У Р А ; ******************************************************** ; -------------------------------------------------------{ ; Название: UnsignedNumberToString() ; Описание: Преобразование 32-битного числа в строку ; Вход: EAX - 32-битное число ; Выход: EDI - указатель на строку ; ECX - количество символов в строке ; -------------------------------------------------------- UnsignedNumberToString: mov EDI,string1 mov ECX,0 mov EBX,10 UnsignedNumberToString__Label_Div: div EBX add EDX,48 mov [EDI],byte DL inc EDI inc ECX test EAX,EAX 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 inc EBX cmp EBX,ECX jz UnsignedNumberToString__Label_BuildConplete jmp UnsignedNumberToString__Label_Build_Copy UnsignedNumberToString__Label_BuildConplete: 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 Если есть какие-то комментарии или нашли ошибки, то пишите.
Обнаружил я что моя процедура перевода числа в строку не работает. Обидно! А главное я не понимаю ошибку. Выявил что запинается у меня всё на команде div: Code (Text): div EBX Но не понимаю в чём дело. Кто поможет? Вот весь код: Code (Text): ; ******************************************************** ; П Р О Ц Е Д У Р А ; ******************************************************** ; -------------------------------------------------------{ ; Название: UnsignedNumberToString() ; Описание: Преобразование 32-битного числа в строку ; Вход: EAX - 32-битное число ; Выход: EDI - указатель на строку ; ECX - количество символов в строке ; -------------------------------------------------------- UnsignedNumberToString: mov EDI,string1 mov ECX,0 mov EBX,10 UnsignedNumberToString__Label_Div: 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 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
s3dworld Ну вообще да, для вашей задачи эта функция подойдет. Но зачем вам определение адресов ОЗУ . У этой функции куча ограничений. И мало того - многие адреса и так уже известно для чего используются. Так что, я считаю есть смысл использовать ее для получение объема ОЗУ, для других целей - она не имеет смысла. Вы почитайте в той статье раздел "При использовании функции E820h прерывания INT 15h следует учитывать следующие соглашения и ограничения:". Вы сами определяете соответствие линейных адресов с физическими - для этого вы составляете катало и таблицы страниц. И еще раз гляньте на схему формирования линейного адреса в манах интела - очень полезно. И вообще - вы кончайте теоретизировать. Займитесь практикой. На счет перевода символов - кончайте это извращение с делением. Сделайте таблицу и по ней индексируйте. Допустим по индексу 0 у вас будет храниться символ "0", и так вам нужно всего-то 10 ячеек . Это просто один из вариантов. И никаких делений и сложений. Просто выборка и копирование символа.
TermoSINteZ И как же мне тогда выявить адреса оперативной памяти (ОЗУ)? Должен же я знать что у меня является оперативной памятью (ОЗУ). Да даже если через таблицу, это только избавляет от сложения (что не так существенно). А узнать циферку всё равно без деления не получится. Но не пойму, почему у меня там ошибка?