NoneX 86 - это архитектура, производная от процессора Intel 8086. Семейство x86 включает 32-битные архитектуры IA-32 и 64-битные x86-64, а также унаследованные 16-битные архитектуры. Вопросы о последнем должны быть помечены тегами [x86-16] и / или [emu8086]. Используйте тег [x86-64], если ваш вопрос касается 64-битных x86-64. Для FPU x86 используйте тег [x87]. Для SSE1/2/3/4 / AVX* также используйте [sse] и любой из [avx] / [avx2] / [avx512], которые применяются

Семейство процессоров x86 содержит 16-, 32- и 64-разрядные процессоры от нескольких производителей с обратно совместимыми наборами инструкций, восходящими к Intel 8086, представленному в 1978 году.

Для вещей, специфичных для этой архитектуры, есть тег x86-64, но большая часть информации здесь применима к обоим. Имеет смысл собирать все здесь. Вопросы могут быть помечены одним или обоими. Вопросы, относящиеся к функциям, имеющимся только в архитектуре x86-64, например относительной адресации RIP, явно относятся кx86-64. Вопросы типа "как ускорить этот код с помощью векторов или любых других уловок" подходят дляx86, даже если предполагается компиляция для 64-битной версии.

Связанный тег с тегом-вики:

  • sse wiki (несколько хороших руководств по SIMD) и avx ( там немного)
  • вики по встроенной сборке для руководств по взаимодействию с компилятором таким образом.
  • Intel-syntax wiki и att wiki содержат более подробную информацию о различиях между двумя основными синтаксисами сборки x86. А для Intel, как определить, какой это синтаксис Intel, например, NASM или MASM/TASM.

Учебные ресурсы

Если вы не знаете, как что-то делать в asm, напишите простую функцию C, которая это сделает, и посмотрите, что делает оптимизирующий компилятор. напримерint foo(char *p) { return *p; } показывает вам, как использовать movsx. См. Также Как удалить "шум" из вывода сборки GCC/clang?


Руководства по настройке / оптимизации производительности:

Ссылки на набор инструкций / asm-синтаксис:

Форк более старой версии включает описания на английском языке. В оригинале были некоторые ошибки, в которых поколение вводило каждую форму каждого insn, но эта версия сохраняет хорошее форматирование, исправляя их. Удобно для людей, все еще разрабатывающих для x86-16. На аналогичной странице в Википедии не упоминается, что 386 требуется для более быстрой формы с двумя операндамиimul r16, r/m16 при этом не нужно вычислять верхнюю половину результата.

Возможные канонические дубликаты для подмножеств регистров: регистры сборки в 64-битной архитектуре включают некоторые соглашения о вызовах / использование. Как AX, AH, AL сопоставляются с EAX? хорош для ошибок, когда AL и RAX использовались для разных целей, разрушая друг друга.

Специфические для ОС вещи: ABI и таблицы системных вызовов:






порядок памяти:

Особое поведение конкретных реализаций

Вопросы и ответы с хорошими ссылками или прямо полезными ответами:


Часто задаваемые вопросы / канонические ответы:

Если у вас возникла проблема, связанная с одной из этих проблем, не задавайте новый вопрос, пока не прочитаете и не поймете соответствующие вопросы и ответы.

(TODO: найдите для них более удачные ссылки на вопросы. В идеале вопросы, которые будут хорошей дублирующей целью для новых дубликатов. Также расширьте это.)

8-битный размер операнда как div dlэто особый случай, когда dx не задействован, только AX и AH/AL. Он по-прежнему дает сбой, если частное превышает 8 бит.

преобразование строки в целое число (32-битный NASM, алгоритм работает везде). (умножьте на 10 для разрядного значения) Также включает цикл преобразования целых чисел в строку.

Печать целых чисел: 16-битный код для печати 16- или 32-битных целых чисел (вdx:ax) (По одной цифре с MS-DOSint 21h, но может быть адаптирован для сохранения в строку или использования другого метода вывода.) Другой пример для чисел без знака 16b в DOS, который вычисляет цифры и сохраняет их в строку в памяти.

