Суммирует адрес переменной памяти в значение регистра eax вместо значения переменной.
Да, синтаксис встроенной сборки gcc довольно загадочный. Если перефразировать соответствующий раздел * HOWTO "m"
, встроенного в сборку GCC, то приблизительно даст вам место в памяти для переменной C.
Это то, что вы используете, когда вам нужен адрес, по которому вы можете писать или читать. Заметьте, я сказал, что местоположение переменной C , поэтому %0
установлено на адрес Word32 *var
- у вас есть указатель на указатель. Трансляция C встроенного блока сборки может выглядеть как EAX += *(&var)
, потому что вы можете сказать, что ограничение "m"
неявно берет адрес переменной C и дает вам адресное выражение, которое вы затем добавляете к %eax
.
Есть ли способ указать команде addl использовать значение var вместо адреса var mem без копирования адреса var mem в регистр?
Это зависит от того, что вы имеете в виду. Вам нужно получить var
из стека, поэтому кто-то должен разыменовать память (см. Ответ @Bo Perssons), но вам не нужно делать это во встроенной сборке
Ограничение должно быть "m"(*var)
(как предложено @fazo). Это даст вам область памяти значения, которое var
указывает на , а не область памяти, указывающую на нее.
Сгенерированный код теперь:
test_func:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
#APP
# 2 "test.c" 1
addl (%eax), %eax
# 0 "" 2
#NO_APP
popl %ebp
ret
Это немного подозрительно, но это понятно, так как вы забыли сообщить GCC, что вы засорились (изменено без наличия в списке ввода / вывода) %eax
. Исправление, которое asm("addl %0, %%eax" : : "m"(*var) : "%eax" )
генерирует:
movl 8(%ebp), %edx
addl (%edx), %eax
Что не лучше и не правильнее в этом случае, но всегда полезно помнить. См. Раздел в списке clobber и обратите особое внимание на "memory"
clobber для расширенного использования встроенной сборки.
Даже если вы не хотите (явно) загружать адрес памяти в регистр, я кратко расскажу о нем.
Изменение ограничения с "m"
на "r"
почти работает, соответствующие разделы изменяются на (если мы включим %eax
в список clobber):
movl 8(%ebp), %edx
addl %edx, %eax
Что почти правильно, мы загрузили значение указателя var
в регистр, но теперь мы должны указать сами, что загружаем из памяти. Изменение кода в соответствии с ограничением (обычно нежелательно, я показываю его только для полноты):
asm("addl (%0), %%eax" : : "r"(var) : "%eax" );
Дает:
movl 8(%ebp), %edx
addl (%edx), %eax
Так же, как с "m"
.