Содержание статьи
Другие статьи курса
- Зачем учить ассемблер в 2020 году
- Делаем первые шаги в освоении асма
- Осваиваем арифметические инструкции
- Как работают переменные, режимы адресации, инструкции условного перехода
- Работаем с большими числами и делаем сложные математические вычисления
- Сокращаем размер программы
- Пишем клон игры Flappy Bird, который уместится в бутсектор
- Пишем бейсик и умещаем его в 512 байт
Знакомимся с сегментными регистрами
Для начала разберемся, что такое сегментные регистры. Процессор 8088 умеет адресовать один мегабайт оперативной памяти, несмотря на то что регистры у него 16-битные. В норме 16 битами можно адресовать только 64 Кбайт. И как же тогда выкручивается 8088? Как ему удается адресовать целый мегабайт? Для этого в 8088 есть сегментные регистры! Четыре сегментных регистра: CS
, ES
, DS
и SS
, по 16 бит каждый. У каждого из этих регистров есть свое назначение.
Регистр CS
указывает на сегмент кода. Процессор обращается к CS
всякий раз, когда надо считать из памяти очередную инструкцию для выполнения.
Регистры DS
и ES
указывают на сегмент данных. К этим регистрам процессор обращается, когда выполняемая инструкция считывает или сохраняет данные. Имей в виду: DS
используется чаще, чем ES
. ES
обычно вступает в игру, когда ты обрабатываешь массивы данных, индексируя их регистром DI
.
Регистр SS
указывает на сегмент стека. К этому регистру процессор обращается, когда выполняет инструкции, взаимодействующие со стеком: push
, pop
, call
и ret
.
Значения, хранимые в сегментных регистрах, — это базовый адрес, поделенный на 16
. Если в CS
записано значение 0x0000
, процессор будет считывать инструкции из области памяти 0x00000 — 0x0FFFF
. Если в регистре CS
записано значение 0x1000
, то процессор будет считывать инструкции из области памяти 0x10000 — 0x1FFFF
.
Если тебе надо адресоваться в какой-то другой сегмент, а не тот, который будет задействован по умолчанию, напиши этот сегмент в префиксе к инструкции, которую используешь.

Поместить какое-то число в сегментные регистры напрямую нельзя. Для этого надо:
- либо сначала записать число в какой-нибудь регистр и уже этот регистр присвоить сегментному регистру;
- либо воспользоваться парой инструкций
push/pop
; - либо воспользоваться инструкциями
lds/les
.

Процессор 8088 настолько лоялен, что позволит тебе даже вот такую инструкцию: pop cs
. Но только имей в виду, что это нарушит поток выполнения инструкций. В более новых процессорах, начиная с 80286, такую диверсию сделать уже не получится. И слава богу!
Ну вот вроде бы и все, что тебе надо знать о сегментных регистрах. Теперь ты с их помощью (в основном с помощью регистров DS
и ES
) можешь получать доступ ко всему первому мегабайту памяти ПК.
Как ПК распределяет память
Понимание того, как распределяется память в ПК, поможет тебе делать разные интересные вещи.

Начало загрузки у всех компьютеров одинаковое: они сначала переходят в текстовый цветной режим 80x25
. К видеопамяти экрана, который работает в таком режиме, можно обращаться напрямую, через вот этот диапазон адресов: 0xB8000 — 0xB8FFF
.
Первый байт диапазона — это первый символ в верхнем левом углу экрана. Второй байт — это цвет фона под символом и цвет самого символа. Затем (третьим байтом) идет второй символ. И так для всех 25 строк по 80 символов каждая.

INFO
Исторический факт. IBM PC образца 1981 года поставлялся в двух модификациях: с монохромным режимом и с цветным режимом. Тогдашним разработчикам игрушек приходилось придумывать разные эвристики, чтобы понять, какая у компьютера графика — монохромная или цветная. Несколько старых добрых игрушек для этого писали какую-нибудь цифру по адресу 0xB8000
и считывали ее обратно, чтобы узнать, в каком режиме сейчас идет работа — в цветном или в монохромном.
Прямой доступ к видеопамяти в текстовом режиме
Перед тем как мы сможем напрямую обращаться к видеопамяти экрана, то есть без использования сервисов BIOS, надо задать нужный нам видеорежим.

В этом режиме видеопамять экрана доступна по адресу 0xB8000
. Теперь ты можешь легко получить доступ к ней. Примерно так, как в коде ниже.

Обрати внимание, что после того, как ты выполнил этот кусок кода, ты не сможешь обращаться к переменным, которые сохраняешь в сегменте кода, как мы это делали в примерах из прошлых уроков. Потому что DS
и ES
теперь нацелены не на сегмент кода, а на видеопамять.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»
Maxim Elchugin
14.09.2020 в 22:32
Разве в современных операционных системах это актуально?
Novosedoff
14.09.2020 в 23:18
Человек 84-го года рождения.. Криса Касперского ещё застал
Victor__v
16.10.2020 в 14:18
В Винде для адресации TIB используется сегментный регистр FS: (GS: ,если 64 бита)
Но вашего вопроса он не отменяет)
Антон Карев
14.09.2020 в 23:54
Да, актуально. Работа с памятью и сегментация будут актуальными всегда. Да, они сегодня других размеров и называются по-другому, но сам принцип остаётся. Вот этому принципу и посвящена статья. Разобравшись с самим принципом, можно полученные знания транслировать — и на современные ОС, и на те, которые после них появятся, с ещё более новыми архитектурными особенностями.
Victor__v
17.09.2020 в 10:17
На мой взгляд, учить сейчас людей ассемблеру под 16 бит преступление против здравого смысла.
Не актуально же!
Так уж сложно под 32 или 64?
Антон Карев
17.09.2020 в 17:05
Здравый смысл вещь субъективная. А основы никто не отменял. Кроме того, BIOS, когда компьютер только включился, смотрит на любой процессор (даже если это Ryzen или Core i9) – как на примитивный 16-битный 8088.
Я убеждён, что на первых парах лучше учить ассемблер – на той версии процессора, где наворотов по минимуму. А потом, когда основы хорошо усвоены, можно легко и в новых наворотах разобраться.
Я учился именно так (и своим студентам рекомендую также), и мне поэтому сейчас сравнительно легко в новомодных наворотах разбираться. Смотри, например, мои статьи про SIMD (https://xakep.ru/2019/07/30/interprocess/) и SGX (https://xakep.ru/2019/04/04/sgx-attack/). Но если сразу, например, в SIMD или SGX погружаться, то именно эти технологии ты может быть и освоишь, хорошо, – но поскольку у тебя нет системного понимания как работает процессор в самой своей основе, то каждую следующую модную технологию нужно будет изучать как с нуля.
robotobor
22.09.2020 в 10:14
Зачетный был фильмец! «мы проверяем шестой бит (0x40)» — вроде, как 7ой бит…
Антон Карев
22.09.2020 в 11:28
Я от нуля отсчитывал — так вроде общепринято.
impulsgraw
16.01.2021 в 01:32
Антон, подскажите, почему мы пишем таблицу синусов прямо в сегменте кода, а не в сегменте данных? Есть ли какая-то принципиальная разница где хранить данные, если по факту это ни на что не влияет?
Антон Карев
28.01.2021 в 18:53
Потому что программа написана для компиляции в com-формате. А в этом формате код и данные – находятся в одном и том же сегменте.