2-значные десятичные числа (00-99), используя BIOS int 10hдля каждой цифры: Отображение времени сборки. (Это просто частный случай общего алгоритма, а не цикла.)

Функция NASM x86-64 для преобразования и печати 32-разрядного целого числа без знака (с использованием одногоwriteсистемный вызов в буфере). Другие ответы на тот же вопрос показывают печать по одному символу за раз. Версия той же функции AT&T, также показывающая 5-кратную более быструю версию, которая использует мультипликативную обратную функцию вместоdiv разделить на постоянную времени компиляции 10.

Как преобразовать двоичное целое число в шестнадцатеричную строку?(32-битный код NASM. Скалярные версии, SSE2, SSSE3, AVX512F и AVX512VBMI.)


С чего начать / Инструменты для отладки + руководства

Найдите отладчик, который позволит вам выполнять код за один шаг и отображать регистры, пока это происходит. Это очень важно. У нас много вопросов вроде "почему не работает этот код", которые можно было бы решить с помощью отладчика.

В Windows Visual Studio имеет встроенный отладчик. См. Отладка ASM с помощью Visual Studio - содержимое регистра не отображается. И см. Программирование на ассемблере - WinAsm против Visual Studio 2017 для пошагового руководства по настройке проекта Visual Studio для 32-битного или 64-битного консольного приложения MASM Hello World.

В Linux: широко доступным отладчиком является gdb. См. Основные сведения об использовании сборки в Linux в разделе " Отладка сборки". Также как можно увидеть содержимое стека с помощью GDB?

Существуют различные внешние интерфейсы GDB, включая GDBgui. Также гайды для vanilla GDB:

С layout asm а также layout regвключен, GDB будет выделять регистры, измененные с момента последней остановки. Использоватьstepiпошагово по инструкции. Использоватьxдля проверки памяти по заданному адресу (полезно при попытке выяснить, почему ваш код разбился при попытке чтения или записи по заданному адресу). В двоичном формате без символов (или даже разделов) вы можете использоватьstarti вместо того runостановиться до первой инструкции. (В более старых версиях GDB безstarti, вы можете использоватьb *0как хитрость, чтобы заставить GDB останавливаться при ошибке.) Используйтеhelp x или что-то еще для помощи по любой команде.

Инструменты GNU имеют режим Intel-синтаксиса, похожий на MASM, который приятно читать, но редко используется для рукописного кода (NASM/YASM подходит для этого, если вы хотите придерживаться инструментов с открытым исходным кодом, но избегать синтаксиса AT&T):

Еще один ключевой инструмент для отладки - отслеживание системных вызовов. например, в системе Unix,strace ./a.outпокажет вам аргументы и возвращаемые значения всех системных вызовов, которые делает ваш код. Он знает, как декодировать аргументы в символические значения, такие какO_RDWR, так что это намного удобнее (и, вероятно, поймать мозги или неправильные значения для констант), чем использование отладчика для просмотра регистров до / после int или syscallинструкция. Обратите внимание, что в Linux это не работает.int 0x8032-битные системные вызовы ABI в 64-битных процессах: что произойдет, если вы используете 32-битный int 0x80 Linux ABI в 64-битном коде?.

Чтобы отладить загрузочный код или код ядра, загрузите его в bochs, qemu или, возможно, даже в DOSBOX, или в любой другой виртуальной машине / симуляторе / эмуляторе. Используйте средства отладки на виртуальной машине, чтобы получить путь больше информации, чем обычный "он запирает" вы будете испытывать с багги привилегированным кодом.

BOCHS обычно рекомендуется для отладки загрузчиков в реальном режиме, особенно тех, которые переключаются в защищенный режим; Встроенный отладчик BOCHS понимает сегментацию (в отличие от GDB) и может анализировать GDT или IDT, чтобы убедиться, что вы правильно указали поля.