Поскольку никто не упомянул DOS, давайте забудем о старых компьютерах с DOS-ПК и посмотрим на это с общей точки зрения. Тогда, очень упрощенно, это выглядит так:
Любой ЦП имеет шину данных, которая представляет собой максимальный объем данных, которые ЦП может обработать в одной инструкции, т. Е. Равный размеру его регистров. Ширина шины данных выражается в битах: 8 бит, или 16 бит, или 64 бита и т. Д. Отсюда и происходит термин «64-битный ЦП» - он относится к шине данных.
Любой ЦП имеет адресную шину, также с определенной шириной шины, выраженной в битах. Любая ячейка памяти вашего компьютера, к которой центральный процессор может обращаться напрямую, имеет уникальный адрес. Адресная шина достаточно велика, чтобы охватить всю имеющуюся адресную память.
Например, если у компьютера есть 65536 байтов адресуемой памяти, вы можете покрыть их 16-битной адресной шиной, 2 ^ 16 = 65536.
Чаще всего, но не всегда, ширина шины данных равна ширине адресной шины. Хорошо, если они имеют одинаковый размер, так как это делает набор инструкций ЦП и программы, написанные для него, более четкими. Если процессору необходимо вычислить адрес, удобно, если этот адрес достаточно мал, чтобы поместиться в регистры процессора (часто называемые индексными регистрами, когда речь идет об адресах).
Нестандартные ключевые слова far
и near
используются для описания указателей в системах, где необходимо адресовать память сверх нормальной ширины шины адреса ЦП.
Например, для ЦП с 16-битной шиной данных может быть удобно иметь 16-битную адресную шину. Но этому же компьютеру может потребоваться более 2 ^ 16 = 65536 байт = 64 КБ адресуемой памяти.
В этом случае процессор обычно будет иметь специальные инструкции (которые немного медленнее), что позволяет ему обращаться к памяти за пределами этих 64 КБ. Например, ЦП может разделить свою большую память на n
страниц (также иногда называемых банки , сегментов и другие подобные термины, которые могут означать другое вещь из одного процессора в другой), где каждая страница составляет 64 КБ. Затем он будет иметь «страничный» регистр, который должен быть установлен первым, прежде чем обращаться к этой расширенной памяти. Точно так же у него будут специальные инструкции при вызове / возврате из подпрограмм в расширенной памяти.
Чтобы компилятор C генерировал правильные инструкции ЦП при работе с такой расширенной памятью, были изобретены нестандартные ключевые слова near
и far
. Нестандартные, как в, они не определены стандартом C, но они де-факто являются отраслевым стандартом, и почти каждый компилятор в некотором роде поддерживает их.
far
относится к памяти, расположенной в расширенной памяти, за пределами ширины адресной шины. Поскольку это относится к адресам, чаще всего вы используете его при объявлении указателей. Например: int * far x;
означает «дай мне указатель, который указывает на расширенную память». И тогда компилятор будет знать, что он должен генерировать специальные инструкции, необходимые для доступа к такой памяти. Точно так же указатели функций, использующие far
, будут генерировать специальные инструкции для перехода в / из расширенной памяти. Если бы вы не использовали far
, вы бы получили указатель на обычную адресуемую память и в итоге указали бы на что-то совершенно другое.
near
в основном включено для соответствия с far
; это относится к чему-либо в адресуемой памяти, как эквивалентно обычному указателю. Таким образом, это в основном бесполезное ключевое слово, за исключением редких случаев, когда вы хотите убедиться, что код помещен в стандартную адресуемую память. Затем вы можете явно пометить что-то как near
. Наиболее типичным случаем является низкоуровневое аппаратное программирование, когда вы пишете процедуры обслуживания прерываний. Они вызываются аппаратно из вектора прерывания с фиксированной шириной, которая равна ширине адресной шины. Это означает, что подпрограмма обработки прерываний должна находиться в стандартной адресуемой памяти.
Самым известным использованием far
и near
является, возможно, упомянутый старый ПК с MS DOS, который в настоящее время считается довольно древним и поэтому представляет небольшой интерес.
Но эти ключевые слова существуют и на более современных процессорах! Это особенно заметно во встроенных системах, где они существуют практически для каждого семейства микроконтроллеров 8 и 16 бит, представленных на рынке, поскольку эти микроконтроллеры обычно имеют ширину адресной шины 16 бит, но иногда больше 64 КБ памяти.
Всякий раз, когда у вас есть ЦП, где вам нужно адресовать память сверх ширины адресной шины, вам потребуются far
и near
. Как правило, такие решения не одобряются, поскольку программировать на них довольно сложно и всегда учитывать расширенную память.
Одной из основных причин, по которой возникла тенденция к разработке 64-битного ПК, было то, что 32-битные ПК достигли точки, когда их использование памяти начало достигать предела адресной шины: они могли адресовать только 4 ГБ оперативной памяти 2 ^ 32 = 4,29 млрд байт = 4 Гб. Чтобы можно было использовать больше оперативной памяти, можно было либо прибегнуть к какому-нибудь обременительному решению с расширенной памятью, как в дни DOS, либо расширить компьютеры, включая их адресную шину, до 64 бит.