Единственная причина, по которой вы обычно используете .code16
, .code32
или .code64
, заключается в ядре или загрузчике , когда вы хотите иметь машинный код для разных режимов в одном файле, Например, загрузчик, который запускается в реальном режиме (.code16
), может включить защищенный режим и выполнить дальний переход (ljmp
) к сегменту 32-битного кода. Вы хотите использовать .code32
перед этим блоком кода.
Если это не то, что вы делаете, не используйте их.
Использование их в других случаях просто позволяет вам застрелите себя в ногу и поместите 16-битный машинный код в 32-битный или 64-битный исполняемый файл ELF, чтобы вы получили ошибку времени выполнения вместо того, чтобы перехватить ошибку во время сборки. (например, потому что push %eax
недопустим в 64-битном режиме). Не помещайте .code32
в начало вашей 32-битной программы; используйте комментарий, который говорит, что для сборки с gcc -m32
.
Эти директивы сообщают ассемблеру, в каком режиме будет CPU, когда он декодирует эти инструкции . Таким образом, он знает, каким будет размер операнда по умолчанию и размер адреса, и нужен ли префикс для инструкции, которая использует 32-битный или 16-битный регистр.
Так, например, mov %eax, (%ecx)
монтируется в 89 01
в 32-битном режиме.
Но после .code16
он монтируется в 67 66 89 01
.
Если вы затем разберете это как 32-битный машинный код, это 67 66 89 01 mov %ax, (%bx,%di)
(потому что ModRM отличается для операндов памяти в 16 против 32 и 64-битном режиме).
Обычно вы не используете .code16
вручную. Вы можете использовать gcc -m16 foo.c
, чтобы получить G CC для вставки .code16gcc
в начало файла, так что вы можете запустить его в 16-битном режиме, даже если он по-прежнему будет использовать 32-битный размер операнда и размер адреса (требуется 386-совместимый ЦП).
Если вы хотите включить 32 или 16-битный машинный код в качестве данных в обычную 64-битную программу, например, вашу программу Вы можете записать его в файл или изменить запущенный процесс, вы также можете использовать .code32
или .code16
.