При сборке с NASM следующее:
BITS 64
push 32767
Я понимаю 68 ff 7f 00 00
. Мне это интересно, так как это кодировка 32b (push dword
). Есть идеи, почему он не прибегает к кодировке 16b (которая будет короче и будет использовать меньше памяти стека)?
Я пробовал различные комбинации немедленных действий, но, похоже, он никогда не использует кодировку 16b.
Если вы не указываете размер, NASM предполагает, что вы имеете в виду размер операнда по умолчанию, в данном случае 64 бита. Если вы хотите передать 16 бит, вам необходимо указать размер.
16-битный немедленный доступ доступен только при 16-битном размере операнда.
(RSP -= 2
и делаем 2-байтовое хранилище: push word 0x7fff
).
Как и большинство инструкций x86, таких как add
, здесь нет кодировки sign_extended_imm16
. (Особенность push
и других операций стека заключается в том, что размер операнда по умолчанию равен 64 в 64-битном режиме, его невозможно переопределить до 32 даже с префиксом REX, а только до 16-битного с префиксом 66
. По сравнению с другими кодами операций по умолчанию. до 32, с 64-битной кодировкой с помощью REX.W. 8-битная версия имеет свои собственные коды операций, поскольку она восходит к 8086. 32 и 64 были добавлены расширениями, и для новых кодов операций не было места, только префиксы.)
В 32- и 64-битном режиме без префикса размера операнда для указания 16-битного размера операнда непосредственные значения либо 8-битные с расширением знака, либо 32-битные (с расширением знака, если размер операнда 32-битный). Это относится ко всем обычным кодам операций; есть пара особых случаев, таких как mov r64, imm64
и enter imm16,imm8
.
В NASM push 1234
по умолчанию равен push qword 1234
, а не push word 1234
, потому что это то, чего обычно хотят люди. (См. Сколько байтов инструкция push помещает в стек, когда я не указываю размер операнда? Не дубликат, поскольку в моем ответе IIRC не подробно рассказывается о том, что push imm16
существует только для 16-битных размер операнда.)
Таблица в верхней части руководства Intel для push
(выдержка из HTML: https://www.felixcloutier.com/x86/push) не совсем ясна по этому поводу, поскольку в столбце «описание» не упоминается операнд. -размер. В текстовом разделе «Описание» об этом также не упоминается.
68 iw
и 68 id
— это один и тот же код операции, поэтому единственный способ узнать, что ЦП вам нужно, — это атрибут размера операнда. Это, а также общие правила кодирования размера операнда (по умолчанию, подразумеваемые текущим режимом, переопределяемые префиксами) подразумевают, что невозможно закодировать 68 iw
, который будет расширен по знаку до более широкой ширины; 68
принимает iw
(непосредственное слово) только в том случае, если размер операнда 16-битный.
Я вижу, это имеет смысл. Спасибо!
Посмотрите это