Как заставить NASM кодировать `push` с помощью 16-битного расширения со знаком?

При сборке с NASM следующее:

BITS 64
push 32767

Я понимаю 68 ff 7f 00 00. Мне это интересно, так как это кодировка 32b (push dword). Есть идеи, почему он не прибегает к кодировке 16b (которая будет короче и будет использовать меньше памяти стека)?

Я пробовал различные комбинации немедленных действий, но, похоже, он никогда не использует кодировку 16b.

Посмотрите это

Iman Abdollahzadeh 06.07.2024 10:04

Если вы не указываете размер, NASM предполагает, что вы имеете в виду размер операнда по умолчанию, в данном случае 64 бита. Если вы хотите передать 16 бит, вам необходимо указать размер.

ecm 06.07.2024 10:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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-битный.

Я вижу, это имеет смысл. Спасибо!

Goubermouche 07.07.2024 15:55

Другие вопросы по теме