суббота, 4 июля 2009 г.

Архитектура x86 - очень странная

Это перевод The x86 architecture is the weirdo. Автор: Реймонд Чен.

Архитектура x86 делает множество вещей, которые не делает никакая другая современная архитектура, но из-за её ошеломляющей популярности люди думают, что x86 - это нормальный путь, а странные - это все остальные.

Давайте сразу прямо уточним: архитектура x86 является странной (x86 architecture is the weirdo).

x86 имеет небольшое количество (8) регистров общего назначения; другие современные процессоры имеют намного больше (PPC, MIPS и Alpha имеют по 32; у ia64 их 128).

x86 использует стек для передачи параметров функциям; все прочие используют регистры.

x86 прощает доступ к данным без выравнивания, молчаливо исправляя ошибки. Другие возбуждают misalignment-исключение, которое также при желании может быть эмулировано supervisor-ом за огромное пенальти по производительности.

x86 использует инструкции переменного размера. Остальные используют инструкции фиксированного размера (PPC, MIPS и Alpha используют инструкции в 32 бита ровно; ia64 использует инструкции длиной 41 бит каждая. Да, инструкции размером ровно 41 бит).

x86 имеет строгую модель памяти, где порядок доступа к внешней памяти соответствует порядку запросов к памяти, вызываемых потоком кода. Все прочие используют слабые модели памяти, требуя наличия явных барьеров памяти для гарантирования явного порядка доступа к памяти.

x86 поддерживает атомарные операции типа загрузить-изменить-сохранить. Нигде больше такого нет.

x86 передаёт адрес возврата в стеке. Остальные используют специальный регистр.

Имейте это ввиду, когда вы собираетесь писать переносимый код (portable code). Как и множество других вещей, культура, в которой вы выросли, кажется вам "нормальной", даже если, по сравнению с прочими, она является одной из самых выделяющихся.

