Давным-давно, но мне, вероятно, понадобится это для моей собственной будущей справки ...
Добавляя к замечательному ответу Криса, ключ использует модификатор между '%' и номером выходного операнда. Например, "MOV %1, %0"
может стать "MOV %q1, %w0"
.
Я не мог найти что-нибудь в constraints.md, но /gcc/config/i386/i386.c было это потенциально полезный комментарий в источнике для print_reg()
:
/* Print the name of register X to FILE based on its machine mode and number.
If CODE is 'w', pretend the mode is HImode.
If CODE is 'b', pretend the mode is QImode.
If CODE is 'k', pretend the mode is SImode.
If CODE is 'q', pretend the mode is DImode.
If CODE is 'x', pretend the mode is V4SFmode.
If CODE is 't', pretend the mode is V8SFmode.
If CODE is 'h', pretend the reg is the 'high' byte register.
If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
If CODE is 'd', duplicate the operand for AVX instruction.
*/
Комментарий ниже ix86_print_operand()
предложение пример:
b - напечатать имя регистра QI для указанного операнда.
% b0 напечатает% Аl, если операнды [0] является р 0.
Несколько более полезные варианты перечислены в Output Template в GCC Internals документации:
'% cdigit' может используется для замены операнда, который является постоянным значением без синтаксиса, который обычно указывает на непосредственный операнд.
«% ndigit» похоже на «% cdigit», за исключением того, что значение константы равно , которое было отменено перед печатью.
«% adigit» может использоваться для замены операнда, как если бы это была память ссылка с фактическим операндом, рассматриваемым как адрес. Это может быть полезно при выводе команды «адрес загрузки», потому что часто для синтаксиса ассемблера для такой инструкции требуется написать операнд , как если бы это была ссылка на память.
'% ldigit' используется для замены label_ref в инструкции перехода.
'% =' выводит число, которое уникально для каждой команды в сборнике . Это полезно для создания локальных ярлыков , упомянутых более одного раза в одном шаблоне, который генерирует несколько инструкций ассемблера.
«%c2
» конструкция позволяет правильно форматировать команду LEA с помощью смещения:
#define ASM_LEA_ADD_BYTES(ptr, bytes) \
__asm volatile("lea %c1(%0), %0" : \
/* reads/writes %0 */ "+r" (ptr) : \
/* reads */ "i" (bytes));
Примечания решающего, но редко задокументирован «с» в «%c1
». Этот макрос эквивалентен
ptr = (char *)ptr + bytes
, но без использования обычных целых арифметических портов выполнения.
Изменить, чтобы добавить:
Выполнение прямых вызовов в x64 может быть трудно, так как она требует еще один нелегальную модификатор: «%P0
» (который, кажется, для ПОС)
#define ASM_CALL_FUNC(func) \
__asm volatile("call %P0") : \
/* no writes */ : \
/* reads %0 */ "i" (func))
строчная Модификатор «p» также, похоже, действует одинаково в GCC, хотя ICC признает только капитал «P». Более подробная информация, вероятно, доступна по адресу /gcc/config/i386/i386.c. Найдите «p».
Я также тестировал .. Знаете ли вы также и модификаторы для низких и высоких байтов? –
Спасибо, я рад, что это помогло! –
'xchg% al,% ah' - это 3 процессора на процессорах Intel, а чтение 16-битного топора приводит к тому, что на некоторых процессорах происходит свалка с частичным регистром или дополнительные удары. 'ror $ 8,% ax' - 1 uop, поэтому это определенно предпочтительнее. Кроме того, модификаторы операндов [теперь задокументированы в руководстве] (https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#x86Operandmodifiers) (используя этот же пример, возможно, не совпадение: P). См. Также: модификаторы операнда для векторных рег: http://stackoverflow.com/questions/34459803/in-gnu-c-inline-asm-whatre-the-modifiers-for-xmm-ymm-zmm-for-a-single -operand –