Hacemos una revisión exhaustiva cada secciones en nuestro sitio web con la meta de enseñarte siempre información con la mayor veracidad y actual.
Solución:
Usa la etiqueta _start
en vez de main
para el punto de entrada ELF.main
implica que es como la C main
función, pero esto ni siquiera es una función (por ejemplo, no puede ret
).
No dice, pero a partir de los mensajes de error y el código, asumo que está creando su código de 32 bits con nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o
(Si en realidad está creando un código de 64 bits, tiene suerte de que funcione, pero se romperá tan pronto como haga algo con esp
en vez de rsp
.)
El mensaje de error es de ld
no de nasm
. Lo dice justo en el mensaje. El comentario de Tim es correcto: ld
busca un _start
símbolo en los archivos que vincula, pero establece el punto de entrada al principio del segmento de texto si no encuentra uno.
No importa qué otros símbolos globales/externos defina. main
no tiene ninguna relevancia aquí y podría apuntar a cualquier lugar que desee. Solo es útil para una salida de desmontaje y cosas por el estilo. Su código funcionaría exactamente igual si sacara el global main
/ main:
líneas, o las cambió a cualquier otro nombre.
Etiquetando eso como main
es imprudente porque el punto de entrada ELF es no es una función. Es nomain()
y no recibe argc
y argv
argumentos y no puedo ret
porque ESP está apuntando a argc
en lugar de una dirección de retorno.
Uso único main
si se vincula con el código de inicio CRT de gcc/glibc que busca un main
símbolo y lo llama después de inicializar libc. (Así que funciona como el trabajo de printf. Los ganchos enlazadores técnicamente dinámicos permiten que libc se inicialice antes que su _start
si lo vinculó, pero generalmente no lo haga a menos que comprenda exactamente lo que está haciendo). Relacionado: Montaje de archivos binarios de 32 bits en un sistema de 64 bits (cadena de herramientas GNU)
p.ej gcc -m32 -o hello main.o
si defines un main:
en vez de gcc -m32 -static -nostdlib -o hello start.o
(que es equivalente a su desnudo ld
).
Le sugiero que vincule sus archivos de objetos (sin importar cómo se produzcan) con gcc
no ld
.
gcc
llamará ld
con las opciones adecuadas, ya que conoce más sobre el código fuente y creará lo necesario para los supuestos que ld
hace.
No sé si esta es una solución válida, pero parece funcionar para mí:
intente usar la opción
--entry main
mientras vincula su código kernel C.
ld -o kernel.bin -Ttext 0x1000 kernel_entry.o kernel.o --oformat binary --entry main