Добавить Автора
Программист C++ может каждый день иметь дело с различной семантикой верхнего уровня, шаблонами проектирования, программными методами и т. д. Но вы, возможно, не знакомы с тем, «как программа C++ работает на машине». Иногда, когда вы сталкиваетесь с некоторыми проблемами, может показаться трудным объяснить их с точки зрения макроса, но на самом деле, начиная с нижнего уровня, вы можете обнаружить, что эта проблема вообще не является проблемой. Подобные вопросы включают в себя:
int *p = nullptr; *p = 5;
)int a; std::cout << &a;
)*(int *)0xa0000 = 0x41;
)Некоторые из вышеперечисленных вопросов были заданы читателями, некоторые были обдуманы автором, но не решены быстро. В то же время автор обнаружил, что существует множество учебных пособий среднего и общего назначения, но очень мало специализированных учебных пособий высокого и низкого уровня. Многие проблемы на самом деле могут быть очень простыми, но соответствующих руководств не найдено. Автор также пытался найти ответы в некоторых книгах, которые систематически объясняют нижний слой, но также обнаружил, что они подробно объясняют в своих соответствующих выдающихся областях, но всегда не хватает частей, которые соединяют верхний и нижний слои, что приводит к знания в каждой области будут неполными и их трудно соединить воедино, чтобы построить более макроскопическую систему.
Итак, после ряда исследований и экспериментов автор решил написать эту статью. В этой статье мы представим:
Что касается этой статьи, то следует отметить несколько моментов:
Если вы готовы, давайте начнем!
Я думаю, что читатели наверняка знакомы с термином x86, но что именно он означает?
Для ЦП это на самом деле высокоинтегрированная логическая схема. Если вы играли с цифровыми схемами, вы наверняка знакомы с так называемыми вентильными схемами «И», «ИЛИ» и «НЕ». Комбинируя эти вентильные схемы, мы можем достигать все более и более сложных функций.
Однако какой бы сложной ни была логическая схема, она представляет собой не что иное, как преобразование «набора входных электрических сигналов» в «набор выходных электрических сигналов». Например, определенный чип имеет 3 входных контакта и 2 выходных контакта. Когда я назначаю входным контактам «высокий уровень, высокий уровень, низкий уровень», он может назначить выходным контактам «высокий уровень, высокий уровень, низкий уровень». У меня есть сигнал «низкий уровень, высокий уровень». В описании только что «количество входных и выходных контактов чипа» называется «размером интерфейса чипа», а «при вводе сигнала на XXX он может выводить сигнал YYY» называется «размером». интерфейса чипа «Логическая функция».
поэтому,Мы называем те «сигналы, которые можно вывести» «инструкцией».,И сборник всех "инструкций", которые может поддерживать этот чип.,Это называется "набор" команда». Таким образом, процессор Команда непосредственно определяет ее первоначальную функцию.
иархитектура Этот тип набора используется x86 команда, мы можем назвать его x86набор команда, используется для описания всей архитектуры Какая инструкция может поддерживаться процессором x86?
конечно,За исключением основного набора команд,«Системная архитектура», естественно, включает в себя и другие компоненты ЦП.,И как взаимодействовать с внешним оборудованием. Суммируя,Мы можем думать об этом как о наборе стандартов протокола.,Когда мы используем системный процессор x86,Какие части он должен содержать, как дать ему инструкции, чтобы он мог нормально функционировать, как должно быть расположено внешнее оборудование и т. д. уже определено. Нам просто нужно написать программу в соответствии с протоколом, который она предусматривает.,Вы можете нормально функционировать в этой системе.
После объяснения того, что такое x86, я думаю, некоторым читателям будет любопытно, почему эта архитектура называется именно так? Каково его отношение к основным аппаратным устройствам, представленным сегодня на рынке?
История начинается в 1978 году. В 1978 году Intel выпустила модель процессора под названием 8086 (что касается того, почему она так названа, я думаю, вы можете спросить только у Intel...). На самом деле тогда этот процессор не вызвал особого ажиотажа. Теперь, когда мы все его изучаем, это просто предвзятость выживших. Итак, нам достаточно знать, что в конце 1970-х годов компания Ying (Intel) выпустила чип с номером модели 8086.
В чипе 8086 мало движения. Есть очень критичная проблема, то есть он слишком дорогой! Потому что это стоит 360 долларов за штуку. Уведомление! Это только цена процессора, не считая другого оборудования. Поэтому тех, кто может себе это позволить, как правило, очень мало, а отдельные пользователи им недоступны. Что действительно сделало эту серию чипов популярной, так это 8088.
Мы можем думать о 8088 как об упрощенной версии 8086 или в шутку называть его «8086 SE»~. В 1981 году IBM использовала чип 8088 для производства индивидуального ПК по доступной цене. Поэтому он стал популярен во всем мире, что также способствовало росту продаж этой серии чипов.
С тех пор Intel начала исследования и разработку процессоров с этой архитектурой и впоследствии выпустила 80186, 80286 и 80386. Все они совместимы с рабочим режимом 8086, но в процессе все же есть некоторые сбои (или их можно понимать как небольшие ошибки, которые будут рассмотрены в следующей главе).
Поскольку вся эта серия заканчивается цифрой 86, эта серия называется серией «x86». Но обратите внимание, что «архитектура x86» относится конкретно к чипам 80386 и более поздних версий и не включает 8086, 80186 и 80286. Мы объясним причины в последующих главах.
До 1992 года, до того, как на свет появился процессор, который должен был называться «80586», Intel пришлось сменить название из-за некоторых проблем с авторскими правами на товарный знак. Когда процессор 80586 был выпущен, он назывался «Pentium», что переводилось на китайский язык как «Пентиум». пентиум».
Впоследствии Intel выпустила серию «Celeron», серию «Core» и серию «Xeon», каждая из которых использовала архитектуру x86. Intel назвала ее «архитектурой IA-32», и все они остаются обратно совместимыми.
Поворотный момент истории произошел в 2001 году. В то время некоторые люди считали, что архитектура x86 ошибочна и ее не следует использовать в дальнейшем, поэтому они запустили новую архитектуру под названием «IA-64» и выпустили процессор с такой архитектурой — серия «Итаниум».
Здесь IA относится к архитектуре Intel, а 64 представляет длину слова инструкции (подробно будет объяснено позже). Первоначально цель этого названия также была очень ясна. Раньше это было «IA-32», но теперь после редизайна оно называется «IA-64». Но поскольку он не был обратно совместим с IA-32 и был дорогим, он не произвел фурора в области персональных ПК. Серверная область, на которой она сосредоточена, не конкурирует с IBM PowerPC, поэтому у нее не так уж много рынка. Это также привело к тому, что процессоры серии Itanium пока не очень известны.
IA-64 не имела успеха, но стала популярной другая 64-битная архитектура. Это была архитектура AMD64, впервые представленная AMD в 1999 году. Последующая архитектура AMD64 получила широкое распространение в персональных ПК. Так в чем же прелесть AMD64? Фактически, она совместима с архитектурой IA-32 и расширена на ее основе. Поэтому архитектуру AMD64 также называют архитектурой «x86-64», то есть архитектурой x86, расширяющей 64 бита.
Итак, здесь наблюдается очень интересное явление. Будучи преемником IA-32, IA-64 несовместим с IA-32 и отказался от него. Вместо этого AMD64 взял на себя корону и обратно совместим с IA-32. Благодаря успеху архитектуры AMD64 позже она была использована Intel и получила название Intel 64.
На самом деле разницы между Intel 64 и AMD64 в принципе нет. Основная причина в том, что их намеренно выделяют в коммерческой конкуренции. Но эти бизнес-конкуренции между производителями оборудования не имеют значения для этих компаний-разработчиков программного обеспечения. Их волнует только то, для какой архитектуры подходит мое программное обеспечение. Поэтому независимо от того, описывают ли они это как «AMD64» или «Intel 64», они кажутся на одной стороне. И поскольку Intel 64 и AMD64 на самом деле представляют собой одну и ту же архитектуру, эти производители программного обеспечения называют эту архитектуру «архитектурой x64», где «. x» можно разобраться самостоятельно, Intel подойдет, AMD тоже подойдет.
Итак, подведем итоги:
Стоит отметить, что поскольку x64 обратно совместим с x86, многие люди не будут различать их, а поскольку архитектура x86 уже давно устарела, сейчас ее используют лишь немногие устройства. Поэтому иногда мы слышим, что «x86» на самом деле относится к архитектуре x64, особенно когда оно описывается вместе с архитектурой ARM (например, мы часто говорим, что Apple перешла с x86 на ARM, но на самом деле x86 здесь относится к x64, а не к истинному архитектура IA-32).
Поэтому, во избежание путаницы, в этой серии статей автор использует названия «архитектура IA-32» и «AMD64» единообразно, вместо использования «x86», которое может быть двусмысленным.
Потому что сегодня это наиболее часто используемая архитектура на рынке. Процессоры Intel Core и процессоры AMD Ryzen, которые можно увидеть повсюду, используют архитектуру AMD64. Более того, процессор Intel Xeon, наиболее часто используемый в серверах, также имеет эту архитектуру, поэтому для нас не является потерей понимание самой массовой архитектуры.
С другой стороны, именно потому, что это текущая основная архитектура, связанная с ней информация также является наиболее полной и простой для поиска. Она имеет меньше черных ящиков и более прозрачна, поэтому порог обучения ниже. В основных учебниках для базовых компьютерных профессиональных курсов эта архитектура также используется в качестве примера для объяснения.
Поскольку мы здесь для того, чтобы уточнить знания, связанные с построением и работой программы, архитектура не должна представлять для нас большой трудности, поэтому автор «решительно» выбрал ее. (Смеюсь, вообще-то, потому что у меня нет выбора~)
После понимания ситуации с этой архитектурой, следующее, что нам нужно сделать, — это найти машину и затем разработать ее.
Поскольку мы разрабатываем устройства для архитектуры AMD64, в первую очередь у нас должно быть аппаратное устройство с архитектурой AMD64. Первое и самое простое, о чем нужно подумать, — это построить компьютер с архитектурой AMD64.
Этот метод является наиболее прямым, но его стоимость немного высока, а загрузка программы может оказаться не такой удобной. Конечно, если у вас под рукой есть запасное оборудование или старое оборудование, которое больше не используется, в этом нет ничего страшного. Вы можете запустить программу прямо на реальной машине, и у вас будет другой опыт, и она полна ритуалов, и это круто!
Если нет, это не имеет значения, потому что мы можем использовать виртуальную машину. Что касается запуска виртуальных машин, то обычно есть два пути:
Здесь~переводчик должен выйти и взять вину на себя! Виртуализация и симуляция — это две совершенно разные виртуальные технологии, но перевод здесь их вообще не различает. В чем разница между «виртуализацией» и «симуляцией»? Во всяком случае, буквально... Я не могу отличить...
Так что же означают эти двое? Прежде всего, нам нужно знать, что если мы хотим смоделировать аппаратное устройство с помощью программного обеспечения, то это «программное обеспечение» должно работать в уже хорошо работающей операционной системе. Другими словами, нам нужно использовать операционную систему, чтобы открыть приложение, а затем смоделировать различные компоненты аппаратного устройства в этом приложении, а затем использовать эти смоделированные компоненты для выполнения инструкций.
Так Самое простое, что можно придумать, это использовать「Чистое программное обеспечение」способ симулировать。Например Я установил переменную,используется для выраженияrax
зарегистрироваться,Установите другую переменную для представленияrip
зарегистрироваться。Установите еще один кусок Памятьпространство для представления симулятора Памятькосмос。после,Когда я получаю что-то вроде「Пучок0x10
Памятькосмосизценить Писатьприезжатьrax
зарегистрироватьсясередина」такизинструкциячас,Просто поместите его в соответствующее место Память.,компенсироватьда0x10
изценить,назначен представлятьrax
зарегистрироватьсяизпеременнаясередина。грубоиспользовать Простойизпоколениекод Приходитьвыражать Сразуда:
uint64_t rax; // Используется для имитации регистра RAX.
std::byte mem[1024 * 1024]; // Память для эмуляции 1МБ
// Исполнение будет данных память читает стандарты в rax
void load_mem_to_rax(std::ptrdiff_t address) {
rax = *reinterpret_cast<uint64_t *>(mem + address);
}
Таким образом моделируются все аппаратные компоненты и все аппаратные компоненты. командсерединаизинструкция,Такприрода Сразу Можетк Имитировать аппаратные устройстваизбегать Состояние。
Вышеописанный метод моделирования называется методом «Моделирование» или методом «программного моделирования».
Преимущества такого подхода весьма очевидны:
Конечно, очень очевиден и его недостаток, то есть плохая производительность. Представьте себе, что программно смоделированная инструкция «регистр чтения памяти» моделируется программным обеспечением в присваивании различных переменных. Этот процесс включает в себя множество программной логики, а также собственный алгоритм планирования ОС и т. д. Между ними очень много слоев, а фактические инструкции, выполняемые ЦП, расширены до множества чисел. Таким образом, снижение производительности этого симулятора экспоненциально.
Поскольку использование виртуальных машин становится все более распространенным, основные операционные системы на рынке начали обращать внимание на эту проблему. Поэтому API для виртуализации был упакован на уровне ОС. Затем приложение «виртуальной машины» напрямую вызывает API виртуализации, предоставляемый ОС, для завершения моделирования.
Эта технология больше не использует полностью программное обеспечение для моделирования состояния оборудования.,идавстреча「как можно больше」Используйте оборудование напрямую。Например, для выполнения на виртуальной машине「Память0x10
данныечитатьrax
зарегистрироватьсясередина」такизинструкция,Через API виртуализации,CPUна самом деле выполнит последующие действия Память Читать вданныепомещатьприезжатьзарегистрироватьсясерединаизинструкция。Это просто этот кусок Памятькосмос Нет0x10
(OSСделаю слой маппинга),этотиндивидуальныйзарегистрироватьсятакже Может能Нетдаrax
。
Таким образом, программное обеспечение виртуальной машины, работающее через API виртуализации, будет рассматриваться ОС как особый процесс. Инструкции, выполняемые внутри, просто сопоставляются, а затем напрямую передаются на исполнение аппаратному обеспечению. Но поэтому одна инструкция может стать только несколькими инструкциями для ЦП. Снижение производительности линейно, и при хорошей оптимизации это снижение может быть очень небольшим.
Поскольку этот метод основан на «API виртуализации», предоставляемом ОС, этот метод называется методом «виртуализации».
Сравнить метод программного моделирования,Преимущества метода виртуализации весьма очевидны.,Это значительное улучшение производительности. Но все, что у него есть, это недостатки.,Например, его нельзя смоделировать в Архитектуре.,Также непросто напрямую наблюдать за состоянием оборудования.
На самом деле существует еще один метод моделирования, который находится между двумя ранее представленными и подходит для межархитектурного моделирования. Точнее, это не «симуляция», а «побег».
Например,Я хочу, чтобы программа на архитектуре ARM заказала архитектуру AMD64. Итак, прежде чем запускать,Дай мне сначала прочитать оригинальный текст,Напримеркогда оно появится「Пучокданныезагрузить вrax
зарегистрироватьсясередина」инструкцияизчасждать,я просто хочу,Хм……ХотяяизARMАрхитектура Никтоrax
зарегистрироваться,но,Вместо этого я могу использовать другие регистры,Напримерx0
。Чтоя Сразу Пучоквсе хотят Даватьrax
китайское письмоданныеизинструкция,переводятся как предоставлениеx0
зарегистрироватьсякитайское письмоданные。
Образно говоря, прежде чем запускать программу, сначала «поймите» программу, затем транслируйте ее в новую программу текущей архитектуры, а затем запустите ее.
Потери производительности этого метода моделирования находятся между «симуляцией» и «виртуализацией». При хорошей оптимизации можно получить хорошую производительность. Но самым большим недостатком является то, что требования к этому «программному обеспечению для перевода» слишком высоки! Обычно подходит только для запуска приложения, а не для работы ОС. А «программное обеспечение для перевода» должно не только очень четко понимать архитектурные инструкции до и после перевода, но также хорошо понимать методы планирования ОС.
Очень типичный пример такого подхода — Rosetta от Apple. Только Apple может одновременно понимать и старую, и новую архитектуру инструкций и macOS, поэтому неудивительно, что он может создать Rosetta.
Законченное пониманиевиртуальная средапосле,Вопрос к читателям,Какой из них нам следует использовать?
Прежде всего, мы просто пишем несколько очень простых программ с целью изучения и разбора лежащих в основе знаний, поэтому мы не можем учитывать снижение производительности виртуальной машины.
Во-вторых, нам нужно наблюдать за работой железа и понимать данные в регистрах и памяти в любой момент времени.
Наконец, я верю, что есть много таких друзей, как я, которые используют Mac с чипами собственной разработки Apple. Эта штука сама по себе не является машиной с архитектурой AMD64 или IA-32, и ее необходимо моделировать на разных архитектурах.
Такв заключение Сразупоказыватьи Легко увидеть Понятно,мы будем использовать「программное моделирование」Способ。использоватьприезжатьизпрограммное обеспечениедаbochs
,Это эмулятор AMD64.,И поддерживает очень мощную инструкцию по отлаживанию.,非常适合я们когдавпередизтребования。Следующий Позвольте мне представить вам, какmacOSиWindowsНастроить в системеbochs
。
bochs
даодининдивидуальныйAMD64эмулятор,мы можем быть на этомбегатьAMD64Архитектура、IA-32Архитектура、80286Архитектурадажеда8086Архитектураизпрограмма。ноbochs
самда Кросс-платформенныйизпрограммное обеспечение,поэтому,Независимо от того, используете ли вы Mac с чипом Intel или Mac с чипом собственной разработки Apple.,Все можно установитьbochs
。
Хотя мы также можем начать сbochs
Официальный сайт загрузки исходного проекта Затем Сборка и установка,но Конфигурация среды и различное зависимое программное обеспечение слишком сложны в настройке.,Поэтому мы выбираем самый простой способ,Используйте домашнее пиво.
Home Brew — это менеджер программного обеспечения с открытым исходным кодом для Mac, похожий на apt-get в Debian и yum в RedHat. Но он не интегрирован в macOS, поэтому нам нужно сначала его установить.
этотдаОфициальный сайт Home Brew,Но по известным причинам,Его ресурсы по умолчанию недоступны в материковом Китае.,так Нам нужно использовать зеркальные ресурсы。有одининдивидуальныйодомашненныйиз Изготовлено мастером Понятноодининдивидуальный УстановитьHome Brew и заменяет библиотеку ресурсов скриптом, который отражает ресурсы, которые мы можем использовать напрямую.
Откройте терминал и выполните следующую команду:
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
Этот сценарий будет автоматически загружен, затем следуйте инструкциям, чтобы указать источник зеркала, ввести системный пароль и затем установить Home Brew.
Поскольку в DNS GitHub, где расположен Home Brew, произошел инцидент с загрязнением, при его использовании возникает ошибка, подобная следующей:
Warning: No remote 'origin' in /opt/homebrew/Library/Taps/homebrew/homebrew-cask, skipping update!
В это время мы можем выполнить следующие инструкции для решения проблемы:
git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew-core
git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew-cask
git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew-services
Когда Home установлен Варить позже,Сразу Можеткпроходить Внизлапшаизинструкцияустановитьbochs
:
brew install bochs
После завершения установки выполняем:
bochs --help
Если справочную информацию можно успешно распечатать,Итак, поздравляю,bochs
Установлен успешно!
Так же,потому чтоbochs
дачерез Архитектура、кроссплатформенное программное обеспечение,поэтому Также доступен вWindowsНормальныйбегать,Также включает Windows для ARM-архитектуры (например, компьютеров, оснащенных чипом Snapdragon 8cx).,СразудаARMАрхитектураиз)。Представлено ниже Установить Бохс на Метод Windows.
первыйсуществоватьВеб-сайт SourceForgeскачатьbochs
из Установить包。
После загрузки дважды щелкните, чтобы установить.
Просто оставьте параметры во время процесса установки по умолчанию. После завершения установки,bochs можно найти в стартовом меню,Здесь мы не хотим напрямую программировать,идавыбирать ВнизлапшаизFolder
Папка открыта。
После открытия выбираемbochsdbg.exe
Открыть。Уведомление,существоватьWindowsсерединаизbochs
по умолчаниюда Безотлаживать Функцияиз,долженбегатьbochsdbg
можно продолжитьотлаживать。Все последующие требования к этой статьебегатьbochs
изместо,Для читателей, использующих Windows,Все должно быть замененоbochsdbg
。(включая командную строку、makefileсерединанаполнять Писатьизтакжеотвечатькогдадаbochsdbg
и Нетдаbochs
,Читатели должны Уведомление!)
После открытия,Вы можете выбрать левуюLoadКнопка для загрузкиbochsrc
Конфигурационный файлбегать,Позже, если мы воспользуемся командной строкой, чтобы добавить-f
После параметров нет необходимости вручную загружать。сейчассуществоватьвременночас ХОРОШОНетиспользоватьнагрузка Конфигурационный файл,Непосредственное выполнение в режиме по умолчанию,Нажмите «Пуск» справа, чтобы увидеть эффект запуска.
после便Можетксмотретьприезжатьbochs
избегатьсостояние,Слева находится командная строка для отлаживать,Правая часть — эффект отображения виртуальной машины.
Теперь, когда «Аппаратная среда» готова,Тогда что дальше,Нам нужно найти способ сделать это нашей программой. Но перед этим,Мы должны понять основные особенности 8086.,А также способ выполнения программы.
Кстати, разве мы не собираемся изучать архитектуру AMD64, почему мы говорим об этом процессоре десятилетней давности с седой бородой? Фактически, мы упоминали ранее, знакомя с историей AMD64, что будь то IA-32 или AMD64, по сути это не совершенно новая архитектура, но она остается обратно совместимой.
С одной стороны, и IA-32, и AMD64 запускаются из режима 8086. В момент загрузки ваш компьютер на самом деле имеет 8086, а затем через некоторые конфигурации он переключается в режим 286, режим 386, режим AMD64 и т. д. Подождите. Поэтому, если мы хотим начать загрузку программ на «голом железе» архитектуры AMD64, нам не избежать метода работы 8086.
С другой стороны, с точки зрения архитектуры IA-32 и AMD64, на самом деле он все еще имеет сильный стиль 8086, и основная структура существенно не изменилась. Поэтому, поняв 8086, естественно понять и AMD64. .
Поэтому нам необходимо понять 8086 перед этими дополнительными ссылками расширения.
Нам необходимо понять основное оборудование системного компьютера 8086. Это:
ЦП — это ядро,Давай поговорим об этом позже,Давайте сначала поговорим Память、жесткий диск(Внешнее хранилище)ивидеокарта。
Кажется, что слово «память» в последние годы «загрязнено» терминологией индустрии мобильных устройств. Потому что то, что мы часто называем «памятью мобильного телефона», на самом деле не относится к «памяти» в компьютерной терминологии.
Память, полное имя — «внутренняя память», английское название — «Внутренняя память», также известная как «основная память». Причина, по которой его называют «внутренним», также имеет исторические причины. Потому что в первые годы память не была самостоятельным аппаратным обеспечением, а частицы памяти были непосредственно приварены к материнской плате.
Следовательно, если этот основной компонент является границей, память «внутри» называется памятью, а память вне системы называется «внешней памятью».
Другая причина заключается в том, что память может напрямую взаимодействовать с ЦП, а внешняя память - нет. Она должна пройти через интерфейс ввода-вывода, чтобы передать данные через память, прежде чем они смогут быть обработаны ЦП.
В памяти обычно используется схемный метод хранения, например, бистабильная схема, состоящая из транзисторов, и напряжение схемы представляет собой битовый сигнал. Преимущество этого метода хранения заключается в том, что скорость чтения и записи очень высока (в конце концов, он реализуется схемой), но недостатком является то, что он зависит от постоянного питания. Другими словами, если отключить питание, данные будут потеряны. После повторного включения питания неизвестно, что это за данные внутри (это зависит от судьбы, очень Шредингера), и они будут доступны после. переписывание.
Таким образом, так называемая «память мобильного телефона» в индустрии мобильных устройств, очевидно, не относится к памяти в этом смысле. На самом деле это тоже вопрос разграничения, поскольку «память» в памяти мобильного телефона относится к SD-карте, а встроенная память мобильного телефона называется «памятью». Но «память» в компьютерной профессиональной сфере — это внутренняя часть архитектуры. (Позже это произошло еще и потому, что термин «память мобильного телефона» уже существовал. Когда я хотел указать на реальную «память» мобильного телефона, мне пришлось добавить атрибут и назвать ее «текущей памятью». Поэтому я использовал концепцию В компьютерной профессиональной сфере говорят, что «память мобильного телефона» на самом деле является «внешней памятью», а «оперативная память мобильного телефона» — это «память»).
Давайте еще раз поговорим о внешнем хранилище. Внешнее хранилище, естественно, представляет собой устройство хранения, отличное от упомянутого выше, например, ранние дискеты. Подумайте об этом: на самом деле в машине есть только один дисковод. Если вы хотите его использовать, вставьте дискету в дисковод и затем прочитайте данные. Итак, не является ли эта «дискета» устройством хранения данных, «внешним по отношению к компьютеру»? Это объяснение может быть более приемлемым.
Конечно, жесткие диски, оптические диски, U-диски и т. д. являются внешними запоминающими устройствами. Хотя жесткие диски обычно размещаются внутри корпуса и не часто подключаются и отключаются, это не влияет на их роль в архитектуре.
Внешняя память обычно хранится без схемы. Например, на дискетах и механических жестких дисках используется магнитное хранилище. Магнитная головка используется для определения северного или южного полюса магнитного порошка в определенном положении для идентификации бита. . Оптические диски используют светоотражающее хранилище, а привод определяет отражательную способность определенной позиции для идентификации битов. U-диски (флэш-диски) и твердотельные накопители используют слои с плавающими затворами для хранения данных, а количество электронов в сетке определяет битовые данные в этом месте.
Поскольку это бесконтурный метод, ему не страшны сбои в питании и данные будут сохраняться более длительный период времени. Но относительно скорость его чтения и записи будет намного медленнее.
видеокарта,Полное название «адаптер дисплея»,Английскийда「Graphics Адаптер». Как следует из названия, это аппаратное обеспечение, используемое для преобразования сигналов в изображения и представления их на мониторе.
в первые дни,видеокарта используется только для преобразования сигналов,В Память выделят эксклюзивный участок,Для использования видеокартой. видеокарта — это данные, которые продолжают читать эту область Память,Затем поставить его в соответствии с определенным протоколом,Преобразование в изображение на мониторе. Когда нужно изменить отображаемые вещи,ЦП перезапишет это пространство Память,Итак, в следующем кадре,видеокарта будет соответствовать соответствующим требованиям,Преобразуйте отображаемое изображение.
В этой системе обработка графики полностью выполняется центральным процессором, а данные, используемые для вывода на дисплей, также выполняются частью памяти. Мы называем эту область памяти, используемую для отображения изображений, «видеопамятью».
Однако позже, когда требования людей к качеству графики становились все выше и выше, они задумались о создании процессора специально для обработки данных изображения, то есть графическому процессору также нужна собственная основная память, называемая также «независимой видеопамятью».
Скажи еще немного,Теперь поговорим о «видеокарте».,По умолчанию включен графический процессор.,Это больше не простой адаптер дисплея. Благодаря постоянному развитию производительности современной видеокарты,На некоторых устройствах, которым не требуется столь высокая графическая производительность,Просто подумайте о том, чтобы не использовать автономную видеокарту.,Вместо этого видеокарта (включая GPU) наследуется от других компонентов.,Этот вид видеокарты еще называют «интегрированной видеокартой». Интеграция графического процессора на материнской плате называется «встроенной видеокартой».,Интеграция графического процессора в процессор называется «ядерной видеокартой». Но встроенная видеокарта была устранена,В настоящее время, если на вашем компьютере нет дискретной графики,Должно быть, это ядерная демонстрация. Уведомление,В этом случае графический процессор интегрирован в «чип процессора».,Но это уже не то, что в первые дни,Ситуации с графическим процессором больше нет.
Ранее мы представили Память и внешнее хранилищеизхарактеристика,Не знаю, возникнет ли у читателей такой вопрос: Так как ЦП может работать только Память,А Память пропала после отключения электроэнергии.,Хотя внешнее хранилище можно хранить долго,но Только что включилсяизчасждать,ЦП не может выполнять здесь. Так,Какую программу должен выполнить процессор после загрузки?
Это действительно очень серьезная проблема, поэтому компьютеру нужна «затвердевшая» программа запуска, чтобы выполнить некоторые функции самотестирования оборудования, а затем прочитать инструкцию из внешней памяти в память перед началом выполнения. За эту задачу отвечает BIOS, полное название — Basic Input/Output System, что переводится на китайский язык как «Базовая система ввода-вывода». Обычно используется ПЗУ, подобное FPGA. При разработке новых машин оно закрепляется непосредственно на материнской плате. Конечно, позже выпускаются и некоторые BIOS, которые позволяют обновить прошивку.
Аппаратная проблема решена, но есть еще одна проблема. Логически говоря, BIOS не принадлежит памяти, так как же процессор выполняет инструкции в BIOS? Метод Intel для решения этой проблемы называется «унифицированной адресацией». Проще говоря, он отображает часть адреса памяти на компоненты вне памяти, такие как BIOS. Что касается ЦП, то он «думает», что управляет памятью через линию данных памяти, но на самом деле средняя часть связана с BIOS.
Поэтому при запуске компьютера он сначала выполнит инструкции BIOS. BIOS загрузит код из внешней памяти в память, а затем выполнит его. Поскольку этот код полностью контролируется программистом, дальнейшие действия выполняются этим кодом. Первую программу, загружаемую BIOS, мы называем «MBR (Master Boot Record)».
Кроме того, еще несколько слов, представленный ранее BIOS также является понятием «BIOS» в профессиональной компьютерной сфере. В наше время то, что мы часто называем «BIOS», имеет богатый графический интерфейс и множество функций (даже ту, что есть). можно разогнать). Фактически, это уже не традиционный BIOS, а UEFI (Unified Extensible Firmware Interface). Просто поскольку он играет аналогичную роль с BIOS, все до сих пор привыкли называть его «BIOS», надеюсь, читатели об этом знают. «BIOS» в последующем описании автора конкретно относится к BIOS в профессиональной компьютерной сфере, тогда как UEFI будет называться только «UEFI».
Наконец, мы подошли к основному компоненту — процессору. ЦП, полное название — «Центральный процессор», а китайский перевод — «Центральный процессор» или «Центральный процессор», но это китайское имя используется нечасто, и его обычно называют просто ЦП.
[Примечание. Чтобы упростить задачу и помочь читателям быстро приступить к работе, следующая структура структуры ЦП представляет собой упрощенную версию. Читатели, которые хотят узнать полную и стандартизированную внутреннюю структуру ЦП 8086, могут выполнить поиск в Интернете самостоятельно. 】
ЦП состоит из трех важных частей: арифметического блока (CU, Calculation Unit), исполнителя (EU, Execution Unit) и регистра (Register). Я не буду говорить о других вещах, таких как кэш (Cache), потому что мы пока не можем его ощутить.
оператор,Проще говоря, это атомарная функция процессора.,Например Умеет выполнять операции сложения и вычитания Издобрыйиз。Какие операции он может выполнять, зависит от него.изнабор команд。
Исполнитель отвечает за то, какая функция арифметического блока используется в данный момент и какие инструкции выполняются.
Регистры — это место, где данные хранятся внутри ЦП. На программном уровне мы в основном управляем регистрами, поскольку другие компоненты выполняются по своим собственным правилам. Нам нужно только контролировать регистры, чтобы выполнять то, что мы хотим. процессор.
Логично говоря,На данный момент мне предстоит представить 14 регистраторов по 8086.,но Автор считает,Впереди слишком много предзнаменований.,Читатели, возможно, захотят написать какую-нибудь программу,так,это содержимое,Давай поговорим об этом, когда нам это понадобится~
Приветвнутри Восемь слов Понятно Такмного,Окончательнода Можеткначинатьбегатьпрограмма Понятно!сейчассуществовать Сразупожалуйста Открытьbochs
,Давайте воспользуемся режимом отладки на «голом железе».,Посмотрите, что произойдет.
Для систем Windows,прямойбегатьbochsdbg.exe
Сразу Можетк Понятно,Файл конфигурации пока загружать не нужно,Для MacOS,Вам необходимо указать конфигурацию дисплея. Найдем рабочий путь (туда можно поместить все будущие коды проектов),Например~/code
,Затем создайте файл с именемbochsrc
,Это файл конфигурации виртуальной машины,Затем отредактируйте содержимое внутри следующим образом:
display_library: sdl2
Главным образом потому, что,bochs
изпоказывать示терять出,по умолчаниюиспользоватьиз并Нетдаsdl2
,Это не отображается в macOS,так Нам нужно указать этой библиотеке。
Если он еще не установлен на вашем компьютере,Такдоступныйbrew install sdl2
установить。
После сохранения запустите виртуальную машину через этот файл конфигурации по рабочему пути:
bochs -qf bochsrc
Вы можете запустить виртуальную машину, и командная строка останется в состоянии отладки:
этотчасждатья们Можетквходитьc
,Входить,Указывает на продолжение выполнения,Если не произойдет ничего неожиданного,Появится окно отображения виртуальной машины:
Видно, что инструкции в биосе были выполнены, но поскольку он не искал внешнюю память, то в итоге остановился здесь.
очень хороший! Далее нам останется только загрузить инструкции во внешнюю память и всё! Вы можете себе представить, что теперь мы написали программу, поместили ее на дискету, затем вставили дискету в дисковод и затем перезагрузили компьютер. В этом случае BIOS должен уметь определять содержимое дискеты. диск и автоматически загрузить его в память Inside.
Но для виртуальных машин,начальстволапшаэтот Зависит от набора ходов Конфигурационный файлзавершить。Открытья们Прямо сейчасизbochsrc
(Если вы используете Windows,Если оно не было установлено ранее,Пришло время настроиться! ),Добавьте следующий контент (примечание,macOSизразговаривать Нет Можеткудалитьsdl2
из Конфигурация Сян Ха!):
boot: floppy # Настроить загрузку с дискеты
floppy_bootsig_check: disabled=0 # Включите самотестирование
floppya: type=1_44, 1_44="a.img", status=inserted, write_protected=0 # Используйте 3,5-дюймовую дискету емкостью 1,44 МБ, возьмите образ в формате .img, дисковод вставляется по умолчанию при загрузке, а защита от записи не включена.
так Перезагрузитьизчасждать,Вы можете прочитать образ дискеты. Затем следующий,Нам просто нужно поставить инструкцию на исполнение,Напишите это имяa.img
изобраз дискетывнутри Сразу Сделанный Понятно。
Итак, как создать образ дискеты? Требуется бинарный редактор. Для macOS рекомендуется использовать множество бинарных редакторов, которые можно загрузить прямо из App Store:
HexFiend
Для Windows можно использовать ультраредактирование. Читателям предлагается установить его самостоятельно. Если вы действительно не можете найти подходящую, ничего страшного, ведь мы не всегда можем писать программы, редактируя бинарники. Мы перейдем к другим методам. начиная со следующей главы. Теперь вы можете взглянуть на работу автора и понять ее дух.
Чтобы увидеть Эффект казни,Мы просто записываем число в регистр,Затемпроходитьbochs
изотлаживатьинструкция Приходитьсмотретьсмотретьзарегистрироватьсявнутриизценить,Если оно вступит в силу,Тогда это доказывает, что наша MBR успешно загружена и выполнена. Например,мы даемax
зарегистрироватьсясерединапомещатьодининдивидуальныйчислоценить6
。оax
зарегистрироватьсяда Чтоназадлапша章节встреча讲,В любом случае, сейчас вам просто нужно знать, что это регистр 8086.
Так,Пучок6
писатьax
зарегистрироватьсяиз Заказда Что?этотиндивидуальный МожеткпроходитьпроверятьIntelруководство знает,Должно быть:
B8 06 00
B8
даинструкциякод,выражатьax
зарегистрироватьсясередина Депозитданные。назадлапшаиз06 00
да Количество операций,потому чтоax
даодининдивидуальныйшестнадцать Кусочекзарегистрироваться,так Должен быть один для этого16Кусочекиз Количество операций。Чтодля Чтода06 00
и Нетда00 06
Шерстяная ткань?этотдапотому что,В системе 8086 используется прямой порядок байтов.,также Сразуда Низкийбайтпомещатьчислоиз Низкий Кусочек。носуществовать Книга Писатьданныеизчасждать,Мы привыкли писать от низкого к высокому,так Сразустановиться Понятно06 00
,Вы можете выглядеть немного неловко,новозвращатьсядануждаться大家适отвечатьодин раз~
Чтода Нетдатак СразуOKПонятно?并Нетда!ХотяBIOSбудет загружен автоматическиданные,но,В BIOS есть соглашение,Он обнаружит этоданныеизбольшинствоназаддваиндивидуальныйбайтданетда55 AA
,Только тогда вы сможете считать это законным MBR.,будет загружен. Что касается того, почему используются эти два магических числа... эммм... думаю, никто не знает~
потому чтоBIOSбудет только загружаться512 байта(также Сразудадля Что касается дискетыиз Нет.одининдивидуальныйсектор),Также имеется обнаружение флагов для последних двух байтов.,так,MBR должен быть не больше и не меньше ровно 512 байт.,И оно должно находиться в первом секторе дискеты.,так можно загрузить корректно. так,Дополняем его до 512 байт,и Пучокназаддваиндивидуальныйбайтустановлен на55 AA
,Как показано ниже:
MBR
Сохраните его как .img и можете использовать!
Затем Давайте выполним еще разbochs -qf bochsrc
,(WindowsМожетк Первый Открытьbochsdbg.exe
,ЗатемвыбиратьLoad
Кнопка для загрузкиbochsrc
),Уведомление,сейчассуществоватьвозвращаться Нет能无脑в соответствии сc
,Потому что в нашем MBR только одна инструкция,Иди во тьму Вниз Выполнять ХОРОШОизразговариватьвстреча观察Нетприезжать。так,Нам нужно сделать точку останова,позволятьbochs
Выполнять ХОРОШОприезжатьэтотиндивидуальный Кусочекнаборизчасждать停один раз。
Так另одининдивидуальныйвопрос Приходить Понятно,Где должна быть точка останова? это зависит,BIOSвстреча ПучокMBRзагрузить в Памятьиз哪одининдивидуальный Кусочекнабор。этотвнутрииз Соглашениеда0x7c00
из Кусочекнабор(такой же,А почему используется этот адрес, наверное, никто не знает~ В любом случае, это всего лишь соглашение),Такя们Сразухотетьсуществовать0x7c00
из Кусочекнаборточка разрыва,так Выполнять ХОРОШОВнизлапшаизотлаживатьинструкция:
pb 0x7c00
Затем Нажмите еще разc
,так Выполнять ХОРОШОприезжатьэтотодин Кусочекнаборизчасждать Сразувстреча停Вниз Приходить:
точка разрыва
При остановке страница отладки будет отображать что-то вроде этого:
отлаживать
Уведомлениеитоговый результат,В квадратных скобках указан адрес Память, который должен быть выполнен первым.,также Сразуда0x7c00
,Докажите, что это местоположение точки останова правильное,прежде чем продолжить,Давайте сначала посмотрим на нынешнююax
зарегистрироватьсяиз Состояние,входитьr
инструкция,Входить Можетксмотретьприезжать Проходитьиспользоватьзарегистрироватьсяизсостояние:
Статус регистрации
Здесь нужно кое-что объяснить,потому чтоbochs
даAMD64Архитектураизэмулятор,такэтотвнутрииззарегистрироваться Вседав соответствии с64Кусочекпоказывать示из,Их расширение будет представлено в последующих главах.,На данный момент нам просто нужно знать,Хочу увидетьax
зарегистрироватьсяизценить,на самом деле Сразудасмотретьrax
избольшинствоназад16Кусочек(также Сразудабольшинствоназад4Кусочекшестнадцать进制Кусочек),Как показано в красной рамке на рисунке выше.,Сразудаax
изценить,сейчассуществоватьдаaa55
。
Затем,Давайте просто выполним следующую строку инструкции,s
Заказда单полоска Выполнять ХОРОШО,Только одно предложение будет исполнено внизинструкция。такя们входитьs
,Входить,Сновавходитьr
Приходить打印один раззарегистрироватьсяиз Состояние:
выполнить один шаг
OK,ax
зарегистрироватьсянастоящийизодеялоизменять Писатьстановиться0006
Понятно,Это значит, что наша инструкция удалась!
Не знаю, есть ли такие читатели, как я.,Это первый раз, когда я играю в бега на голом металлическом устройстве, и я буду очень рад в будущем.,Это как открыть дверь в новый мир,恨Нетпридетсясейчассуществовать Сразуначинать Писатьодин片江山начальство去!но Не волнуйся пока!потому чтоэтотдобрыйиспользоватьдвоичная машинакодпрямойпрограммированиеизтрудностьтакже Слишком большой Понятно。япридется去помнить Место有изинструкциякодиинструкция Формат,Если одно число неверно, все будет неправильно.,Кроме того, его читаемость также очень плохая.!Кто может сказать с первого взглядаB80600
да Что鬼?
конечно Понятно,Если мы вернемся в эпоху 8086 года,Возможно, участник программы действительно сделал это,носейчассуществовать,У нас есть более удобные инструменты,Этот старинный метод программирования,Это нормально, когда есть небольшой опыт. Вернуться к инструкции выше,теперь этоB80600
да「Даватьax
зарегистрироватьсяписать0006
Этот номер」иззначение,Так,Есть ли переводчик,Дай мне это выражение,Преобразовать в машинную инструкцию?
Конечно! Это ассемблер, который преобразует язык ассемблера в машинный код. Например:
mov ax, 0x06
показывать Даватьax
зарегистрироватьсясерединавходящий0x06
Это шестнадцатеричное число,Затем Пусть ассемблер преобразует его вB80600
。такизязык Сразуназываетсяязык ассемблера,Язык ассемблера кажется гораздо более дружелюбным, чем машинный код, не так ли?
Однако, помимо трансляции инструкций, зрелый ассемблер может иметь и несколько более удобных функций, которые аналогичны предварительной обработке компилятором и выполняют некоторые статические числовые преобразования и другую работу. Однако языки ассемблера, поддерживаемые разными ассемблерами, также различаются. Будут небольшие различия. В отрасли обычно используются два: nasm и gas.
Gas — это ассемблер GNU (язык ассемблера). Он широко используется, поскольку gcc может компилировать код C только в формат gas. В следующих примерах этой статьи также будет использоваться компилятор gcc, а скомпилированный код находится в формате gas.
nasm — относительно широко известный ассемблер, его полное название — Netwide Assembler. Его преимущество в том, что его синтаксис прост и удобен в использовании. В примерах этой статьи nasm будет использоваться для частей языка ассемблера, требующих прямой ручной разработки.
Далее давайте познакомимся с тем, как установить nasm.
первый,Авторизоватьсяофициальный сайт НАСМ,Нажмите на последнюю стабильную версию (когда читатели увидят ее, возможно, это уже версия выше, чем на скриншоте),Но это не имеет значения,Просто выберите последнюю стабильную версию).
официальный сайт НАСМ
Следующий,Выберите соответствующую папку в соответствии с используемой вами ОС.,Если вы используете macOS,Сразувыбиратьmacosx
,Если вы используете Windows,Сразувыбиратьwin64
。Уведомление,Здесь различают только операционную систему,Не различает фактическую аппаратную архитектуру.,Даже если вы используете Mac с собственным чипом Apple,Или Windows с чипом Snapdragon,То же самое касается и программного обеспечения.
Загрузите nasm, соответствующий версии ОС.
Далее шаги для Windows и macOS будут разными, и я представлю их отдельно.
Так как установочный пакет предоставляется в версии для Windows,поэтому,метод сравненияизупражнятьсяда Внизнагрузкаэтотиндивидуальныйinstaller
,Затем установите его на свой компьютер с помощью прилагаемой программы установки. конечно,Если вы знакомы с настройкой среды,ХОРОШОпрямой Внизнагрузка Внизлапшаизzip
,Разархивироватьназадпридетсяприезжатьизпрямойдаnasm
программасам。
Выберите установщик
Если вы выберете версию установщика, просто запустите установщик напрямую, и все параметры установки будут установлены по умолчанию.
установщик nasm
Но вот оно Уведомлениеодин раз Путь установки,по умолчанию СостояниедаC:\Program Files\NASM
,Путь Windows по умолчанию с пробелами действительно является исторически раскритикованной проблемой.,Но дляnasm
Это мало влияет,Установка по пути по умолчанию также в порядке.,Но мы должны помнить этот путь,Гарантированно найдем. Если вы не используете установщик,идапрямой Внизнагрузкаизzip
Затем Разархивироватьизразговаривать,Пожалуйста, также поместите всю папку по соответствующему пути.,Убедитесь, что вы найдете его сами.
Путь установки
После завершения установки,nasm
Сразу Уже лежасуществовать Прямо сейчасиз Путь установка не работает. Однако каждый раз указывать абсолютный путь для запуска действительно затруднительно, а мигрировать проект нам не удобно. Поэтому приходится настраивать его на переменные. средывнутри。в соответствии сWin+RКомбинация клавиш,Выскакивает окно "Запустить",входитьsysdm.cpl
,Входить,Откроется настройка Свойства системы.
бегать
В настройках «Свойства системы» выберите вкладку «Дополнительно», а затем нажмите кнопку «Переменные среды» ниже.
Свойства системы
затем,существоватьпеременные средысерединапопытаться найтиприезжатьиспользовать户переменнаявнутриизPath
,Эта переменная определяет,Если вы не укажете абсолютный путь,Но при непосредственном вводе команды,По каким путям пойдет система, чтобы найти программу. Мы надеемся, что эффект,когда мы хотимбегатьnasm
изчасждать,прямойтерять「nasm
」Сразухороший Понятно,и Нетда Каждый Второсортный Всехотетьтерять「C:\Program Files\NASM\nasm
」,поэтому,Необходимо настроить этот путь на переменные среды.
выбиратьPath
нажмите после「редактировать」,илипрямойдвойной щелчокPath
ХОРОШО,Вы можете редактировать переменные среды.
переменные среды
Нажмите «Создать» в окне «Редактировать переменные среды».,Затем Пучокnams
из Путь установкинапишите в。Уведомление,Чтобы написать полный путь,и просто напишиNASM
этотпуть к слою Сразухороший Понятно,Убедитесь, что этот путь содержитnasm.exe
Это исполняемый файлпрограмма。
редактироватьпеременные среды
переменные среды设наборхорошийпосле,я们Сразу Можеткпытатьсябегатьодин разnasm
Понятно。в соответствии сWin+RОткрыть「бегать」,входитьcmd
,Входить,Это вызовет консоль.
бегать
существоватьконсольсерединавходитьnasm -v
,если возможносмотретьприезжатьраспечататьизnasm
Информация о номере версии,Это значит, что мы завершили установку и настройку!
бегатьnasm
потому чтоmacOSВерсияизnasm
Нет установочного пакета,так Мы можем только скачать исходникпрограммаиз Сжатый пакет。
скачатьнасм
После распаковки это уже исполняемый файл. Однако в обычных условиях браузер по умолчанию загрузит файл по пути «Загрузить». Естественно, сюда не подходит часто используемая программа, поэтому загрузите ее вручную. . Переместитесь в подходящее положение.
Здесь я выбираю корневой путь пользователя.,также Сразуда~/
。По умолчанию папка имеет номер версии.,ты можешь изменить свое имя,Вы также можете игнорировать это,Толькохотеть确保внутрилапша有nasm
Это исполняемый файлпрограмма Сразухороший Понятно。яэтотвнутриизпутьда~/nasm-2.16.01
。
Так же,для Понятнопозволятья们делатьиспользоватьчас Можетк Тольковходитьnasm
,и Нетда~/nasm-2.16.01/nasm
,Нам также необходимо поместить этот путь в переменные среды.
Самый ранний bash, используемый по умолчанию в macOS.,Позже изменен на zsh,Потому что прошло много времени с тех пор, как я переключился,так Представление автораzshиз Состояние,Если вы используете другую версию оболочки,Сразупожалуйста自ХОРОШОрешатьпеременные Проблема конфигурации среды.
Выполните следующую команду, чтобы отредактировать файл конфигурации zsh:
vim ~/.zprofile
Уведомление,Даже если у вас в настоящее время нет.zprofile
Этот файл тоже не имеет значения,Приведенная выше команда будет выполнена как новый файл.
Затем нажмите клавишу «i» в интерфейсе редактирования, чтобы войти в режим редактирования. В это время в левом нижнем углу отобразится «ВСТАВКА», указывающая, что вы находитесь в режиме редактирования. Если в нем уже есть какая-то конфигурация, просто игнорируем ее. Добавляем: в конце файла:
PATH=$PATH:/Users/xxx/nasm-2.16.01
Уведомление,потому чтоядапомещатьсуществовать~/
внутрииз,ноэтотвнутри Чтобы написать полный путь,тактебе нужно Хочу увидетьодин раз全путьда Что,Использование волнистых линий иногда может оказаться неудачным.
Это предложение означает,существоватьPATH
за этой переменной,плюс одинnasm
изпуть,такэтотвнутрихотетьнаполнять Писатьтыизnasm
Местосуществоватьпуть。
потому что.zprofile
встречасуществовать Каждый Второсортныйбегать Терминализчасждать自动Выполнять ХОРОШО,поэтомуя们Пучок Заказ Писатьсуществоватьэтотиндивидуальныйдокументвнутри Сразу Нетиспользовать Каждый Второсортный Руководство Конфигурация Понятно,Но поскольку это еще не эффективно,так Вам все еще нужно выполнить одно предложение:
source ~/.zprofile
Или просто закройте терминал и откройте его снова, и все вступит в силу.
Затем вводим в консоль
nasm -v
Если вы видите информацию о версии,Такиллюстрироватьnasm
Установлено и настроено успешно。
НАСМ-версия
В предыдущей главе мы успешно установили проект по стандарту 8086.,такой жечастакжепредставлять Понятноnasmязык ассемблера。Так Следующийэта глава,Давайте разберемся, как записать первый шаг после самотестирования биоса — MBR.
Теперь, когда мы решили использовать програмку на 8086,Такприрода,Теперь от знания о 8086 никуда не деться. Некоторые подробности о процессоре.
ценность Уведомлениеизда,8086Там не только 14 регистров,Просто с этими 14 регистрами напрямую занимается программа. Естественно, внутри ЦП есть некоторые функции, которые используются в самой системе.,Внешне непрозрачные регистры,Но нам это знать не обязательно (на самом деле многие более подробные тоже являются коммерческой тайной Intel),Мы тоже не знаем).
Сначала я перечислю названия 14 регистров, на которые хочу обратить внимание, а затем поясню их:
Необходимо подчеркнуть один момент,Помимо IP и FLAG,Исходное значение, описанное названием регистра выше,Именно то, что этот регистр используется «обычно» или «по умолчанию».,Это не значит, что этот регистр можно использовать только в этой ситуации.。зарегистрироватьсяда Очень ценноизресурс,поэтому Практическая работаизделатьиспользоватьиспользовать Закондагибкиймного Образециз,так笔者并Нет想拿этотнекоторыйзарегистрироватьсяимясамиззначение去大Книга特Книга。На самом деле каждый должен знать,Мы хотим сосредоточиться на этих 14 регистрах.,Просто запомните их символы (потому что они используются на языке ассемблера),В некоторых сценариях, где необходимо указать регистры,Было бы лучше, если бы мы могли просто помнить это в одиночестве.
Кроме того, все вышеуказанные регистры имеют 16 бит, а это означает, что данные, обрабатываемые процессором 8086 в каждом такте, составляют 16 бит. В процессоре 8086 базовая единица обработки и передачи данных составляет 16 бит, которые мы также называем «The». длина слова 8086 составляет 16 бит», также известный как «8086 — это 16-битный процессор».
Ранее мы говорили, что 8086 — это 16-битный процессор. Это относится только к его разрядности, но не соответствует его максимальному адресному пространству. Максимальное адресное пространство ЦП зависит не от длины его слова, а от количества внешних адресных шин.
Если вы играли с цифровыми логическими устройствами, вы должны знать, что существует устройство, называемое «декодер». Например, на рисунке ниже показан 74138, декодер с тремя на восемь строк:
74138
Его входные клеммы (A~0~, A~1~, A~2~) представляют собой адресную шину. Мы можем представить, что эти три линии подключены к процессору. Задний выходной разъем (Y~0~~Y~7~) — это линия данных. Мы можем представить, что эти 8 линий подключены к блоку хранения данных.
когдаA~0~A~1~A~2~входитьдля010
час,Указывает на необходимость управления адресом №2.,ТакY~2~ выведет 1. Та же причина,когдаA~0~A~1~A~2~входитьдля101
час,Указывает на необходимость управления адресом №52.,ТакY~5~выведет1。И так далее
В описанной выше структуре,Мы думаем, что у ЦП 3 адресные шины.,Такобращениекосмос Сразуда2^3^=8,Адрес от000
приезжать111
。
В компьютерных системах единицы хранения обычно адресуются не в двоичных битах (битах), а в байтах (байтах). То есть каждые 8 бит представляют собой группу и программируется адрес. Тогда процессор с адресной шиной 3 может получить доступ к 8 байтам памяти.
И для 8086,он содержит20корневая адресная шина(Заметьте, это не 16!),Так,Адресное пространство 8086:
так,8086 поддерживает до 1 МБ пространства Памяти.,Адрес от20индивидуальный0
приезжать20индивидуальный1
,Однако использование двоичного представления было бы более многословным.,Так Мы обычно используем шестнадцатеричный формат адреса Память.,также Сразуда0x00000
приезжать0xfffff
。
Как мы упоминали ранее, такие компоненты, как BIOS, не принадлежат памяти, а используют унифицированную адресацию. Таким образом, данные в BIOS все равно будут включены в этот 1 МБ, поэтому фактическая доступная физическая память составляет менее 1 МБ, но об этом не известно. ЦП будет управлять внешним оборудованием таким же образом через адресную шину, будь то память или BIOS. Именно из-за этого метода адресации ЦП не различает реальное оборудование. Поэтому для оборудования с единой адресацией мы все еще называем его «адресом памяти», хотя это вовсе не память.
Тогда возникает еще одна очень серьезная проблема. 8086 — это 16-битный процессор, его регистры тоже 16-битные, но у него 20 адресных шин. Как же нам представить адрес памяти? Метод, принятый в 8086, заключается в использовании двух 16-битных регистров для формирования 20-битного адреса памяти. Принципиальная схема выглядит следующим образом:
Сращивание адресов 8086
Другими словами, один из регистров используется как «сегментный регистр», а его адресные строки 0–15 подключены к битам 4–19 полного сумматора в качестве первого слагаемого. Затем используйте другой регистр в качестве «регистра адреса», и его адресные строки 0–15 соединяются с битами 0–15 полного сумматора в качестве еще одного слагаемого.
Сумма выше служит выходным адресом. (Конечно, реальные внутренние логические устройства 8086 гораздо сложнее. Автор просто дает подсказку)
Тогда выражается формулой:
в
Представляет значение в регистре сегмента,
Представляет значение в адресном регистре. Сдвиг на 4 бита влево относится к двоичным битам, и эффект эквивалентен десятичному.
, что эквивалентно дополнению конца 0 в шестнадцатеричном формате.
Приведу простой пример: если
да0xf055
,
да0xa003
Такадрес怎么Приходить算Шерстяная ткань?первый Давать
Добавьте 0 в конце (потому что он шестнадцатеричный), а затем следуйте
Просто сложите,также Сразуда0xf0550 + 0xa003
,равный0xfa553
。
В 8086 сегментные регистры — cs, ds, es и ss, а адресные — bx, di, si, bp и sp. Если хотите спросить, почему не другие регистры? Это легко объяснить, поскольку только эти регистры имеют схемы, подключенные к полному сумматору перед декодером. Другие регистры не имеют этой схемы, поэтому, естественно, их нельзя использовать непосредственно для этой цели.
Поскольку двадцатибитный адрес Память требует двух шестнадцатибитных операндов для представления,на ассемблере,будут разделены двоеточиями,также Сразудаs:d
из Способ。Например0xf055:0xa003
выражать Понятно0xfa553
этотиндивидуальныйадрес。конечно,мы также нашли,Таким образом,Представление адреса не уникально,Например0xfa00:0x0553
такжетакой жевыражать0xfa553
этотиндивидуальныйадрес。такпотому чтоэтотиндивидуальныйхарактеристикатакжевстреча导致одиннекоторый有趣извопрос,Мы объясним подробно в следующих главах.
Мы уже сталкивались с запуском 8086 раньше.,Но в то время автор хотел дать каждому быстрое перцептивное понимание.,Я не представил слишком много контента. Прежде чем продолжить Написать MBR,Нам еще предстоит детально разобраться в процессе запуска 8086.
После включения ЦП механически он будет делать только одно: читать инструкцию и выполнять ее каждый такт, а затем читать следующую инструкцию и выполнять ее... и так далее.
Итак, откуда следует читать инструкцию? Это определяется регистром IP. Куда бы ни указывал регистр IP, ЦП будет читать инструкцию. После завершения инструкции IP автоматически увеличит значение длины инструкции, чтобы ЦП мог выполнить следующую инструкцию.
потому что8086набор командпринадлежатьCISCнабор команд(Complex Instruction Set Компьютер) длина его инструкции различна, поэтому после выполнения каждой инструкции номер смещения IP также отличается в зависимости от длины только что выполненной инструкции. Но нам не нужно слишком беспокоиться: ЦП сам справится с длиной инструкции.
Здесь есть еще одна проблема: IP также является 16-битным регистром. Он не может полностью представлять адрес памяти сам по себе. Для его объединения также требуется регистр стека. Тогда этот регистр стека будет CS.
другими словами,CPUвсегда будет выполнятьсяCS:IP
визинструкция,Просто установите эти два регистра,ЦП может нормально выполнять инструкцию.
Когда 8086 включен,CSзарегистрироватьсяодеялоинициализациядля0xf000
,иIPзарегистрироватьсяодеялоинициализациядля0xfff0
,такприрода,CPUВыполнять ХОРОШОиз Нет.одинполоска Выполнять ХОРОШОсуществоватьxffff0
этотиндивидуальный Кусочекнабор。для Понятно Обеспечьте самотестирование машины после включения питания,И вопросы загрузки MBR могут быть выполнены без проблем.,Такэтотиндивидуальный КусочекнаборужевстречаодеялокартографированиеприезжатьBIOSкогдасередина,Это гарантирует, что после включения машины,Содержимое BIOS может выполняться естественным образом.
в 8086 году,BIOSвстречаодеялокартографированиеприезжать0xf0000
приезжать0xfffff
из Кусочекнабор,Этот адрес размером 64 КБ контролируется BIOS.
Мы не знаем точно, какая инструкция будет выполняться внутри биоса (хотя мы действительно можем это увидеть через bochs,Но используемый им BIOS — это всего лишь версия прошивки с открытым исходным кодом.,Содержимое BIOS на реальных машинах не является открытым исходным кодом.,У нас нет возможности узнать),Но биос обязательно сделает какие-то согласованные вещи,Это позволит нормально загрузить ядро ОС на следующем этапе. Например,BIOS проверит, в порядке ли внешняя память и устройства ввода-вывода.,И если MBR (то есть внешняя память) найдена,данные для первого сектора,к0xaa55
окончаниеиз),Содержимое этого сектора (512 байт) будет,загрузить в0x7c00
из Кусочекнабор,Затем ПучокCS:IP
установлен на0x0000:0x7c00
,Гарантия следующегоинструкция Сразуда0x7c00
визинструкция。
Напомним, что в предыдущей главе,мы даемдискетаиз Нет.одининдивидуальныйсекториз Нет.один ХОРОШОПисать ПонятноодининдивидуальныйB80600
,Затемсуществовать0x7c00
Выходи и сражайся Понятноточка останова,Сразу Можетксмотретьприезжатьaxзарегистрироваться确实становиться Понятно6
,это потому что,данные этого сектора,одеялоBIOSзагрузить в Понятно0x7c00
изместо,Затем ПучокCS:IP
установлен на0x0000:0x7c00
,так,B80600
Сразустановиться ПонятноBIOSпосле Выполнять ХОРОШОиз Первая статьяинструкция Понятно。
Благодаря этим теоретическим основам,Можем продолжить Написать MBR. Я верю в то, что каждый хочет сделать в первую очередь,Он должен просто вывести что-то на экран! Далее будем следовать международной практике,существовать Экранначальствотерять出Hello World!
。
существоватьуже Установитьхорошийnasm
извпереднести Вниз,Создаем новый файл в пути к проекту,называетсяmbr.nas
,Затемвходить Внизлапшасодержание:
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'H'
hlt
times 510-($-$$) db 0
dw 0xaa55
Код мы объясним позже, а сейчас посмотрим эффект.
первый,Чтобы преобразовать ассемблерный код в машинный код,Введите ниже стандарт,проходитьnasm
собрать:
nasm mbr.nas -o mbr.bin
придетсяприезжатьmbr.bin
документ,Затем Переименуйте его вa.img
(Можеткпрямойиспользовать图形界лапшадействовать,ХОРОШОВыполнять ХОРОШОЗаказcp mbr.bin a.img
),перезапускbochs
。(Уведомление,Здесь повторно используется путь проекта из предыдущей главы.,поэтому Нужен фронтbochrc
из Конфигурационный файл,Подробности можно найти в предыдущих главах)
bochs -qf bochsrc
Затемв соответствии сc
Заказ,Вы можете увидеть результаты вывода. Если ты похож на меня в начале,смотреть ВнизлапшаизBooting from Floppy...
Нет ответа,Тогда если вы считаете, что программа не эффективна,Тогда перейдите в начало и прочтите:
выход Боха
Как видите, изначально это должно было быть «Bochs», но мы изменили первую букву на «H», поэтому вывод удался. Это происходит главным образом потому, что BIOS что-то выводит на экран, а затем не очищает экран, в результате чего наш собственный вывод «погружается» в него. Однако очистка экрана требует дополнительных объяснений других вещей. Чтобы двигаться дальше шаг за шагом, мы можем пока смириться с этим и знать, что нам нужно найти результат в этих беспорядочных сообщениях.
Далее мы сосредоточимся на этих строках ассемблерных операторов и объясним, что мы сделали.
mov ax, 0xb800
Это предложение,да Даватьax
зарегистрироватьсясередина赋ценить0xb800
,mov
инструкцияна самом деле更准确отвечать该да「copy」,Он присваивает операнд справа операнду слева.,Следующие операнды не исчезнут после перемещения. Последнее предложение
mov ds, ax
нода Пучокax
изценить赋ценить Даватьds
зарегистрироваться,такds
зарегистрироватьсясерединатакжеда0xb800
Понятно。
Думаю, здесь у читателей возникнут сомнения.,для Чтоя Нет能прямойmov ds, 0xb800
Шерстяная ткань?Зачем беспокоитьсяax
так Посторонние ветки?этот Сразудая们编Писатьязык ассемблераизчасждатьдолженучитыватьизвопрос。язык ассемблератолькода Пучокдвоичныйизмашинакод,Просто это отображается способом, более близким к человеческому языку.,Но суть его не изменилась,汇编器встреча Пучокэто转换становиться对отвечатьизмашинакод。так,Для каждой компиляции мы пишем стандарты,Должны быть соответствующие машины стандарта,То есть то, что машина может поддерживать. Регистр сегмента в 8086 не может быть назначен напрямую через непосредственные данные.,потому что8086Системы вообще неттакизмашинаинструкция。
так,При написании языка ассемблера,Мы должны думать с точки зрения аппаратного обеспечения процессора.,Написание самой «инструкции»,а не абстрактная семантика высокого уровня. Используя предыдущий пример,мы хотим достичь「Пучок0xb800
Этот номер赋ценить Даватьds
зарегистрироваться」изэтотиндивидуальныйнуждаться,Чтобы использовать「mov ax, 0xb800
иmov ds, ax
」Эти двоеинструкциязавершить。конечно,Вы меняете его наbx
、cx
илиdx
Делатьсерединаколичество временитакжедаOKиз,Потому что этим регистрам можно присваивать значения через непосредственные значения.
Смысл этих двух строк кода уже ясен,Давайте объясним цель. В предыдущей главе автор ввел понятие «видеопамять».,видеокарта будет следить за каждым циклом обновления,Прочитать определенный фрагмент Память пространства,Затем проанализируйте его по определенным правилам,и выводим на дисплей,Это пространство Памяти и есть «видеопамять».
Когда машина 8086 инициализируется,По умолчанию будет использоваться стандартный протокол VGA.,ида80×25×16изтекстовый режим。То есть,В этом режиме,Монитор может отображать 25 строк.,80 символов в строке (символы ASCII),и支持большинствомного16цвет。В этом режиме,对отвечатьизпоказывать存да0xb8000
~0xb8f9f
,Всего 4000 байт местоположения. Каждые два байта соответствуют биту отображения символов.,Младший байт представляет код ASCII.,Старший байт представляет информацию о цвете.
поэтому,0xb8000
этотиндивидуальный Памятьадрес,Соответствующим является код ASCII, соответствующий первому символу первой строки на экране.,0xb8001
对отвечатьиздаэтоизинформация о цвете。Та же причина,0xb8002
В соответствии содин ХОРОШОНет.дваиндивидуальныйхарактеризASCII,0xb8003
对отвечатьэтоизцвет……0xb80a0
В соответствии сдва ХОРОШОНет.одининдивидуальныйхарактеризASCII,0xb80a1
对отвечатьэтоизцвет……0xb8f9e
В соответствии с25ХОРОШО(большинствоназадодин ХОРОШО)Нет.80индивидуальныйхарактер(большинствоназадодининдивидуальныйхарактер)изASCII,0xb8f9f
对отвечатьэтоизцвет。проходить Даватьпоказывать存китайское письмовходитьданные,Вы можете управлять персонажами на экране.
Итак, как же выглядит информация о цвете? Среди байтов информации о цвете биты 0–2 указывают цвет текста RGB, бит 3 указывает, следует ли подсвечивать или нет, биты 4–6 указывают цвет фона RGB, а бит 7 указывает, следует ли мигать. Мы можем суммировать цвета в следующей таблице:
С битом I цвет переднего плана может иметь 16 цветов, а именно:
Цвет фона не имеет подсветки, поэтому поддерживаются только 8 типов:
Наконец, он соответствует биту K, чтобы указать, следует ли мигать.
Вот предложение цвета, который вы хотите увидеть.,Вы можете сделать несколько попыток,Вы также можете написать код в зависимости от местоположения,Например,я想существовать Экран Нет.один排Нет.одининдивидуальный、второй ряд второй、Нет.три ряда Нет.трииндивидуальныйсоответственнопоказывать示ABC
,Затем просто добавьте немного цветов и посмотрите эффект.,Это можно записать как:
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'A'
mov [0x0001], byte 0xF0
mov [0x00A2], byte 'B'
mov [0x00A3], byte 0x46
mov [0x0144], byte 'C'
mov [0x0145], byte 0x32
hlt
times 510-($-$$) db 0
dw 0xaa55
Эффект следующий (обратите внимание, что A мигает, но на скриншоте этого не видно):
цвет текста
Продолжим объяснение кода,Квадратные скобки означают взятие адреса Память.,такэтотвнутрииз[0x0000]
выражать Выбиратьадресда0x0000
из Памятьадрес,существоватьmov
инструкция Вниз,Чтобы выразить Память, напишите данные. мы знаем,Полный адрес Память должен состоять из двух частей.,Для немедленного обращения,,по умолчанию段зарегистрироватьсядаds
,То есть,[0x0000]
Фактически эквивалентно[ds:0x0000]
,этот Сразуда Прямо сейчася们Изтак Чтобы настроить сначалаds
изпричина。потому чтоds
ужеодеялоустановлен на0xb800
,поэтому[0x0000]
Сразуда[0xb800:0x0000]
,природатакже Сразувыражать Понятно0xb8000
изадрес,Это первый байт видеопамяти.
Чтодля Чтохотеть Писать Чтоиндивидуальныйbyte
Шерстяная ткань?когдая们действоватьзарегистрироватьсяизчасждать,Операнды будут идентифицированы в соответствии с размером регистра.,Напримерmov ax, 0x5
,потому чтоax
да16Кусочекиз,поэтому,назадлапшаиз0x5
будет автоматически завершено как0x0005
。но,Когда мы работаем Память,Сразунуждаться Руководство指定Количество операцийиздлина Понятно。Дескриптор длиныbyte
、word
、dword
иqword
,соответственновыражать1байт、2 байта、4байти8байт。Уведомление,Если вы используетеword
иликначальствоизформа,Будет обрабатываться в прямом порядке,Напримерmov [0], word 0xabcd
новстречасуществоватьds:0
из Кусочекнаборписать0xcd
,Затемсуществоватьds:1
из Кусочекнаборписать0xab
。Сновамного Привет嗦один句,если не напиши0x
префикс илиh
назадукрашенныйизразговаривать,Будет интерпретироваться в соответствии с десятичным классом.
Подводя итог, первые три строки кода:
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'H'
означает,Отображение буквы «H» в левом верхнем углу экрана.,Потому что биос уже записал часть данных видеопамяти,такэтоизцветвстреча保持постоянный,конечно,я们Можеткпроходитьдобрый似Вmov [0x0001], byte 0x0f
иззаявление Пучокэтоизцветстановиться白色。
Вы можете попробовать этот метод для вывода различного контента на экран.
За этим стоит предложение
hlt
Это инструкция зависания, которая позволяет ЦП временно прекратить выполнение до тех пор, пока он не отреагирует на прерывание (прерывания будут представлены в последующих главах). Цель написания этой строки здесь - каждый раз давать бочсточку. разрыванемного хлопотно,иделатьиспользоватьhlt
инструкция Сразу МожеткпозволятьCPUНаведите курсор сюда,Нам удобно наблюдать за выводом,так Сразу Нетиспользоватьточка разрыва Понятно。
большинствоназадодин ХОРОШОизdw 0xaa55
,этотвнутриизdw
дафальшивыйинструкция,То есть,Это не переводится как машинная инструкция.,Он используется для указания компилятору выполнить предварительную обработку.,чем-то похож наC/C++серединак#
началоиззаявление。dw
изиметь в виду Сразудав соответствии с字лапша Писать2индивидуальныйбайт,Содержимое - следующий номер,также Сразуда0xaa55
。Мы говорили раньше,BIOSТолько有существовать Обнаружение Нет.одининдивидуальныйсекторизназаддваиндивидуальныйбайтда0x55
и0xaa
изчасждать,Только тогда он считается легальным MBR.,и загрузить. так,Эта строка утверждения делает именно это.,Мы видим это в двоичном файле после сборки.,Последние 2 символа были записаны успешно:
mbr.bin
dw
выражать Писать2индивидуальныйбайт,对отвечатьизвозвращаться有db
Писать1индивидуальныйбайт,dd
Писать4индивидуальныйбайт,dw
Писать8индивидуальныйбайт,Уведомление,Вседас прямым порядком байтов。такначальстволапшаизфальшивыйинструкцияна самом делевозвращаться Можеткизменятьстановитьсяdb 0x55 0xaa
,Эффект тот же.
Последний вопрос,0xaa55
даэтот512 байтаизбольшинствоназаддваиндивидуальныйбайт,Но мы просто не написали несколько предложений инструкции,Как отрегулировать среднюю часть? Могу добавить 0,Но сколько нулей нужно добавить? В основном это зависит от,Прямо сейчася们Писатьиз Место有инструкциязанимать Понятномногонемногобайт。Уведомление,Номера строк на языке ассемблера не имеют значения на уровне выполнения.,Потому что для команды CISCнабора,Длина каждой инструкции может варьироваться.,так ХОРОШОСчитай синструкцияизбайт Считай нетпрямойсвязь。
Символ амперсанда — это номер смещения стандарта.,Представляет номер смещения текущей позиции.,выражатьголова ХОРОШОиз Номер смещения。Уведомление,Изтакголова ХОРОШОтакжевстреча有Номер смещения,Это ситуация,То есть первая инструкция текущего файла не обязательно загружается в расположение Память0.,Хотя в этом коде это 0,Но мы по-прежнему используем-Приходить计算один разкомпенсировать,вместо того, чтобы использовать его напрямую
Поэтому смысл этой строки очень ясен, раз 510-(-
Поскольку данная серия статей не является профессиональным руководством по сборке 8086. ,поэтому Нетвстреча过分纠结язык ассемблераизинструкцияипрограммирование技巧。норасстояниея们из Цель——бегатьодининдивидуальныйC++программавозвращаться有挺远израсстояние,Точно так же, как,BIOS отвечает только за загрузку 512-байтовой MBR.,Что делать с лишними деталями? Еще есть очень волнующий вопрос,Только как очистить экран?
конечно Понятно,Расположение видеопамяти уже понятно.,Сделайте их всеми пространствами,Естественно, это эквивалентно очистке экрана. Просто нам не нужно писать эту функцию самостоятельно.,использоватьмягкое прерывание способом можно решить.
решить эти проблемы,Сначала нам нужно понять мягкое прерывание.,до этого,Сначала вам нужно понять прерывания.
Проще говоря, Механизм прерываниярешатьиз СразудаCPUи外部设备速度严重Нет匹соответствоватьизвопрос。Например,Когда вы нажимаете кнопку на клавиатуре,Процессор должен ответить,но,Как процессор узнает, нажали ли вы клавиатуру или нет?
Один из способов — активно отслеживать. Если объяснить простым языком, процессор должен время от времени проверять, была ли нажата клавиатура. Если да, то он ответит. Если нет, он вернется и продолжит работу.
Но у этого метода активного мониторинга есть очень серьезная проблема — несоответствие ставок. Основная частота современных процессоров обычно составляет порядка 3 ГГц. Даже самый ранний 8086 имеет основную частоту 4,77 МГц. Затем подумайте о скорости, с которой вы печатаете на клавиатуре. Согласно официальным рекордам Гиннеса, скорость набора текста чемпиона мира составляет всего 807 символов в минуту, что соответствует примерно 13 Гц. Другими словами, когда вы нажимаете на клавиатуру, процессор выполняет более 500 000 раз работу. Из-за такого несоответствия скорости использование активного мониторинга является огромной тратой ресурсов.
поэтому,Люди придумали способ,Спроектировал контроллер прерываний.,Используется для мониторинга внешних событий (например, сигналов нажатия клавиатуры),Когда требуется реакция процессора,Затем контроллер прерываний «уведомляет» ЦП.,«Остановись на мгновение, что ты делаешь.,Есть с чем разобраться. «Этот механизм называется Механизм прерывания.
Для сигнала прерывания,ЦП должен выполнить соответствующую обработку,Такприрода Сразухотеть有одиннекоторыйиспользовать Ввпричинасерединаперерывизинструкция,Когда ЦП получает соответствующее прерывание,Просто выполните соответствующую инструкцию. Этот механизм немного похож на механизм сигнальных слотов в Qt.,также有点добрый似ВVueсерединаиз@click
Привязать триггерное событие。общий Из,Все они связывают событие (или сигнал) с функцией.,Когда получен сигнал о событии,Выполните соответствующую функцию.
Но поскольку процесс обработки прерывания эквивалентен функции,,этоприродаЕго также можно вызвать напрямую как обычную функцию.,этотдобрый Способ Сразуодеялосказатьдля「мягкое прерывание». Другими словами, мягкое Механизм прерывания на самом деле такой же, как и оригинальный Механизм. прерывания Это не имеет значения,Он просто использует номер прерывания,Просто выполните соответствующую функцию ответа на прерывание напрямую.
так,мягкое прерывание — это, по сути, вызов функции。
Внутри биоса,Будет реализован процесс сохранения некоторых ответов на прерывания согласно инструкции.,такя们Можеткпроходитьмягкое прерывание вызова метода для выполнения некоторых функций, предусмотренных BIOS. Функции, предоставляемые этим BIOS, также называются «прерываниями BIOS».
Прерывания BIOS могут выполнять множество функций. Подробную информацию можно найти только в руководстве по BIOS. Здесь я представляю только те, которые мы можем использовать. Для начала решим проблему с очисткой экрана.
Вызовы прерываний должны передаваться с фиксированными параметрами регистра.,мы говорили раньше,По умолчанию видеокарта использует текстовый режим.,Так Толькохотеть重新Снова进входитьодин Второсортныйтекстовый режим Сразу Можетк自动清屏Функция,нуждатьсяal
входящий0x03
,ah
входящий0x0
,Затемделатьиспользовать0x10
Прервите номер, чтобы очистить экран(еслида其他показывать示модель,переключится в текстовый режим).
и т. д.,al
иah
зарегистрироватьсяда哪冒出Приходитьиз?на самом деледатакиз,дляax
、bx
、cx
иdx
этот4индивидуальныйзарегистрироваться Давайте поговорим,Можетк拆становитьсявысокий8Кусочеки Низкий8Кусочекдваиндивидуальный8Кусочекзарегистрироваться Приходитьделатьиспользовать。al
Сразудаax
из Низкий8Кусочек,bh
Сразудаbx
извысокий8Кусочек,И так далее.
так,al=0x03
,ah=0x0
,Эффект такой же, какax=0x0003
даодин Образециз。
Давайте изменим код MBR,Сначала очистите экран,Затем Распечатать еще разHello,World!
Посмотрим эффект:
mov al, 0x03
mov ah, 0x00
; Также могу написать mov ax, 0x0003
int 0x10 ; Вызовите прерывание BIOS с номером 0x10, чтобы очистить экран.
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'H'
mov [0x0001], byte 0x0f ; Белый текст на черном фоне
mov [0x0002], byte 'e'
mov [0x0003], byte 0x0f
mov [0x0004], byte 'l'
mov [0x0005], byte 0x0f
mov [0x0006], byte 'l'
mov [0x0007], byte 0x0f
mov [0x0008], byte 'o'
mov [0x0009], byte 0x0f
mov [0x000a], byte ','
mov [0x000b], byte 0x0f
mov [0x000c], byte 'W'
mov [0x000d], byte 0x70 ; Черный текст на светло-сером фоне
mov [0x000e], byte 'o'
mov [0x000f], byte 0x70
mov [0x0010], byte 'r'
mov [0x0011], byte 0x70
mov [0x0012], byte 'd'
mov [0x0013], byte 0x70
mov [0x0014], byte '!'
mov [0x0015], byte 0x70
hlt
times 510-($-$$) db 0
dw 0xaa55
Эффект следующий:
Отображение после очистки экрана
Разве это не выглядит приятнее для глаз?
Мы представили его ранее,8086CPUобщийдасуществовать Выполнять ХОРОШОCS:IP
Место对отвечатьиз Память Кусочекнаборизинструкция,Обычно,Он будет выполняться один за другим по порядку. За исключением особого случая – Прыжокинструкция.
Так называемый «Прыжок».,Как следует из названия,Просто не продолжайте выполнять движение вниз,ида Прыжокприезжать某одининдивидуальный Кусочекнаборначинать Выполнять ХОРОШО。поэтому,Прыжокинструкция Сразудахотетьизменять变CS:IP
изориентированный。
Прыжокинструкция в основном делится на два типа.,Это «Близкий прыжок» и «прыжок в разрез». Однако я думаю,Эти два названия тоже не особенно подходят.,На самом деле они не имеют прямой связи с расстоянием.
так называемый「Близкий прыжок」,я们Можеткпричина解дляCS
постоянный,IP
Делатьодининдивидуальныйкомпенсировать,Его операнд — компенсировать,Например-3
Сразувыражать Квперед Прыжок3
байт、5
Сразувыражать Кназадкомпенсировать5
байт。
Однако на языке ассемблера нам нелегко вычислить смещение вручную, поэтому в этом случае нам нужно использовать мощную функцию предварительной обработки ассемблера — метку. Давайте посмотрим на пример:
L1:
mov ax, 1
jmp L2
mov bx, 2
L2:
mov cx, 8
визL1:
иL2:
Сразуда Этикетка,Это тоже псевдодокументация,Соответствующий машинный код не будет сгенерирован.,Вместо этого это влияет на предварительную обработку ассемблера. Вы можете выбрать любое имя тега, которое вам нравится.,Если это не конфликтует с ключевыми словами сборки.,Следующее двоеточие также можно опустить.
Близкая прыжокинструкция в приведенной выше программе такова:
jmp L2
Во время предварительной обработки,Ассемблер будетL2
Этикеткаприезжатькогдавперед Кусочекнабор(Прыжокинструкцияиз Кусочекнабор)ИзвпередизкомпенсироватьПриходить Давать Близкий прыжокинструкция Добавить операнды。кначальстволапша例程Давайте поговорим,действительныйиз Количество операций正хорошийдаmov bx, 2
этотполоскаинструкцияиздлина,это 3,Такjmp L2
Сразу Взаимнокогда Вjmp +3
。
Когда ЦП выполняет Близкий прыжокинструкциячас,воляIP
зарегистрироватьсяи Близкий прыжокинструкцияиз Количество операций Взаимно加,Затем выполните соответствующее положение инструкции,И тогда Прыжок добьется своей цели.
Так называемый «прыжок». в длину」,на самом деледа ДаватьCS
иIP
Все Даватьодининдивидуальный绝对ценить,Его операнд — абсолютный адрес Память.,Вместо того, чтобы компенсировать. Например:
jmp 0x0820:0x0000
После выполнения данной инструкции,CS
будет присвоено значение0x0820
,IP
будет присвоено значение0x0000
,затем Сразувстреча Выполнять ХОРОШО0x08200
Кусочекнаборизинструкция。
Что здесь необходимо подчеркнуть, так это,Язык ассемблера инструктирует машину,Он не имеет семантики высокого уровня.,поэтому,Ассемблер не будет проверять0x08200
этотиндивидуальныйадрессуществовать Нетсуществоватьтыкогдавпереддействоватьизисточникдокументвнутри,Меня не волнует, будет ли это место загружать юридические нормы.,Все это должно быть обязанностью самих членов.
конечно,Вы также можете использовать метки при использовании прыжок в длину.,Только Нет过этотчасиз Этикеткавстречаделатьиспользовать「Взаимнодлядокументголова」изкомпенсировать。Например:
mov ax, 0
mov bx, 1
L1:
mov cx, 2
jmp 0x0000:L1
В приведенной выше процедуреjmp 0x0000:L1
Сразудапрыжок в длинуинструкция,этотчасизL1
Сразувстреча解析дляэтотиндивидуальный Этикетка Взаимнодлядокументголоваизкомпенсировать,действительныйначальствотакже Сразудаmov ax, 0
иmov bx, 1
изинструкциядлинаи,также Сразуда6。Такэтотполоскаинструкцияна самом делеотвечать该даjmp 0x0000:0x0006
。
И здесь акцент сделан: Близкий прыжокинструкция Не менятьCS
,Количество операцийдакомпенсировать;прыжок в длинуинструкцияизменитсяCS
,Количество операцийдаабсолютное число。этотодин点существовать8086модель Вниз Может能смотретьначальство去没Такважный,Но когда мы переключимся в режим 286 позже,Это будет очень важно,так Читатели должныпомнить。
Пока что наши программы втиснули в первый сектор дискеты, надеясь, что биос загрузится автоматически. Но очевидно, что эти всего лишь 512 байт пространства легко растягиваются, так как же загрузить в память содержимое других секторов дискеты? В режиме 8086 прерывания BIOS могут сделать это за нас.
; Загрузите сектор по адресу 0x08000.
mov ax, 0x0800
mov es, ax
mov bx, 0 ; Содержимое дискеты будет загружено в папку es:bx.
mov ah, 2 ; ah=2, Используйте функцию чтения диска
mov al, 2 ; ah указывает, что необходимо прочитать несколько последовательных секторов (чтение 2 соответствует размеру 1 КБ)
mov ch, 0 ; ch представляет, какой цилиндр
mov dh, 0 ; dh указывает, какая магнитная головка
mov cl, 2 ; cl указывает, какой сектор
mov dl, 0 ; dl представляет букву диска, дискета будет иметь номер 0x00~0x7F, жесткий диск будет в 0x80~0xFF
int 0x13 ; Выполнить функцию №2 прерывания №0x13 (функция чтения диска)
Для старинной техники жесткий диск、Что касается дискеты,Все они представляют собой разновидность «диска». По механическому строению он делится на цилиндр, головку и сектор.,один般выражатьдляCHS
,柱лапшаи磁головаот0
начинать,сектор из1
начинатьотметка Число。
Если в BIOS настроена загрузка с дискеты,Сразувстречанагрузка0
Числоводить машинуизC0-H0-S1
приезжать Памятьиз0x07c00
из Кусочекнабор。еслиустановлен нажесткий дискстарт,Сразувстречанагрузка0x80
Числоводить машинуизC0-H0-S1
приезжать Памятьиз0x07c00
из Кусочекнабор。
Таксейчассуществовать,Берем на себя роль программы MBR,Вам необходимо загрузить в Память другие данные. Но на данный момент местонахождение Память зависит от нас по своему желанию.,Он не обязательно должен находиться сразу после места загрузки MBR.,В приведенной выше процедуревыбирать Понятно0x08000
из Кусочекнабор,Вы также можете выбрать другое место,Но главным образом,Невозможно занять место, зарезервированное BIOS.,Он не может занимать пространство видеопамяти. Обычно раскладка Память 8086 выглядит следующим образом:
Это видно из таблицы выше,0x00500
приезжать0x9fbff
этот638.75KBизкосмос Вседа Можетиспользоватьиз,нопотому чтоMBRзаниматьиспользовать Понятновиз512B,Остальное в нашем распоряжении.
Далее мы напишем программу,Первый 512B как MBR,нагрузкадваиндивидуальныйсектор(1KB)изданныеприезжать0x08000
из Кусочекнабор,Затем снова перейдите в эту позицию,Выполнять ХОРОШОинструкция:
; C0H0S1
; Вызовите прерывание BIOS с номером 0x10, чтобы очистить экран.
mov al, 0x03
mov ah, 0x00
int 0x10
; Загрузите сектор по адресу 0x08000.
mov ax, 0x0800
mov es, ax
mov bx, 0 ; Содержимое дискеты будет загружено в папку es:bx.
mov ah, 2 ; ah=2, Используйте функцию чтения диска
mov al, 2 ; ah указывает, что необходимо прочитать несколько последовательных секторов (чтение 2 соответствует размеру 1 КБ)
mov ch, 0 ; ch представляет, какой цилиндр
mov dh, 0 ; dh указывает, какая магнитная головка
mov cl, 2 ; cl указывает, какой сектор
mov dl, 0 ; dl представляет букву диска, дискета будет иметь номер 0x00~0x7F, жесткий диск будет в 0x80~0xFF
int 0x13 ; Выполнить функцию №2 прерывания №0x13 (функция чтения диска)
jmp 0x0800:0x0000 ; Здесь можно написать 0x0000:0x8000, но значения CS и IP будут разными, а CS:IP одинаковыми.
times 510-($-$$) db 0 ; Оставшаяся часть MBR заполнена 0
dw 0xaa55
; Теперь это содержимое C0H0S2.
begin:
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'H'
mov [0x0001], byte 0x0f
mov [0x0002], byte 'e'
mov [0x0003], byte 0x0f
mov [0x0004], byte 'l'
mov [0x0005], byte 0x0f
mov [0x0006], byte 'l'
mov [0x0007], byte 0x0f
mov [0x0008], byte 'o'
mov [0x0009], byte 0x0f
hlt
times 1024-($-begin) db 0 ; Заполните 2 сектора
Можете ли вы подтвердить,этотчасизmbr.bin
становиться Понятно1536B,конечно,Его уже не уместно называть «MBR».,Это должен быть полный пакет, включающий MBR и программу ядра. На данный момент давайте проигнорируем проблему именования.,Позже мы увидим, как отделить MBR от ядра.
такой же,Переименуйте его вa.img
,Затем Открытьbochsсмотретьбегать Эффект:
Результат выполнения
Это доказывает,Содержимое последующих секторов также было загружено успешно.,Прыжокинструкция также заполнена правильно Прыжок.
кроме того,Когда наша программа имеет небольшой размер,Вы можете рассмотреть возможность использования команд одношагового выполнения, чтобы отлаживать. Например, после запуска,я们Первыйсуществовать0x7c00
вточка разрыва,Затемc
Выполнять ХОРОШОBIOSизинструкция,Затемв соответствии сn
начинать Прыжок过调использоватьпроцессизодин шаготлаживать(s
дапростойизодин шаготлаживать,новстреча ПучокBIOSсерединаперерывсерединаизинструкциятакжепоказывать示出Приходить,в соответствии сn
не будет)。возможно Эффект следующий:
отлаживать
И после выполнения некоторых функций загрузки данных,я们возвращатьсядоступныйx
Заказ Приходитьпроверятьсмотреть对отвечать Память Кусочекнабор,Напримеркогда Выполнять ХОРОШОнад0x13
после перерыва,я Можетксмотретьодин раз0x08000
Кусочекнабориз Память,Независимо от того, записаны ли данные:
данные памяти
также Можетпроходитьr
иsreg
инструкцияпроверятьсмотретьзарегистрироватьсяизценить,Например, до и после Прыжокинструкции.,проверятьсмотретьCS
иIP
изценить。Прыжоквперед:
Зарегистрироваться 1
Зарегистрироваться 2
Затем Выполнять ХОРОШОn
,Заканчивать Прыжокинструкцияназад,Сновасмотретьодин разCS
иIP
изценить:
Зарегистрироваться 3
Зарегистрироваться 4
Каждый может наблюдать свою собственную программу по мере необходимости.
Логически говоря, по методу из предыдущего раздела, используя прерывание BIOS для загрузки данных с дискеты в память и затем исполняя его, под 8086 вроде бы проблем нет. Но это ненадолго. В нашем распоряжении под 8086 всего меньше 640КБ. Естественно, проблем с использованием текущего способа нет, но ведь режим 8086 - это всего лишь переход. в 32-битный режим в будущем для поддержки памяти 4 ГБ. Также переключитесь на 64-битный режим для поддержки большего объема памяти.
Хотя прерывания BIOS — очень удобный инструмент,Это эквивалентно базовой системе, предоставляющей нам некоторые библиотечные функции для использования.,Но все-таки это зависит от биоса,Все инструкции, представленные в BIOS, относятся к 16-битному реальному режиму (режим 8086).,Как только мы переключимся в режим i286, а затем в режим i386,,этотнекоторыйBIOSсерединаперерыв Сразу无Законделатьиспользовать Понятно(потому чтонабор команда не соответствует).
На самом деле необходимость записи данных в видеопамять может быть реализована и через прерывания BIOS, но автор не ввел этот метод, а использовал метод непосредственного управления видеопамятью. В этом и заключается цель, ведь мы не можем всегда Оставаться. в режиме 8086. Точно так же необходимость загрузки данных из внешней памяти также должна иметь свой оригинальный метод.
Ранее мы представили ввод-вывод. Некоторые из них имеют единую адресацию (например, видеопамять), а некоторые имеют независимую адресацию. ЦП будет управлять контроллером ввода-вывода (или его также можно назвать микросхемой южного моста) с помощью специальных инструкций. управлять этими устройствами ввода-вывода.
Устройства Ввод-вывода будет сопоставлен с номером порта. ЦП отправляет или считывает данные на соответствующий номер порта и косвенно управляет периферийными устройствами через контроллер ввода-вывода. ввод-вывода. Дисковод гибких дисков также является членом команды v. Мы можем управлять несколькими контроллерами дисководов (такими как DOR, FDC) для чтения и записи содержимого дискеты. Однако метод управления дисководом более сложен (поддерживается только режим CHS, а режим LBA не поддерживается. Режим LBA будет подробно описан в следующих главах), а также потому, что 3,5-дюймовый дисковод предназначен только для ограничено 1440Кб, рано или поздно его будет недостаточно, поэтому подробно изучать, как управлять дисководом, мы пока не будем. Далее нам нужно изменить среду нашего симулятора, чтобы использовать жесткие дискстарт。
Конфигурацияжесткий диск,нуждаться修изменятьbochsrc
изсодержание,Мы закомментируем или удалим конфигурацию, связанную с запуском дискеты.,Измените на следующее:
# boot: floppy # Настроить загрузку с дискеты
# floppy_bootsig_check: disabled=0 # Включите самотестирование
# floppya: type=1_44, 1_44="a.img", status=inserted, write_protected=0 # Используйте 3,5-дюймовую дискету емкостью 1,44 МБ, возьмите образ в формате .img, дисковод вставляется по умолчанию при загрузке, а защита от записи не включена.
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 # Сопоставление портов главного диска — 1f0, сопоставление порта подчиненного диска — 3f0, а номер прерывания установлен на 14 (хотя эти параметры можно настроить, этот параметр является отраслевым стандартом и не рекомендуется изменять).
ata0-master: type=disk, mode=flat, path=a.img, cylinders=1, heads=1, spt=1 # Загрузите кусок жесткого диска со спецификацией C1H1S1 в место основного диска. диск, зеркало с использованием a.img
boot: disk # установлен нажесткий дискстарт
Здесь есть что отметить, жесткий Спецификации диска, которые мы временно установили, — 1 цилиндр, 1 головка и 1 сектор, что составляет всего 512 байт жесткого диска. диск,Такдляa.img
Давайте поговорим,Превосходить512Bизчастьда Нетвстречанагрузка进去из。(временночастак设набородин раз,Позже это обязательно будет изменено. )
первый Первый Приходить测试один разMBRМожет ли она нормально загрузиться?,Сначала мы удаляем все операторы Прыжок, которые мы написали в MBR ранее, а также часть после 512B.,Напечатайте несколько слов, чтобы проверить эффект:
; Вызовите прерывание BIOS с номером 0x10, чтобы очистить экран.
mov al, 0x03
mov ah, 0x00
int 0x10
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'H'
mov [0x0001], byte 0x0f
mov [0x0002], byte 'e'
mov [0x0003], byte 0x0f
mov [0x0004], byte 'l'
mov [0x0005], byte 0x0f
mov [0x0006], byte 'l'
mov [0x0007], byte 0x0f
mov [0x0008], byte 'o'
mov [0x0009], byte 0x0f
hlt
times 510-($-$$) db 0 ; Оставшаяся часть MBR заполнена 0
dw 0xaa55
скомпилировать его вmbr.bin
,подтверждатьодин разэтоизразмерда512 байта:
mbr.bin
Затем Пучокэтокопироватьдляa.img
,Запустите его снова и посмотрите эффект:
После запуска жесткого диска
Если вы видите результат, это означает, что мы успешно переключились на загрузку с жесткого диска. Затем следующим шагом будет загрузка данных в последующие сектора.
Ранее мы использовали метод CHS для нумерации жесткого диска, но помимо CHS существует еще один метод, называемый LBA, который представляет собой адрес логического блока. Таким образом, жесткий диск будет нумероваться напрямую в соответствии с последовательными секторами и больше не будет учитывать головку и цилиндр.
LBA28 — относительно примитивный способ,28 означает использование 28 бит для нумерации.,также Сразуда0x0000000
~0xFFFFFFF
изсектор Число,Уведомление,0
Числодасдержанный Кусочек,настоящий正изсектордаот1
Числоначинатьиз。
для управления жестким дискиз设备встреча有对отвечатьизпорт Число,существоватьвпередлапшая们bochsrc
серединатакже有对отвечатьиз Конфигурация,Например, в настоящее время используется значение по умолчанию.,также Сразуда0x01f0
,отэтотиндивидуальныйпорт Кназадиз Несколькопорт Вседаиспользовать Приходитьдействоватьжесткий диски. Поэтому нам нужно записать данные в соответствующий порт в определенном порядке, чтобы направлять жесткий дискконтроллер читаетжесткий дискданные。
первыйхотеть Конфигурацияиздануждатьсячитать Выбиратьизпортчисло,этотиндивидуальныйданныехотетьписать0x01f2
в порту:
; Установите количество секторов для чтения
mov dx, 0x01f2
mov al, 2 ; Прочитайте несколько последовательных секторов, и при каждом чтении al будет вычитаться на 1.
out dx, al
Затемя们Приходить Конфигурация起始сектор Число。1Числосектор СразудаMBR,Уже загружено,такя们от Нет.2Числосекторначинатьнагрузка。Хотя Толькодаодининдивидуальный Простойиз2Число,Но на самом деле номер сектора в режиме LBA28 имеет 28 бит.,поэтому Мы хотим разделить его на4Второсортный,соответственнописать Неттакой жеизв порту。0x01f3
нуждатьсявходящийсектор Числоиз0~7
Кусочек,0x01f4
нуждатьсявходящийсектор Числоиз8~15
Кусочек,0x01f5
нуждатьсявходящийсектор Числоиз16~23
Кусочек,0x01f5
но拆分для3часть,Низкий4Кусочекдасектор Числоиз24~27
Кусочек,4-й бит указывает на главный и подчиненный диски.,Старшие 3 бита указывают шаблон нумерации секторов.
Код этой части следующий. Автор добавил подробные комментарии. Пожалуйста, внимательно прочитайте:
; Установите номер начального сектора, необходимо разделить 28 бит
mov dx, 0x01f3
mov al, 0x02 ; Начните чтение со 2-го сектора (начиная с 1, оставляя 0 пустым), номер сектора 0–7 цифр.
out dx, al
mov dx, 0x01f4 ; Номер сектора 8~15 цифр
mov al, 0
out dx, al
mov dx, 0x01f5 ; Номер сектора 16~23 цифры
mov al, 0
out dx, al
mov dx, 0x01f6
mov al, 111_0_0000b ; Нижние 4 бита — это номера секторов 24–27, 4-й бит — это главный и подчиненный диск (0 главный, 1 подчиненный), а верхние 3 бита указывают режим диска (111 указывает режим LBA).
Следующийхотеть Конфигурациядействовать Заказ,Нам нужно выполнить операцию «чтения диска».,对отвечатьиз Заказ Числода0x20
,этохотетьписать0x01f7
порт:
; Команды конфигурации
mov dx, 0x01f7
mov al, 0x20 ; Команда 0x20 указывает на чтение диска
out dx, al
После того, как все будет готово,Контроллер начнет читать диск.,Но это занимает некоторое время,такэтотчаспрограммахотеть等待водить машину工作Заканчивать。0x01f7
порт Если вы используетеin
Заказ,Считывается статус данных контроллера жесткого диска.,в Нет.7
Кусочеквыражатьданет忙碌,Нет.3
Кусочеквыражатьданет Сразунить。Так То есть,когда Нет.7
Кусочекда0
и Нет.3
Кусочекда1
изразговаривать,Указывает, что диск завершен,В противном случае продолжайте ждать:
wait_finish:
; Статус обнаружения, завершено ли чтение
mov dx, 0x01f7
in al, dx ; Чтение статуса через данные этого порта
and al, 1000_1000b ; Сохраняйте позиции 7 и 3.
cmp al, 0000_1000b ; Чтобы определить, равен ли 7-й бит 0 (указывая, что он не занят), а 3-й бит равен 1 (указывая, что чтение завершено)
jne wait_finish ; Если не удовлетворено, подождите в цикле
Когда диск будет готов,я们Сразу Можеткпроходить0x01f0
порт Приходитьнагрузкаданныеприезжать Память Понятно。этотиндивидуальныйпортдаиндивидуальный16Кусочекпорт,поэтому Каждый Второсортный Можеткчитать2 байта。этотвнутрия们использоватьодининдивидуальныйциклзаявлениезавершить,циклзаявлениеизцикл Второсортныйчислохотеть Писатьсуществоватьcx
середина,Каждый Второсортныйциклчасcx
автоматически уменьшится1,прямойприезжатьcx
для0затем выпрыгни из цикла。
так,Если нам нужно загрузить 2 сектора данных,Так Сразуда1024
байтизсодержание,ицикл Второсортныйчисло Сразуда512
,так Пучок Этот номерсоответствоватьприезжатьcx
середина:
mov cx, 512 ; Общее количество читаемых байт делится на 2 (указывает количество раз, поскольку каждый раз будет считываться 2 байта, поэтому его необходимо разделить на 2)
Все еще следуйте первоначальному плану,Помещаем часть трафаретной печати во второй сектор.,Затем Пучокэтозагрузить в0x08000
из Память Кусочекнабор:
mov dx, 0x01f0
mov ax, 0x0800
mov ds, ax
xor bx, bx ; [ds:bx] = 0x08000
read:
in ax, dx ; 16-битный порт, поэтому используйте 16-битные регистры
mov [bx], ax
add bx, 2 ; Поскольку размер ax составляет 16 бит, за раз будет записываться 2 байта.
loop read
Наконец, пройдите Прыжокинструкцию Прыжок, чтобы проверить, прошла ли загрузка успешно. Полный код приведен ниже:
; C0H0S1
; Вызовите прерывание BIOS с номером 0x10, чтобы очистить экран.
mov al, 0x03
mov ah, 0x00
int 0x10
; Режим LBA28, номер логического сектора 28 бит, от 0x0000000 до 0xFFFFFFF.
; Установите количество секторов для чтения
mov dx, 0x01f2
mov al, 2 ; Прочитайте несколько последовательных секторов, и при каждом чтении al будет вычитаться на 1.
out dx, al
; Установите номер начального сектора, необходимо разделить 28 бит
mov dx, 0x01f3
mov al, 0x02 ; Начните чтение со 2-го сектора (начиная с 1, оставляя 0 пустым), номер сектора 0–7 цифр.
out dx, al
mov dx, 0x01f4 ; Номер сектора 8~15 цифр
mov al, 0
out dx, al
mov dx, 0x01f5 ; Номер сектора 16~23 цифры
mov al, 0
out dx, al
mov dx, 0x01f6
mov al, 111_0_0000b ; Нижние 4 бита — это номера секторов 24–27, 4-й бит — это главный и подчиненный диск (0 главный, 1 подчиненный), а верхние 3 бита представляют режим диска (111 представляет LBA).
; Команды конфигурации
mov dx, 0x01f7
mov al, 0x20 ; Команда 0x20 указывает на чтение диска
out dx, al
wait_finish:
; Статус обнаружения, завершено ли чтение
mov dx, 0x01f7
in al, dx ; Чтение статуса через данные этого порта
and al, 1000_1000b ; Сохраняйте позиции 7 и 3.
cmp al, 0000_1000b ; Чтобы определить, равен ли 7-й бит 0 (указывая, что он не занят), а 3-й бит равен 1 (указывая, что чтение завершено)
jne wait_finish ; Если не удовлетворено, подождите в цикле
; Загрузить данные в Память из порта
mov cx, 512 ; Общее количество читаемых байт делится на 2 (указывает количество раз, поскольку каждый раз будет считываться 2 байта, поэтому его необходимо разделить на 2)
mov dx, 0x01f0
mov ax, 0x0800
mov ds, ax
xor bx, bx ; [ds:bx] = 0x08000
read:
in ax, dx ; 16-битный порт, поэтому используйте 16-битные регистры
mov [bx], ax
add bx, 2 ; Поскольку размер ax составляет 16 бит, за раз будет записываться 2 байта.
loop read
jmp 0x0800:0x0000 ; Здесь можно написать 0x0000:0x8000, но значения CS и IP будут разными, а CS:IP одинаковыми.
times 510-($-$$) db 0 ; Оставшаяся часть MBR заполнена 0
dw 0xaa55
; Теперь это содержимое C0H0S2.
begin:
mov ax, 0xb800
mov ds, ax
mov [0x0000], byte 'H'
mov [0x0001], byte 0x0f
mov [0x0002], byte 'e'
mov [0x0003], byte 0x0f
mov [0x0004], byte 'l'
mov [0x0005], byte 0x0f
mov [0x0006], byte 'l'
mov [0x0007], byte 0x0f
mov [0x0008], byte 'o'
mov [0x0009], byte 0x0f
hlt
times 1024-($-begin) db 0 ; Заполните 2 сектора
Уведомление,Поскольку мы расширили сектор до 3,поэтомуbochsrc
внутрилапша Вам также необходимо изменить размер жесткого диска:
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 # Сопоставление портов главного диска — 1f0, сопоставление порта подчиненного диска — 3f0, а номер прерывания установлен на 14 (хотя эти параметры можно настроить, этот параметр является отраслевым стандартом и не рекомендуется изменять).
ata0-master: type=disk, mode=flat, path=a.img, cylinders=1, heads=1, spt=3 # Загрузите кусок жесткого диска со спецификацией C1H1S3 в место основного диска. диск, зеркало с использованием a.img
boot: disk # установлен нажесткий дискстарт
большинствоназадпроходить汇编生становитьсяmbr.bin
,копироватьдляa.img
,перезапускbochs
Сразу Можетксмотретьприезжать Эффект казни:
Эффект казни
этотчас ХОРОШОпроходитьотлаживатьинструкцияпроверить0x8000
из Памятьсередина确实нагрузка Понятно对отвечатьизинструкция:
инструкция
Это преследует ту же цель. Мы не использовали прерывания BIOS, а также завершили работу по загрузке жесткого диска.