В цепочке инструментов GCC по умолчанию используется синтаксис ассемблера AT & T, но поддержка синтаксиса Intel доступна через директиву .intel_syntax
.
Кроме того, синтаксис AT & T и Intel доступен в версиях prefix
и noprefix
, которые различаются в зависимости от того, требуется ли им префикс имени регистра с символом %
.
В зависимости от того, какие директивы присутствуют, формат адресных констант изменяется.
Давайте рассмотрим следующий код C
*(int *)0xdeadbeef = 0x1234;
Используя objdump -d
, мы находим, что он скомпилирован в следующую инструкцию ассемблера
movl $0x1234,0xdeadbeef
Поскольку здесь нет регистров, это правильный синтаксис для .att_syntax prefix
и .att_syntax noprefix
, т.е. встроенный в код C, они выглядят так:
__asm__(".att_syntax prefix");
__asm__("movl $0x1234,0xdeadbeef");
__asm__(".att_syntax noprefix");
__asm__("movl $0x1234,0xdeadbeef");
При желании вы можете заключить адресную константу в круглые скобки, например.
__asm__("movl $0x1234,(0xdeadbeef)");
тоже будет работать.
При добавлении сигиллы в константу простого адреса код не будет скопирован
__asm__("movl $0x1234,$0xdeadbeef"); // won't compile
При окружении этого выражения парантезом компилятор выдаст неверный код без предупреждения, т.е.
__asm__("movl $0x1234,($0xdeadbeef)"); // doesn't warn, but doesn't work!
Это неправильно выдает инструкцию
movl $0x1234,0x0
В режиме Intel перед константой адреса должен стоять регистр сегмента, а также размер операнда и флаг PTR
, если возможна неоднозначность. На моей машине (двухъядерный ноутбук Intel с Windows XP и текущими версиями MinGW и Cygwin GCC) регистр ds
используется по умолчанию.
Квадратные скобки вокруг константы являются необязательными. Адресная константа также правильно распознается, если регистр сегмента опущен, но скобки присутствуют. Если пропустить регистр, в моей системе выдается предупреждение.
В режиме prefix
регистр сегмента должен начинаться с префикса %
, но работать будут только скобки. Это разные способы создания правильной инструкции:
__asm__(".intel_syntax noprefix");
__asm__("mov DWORD PTR ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!
__asm__(".intel_syntax prefix");
__asm__("mov DWORD PTR %ds:0xdeadbeef,0x1234");
__asm__("mov DWORD PTR %ds:[0xdeadbeef],0x1234");
__asm__("mov DWORD PTR [0xdeadbeef],0x1234"); // works, but warns!
Если регистр сегмента и скобки пропущены, компиляция не будет
__asm__("mov DWORD PTR 0xdeadbeef,0x1234"); // won't compile
Я отмечу этот вопрос как вики сообщества , поэтому, если у вас есть что добавить, не стесняйтесь.