#assembly #arm #ds-5
#сборка #arm #ds-5
Вопрос:
Я пытаюсь собрать некоторый относительно простой код, который использует две функции, fact
и exp
. Однако всякий раз, когда я пытаюсь перейти к любому из них, я получаю сообщение об ошибке следующего содержания: undefined reference to 'fact'
и undefined reference to 'exp'
. Я попытался добавить .global fact
и .global exp
в начало файла, но это не помогло. Вот мой код:
.text
.global main
.extern printf
main:
ldr x2,=x // load 'x' -> x value
ldr d2,[x2]
ldr x2,=n // load 'n' -> stopping point
ldr x3,[x2]
mov x2,#1 // set i/exp value to 1
scvtf d1,x2 // default d1 (return value) to 1.0
loop:
subs xzr, x3, x2
ble done
sub sp, sp, #16
str x2,[sp] // save the value of x2 first
sub x7, x2, #1
bl fact
ldr x2,[sp] // get original x2 value back
add sp, sp, #16
mov x5, #0
fmov d4, d2
.func fact
mul x2, x2, x7
sub x7, x7, #1
cbnz x7,fact
mov x4, x2
br x30
.endfunc
.func exp
fmul d4, d4, d4
add x5, x5, #1
cmp x5, x2
bl exp
br x30
.endfunc
done:
// done
.data
n:
.quad 5
x:
.double 1.45
.end
Комментарии:
1. Какой ассемблер вы используете? Я подозреваю, что
.func
это не делает того, что вы думаете.2. В частности, если это ассемблер GNU
.func
и.endfunc
не генерирует никакого кода или меток, только отладочную информацию. Вы должны просто поставить меткуfact:
в начале своей функции и пропустить.func/.endfunc
, если вы действительно не знаете, что вы делаете, что касается отладочной информации.3. Кстати, я считаю, что в ARM64 обычно следует использовать
ret
вместоbr x30
возврата из подпрограммы. В отличие от ARM32, на самом деле это разные кодировки, и я думаюret
, что это лучше для предсказателя ветвлений.4. @NateEldredge понял, спасибо.
5. О, и ваш
bl exp
внутреннийexp
цикл создаст бесконечный цикл. Я думаю, возможно, вы имели в видуb.lt
.
Ответ №1:
В ассемблере GNU .func
и .endfunc
служит только для передачи отладочной информации. Они не заменяют фактическое определение метки. (Они также не выдают никакого кода пролога или эпилога, что могло быть вашим следующим предположением.)
Поэтому вы должны просто написать, как и для других ваших точек входа:
fact:
mul x2, x2, x7
// ...
Вы могли бы также опустить .func/.endfunc
, если вы не собираетесь также создавать надлежащую информацию об отладке для остальной части вашего кода, что обычно не стоит проблем для рукописной сборки.