Вызов функции сборки из c
Я пытаюсь вызвать функцию сборки из c, но я продолжаю получать ошибки.
.text
.globl integrate
.type integrate, @function
integrate:
push %ebp
mov %esp, %ebp
mov $0,%edi
start_loop:
cmp %edi,1024
je loop_exit
mov 8(%ebp),%eax
mov 12(%ebp),%ecx
sub %eax,%ecx
add %edi,%ecx
incl %edi
jmp start_loop
loop_exit:
movl %ebp, %esp
popl %ebp
ret
Это моя функция сборки, файл с именем integrate.s.
#include <stdio.h>
extern int integrate(int from,int to);
void main()
{
printf("%d",integrate(1,10));
}
Вот мой код c.
function.c:5:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
/tmp/cciR63og.o: In function `main':
function.c:(.text+0x19): undefined reference to `integrate'
collect2: ld returned 1 exit status
Всякий раз, когда я пытаюсь скомпилировать свой код с помощью функции gcc -Wall function.c -o, он дает ссылку undefined для интеграции ошибки. Я также попытался добавить ссылку на файл integrate.s из c, например
#include<(file path)/integrate.s>
но он не работал так хорошо. Кстати, что делает код сборки, это не важно, на данный момент я просто пытаюсь вызвать функцию из c успешно. Может ли кто-нибудь помочь мне решить эту проблему?
Ответы
Ответ 1
Я вижу следующие проблемы с кодом:
- вы должны сохранить значение
edi
-
cmp %edi,1024
использует 1024
как адрес и, вероятно, будет виноват. Вы хотите cmp $1024,%edi
для сравнения с немедленным числом
- вы перезагружаете
eax
и ecx
из аргументов каждой итерации, поэтому выполняемый вами расчет не имеет эффекта
- вы, кажется, не помещаете никакого разумного возвращаемого значения в
eax
(он вернет значение from
, которое было передано)
Первые два пункта применяются, даже если "какой код сборки не важен".
Ответ 2
предупреждение: тип возврата 'main is not' int
означает, что возвращаемый тип "main is not" int... Измените его на int
, затем:
int main()
{
}
Кроме того, чтобы решить ошибку компоновщика, вызовите GCC как
gcc -o myprog main.c integrate.s
и это должно работать.
Ответ 3
Не уверен, что вы решили это или нет, но вот как я это сделал.
При компиляции обязательно добавьте оба файла: $gcc main.c print_msg.s -o main
Чтобы запустить файл ассемблера самостоятельно: $as print_msg.s -o print_msg.o
, а затем $ld print_msg.o -e print -o print_msg
. Обратите внимание, что это не требуется, если вы хотите запустить его только из своего файла C.
Файл ассемблера:
print_msg.s
# A program to be called from a C program
# Declaring data that doesn't change
.section .data
string: .ascii "Hello from assembler\n"
length: .quad . - string
# The actual code
.section .text
.global print
.type print, @function #<-Important
print:
mov $0x1,%rax # Move 1(write) into rax
mov $0x1,%rdi # Move 1(fd stdOut) into rdi.
mov $string,%rsi # Move the _location_ of the string into rsi
mov length,%rdx # Move the _length_ of the string into rdx
syscall # Call the kernel
mov %rax,%rdi # Move the number of bytes written to rdi
mov $0x3c,%rax # Move 60(sys_exit) into rax
syscall # Call the kernel
то файл C: main.c
extern void print(void);
int main(void)
{
print();
return 0;
}