Макрос, заменяющий постоянное число в ГАЗЕ - PullRequest
8 голосов
/ 05 мая 2011

Что не так с этим макросом в сборке X86 GNU? Он говорит, что символ S не определен во время связывания.

.macro S size=40
\size
.endm

Я использую это как

mov %eax, S

Ответы [ 2 ]

17 голосов
/ 05 мая 2011

Макросы используются для создания шаблонов для кода, который вы часто используете, а не для ввода постоянного числа.Таким образом, я не верю, что ассемблер выполняет расширение макроса в выражении.Поскольку вам просто нужно число, вы можете использовать .set для определения константы.

.set S, 40
mov %eax, S

Кроме того, если вы обычно используете синтаксис Intel, убедитесь, что вы понимаете, что делает этот код: он в настоящий момент хранитзначение eax в памяти по адресу 0x28.Если вы хотите ввести число 40 в eax, вам нужно обратить операнды в обратном направлении и использовать знак доллара перед S.

mov $S, %eax
1 голос

Вы также можете напрямую назначать символы со знаком равенства =:

S = 40

, что, как сказано в руководстве GNU, эквивалентно использованию .set https://sourceware.org/binutils/docs-2.19/as/Setting-Symbols.html#Setting-Symbols

Символу можно присвоить произвольное значение, написав символ с последующим знаком равенства =', followed by an expression (see Expressions). This is equivalent to using the .set directive. See .set. In the same way, using a double equals sign = '`=' здесь представляет эквивалент директивы .eqv.См. * .Eqv.

.equ - это еще один синоним ...

 .equ S, 40

Один из типичных случаев использования таких констант - это вычисление длины статических строк, напримерПриветственный мир Linux x86_64 можно записать в виде:

    .data
hello_world:
    .ascii "hello world\n"
    hello_world_len = . - hello_world
.text
.global _start
_start:
    /* write */
    mov $1, %rax
    mov $1, %rdi
    mov $hello_world, %rsi
    mov $hello_world_len, %rdx
    syscall

    /* exit */
    mov $60, %rax
    mov $0, %rdi
    syscall

, который вы можете скомпилировать и запустить с помощью wth:

as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out

%rdx будет содержать длину записываемой строки.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * $ требуется, как и для любой обычной метки адреса, в противном случае вы бы попытались получить доступ к этому адресу памяти, а не перемещать немедленный.

...