Привет.
Почему не линкуется такая конструкция:
Есть файл foo.S
.global foo
.data
.text
foo:
movl 4(%esp), %eax
imull %eax, %eax
ret
и main.c
#include <stdio.h>
int foo(int);
int main()
{
int sum = foo(100);
printf("%d", sum); // sum = 3, x = 1, y = 2
return 0;
}
Собираю:
gcc main.c foo.S
Но линкер не находит функцию foo
main.c
.text+0x16): undefined reference to `foo'
Чего не хватает ему?
Спасибо.
Здравствуйте, Losar, Вы писали:
L>Но линкер не находит функцию foo
L>main.c:(.text+0x16): undefined reference to `foo'
L>Чего не хватает ему?
Это всё проклятый name mangling.
Есть пара приемлемых способов исправить это:
extern int foo(int) __asm__("foo");
Либо изменить имя в соответствии с соглашениями конкретной платформы:
.global _foo
.data
.text
_foo:
...
Но в этом случае сломается сборка под другие платформы.
В теории ещё можно задействовать опасные опции компилятора вроде -fno-leading-underscore, но даже если они помогут тут, это приведёт к более серьёзным проблемам, так как нарушит ABI.
Здравствуйте, watch-maker, Вы писали:
WM>Здравствуйте, Losar, Вы писали:
L>>Но линкер не находит функцию foo
L>>main.c.text+0x16): undefined reference to `foo'
L>>Чего не хватает ему?
WM>Это всё проклятый name mangling.
WM>Есть пара приемлемых способов исправить это:
WM>
WM>Задать явное имя:
WM>extern int foo(int) __asm__("foo");
WM>Либо изменить имя в соответствии с соглашениями конкретной платформы:
WM>WM>.global _foo
WM>.data
WM>.text
WM>_foo:
WM>...
WM>
Но в этом случае сломается сборка под другие платформы.
WM>
WM>В теории ещё можно задействовать опасные опции компилятора вроде -fno-leading-underscore, но даже если они помогут тут, это приведёт к более серьёзным проблемам, так как нарушит ABI.
Спасибо за советы, буду смотреть.
Здравствуйте, Losar, Вы писали:
L>Привет.
L>Почему не линкуется такая конструкция:
L>Есть файл foo.S
L>L>.global foo
L>.data
L>.text
L>foo:
L> movl 4(%esp), %eax
L> imull %eax, %eax
L> ret
L>
L>Но линкер не находит функцию foo
L>main.c.text+0x16): undefined reference to `foo'
L>Чего не хватает ему?
L>Спасибо.
Думаю дело в том, что вы не объявляете ваш символ публичным.
Лучше всего оформить это дело в виде процедуры:
foo proc PUBLIC
ret
foo endp
Ассемблер не имеет манглинга, и выставляет такое имя которое вы укажете, например: ?swap@@YIKK@Z
Поэтому если вы видите, что С не находит символ просто копируете эту строчку и подставляете вместо имени
Ну и не забывайте про call-conventions.