Это просто gdtr+2
gdtr(2,1)
[выдает ошибку], но использование gdtr(,1)
работает нормально.
Материал внутри ()
Парены в режиме адресации AT & T могут быть только регистрами (и масштабным коэффициентом): disp(base, index, scale)
. База и индекс необязательны, поэтому пусто - это хорошо, но недопустимо (не зарегистрировано) - нет.
И когда вы указываете шкалу без базы или индекса, очевидно, вы должны использовать только одну запятую: (,,1)
является ошибкой относительно пустого масштабного коэффициента.
Вы можете написать его как gdtr+2(,1)
, чтобы явно не использовать регистры.
+2 является частью смещения в режиме адресации, а не регистры базы или индекса независимо от синтаксиса . См. Несколько вопросов о [base + index * scale + disp] или руководстве Intel или AMD о том, как кодируются режимы адресации. (То, что вы делаете, это режим адресации [disp32]
или [disp16]
, с точки зрения того, как он будет закодирован в машинный код.)
Как указал Нейт, компоновщик позаботится о повороте сборки -временные литеральные константы + адреса константных символов времени связи в конечный адрес в машинном коде, закодированный как disp32
(или disp16
для 16-битного размера адреса). Или RIP-относительный rel32
для x86-64.
Интересный факт: некоторые сборщики AT & T принимают (gdtr)
в качестве альтернативы gdtr
, но не 2(gdtr)
.
Способы решить это самостоятельно:
Обычно, если вы застряли на NASM -> AT & T, вы можете собрать источник NASM (например, nasm -felf
) и разобрать с помощью дизассемблера AT & T, например objdump -drwC
. Но это не поможет здесь для символического c синтаксиса режима адресации, потому что в лучшем случае objdump -dr
просто аннотирует числительные c режимы адресации с информацией об имени символа.
Так что в этом случае вам лучше всего получить G CC или clang для выдачи инструкции, которая использует имя символа и константу цифры c, например,
char gdtr[1024]; // global var so it has a symbol
char foo() { return gdtr[2]; } // load from global symbol + constant.
компилируется с gcc9.3 -O2 -m32
в проводнике компилятора Godbolt к этому asm:
foo:
movzbl gdtr+2, %eax
ret
gdtr:
.zero 1024
Есть ваш режим адресации, и в качестве бонуса AT & T мнемони c для movzx с источником байтов. Конечно, вы можете поиграть с типами.
Компиляторы являются полезными ресурсами; они знают, как делать много вещей "обычным образом" при компиляции простых функций C, и они знают соглашение о вызовах и ширину типов. И AT & T синтаксис для всего, включая указатели функций. Если вы застряли, попросите компилятор . По сути, единственное, что вы не можете заставить показать компилятор, это синтаксис jmp far
(AT & T ljmp
)