Какая польза от директивы ассемблера.byte в сборке GNU?
При прохождении некоторого кода C, имеющего встроенную сборку, я натолкнулся на директиву.byte (с точкой в начале).
При проверке ссылки на сборку в Интернете я обнаружил, что она используется для резервирования байта в памяти.
Но в коде не было метки перед утверждением. Поэтому мне было интересно, что такое использование немаркированной директивы.byte или любой другой директивы хранения данных в этом отношении.
Например, если я код .byte 0x0a
как я могу использовать это?
4 ответа
Есть несколько возможностей... вот пара, о которой я могу подумать:
Вы можете получить к нему доступ по отношению к ярлыку, который идет после
.byte
директивы. Пример:.byte 0x0a label: mov (label - 1), %eax
На основе окончательного связанного макета программы, возможно,
.byte
директивы будут выполняться как код. Обычно в этом случае у вас тоже будет ярлык...Некоторые ассемблеры не поддерживают генерацию префиксов команд x86 для размера операнда и т. Д. В коде, написанном для этих ассемблеров, вы часто будете видеть что-то вроде:
.byte 0x66 mov $12, %eax
Чтобы ассемблер испускал код, который вы хотите иметь.
Минимальный работоспособный пример
.byte
выплевывает байты, где бы вы ни находились. Есть ли метка или нет, указывающая на байт, не имеет значения.
Если вы оказались в текстовом сегменте, то этот байт может быть запущен как код.
Карл упомянул об этом, но вот полный пример, который позволит углубиться в это: реализация Linux x86_64 true
с nop
добавлено:
.global _start
_start:
mov $60, %rax
nop
mov $0, %rdi
syscall
производит точно такой же исполняемый файл как:
.global _start
_start:
mov $60, %rax
.byte 0x90
mov $0, %rdi
syscall
поскольку nop
закодирован как байт 0x90
,
Один вариант использования: новые инструкции
Один из вариантов использования - это когда новые инструкции добавляются в ISA процессора, но только самые передовые версии ассемблера будут поддерживать его.
Поэтому сопровождающие проекта могут выбрать встроенные байты напрямую, чтобы их можно было компилировать на старых ассемблерах.
Посмотрите, например, этот обходной путь Spectre для ядра Linux с аналогичным .inst
директива: https://github.com/torvalds/linux/blob/94710cac0ef4ee177a63b5227664b38c95bbf703/arch/arm/include/asm/barrier.h#L23
#define CSDB ".inst 0xe320f014"
Для Specter была добавлена новая инструкция, и ядро пока решило жестко ее кодировать.
Вот пример с встроенной сборкой:
#include <stdio.h>
void main() {
int dst;
// .byte 0xb8 0x01 0x00 0x00 0x00 = mov $1, %%eax
asm (".byte 0xb8, 0x01, 0x00, 0x00, 0x00\n\t"
"mov %%eax, %0"
: "=r" (dst)
: : "eax" // tell the compiler we clobber eax
);
printf ("dst value : %d\n", dst);
return;
}
Вы можете заменить .byte 0xb8, 0x01, 0x00, 0x00, 0x00
с mov $1, %%eax
результат запуска будет таким же. Это указывало на то, что это может быть байт, который может представлять какую-либо инструкцию, например, или другие.
.Byte - это директива, которая позволяет объявлять постоянный байт, известный только через проверку, без какого-либо контекста.
Из Руководства по сборке GNU:
.byte 74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.