c linux assembly ld gas

¿Cómo vincular un archivo de objeto C con un archivo de objeto de Lenguaje de ensamblaje?



linux assembly (2)

ld -melf_i386 -e main main2.o strlength.o -o test

No hagas eso. Haz esto en su lugar:

gcc -m32 main2.o strlength.o -o test

(Probablemente no deba realizar la prueba ejecutable de test , ya que puede entrar en conflicto con la norma /bin/test , en la mayoría de los sistemas UNIX).

Explicación: los binarios de UNIX generalmente no comienzan a ejecutarse en main . Empiezan a ejecutar en una función llamada _start , que proviene de crt1.o o similar ("C Runtime startup"). Ese archivo es parte de libc y organiza varias inicializaciones, necesarias para el correcto inicio de su aplicación.

Su programa en realidad no requiere nada de libc , por lo que pudo vincularlo con ld .

Sin embargo, considere lo que sucede después de sus devoluciones main . Normalmente , el código en crt1.o se ejecutará (equivalente a) exit(main(argc, argv)); . Dado que se ha vinculado sin crt1.o , no hay nadie para hacer esa exit final, por lo que el código vuelve a ... ubicación indefinida y se bloquea rápidamente.

Tengo problemas para vincular 2 archivos de objetos, uno de los cuales se generó a partir de un archivo de origen de lenguaje de ensamblado y otro que se generó a partir de un archivo de origen de C.

C código fuente:

//main2.c extern int strlength(char *); int main(){ char * test = "hello"; int num = strlength(test); return num; }

Código fuente de la Asamblea:

#strlength.s .include "Linux32.s" .section .text .globl strlength .type strlength, @function strlength: pushl %ebp movl %esp, %ebp movl $0, %ecx movl 8(%ebp), %edx read_next_byte: movb (%edx), %al cmpb $END_OF_FILE, %al jle end incl %edx incl %ecx jmp read_next_byte end: movl %ecx, %eax popl %ebp ret

Cuando compilo y corro usando ''gcc'' de esta manera:

gcc main2.c strlength.s -m32 -o test ./test echo $?

Obtengo 5 que es correcto Sin embargo, cuando compilo / ensamblo por separado y luego enlace con ''ld'' de esta manera:

as strlength.s --32 -o strlength.o cc main2.c -m32 -o main2.o ld -melf_i386 -e main main2.o strlength.o -o test ./test

Me sale un error de segmentación. ¿Qué está causando esto? ¿No estoy siguiendo la convención de llamadas C al 100% correctamente?


También necesita vincular el crt1.o (podría tener un nombre diferente, contiene el código necesario hasta que se pueda llamar a main ) y las bibliotecas necesarias. GCC también necesita generalmente vincularse a libgcc.so que contiene las funciones auxiliares necesarias (por ejemplo, al hacer cálculos de 64 bits en un sistema de 32 bits) más otras bibliotecas del sistema. Por ejemplo, en mi Mac, también necesita vincularse a libSystem que también contiene las funciones C habituales, como printf . En Linux, eso suele ser libc .

Tenga en cuenta que su programa no puede comenzar directamente con main (ya que está tratando de hacer con ld .. -e main ), el punto de entrada necesita configurar algunas cosas antes de llamar a la función C main . Eso es lo que está haciendo el crt1.o previamente mencionado. Supongo que la falla de segmentación es el resultado de esta configuración faltante.

Para ver qué hace exactamente GCC en su sistema , llame al:

gcc main2.c strlength.s -m32 -o test -v