Описание тега x86
Семейство процессоров 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.
Учебные ресурсы
- Доклад Мэтта Годболта на CppCon2017 "Что мой компилятор сделал для меня за последнее время? Откручивание крышки компилятора " содержит краткое введение в сам ассемблер x86 для начинающих, знающих C или C++, а также очень полезное руководство по просмотру вывода компилятора.
Если вы не знаете, как что-то делать в asm, напишите простую функцию C, которая это сделает, и посмотрите, что делает оптимизирующий компилятор. напримерint foo(char *p) { return *p; }
показывает вам, как использовать movsx
. См. Также Как удалить "шум" из вывода сборки GCC/clang?
Краткое руководство по сборке x86, предназначенное для 32-битного режима и ассемблера MASM, но достаточно краткое и не зависящее от цели, чтобы его можно было использовать в качестве отправной точки для любого ассемблера синтаксического диалекта "Intel" (NASM, YASM, FASM, ...).
Предложения по изучению asm с рекомендацией против 16-битной DOS. В вопросах следует использовать теги x86-16, emu8086 и / или dos, если применимо, а также x86 (который включает все платформы).
OSdev.org: отличный ресурс, если вы хотите понять / изменить внутреннее устройство ОС или создать свою собственную игрушечную ОС. Бесполезен для написания / отладки обычных программ, работающих в существующих операционных системах.
Общие советы по разработке загрузчика. (Используется устаревшая версия BIOS, а не UEFI).
Рабочий пример устаревшего BIOS
int 10h
загрузчик, который загружает "ядро" и вызывает Cmain
в нем работают в 32-битном защищенном режиме. Включает инструкции о том, как создать и связать его с NASM,gcc -m32
, а такжеld
(со сценарием компоновщика). А как сделать образ диска и запустить его на QEMU.рядная сборка теги вика. (Но смотри также https://gcc.gnu.org/wiki/DontUseInlineAsm - рядный асмовый более. Сложнее, чем писать автономный ASM функцию вы называете от C, так что это не хорошо для обучения ассемблера)
Использование встроенного ASM GNU C/C++. Внизу этого ответа есть коллекция ссылок на информацию о том, как написать встроенный asm, который является эффективным и правильным. Первая часть ответа объясняет, почему это не лучший способ изучить asm. Не пытайтесь "намочить ноги" с помощью asm, используя встроенный asm. Вы должны понимать все, чтобы писать правильные ограничения операндов ввода / вывода и клобберы.
Понимание условий / флагов переноса и переполнения, обычно актуальных для неподписанных и подписанных соответственно.
- Краткое руководство по отличиям x86-64. Синтаксис AT&T. NASM и YASM ведут себя по-разному (друг от друга) при выборе кодировки для
mov rax, 1
, и не используйте отдельныйmovabs
мнемоника для 64-битной немедленной формы. - Введение в сборку x64 (опубликовано Intel). Использует синтаксис MASM. Тратит немного времени на разговоры о соглашении о вызовах Windows и проблемах с цепочкой инструментов / MSVC (например, об отсутствии встроенного asm MSVC в 64-битном режиме), как можно было бы ожидать от использования "x64" в заголовке статьи вместо x86-64. Но похоже на некоторые хорошие общие вещи, не зависящие от ОС. По какой-то странной причине он предлагает использовать инструкцию медленного цикла LOOP, поэтому она не идеальна.
- Кодирование реальных инструкций x86: учебное пособие (материал курса) о том, как инструкции кодируются в машинный код. Множество диаграмм.
- x86 в Википедии
- wikibook по сборке x86
- Язык ассемблера для процессоров x86 (веб-сайт книги Кипа Ирвина)
- Программирование с нуля, бесплатная книга (GFDL) Джонатана Бартлетта. Исправление к книге. Доступен в виде небольшого (1 МБ) PDF-файла по ссылке "скачать" на этой странице или в виде глав в формате HTML. Он использует 32-битный x86 asm с синтаксисом AT&T в Linux и содержит полезные сведения о том, как "думать как компьютер", чтобы понять, как выполнять работу с помощью asm. Он охватывает некоторые важные вещи операционной системы, такие как виртуальная память и подобные вещи, необходимые для понимания происходящего, а также сам ассемблер / машинный язык.
- Учебное пособие по сборке - доктор Пол Картер
- Учебник по программированию сборки Windows
- Почему функции должны сохранять одни регистры, а другие нет? См. Ниже ссылки на руководства и документы для конкретных соглашений о вызовах.
- Как отследить, что делает функция: выяснить входы и выходы, а затем выяснить, что она с ними делает.
- Запуск программы Linux x86 или - Какого черта нам добраться до main()
- Учебник Whirlwind по созданию действительно маленьких исполняемых файлов ELF для Linux
- Что любят имена регистров
esi
означают, и какое у них особое предназначение. Это все аббревиатуры, например, регистр счетчика или указатель источника.
Руководства по настройке / оптимизации производительности:
- Руководства и ресурсы по оптимизации Agner Fog. Включает таблицы задержки / пропускной способности для P5 и новее. Также много качественного обсуждения того, как сделать ваш код быстрее. Также есть хорошее руководство по различным соглашениям о вызовах в операционных системах, а также рассматривается связывание / символы / перемещение.
- Семейство микроархитектур Intel Sandybridge не может объединять режимы индексированной адресации в неупорядоченном ядре, только в декодерах и uop-кэше. Также: выделенный блок адресов хранилища Haswell на порту 7 работает только с простыми эффективными адресами. Сложные эффективные адреса нуждаются в AGU на порте загрузки.
- Улучшенный REP MOVSB для memcpy: однопоточная полоса пропускания против совокупной пропускной способности на настольных компьютерах против многоядерных процессоров, RFO против не-RFO магазинов. (Современные процессоры имеют большую пропускную способность DRAM / L3, чем может использовать одно ядро; есть и другие узкие места, особенно в многоядерных чипах).
- Что каждый программист должен знать о памяти Ульрих Дреппер. (Первоначально опубликованный как серия статей LWN, Ульрих позже опубликовал PDF-файл). Как работают DRAM и кеши, их поведение и как оптимизировать программное обеспечение для локализации кеша. Включает некоторые диаграммы с реальными данными микробенчмарков для иллюстрации точек и пример умножения матрицы SSE2 с блокировкой кеша. Посмотрите обзор того, что устарело за 2017 год, например, предварительная выборка программного обеспечения P4 в основном устарела.
- Почему
xor same,same
Это лучше чемmov reg, 0
для обнуления регистра Есть несколько причин, некоторые простые и некоторые тонкие (например, избегание задержек частичного регистра в семействе P6/SnB). - Сериализация RDTSC с LFENCE vs. CPUID для тестирования коротких последовательностей в программе.
- Как получить количество циклов процессора в x86_64 из C++?(включая кучу информации о том, что
rdtsc
меры, и предостережения по его использованию, со ссылками на более подробную информацию). - Какие соображения нужно учитывать при прогнозировании задержки для операций на современных суперскалярных процессорах и как я могу рассчитать ее вручную?: введение в статический анализ производительности.
- Intel IACA (Intel Architecture Code Analyzer): анализируйте отмеченные участки кода на предмет пропускной способности (например, циклов на итерацию) или задержки критического пути. Предполагает идеальный кеш и другие упрощения, что не всегда правильно, но может быть полезно. Было остановлено, но снова обновлено для Skylake-X (AVX512). См. Что такое IACA и как его использовать? для учебника.
- Haswell микроархитектура, Бульдозеры микроархитектуры. Анализ Дэвида Кантера. Он также делал рецензии на более ранние исследования, такие как Sandybridge и Nehalem.
- Современные микропроцессоры - 90-минутное руководство!: от упорядоченного конвейерного к суперскалярному неупорядоченному. И brainiac (PPro) против демона скорости (Pentium 4), и Pentium 4 наталкивается на "стену мощности" в дизайне CPU.
- Быстрое введение в графы потоков данных: как анализировать цепочки зависимостей на предмет пропускной способности и задержки.
- http://www.uops.info/ очень подробное тестирование порта выполнения / uop / выполнения на процессорах Intel, обнаружив некоторые вещи, которые иногда не выполняются при повторении большого блока одной и той же инструкции (например, тестирование Агнера Фога).
- Новые процессоры обычно получают результаты AIDA64 InstLatx64 до того, как Agner Fog сможет тестировать и публиковать обновленные таблицы. Например, Skylake-avx512, а также https://github.com/InstLatx64/InstLatx64 для зеркала + таблица назначений портов Skylake-AVX512 (скомпилирована из выходных данных IACA-2.3). BDW vs. SKL указывает на некоторые интересные изменения в SKL (больше пропускной способности для большего количества инструкций, другая задержка FP).
- 2015 IDF слайды из доклада об управлении питанием Skylake К сожалению, основной сайт ( http://myeventagenda.com/sessions/0B9F4191-1C29-408A-8B61-65D7520025A8/7/5), на котором было видео (слайдов + аудио), сейчас отключен.
Ссылки на набор инструкций / asm-синтаксис:
- Поиск / поиск векторных встроенных функций Intel (очень хорошо): поиск по мнемонике asm или внутреннему имени C
- Список инструкций SIMD для x86/x64 (от SSE до AVX512) Бета: хорошая компактная таблица, в которой перечислены мнемоники инструкций и их встроенные функции, разбитые по типу и размеру элемента. Подробные страницы с графическими диаграммами движения данных для каждой инструкции.
- Руководства по SIMD в вики по тегам SSE, фокусируясь на том, как на самом деле эффективно использовать SIMD в целом, а не только на том, какие есть доступные инструкции.
- Руководства Intel, включая справочное руководство по набору инструкций. Чрезвычайно подробное описание всего, что каждая инструкция делает с архитектурным состоянием. Большой, но с приличным указателем / оглавлением. Также на этой странице: руководство Intel по оптимизации. Некоторые из тех же советов, что и руководства Агнера Фога, но иногда без точного объяснения причин с точки зрения портов выполнения микроархитектуры и других скрытых причин. Также иногда является устаревшим, например, не рекомендуется
inc
/dec
долгое время после P4 не имеет значения. - Руководства AMD по x86, включая справочные руководства по набору инструкций и руководства по оптимизации.
- HTML-версия справочника Intel insn set, автоматически сгенерированная из PDF. Одна страница на инструкцию, отлично подходит для ссылок в ответах.
- Другой HTML-экстракт, включая AVX512, CLFLUSHOPT и т. Д. Это делает его более загроможденным и труднее найти то, что вам нужно, если вы не ориентируетесь на AVX512. (Но обратите внимание, что CLFLUSH стал строго упорядоченным, но в HTML-экстракте felixcloutier.com все еще есть старая документация. В старых документах могут быть другие неточности, даже для старых инструкций.)
- https://sandpile.org/ - карты CPUID, кодирование инструкций, диаграммы регистров, карта кодов операций, прочие прочие технические детали.
- x86 Инструкция Ссылка в том числе при введении (8086, 186, 586 и т.д.) - NASM добавление В. Включает недокументированные инструкции, инструкции MMX только для Cyrix и тому подобное.
Форк более старой версии включает описания на английском языке. В оригинале были некоторые ошибки, в которых поколение вводило каждую форму каждого insn, но эта версия сохраняет хорошее форматирование, исправляя их. Удобно для людей, все еще разрабатывающих для x86-16. На аналогичной странице в Википедии не упоминается, что 386 требуется для более быстрой формы с двумя операндамиimul r16, r/m16
при этом не нужно вычислять верхнюю половину результата.
- Справочное руководство по коду операции x86, отсортированное по коду операции или мнемонике. 32,64 или оба в одной таблице. Версия "компьютерщика" включает нестандартные / недокументированные коды операций, версия "кодировщика" включает столбцы, показывающие, какие флаги считываются и записываются.
- Исходные ошибки / аномалии 8086, такие как
mov ss, src
неправильное отключение прерываний до конца следующей инструкции. Также смотрите родительский каталог, чтобы узнать о некоторых ошибках, недокументированных инструкциях и т. Д. Для 186/286/386. - Просто FPU: руководство по x87. Полезно для понимания старого кода x87, особенно. ранние разделы о том, как работает стек регистров. (Используйте SSE для нового кода.)
-
fsin
точность намного хуже, чем 1ulp для входов, близких к пи, вопреки предыдущей документации Intel. Другие статьи о FP в серии Брюса Доусона также превосходны ( индекс в этой статье по сравнению FP). - GNU
as
ручной, он же газовый мануал - Руководство NASM
- Руководство YASM: описывает синтаксис и макросы YASM. Отличная диаграмма регистров, показывающая частичные регистры с их кодировками машинного кода и напоминание о расширении нулями и неизмененными верхними частями. (Еще одна более простая диаграмма подмножества регистров для одного регистра).
Возможные канонические дубликаты для подмножеств регистров: регистры сборки в 64-битной архитектуре включают некоторые соглашения о вызовах / использование. Как AX, AH, AL сопоставляются с EAX? хорош для ошибок, когда AL и RAX использовались для разных целей, разрушая друг друга.
- Справочная документация MASM и старое руководство по MASM 6.1 1996 года. Непонятные скобки в MASM32 показывают, что MASM на удивление игнорирует скобки вокруг символических непосредственных значений.
- Синтаксис MASM, используемый JWasm. JWasm - портативный ассемблер.
- Руководство FASM
- таблица синтаксиса AT&T(GNU) и NASM для режимов адресации и косвенного
jmp
/call
- Все доступные режимы адресации (32/64-бит) (синтаксис Intel, с примечанием о NASM и MASM для
mov reg, symbol
) со ссылками на дальнейшие руководства. - Синтаксис режима адресации AT&T
- 16-битные режимы адресации.
- TODO: найдите хорошую ссылку на набор инструкций AMD XOP. (Не рекомендуется для общего использования; даже AMD отказывается от поддержки XOP в своей архитектуре Zen.)
- Памятка в PDF
- Шпаргалка по Win32
Специфические для ОС вещи: ABI и таблицы системных вызовов:
- x86 ABI (википедия): соглашения о вызовах функций, включая x86-64 Windows и System V (Linux). См. Также красивое руководство по соглашению о вызовах Агнера Фога.
- 32-битные абсолютные адреса больше не разрешены в x86-64 Linux?(Исполняемые файлы PIE теперь используются по умолчанию в большинстве дистрибутивов, при этом gcc настроен с
--enable-default-pie
.) - 64-битный формат Mach-O не поддерживает 32-битные абсолютные адреса. NASM Accessing Array (база образов OS X выше нижних 32, в отличие от исполняемых файлов Linux, зависящих от позиции). Также упоминаются 2 известные ошибки в некоторых версиях NASM с macho64 и относительной RIP или 64-битной абсолютной адресацией.
- Краткое изложение ABI System V по osdev: i386 и x86-64, со ссылками на произвольные копии дополнения для каждой архитектуры для различных архитектур, а также на общий gABI, который расширяется во всех документах по дополнению для конкретного процессора (psABI).
- System V psABI - официальные стандартные текущие версии для x86-64 и i386 (wiki-страница на github, обновляется HJ Lu). Прямая ссылка на x86-64 ревизия 1.0. Также ссылки на официальный форум для обсуждения ABI сопровождающими / участниками.
- clang / gcc sign / zero расширяет узкие аргументы до 32-битных, даже несмотря на то, что ABI System V в том виде, в каком они написаны, (пока?) не требует этого. От этого также зависит код, сгенерированный Clang.
- System V 32bit (i386) psABI (официальный стандарт, версия 1.1 от декабря 2015 г.), используется Linux и Unix. (Некоторые операционные системы не требуют выравнивания стека по 16 байт для 32-битного кода; GNU/Linux требует)
(Исторически сложилось так: очень старая версия SCO i386 SysV ABI, до того, как требовалось выравнивание стека 16 байт).
- Соглашение о вызовах OS X 32bit x86 со ссылками на остальные. 64-битное соглашение о вызовах - это System V. Сайт Apple для этого просто ссылается на PDF-файл FreeBSD.
Windows x86-64
__fastcall
соглашение о вызовахWindows
__vectorcall
: документирует 32-битную и 64-битную версииWindows 32 бит
__stdcall
: используется для вызова функций Win32 API. Эта страница ссылается на другие документы соглашения о вызовах (например,__cdecl
).Шпаргалка по ABI: x86 против x64 vectorcall и non-vectorcall против SysV. Раздел SysV не завершен.
Почему Windows64 использует другое соглашение о вызовах, чем все другие операционные системы на x86-64?: интересная история, особенно. для SysV ABI, где архивы списков рассылки являются общедоступными и существуют еще до выпуска AMD первого кремния.
32-битный код запуска CRT MSVC устанавливает точность x87 FPU на 53 (
double
). Вся эта серия статей (оглавление в этой) превосходна, включая вывод asm из MSVC в некоторых примерах.
- Полное руководство по системным вызовам Linux (на x86). Примеры использования
int 0x80
, 32-битныйsysenter
и 64-битныйsyscall
, и как позвонить через vDSO дляgettimeofday
, и есть некоторая информация о оболочках системных вызовов glibc. Множество деталей, а также некоторая справочная информация / основы для начинающих. - Таблицы системных вызовов Linux. 64-битные номера системных вызовов с отображением параметра-> регистр (получено из исходного кода ядра и стандартного правила для порядка аргументов).
- Системные вызовы FreeBSD: вопрос содержит системные вызовы FreeBSD, ответ - Linux и другие.
- Каковы соглашения о вызовах для системных вызовов UNIX и Linux на i386 и x86-64: Обратите внимание, что 32-разрядная версия
int 0x80
восстанавливает все регистры (включая флаги) кромеeax
, а 64-битнаяsyscall
также клобберыrcx
а такжеr11
а также помещая возвращаемое значение вrax
.
- 16-битный список прерываний: системные вызовы BIOS ПК (
int 10h
/int 16h
/ etc, AH=callnumber), системные вызовы DOS (int 21h
/AH=callnumber) и многое другое.
порядок памяти:
- Слабая и сильная модели памяти: что это значит, когда люди говорят, что x86 имеет "строго упорядоченную модель памяти". См. Также информационную страницу C++ для множества хороших ссылок, если вы используете атомику C11/C++11.
- Переупорядочение памяти схвачено: тестовый пример, демонстрирующий на практике переупорядочение памяти на многоядерном процессоре x86.
- Лучшая модель памяти x86: x86-TSO (расширенная версия) Формальное определение модели памяти x86, которое, надеюсь, соответствует тому, как ведет себя реальное оборудование.
- Почему нет
add dword [num], 1
атомарно, хотя это одна инструкция. Также спрашивает о компиляцииnum++
в C++. или См. также Атомарность на x86: что означает атомарность загрузки или хранилища и как это реализовано внутри?
Особое поведение конкретных реализаций
- TLB и Pagewalk Coherence в процессорах x86. Многие микроархитектуры x86, особенно Intel, предоставляют более строгие гарантии упорядочения, чем требует ISA для изменения записи в таблице страниц, которая еще не кэширована в TLB. Win95 даже зависел от этого. (Не пишите новый код, который зависит от этого.)
- Измерение емкости буфера переупорядочения Еще один экспериментальный тест, демонстрирующий возможности и ограничения внеочередного выполнения на реальном оборудовании.
- Каковы характеристики истощения RDRAND на Ivy Bridge? С ответом Дэвида Джонстона (разработчик Intel RNG HW и
librdrand
автор).
Вопросы и ответы с хорошими ссылками или прямо полезными ответами:
Использование встроенного ASM GNU C/C++. (Та же ссылка из раздела учебных ресурсов, но здесь стоит повторить.)
Каковы лучшие последовательности инструкций для генерации векторных констант на лету?
Параллельное программирование с использованием архитектуры Haswell
Деоптимизация программы для конвейера в процессорах семейства Intel Sandybridge. Имеет длинный ответ, включающий некоторые вводные сведения об архитектуре компьютера, а также подробности того, что может остановить конвейер Haswell.
Как я могу запустить этот ассемблерный код в OS X?: Руководство по началу работы с OS X. (Перед именами символов ставится
_
в OS X, в отличие от систем Linux ELF.)add / sub / LEA можно использовать с мусором в старших битах, поэтому
LEA eax, [rdi + rsi*2 - 15]
вычислитьa + 2*b - 15
отлично работает, даже еслиa
а такжеb
должны быть только 8 или 16 битами.TODO: найдите вопрос о том, как использовать профилировщик для измерения ошибок и прочего.
perf
поставляется с большинством дистрибутивов Linux, иocperf.py
- это оболочка для него, которая предоставляет более символические имена для таких вещей, как счетчики uop, специфичные для микроархов.
Часто задаваемые вопросы / канонические ответы:
Если у вас возникла проблема, связанная с одной из этих проблем, не задавайте новый вопрос, пока не прочитаете и не поймете соответствующие вопросы и ответы.
(TODO: найдите для них более удачные ссылки на вопросы. В идеале вопросы, которые будут хорошей дублирующей целью для новых дубликатов. Также расширьте это.)
Моя программа дает сбой / segfaults: вам нужно использовать отладчик, чтобы узнать, какая инструкция дает сбой (советы по GDB и Visual Studio см. Внизу этой вики-страницы по тегам). Большинство программ asm с ошибками дают сбой, поэтому без дополнительной информации это бесполезно. Причины могут включать засорение регистров или стековой памяти, которой у вас не должно быть,
esp
указывая не на то место передret
или по многим другим причинам, помимо следующих распространенных проблем.файл внешней сборки в Visual Studio - проект VS со смешанным исходным кодом x64, для файлов asm как часть программы C / C++.
Также программирование на ассемблере - WinAsm vs Visual Studio 2017 для чистого проекта asm.Сборка 32-битного кода на 64-битной системе (с помощью инструментария GNU).
gcc example.s
создает двоичный файл, который работает в 64-битном режиме, который выйдет из строя, если код был написан для 32-битного режима. Связано: что произойдет, если вы используете 32-битный int 0x80 Linux ABI в 64-битном коде?.Сборка исполняемого файла из источника asm, который определяет
_start
по сравнению с источником, который определяетmain
, сgcc
/as
/ld
и / или NASM. С libc или без, а также статический или динамический исполняемый файл.Падение конца
_start
не делаяsys_exit
.ret
не работает. Что произойдет, если в программе сборки нет системного вызова выхода?Казнь просто продолжается, если нет прыжка или возврата. Что делать, если в блоке кода CALLed в программах на ассемблере нет оператора return и почему не возвращается значение, если функция явно не использует ret.
Код неправильно выполняет условие? провалиться из
if
вelse
тело вif/else
. Красиво объясняет, что ярлыки не волшебство, и исполнение их не выдерживает.Ошибка сегментации при использовании БД (определить байт) внутри функции. Размещение данных там, где они выполняются, как код.
idiv
/div
проблемы: нольedx
сначала или знак-продлитьeax
внутрь.. 32-битныйdiv
ошибки с #DE, если частное 64b/32b => 32b на самом деле не соответствует 32b. (В системах POSIX, включая Linux, это повышаетSIGFPE
).
8-битный размер операнда как div dl
это особый случай, когда dx не задействован, только AX и AH/AL. Он по-прежнему дает сбой, если частное превышает 8 бит.
Нет вывода из
printf
когда я передаю вывод или печатаю что-то без новой строки? Когда вы используете системный вызов exit.Вызов printf в x86_64 с использованием соглашения о вызовах ассемблера GNU, выравнивания стека и рабочего примера. Связанная версия синтаксиса NASM Segfault при вызове функции C (printf) из сборки
Канонический дубликат для scanf segfaulting при смещении стека в современных Linux-сборках glibc: glibc scanf Ошибки сегментации при вызове из функции, которая не выравнивает RSP
Функции библиотеки изменяют регистры / какие регистры мои функции должны сохранять и восстанавливать? Это указывается в соглашении о вызовах (часть ABI) целевой платформы. Найдите эти термины на этой странице. Какие регистры должны быть сохранены функцией x86? достойный канонический дубликат.
несоответствие push/pop: если указатель стека не указывает на адрес возврата, когда вы
ret
, вы рушитесь.Как обращаться с многозначными числами? Системные вызовы Linux, Windows, OS X и DOS для обработки пользовательского ввода / вывода дают вам символы ASCII (или UTF-8) или строки символов. (Канонические вопросы и ответы о невыполнении одной цифры
sub al, '0'
). Обычно вам нужно преобразовывать строки в двоичные целые числа, чтобы вычислять их, как функции Catoi
илиsprintf(buf, "%d", number)
. Ни один из стандартных API системных вызовов для основных операционных систем, работающих на x86, не предоставляет вам эти функции; только как библиотеки.
преобразование строки в целое число (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.)
Загрузка указателей в регистры и загрузка данных в регистры: убедитесь, что вы понимаете разницу между
mov reg, symbol
а такжеmov reg, [symbol]
(Синтаксис NASM) или синтаксис MASM:mov reg, OFFSET symbol
vs.mov reg, symbol
. Многие вопросы новичков вызваны ошибками в разыменовании адресов или отсутствием разыменования. Это то же самое, что и указатели в C.Неверная комбинация кода операции и ошибки операндов на
mov [msg], [ebp+8]
? Вы не можете использовать два операнда памяти для одной инструкции. ( Почему IA32 не позволяет память переместить в память?)Битовые сдвиги и вращения требуют подсчета в
cl
, а не какой-либо другой регистр или как непосредственная константа.shl eax, ebx
невозможно,shl eax, 2
в порядке, и тожеshl eax, cl
Вызов абсолютного указателя в машинном коде x86 или
jmp
по абсолютному адресу. С примерами синтаксиса NASM и AT&T.Почему большинство инструкций x86-64 обнуляют верхнюю часть 32-битного регистра? Фактически, все инструкции, которые записывают 32-битный регистр, обнуляют верхние 32 полного 64-битного регистра, поэтому
mov eax, 1234
более эффективен, чемmov rax, 1234
, но эквивалент. Это не относится к записи в 8- и 16-битные регистры, напримерal
/ah
/ax
, так что тебе нужноmovzx
илиmovsx
если верхние биты могут содержать мусор, и вам необходимо их очистить (например, перед использованием в качестве части адреса памяти).Используете LEA для значений, которые не являются адресами / указателями? Это просто инструкция ALU "сдвиг и сложение", использующая синтаксис операндов памяти и машинное кодирование.
Переворачивая струну? Этот хорошо прокомментированный ответ использует 16-битные системные вызовы ms-dos для чтения строки, но фактический цикл по строке работает одинаково для 32- или 64-битного кода.
Индексирование массива без масштабирования индекса по ширине элемента, что приводит к перекрытию загрузок или сохранений. Объявление и индексирование целочисленного массива qwords в сборке (синтаксис x86-64 AT&T)
Как сделать X в ассемблере: обычно так же, как и на другом языке программирования, например C. Выясните, что должно произойти с данными, прежде чем вы увязнете в написании инструкций, чтобы это произошло.
С чего начать / Инструменты для отладки + руководства
Найдите отладчик, который позволит вам выполнять код за один шаг и отображать регистры, пока это происходит. Это очень важно. У нас много вопросов вроде "почему не работает этот код", которые можно было бы решить с помощью отладчика.
В 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):
-
clang
илиgcc -Wall -O3 -masm=intel foo.c -fverbose-asm -S -o- | less
(влияет на inline-asm) - GDB:
set disassembly-flavor intel
(можете войти в свой~/.gdbinit
) objdump -drwC -Mintel
perf report -Mintel
Еще один ключевой инструмент для отладки - отслеживание системных вызовов. например, в системе Unix,strace ./a.out
покажет вам аргументы и возвращаемые значения всех системных вызовов, которые делает ваш код. Он знает, как декодировать аргументы в символические значения, такие какO_RDWR
, так что это намного удобнее (и, вероятно, поймать мозги или неправильные значения для констант), чем использование отладчика для просмотра регистров до / после int
или syscall
инструкция. Обратите внимание, что в Linux это не работает.int 0x80
32-битные системные вызовы ABI в 64-битных процессах: что произойдет, если вы используете 32-битный int 0x80 Linux ABI в 64-битном коде?.
Чтобы отладить загрузочный код или код ядра, загрузите его в bochs, qemu или, возможно, даже в DOSBOX, или в любой другой виртуальной машине / симуляторе / эмуляторе. Используйте средства отладки на виртуальной машине, чтобы получить путь больше информации, чем обычный "он запирает" вы будете испытывать с багги привилегированным кодом.
BOCHS обычно рекомендуется для отладки загрузчиков в реальном режиме, особенно тех, которые переключаются в защищенный режим; Встроенный отладчик BOCHS понимает сегментацию (в отличие от GDB) и может анализировать GDT или IDT, чтобы убедиться, что вы правильно указали поля.