Газовый макрос altmacro с знаком процента в параметре по умолчанию не выполняется: "% operator нуждается в абсолютном выражении"

Я хочу создать макрос следующим образом:

.altmacro

.macro assert_eq a, b=%eax
    LOCAL ok
    #...
.endm

Используется как:

assert_eq $1
assert_eq $1, %eax

Я хочу .altmacro для LOCAL (я вижу другую возможность использования \@, но хочу LOCAL).

Но когда я пытаюсь скомпилировать это, я получаю:

Error: % operator needs absolute expression

Я предполагаю, что эта проблема возникает из-за того, что b=%eax пытается использовать другую функцию, включенную .altmacro: Результаты выражения как строки, так как без .altmacro я мог бы написать это без проблем.

Если это так, как мне избежать того, что для работы моего макроса? Если нет, что не так с моим кодом?

Бонусный вопрос: как использовать %?

Версия GAS: 2.23.52

Ответ 1

У меня возникла очень похожая проблема, когда я хотел передать регистры в качестве аргументов макроса, который требовал использования .altmacro. Исправление, которое работало, заключалось в том, чтобы заключить регистры в < > и место! до %. Поэтому попробуйте изменить свой макрос

.macro assert_eq a, b=<%eax>

и если вы когда-нибудь захотите вызвать свой макрос с регистром в качестве аргумента, сделайте

assert_eq <%eax>, <%ecx>

Ответ 2

С .altmacro любой переданный или заданный параметр с процентом % обрабатывается как выражение.

Использование образца:

.altmacro

.macro PERCENT x
    mov $\x, %eax
.endm
mov $0, %eax
PERCENT %1+1
/* eax == 2 */

.macro PERCENT_DEFAULT x=%1+1
    mov $\x, %eax
.endm
mov $0, %eax
PERCENT_DEFAULT 1
/* eax == 1 */
PERCENT_DEFAULT
/* eax == 2 */

Чтобы предотвратить это расширение, мы должны сделать как упомянутый mfbutner:

.altmacro

.macro PERCENT x
    mov \x, %eax
.endm
PERCENT <%ebx>

.macro PERCENT_DEFAULT x=<%ebx>
    mov \x, %eax
.endm
PERCENT_DEFAULT

Поскольку это расширение происходит только с аргументами, а не внутри самого макроса, одна альтернатива, если мы уверены, что аргумент является регистром, заключается в том, чтобы поместить процент внутри макроса:

.macro PERCENT_ESCAPE_REG x
    mov %x, %eax
.endm
mov $0, %eax
mov $1, %ebx
PERCENT_ESCAPE_REG ebx
/* eax == 1 */

Но это имеет недостаток, что мы больше не можем передавать такие результаты, как $1:

PERCENT_ESCAPE_REG $1

Это для меня огромный поворот в использовании .altmacro, так как для каждого звонка требуется использовать дополнительный шум...