10 комментариев:

  1. "x86 имеет небольшое количество (8) регистров"

    Наверно, автор ведёт речь про 8086! ))) MMX, SSE, FPU - имеют свои регистры... Да и с изменением разрядности количество регистров процессора как-бы увеличилось, ведь мы можем работать с "половинками" обычных регистров.

    "x86 использует стек для передачи параметров функциям; все прочие используют регистры."

    ээээ... Это к архитектуре x86 никакого отношения не имеет, вообще-то... За это компилятор отвечает. Вот, в том-же паскале или дельфи использует передачу параметров именно по регистрам, хотя можно их передавать и по другому, используя специальные директивы компилятора (register, pascal, cdecl, stdcall, safecall и т.д.)

    "x86 поддерживает атомарные операции типа загрузить-изменить-сохранить. Нигде больше такого нет."

    Странно, даже в Z80 такие операции присутствовали! )))

    И вообще, сложилось впечатления, что сравнивается CISC-архитектура с несколькими RISC-архитектурами. (решил так по списку отличий - атомарные операции, строгая модель памяти, большое количество регистров, инструкции фиксированного размера - всё это "визитная карточка" именно RISC архитектуры) Понятно дело, что с точки зрения одной архитектуры, другая всегда будет "Странной". :)

    ОтветитьУдалить
  2. >>> MMX, SSE, FPU - имеют свои регистры
    Это - расширения.

    >>> Да и с изменением разрядности количество регистров процессора как-бы увеличилось, ведь мы можем работать с "половинками" обычных регистров.
    Обращение к половине регистра не делает его полноценным регистром. Новых регистров нет. Есть увеличение разрядности.

    >>> Это к архитектуре x86 никакого отношения не имеет, вообще-то... За это компилятор отвечает
    Да ну. Не путайте причину и следствие. Компилятор делает так, потому что это диктуется архитектурой. Архитектура - первична.
    Посмотрите ещё эту серию и этот пост.

    >>> Странно, даже в Z80 такие операции присутствовали! )))
    Наверное, это не удивительно. Если учитывать, что Z80 был создан как клон 8080, ушедшими из Intel сотрудниками? Новый процессор изначально создавался совместимым с 8080 (с дополнительным набором команд).

    >>> сложилось впечатления, что сравнивается CISC-архитектура с несколькими RISC-архитектурами
    Да, именно так.
    Наверное это потому, что сложно назвать другую распространённую CISC-архитектуру, кроме x86? ;) (на ум приходят только динозавры из 70-х). В то время, как RISC - это ARM (пример: Apple iPod, iPhone и т.п.), MIPS (PlayStation), Sun-ский SPARC и т.д.
    x86 странная именно потому, что это CISC. В то время, как почти все другие архитектуры являются RISC. Да, с точки зрения другой архитектуры, странно всё то, что не совпадает с твоим собственным. Но в общей куче архитектур выделяется именно x86, а не другая. Об этом и пост.

    P.S. Ну, внутренне новые x86 процессоры выполняются в определённом RISC-стиле, хотя внешний программный интерфейс не изменялся.

    ОтветитьУдалить
  3. "Это - расширения."

    Блин, а чем расширения от "нерасширений" отличаются? Отличие, imho, только в терминалогии... По факту - это регистры, который камень использует...

    "Да ну. Не путайте причину и следствие. Компилятор делает так, потому что это диктуется архитектурой. Архитектура - первична."

    Ну да! В скобках я указал дерективы компилятора паскаля и делфей, которые используют другие способы передачи параметров. И, кстати, дельфи и "си билдер" по умолчанию всегда использует именно "register" передачу. Почему-то, им "архитектура процессора" в этом никак не мешает.
    И первая ваша ссылка по "регистрам" описывает проц 8086, а вторая описывает соглашения, использующиеся ещё во времена MSDOS. Даже Delphi 1 под Win16, между своими процедурами и BPL'ками, параметры передавала регистрами (ну, если регистров хватало). Хотя, в статье там даже написано, что описывается 16-битные соглашения о вызовах - а сейчас обычно используются 32\64 битные программы.
    Хотя, в сиподобных языках и библиотеках Windows данные передаются по стеку - но это не из-за архитектуры, а так просто исторически сложилось... Существуют ведь операционные системы Windows под "не х86-платформы"! Там ведь тоже данные между процедурами в библиотеках стеком передаются!

    ОтветитьУдалить
  4. >>> Блин, а чем расширения от "нерасширений" отличаются?
    В посте идёт речь об архитектуре x86. Я не знаю, зачем вы сюда приплетаете расширения. Расширение - это вполне самостоятельная и автономная единица, у неё своя архитектура. Например, MMX изначально разрабатывалась для RISC-процессора Intel i860 (её RISC-корни можно увидеть и сейчас). А FPU когда-то вообще был аппаратно другим процессором.
    Нет, ради бога, если хотите - напишите сравнение архитектур вместе с расширениями (не забудьте тогда уж и расширения для RISC-процессоров - типа MDMX, MIPS-3D и т.п.) в настоящий момент. Только в формат/идею этого поста такое сравнение не будет укладываться. Это исторический пост.

    >>> И первая ваша ссылка по "регистрам" описывает проц 8086
    Первая ссылка идёт на серию постов.

    >>> В скобках я указал дерективы компилятора паскаля и делфей, которые используют другие способы передачи параметров
    Так, кажется я понял откуда сыр-бор. Вы неверно поняли фразу "x86 использует стек для передачи параметров функциям". Поясняю: эта фраза не означает, что в x86 ВООБЩЕ не используются регистры. Напротив, x86 как раз характеризуется наличием нескольких различных моделей вызовов (это более подробно описывается по ссылкам, приведённым выше), в некоторых из которых используются регистры. Указанную же фразу надо понимать так: другие архитектуры НЕ используют только стек для передачи параметров - они имеют единственную модель вызова, в которой параметры передаются регистрами (да, остаток - в стек, но всё равно там далеко не два-три регистра под параметры, а иногда десятки). Причём некоторые архитектуры не используют стек вообще, а только регистры (да, там есть регистровый стек, но это уже совсем другой зверь, аналога которому в x86 нет).

    >>> Там ведь тоже данные между процедурами в библиотеках стеком передаются!
    Там данные передаются так, как диктуется архитектурой. А передача данных только стеком без регистров есть только в x86.

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

    ОтветитьУдалить
  5. > И, кстати, дельфи и "си билдер" по умолчанию всегда использует именно "register" передачу. Почему-то, им "архитектура процессора" в этом никак не мешает.

    Чудак ты. Используют они это ровно потому, что это позволяет и _одобряет_ архитектура. А ну, попробуй мне передай параметры в регистрах, если это архитектурой не диктуется (к примеру, команда call обнуляет регистры или же свободных регистров нет, есть только preserved-регистры).

    ОтветитьУдалить
  6. > x86 поддерживает атомарные операции типа загрузить-изменить-сохранить. Нигде больше такого нет.

    Неправда, Sparc тоже использует CAS. У остальных перечисленных действительно LL/SC.

    Вообще, из этих страшилок практически важно сейчас большинству только выравнивание.

    ОтветитьУдалить
  7. Да вроде как это не страшилки?

    ОтветитьУдалить
  8. > Да вроде как это не страшилки?

    Ассемблерщикам и системщикам всё равно менять большинство привычек даже при переходе на amd64, а прикладникам почти всё тут описанное - пофиг. Особенно количество регистров, да будь их хоть 2 хоть 100, кэш сейчас нивелирует разницу.

    Из того, что таки всплывёт в ближайшее время - это lock-free/wait-free/etc. алгоритмы, для которых важно именно отношение к упорядочению операций в памяти. Код для x86 не будет работать на RISC из-за отсутствия явного указания release semantics или другой подобной спецификации доступа. Но и то это крайне малое количество авторов.

    ОтветитьУдалить
  9. Я имел ввиду, что это исторический обзор, а не практическое руководство.

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.