Вызов функции сборки из 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;
}