Я полагаю, что проблема, с которой вы сталкиваетесь, проста: формат Mach-O требует перемещения кода, что означает, что доступ к данным должен осуществляться не по абсолютному адресу, а по относительному адресу. То есть ассемблер не может преобразовать name
в константу, поскольку она не константа, данные могут быть по любому адресу.
Теперь, когда вы знаете, что адрес данных относится к адресу вашего кода, посмотрите, сможете ли вы понять вывод из GCC. Например,
static unsigned global_var;
unsigned inc(void)
{
return ++global_var;
}
_inc:
mflr r0 ; Save old link register
bcl 20,31,"L00000000001$pb" ; Jump
"L00000000001$pb":
mflr r10 ; Get address of jump
mtlr r0 ; Restore old link register
addis r2,r10,ha16(_global_var-"L00000000001$pb") ; Add offset to address
lwz r3,lo16(_global_var-"L00000000001$pb")(r2) ; Load global_var
addi r3,r3,1 ; Increment global_var
stw r3,lo16(_global_var-"L00000000001$pb")(r2) ; Store global_var
blr ; Return
Обратите внимание, что это на PowerPC, потому что я не знаю ABI Mach-O для x86-64. На PowerPC вы делаете прыжок, сохраняя счетчик программ, а затем выполняете арифметику с результатом. Я полагаю, что на x86-64 происходит нечто совершенно иное.
(Примечание: если вы посмотрите на вывод сборки GCC, попробуйте посмотреть на него с помощью -O2
. Я не буду беспокоиться о том, чтобы посмотреть -O0
, потому что он слишком многословен и труднее для понимания.)
Моя рекомендация? Если вы не пишете компилятор (а иногда даже тогда), пишите свои ассемблерные функции одним из двух способов:
- Передать все необходимые указатели в качестве аргументов функции, или,
- Запишите сборку как встроенную сборку внутри функции C.
Как правило, это также будет более переносимым, так как вы будете меньше полагаться на определенные детали ABI. Но ABI все еще важен! Если вы не знаете ABI и следите за ним, то вы будете вызывать ошибки, которые довольно сложно обнаружить. Например, несколько лет назад в коде сборки LibSDL была ошибка, из-за которой memcpy
(также сборка) из libc при некоторых очень специфических обстоятельствах копировала неправильные данные.