ejemplos c assembly linker compilation binutils
http://www.owenstephens.co.uk/media/files/kernel.zip

c - meta tags ejemplos



¿Cómo se puede agregar una llamada de función para que otros símbolos no estén definidos al vincular? (7)

Alguna adivinanza salvaje, tal vez su función de ensamblador que se llama (y probablemente está en línea) en gdt_install está estropeando lo que vendrá después. (este salto al final antes del ret es inusual, nunca visto eso)

¿Tu gdt_install en la misma unidad de compilación que tienes la llamada? ¿Utiliza -O[12] para la compilación? ¿La llamada está inline? ¿Cómo se ve el ensamblador que produce el compilador para el lado de la llamada?

¿ -O0 -g compilar con -O0 -g o -fno-inline (o cómo se llama esta opción)?

Espero que alguien pueda ayudar a solucionar lo que creo que es un problema de secuencia de comandos del enlazador.

Me encuentro con un problema extraño después de agregar una llamada a una nueva función. Sin la llamada a la función, mis archivos objeto se vinculan correctamente, sin embargo, con la nueva llamada a la función agregada, obtengo una referencia indefinida a un símbolo de otro archivo objeto (he verificado que está realmente presente usando objdump).

También extrañamente, con la función invocar presente, si enlazo todos los archivos de objeto primero usando ld -r (para dar un resultado reubicable) y luego usando mi script de enlace, no hay referencias indefinidas, pero parece que el script de enlace se está ignorando desde el binario de salida no tiene el punto de entrada correcto.

Mi (compilación cruzada) versión ld:

> i586-elf-ld --version
GNU ld (GNU Binutils) 2.20.1.20100303

Mis intentos de probar que el símbolo ''faltante'' está presente:

> i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt.bin -y putch

main.o: reference to putch stdio.o: definition of putch main.o: In function `main'': main.c:(.text+0x1f): undefined reference to `putch''

NB (cuando produje esta salida, estaba usando un nombre de archivo de gdt.bin para ensamblador compilado nasm, es simplemente otro archivo .o, realmente)

Puedo ver el símbolo que ''falta'' en el archivo de objeto apropiado:

> i586-elf-objdump -ht stdio.o
stdio.o: formato de archivo elf32-i386

Sections: Idx Name Size VMA LMA File off Algn 0 .text 000002f9 00000000 00000000 00000034 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 0000000c 00000000 00000000 00000330 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000008 00000000 00000000 0000033c 2**2 ALLOC 3 .comment 00000012 00000000 00000000 0000033c 2**0 CONTENTS, READONLY SYMBOL TABLE: 00000000 l df *ABS* 00000000 stdio.c 00000000 l d .text 00000000 .text 00000000 l d .data 00000000 .data 00000000 l d .bss 00000000 .bss 00000000 l d .comment 00000000 .comment 00000000 g F .text 00000016 strlen 00000016 g F .text 0000005c scroll 00000008 g O .data 00000004 numrows 00000004 g O .bss 00000004 ypos 00000004 g O .data 00000004 numcols 00000004 O *COM* 00000004 screen_mem 00000000 *UND* 00000000 memcpy 00000000 *UND* 00000000 memsetw 00000072 g F .text 0000007d newline 00000000 g O .bss 00000004 xpos 000000ef g F .text 0000002e writech 00000000 g O .data 00000004 colour 0000011d g F .text 00000061 cls 0000017e g F .text 00000010 init_video 0000018e g F .text 00000133 putch 000002c1 g F .text 00000037 puts 000002f8 g F .text 00000001 set_text_colour

Y el archivo objeto con referencia no resuelta:

> i586-elf-objdump -ht main.o

main.o: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn 0 .text 0000007f 00000000 00000000 00000034 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000000 00000000 00000000 000000b4 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000000 00000000 00000000 000000b4 2**2 ALLOC 3 .rodata.str1.1 00000024 00000000 00000000 000000b4 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .comment 00000012 00000000 00000000 000000d8 2**0 CONTENTS, READONLY SYMBOL TABLE: 00000000 l df *ABS* 00000000 main.c 00000000 l d .text 00000000 .text 00000000 l d .data 00000000 .data 00000000 l d .bss 00000000 .bss 00000000 l d .rodata.str1.1 00000000 .rodata.str1.1 00000000 l d .comment 00000000 .comment 00000000 g F .text 0000007f main 00000000 *UND* 00000000 init_video 00000000 *UND* 00000000 gdt_install 00000000 *UND* 00000000 putch 00000000 *UND* 00000000 puts 00000018 O *COM* 00000001 gdt 00000006 O *COM* 00000001 gdtp

Mi script de enlace (no estoy seguro de si va a ser relevante):

OUTPUT_FORMAT("binary") ENTRY(start) phys = 0x00100000; SECTIONS { .text phys : AT(phys) { code = .; *(.text) *(.rodata*) . = ALIGN(4096); } .data . : AT(data) { data = .; *(.data) . = ALIGN(4096); } .bss . : AT(bss) { bss = .; *(.bss) . = ALIGN(4096); } end = .; }

Si hago un comentario sobre la llamada a putch en main.c, en su lugar obtengo referencias indefinidas a puts ... si elimino la llamada a gdt_install, ¡no hay errores!

gdt_install está en el archivo C, pero gdt_install llama a una función que está definida en gdt.asm.

void gdt_install() { /* ... */ gdt_reset(); } [bits 32] [section .text] global gdt_reset extern gdtp gdt_reset: lgdt [gdtp] mov ax, 0x10 ; 0x10 offset for data segment (sizeof(struct gdt_entry) * 2) mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax jmp 0x08:gdt_reset2 ; 0x08 offset for code segment (sizeof(struct gdt_entry)) gdt_reset2: ret ; ret back to C

Para intentar diagnosticar aún más la causa, he estado jugando tratando de recrear los errores. Si muevo la llamada a la función gdt_install () a un lugar específico en el código fuente, no recibo ningún error y todo funciona bien:

int main() { init_video(); putch(''A''); puts("<- print a single char there.../n"); gdt_install(); puts("asdf/n/n"); int i; for (i = 0; i < 15; ++i) { if (i % 2 == 0) { puts("even/n"); } else { puts("odd/n"); } } return 0; }

Si muevo la llamada encima de la primera llamada a puts (), ¡recibo referencias indefinidas para puts !:

... init_video(); putch(''A''); gdt_install(); puts("<- print a single char there.../n"); puts("asdf/n/n"); ... i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o main.o: In function `main'': main.c:(.text+0x2b): undefined reference to `puts'' main.c:(.text+0x37): undefined reference to `puts'' main.c:(.text+0x51): undefined reference to `puts'' main.c:(.text+0x63): undefined reference to `puts''

A continuación, si muevo la llamada anterior putch (), causa una referencia indefinida a putch (que era donde originalmente tuve la llamada):

... init_video(); gdt_install(); putch(''A''); puts("<- print a single char there.../n"); puts("asdf/n/n"); ... main.o: In function `main'': main.c:(.text+0x1f): undefined reference to `putch''

Y finalmente, arriba de init_video (), causa una referencia indefinida a init_video:

... gdt_install(); init_video(); putch(''A''); puts("<- print a single char there.../n"); puts("asdf/n/n"); ... main.o: In function `main'': main.c:(.text+0x15): undefined reference to `init_video''

¿Qué demonios está causando este error? Es como si la llamada a gdt_install estuviera de alguna manera "corrompiendo" otros símbolos ... No pude encontrar ninguna referencia a ella en ningún documento, pero ¿hay alguna forma de que la llamada a la función gdt_install pueda causar que se sobrepase algún "límite" del enlazador, corrompiéndose? otro código?

¿Alguien ha encontrado un problema como este, o tiene alguna idea de una mayor investigación? He publicado en el foro de osdev: http://forum.osdev.org/viewtopic.php?f=1&t=22227 pero no he tenido mucha suerte.

Gracias

Editar:

No estoy seguro si es relevante, pero si omito el script de enlace al enlazar, todos los errores anteriores desaparecen ... (aunque, entonces mi gestor de arranque no puede llamar al kernel ya que no entiende los binarios de élite).

Según lo solicitado, aquí está el archivo main.c antes y después del preprocesamiento y desmontado del archivo compilado main.o.

antes del preprocesamiento:

#include <stdio.h> #include <common.h> #include <gdt.h> int main() { init_video(); putch(''A''); gdt_install(); puts("<- print a single char there.../n"); puts("asdf/n/n"); int i; for (i = 0; i < 15; ++i) { if (i % 2 == 0) { puts("even/n"); } else { puts("odd/n"); } } return 0; }

Después del preprocesamiento:

i586-elf-gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -E main.c # 1 "main.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "main.c" # 1 "./include/stdio.h" 1 # 1 "./include/common.h" 1 typedef unsigned short ushort; typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; typedef int size_t; void *memcpy(void *dst, const void *src, size_t n); void *memset(void *dst, const char val, size_t n); void *memsetw(void *dst, const ushort val, size_t n); void *memseti(void *dst, const int val, size_t n); # 5 "./include/stdio.h" 2 void cls(); void writech(char c); void putch(char c); void puts(char *str); void set_text_colour(uchar f, uchar b); void init_video(); size_t strlen(char *str); # 2 "main.c" 2 # 1 "./include/gdt.h" 1 struct gdt_entry { ushort limit_low; ushort base_low; uchar base_middle; uchar access; uchar granularity; uchar base_high; } __attribute__((packed)); struct gdt_ptr { ushort limit; uint base; } __attribute__((packed)); void gdt_set_gate(int n, ulong base, ulong limit, uchar access, uchar gran); void gdt_install(); extern void gdt_reset(); # 4 "main.c" 2 int main() { init_video(); putch(''A''); gdt_install(); puts("<- print a single char there.../n"); puts("asdf/n/n"); int i; for (i = 0; i < 15; ++i) { if (i % 2 == 0) { puts("even/n"); } else { puts("odd/n"); } } return 0; }

Editar, de nuevo:

Gracias a nategoose por sugerir -g3 para obtener una salida de desensamblaje más agradable:

main.o: file format elf32-i386 SYMBOL TABLE: 00000000 l df *ABS* 00000000 main.c 00000000 l d .text 00000000 .text 00000000 l d .data 00000000 .data 00000000 l d .bss 00000000 .bss 00000000 l d .rodata.str1.4 00000000 .rodata.str1.4 00000000 l d .rodata.str1.1 00000000 .rodata.str1.1 00000000 l d .stab 00000000 .stab 00000000 l d .stabstr 00000000 .stabstr 00000000 l d .comment 00000000 .comment 00000000 g F .text 0000007f main 00000000 *UND* 00000000 init_video 00000000 *UND* 00000000 putch 00000000 *UND* 00000000 gdt_install 00000000 *UND* 00000000 puts Disassembly of section .text: 00000000 <main>: #include <stdio.h> #include <common.h> #include <gdt.h> int main() { 0: 8d 4c 24 04 lea 0x4(%esp),%ecx 4: 83 e4 f0 and $0xfffffff0,%esp 7: ff 71 fc pushl -0x4(%ecx) a: 55 push %ebp b: 89 e5 mov %esp,%ebp d: 53 push %ebx e: 51 push %ecx init_video(); f: e8 fc ff ff ff call 10 <main+0x10> putch(''A''); 14: 83 ec 0c sub $0xc,%esp 17: 6a 41 push $0x41 19: e8 fc ff ff ff call 1a <main+0x1a> gdt_install(); 1e: e8 fc ff ff ff call 1f <main+0x1f> puts("<- print a single char there.../n"); 23: c7 04 24 00 00 00 00 movl $0x0,(%esp) 2a: e8 fc ff ff ff call 2b <main+0x2b> puts("asdf/n/n"); 2f: c7 04 24 00 00 00 00 movl $0x0,(%esp) 36: e8 fc ff ff ff call 37 <main+0x37> 3b: 83 c4 10 add $0x10,%esp int i; for (i = 0; i < 15; ++i) { 3e: bb 00 00 00 00 mov $0x0,%ebx if (i % 2 == 0) { 43: f6 c3 01 test $0x1,%bl 46: 75 12 jne 5a <main+0x5a> puts("even/n"); 48: 83 ec 0c sub $0xc,%esp 4b: 68 07 00 00 00 push $0x7 50: e8 fc ff ff ff call 51 <main+0x51> 55: 83 c4 10 add $0x10,%esp 58: eb 10 jmp 6a <main+0x6a> } else { puts("odd/n"); 5a: 83 ec 0c sub $0xc,%esp 5d: 68 0d 00 00 00 push $0xd 62: e8 fc ff ff ff call 63 <main+0x63> 67: 83 c4 10 add $0x10,%esp puts("asdf/n/n"); int i; for (i = 0; i < 15; ++i) { 6a: 43 inc %ebx 6b: 83 fb 0f cmp $0xf,%ebx 6e: 75 d3 jne 43 <main+0x43> puts("odd/n"); } } return 0; } 70: b8 00 00 00 00 mov $0x0,%eax 75: 8d 65 f8 lea -0x8(%ebp),%esp 78: 59 pop %ecx 79: 5b pop %ebx 7a: 5d pop %ebp 7b: 8d 61 fc lea -0x4(%ecx),%esp 7e: c3 ret

Y ahora la nueva salida de una marca limpia:

$ make nasm -f elf kernel_loader.asm -o kernel_loader.o i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c main.c i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c stdio.c i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c common.c i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c gdt.c nasm -f elf gdt.asm -o gdt_asm.o i586-elf-ld -T link.ld -o kernel32.bin -/( kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o -/) main.o: In function `main'': /cygdrive/c/programming/os/kernel/main.c:12: undefined reference to `puts'' /cygdrive/c/programming/os/kernel/main.c:14: undefined reference to `puts'' /cygdrive/c/programming/os/kernel/main.c:20: undefined reference to `puts'' /cygdrive/c/programming/os/kernel/main.c:22: undefined reference to `puts'' make: *** [kernel32.bin] Error 1

Editar 3

Según lo solicitado, aquí está la salida de nm -s en stdio.o

i586-elf-nm -s stdio.o 00000042 T cls 00000000 D colour 00000000 T init_video U memcpy U memsetw 0000015e T newline 00000004 D numcols 00000008 D numrows 000001e4 T putch 0000024e T puts 00000004 C screen_mem 000000b8 T scroll 00000291 T set_text_colour 00000016 T strlen 00000199 T writech 00000000 B xpos 00000004 B ypos

Editar 4 Como se solicitó, aquí están los archivos fuente completos. He subido los archivos en un zip a: http://www.owenstephens.co.uk/media/files/kernel.zip Gracias por el continuo interés y ayuda, es muy apreciado.

Makefile:

NASM=nasm GCC=i586-elf-gcc LD=i586-elf-ld FMT=-f elf GFLAGS=-Wall -O0 -fstrength-reduce -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c LFLAGS=-T link.ld ALL=kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o INCLUDES=include/stdio.h include/common.h include/gdt.h all: $(ALL) kernel32.bin kernel_loader.o: kernel_loader.asm $(NASM) $(FMT) $*.asm -o $@ main.o: main.c $(GCC) $(GFLAGS) $< stdio.o: stdio.c include/stdio.h $(GCC) $(GFLAGS) $< common.o: common.c include/common.h $(GCC) $(GFLAGS) $< gdt.o: gdt.c include/gdt.h $(GCC) $(GFLAGS) $< gdt_asm.o: gdt.asm $(NASM) $(FMT) $< -o $@ kernel32.bin: $(ALL) $(INCLUDES) $(LD) $(LFLAGS) -o $@ -/( $(ALL) -/) clean: rm -f $(ALL) kernel32.bin

Script de enlace:

OUTPUT_FORMAT("binary") ENTRY(_start) phys = 0x00100000; SECTIONS { .text phys : AT(phys) { code = .; *(.text) *(.rodata*) . = ALIGN(4096); } .data . : AT(data) { data = .; *(.data) . = ALIGN(4096); } .bss . : AT(bss) { bss = .; *(.bss) . = ALIGN(4096); } end = .; }

C Principal:

#include <stdio.h> #include <common.h> #include <gdt.h> int main() { gdt_install(); puts("This is a minimal example..."); return 0; }

common.c:

#include <common.h> void *memcpy(void *dst, const void *src, size_t n) { return (void *)0; } void *memset(void *dst, const char val, size_t n) { return (void *)0; } void *memsetw(void *dst, const ushort val, size_t n) { return (void *)0; } void *memseti(void *dst, const int val, size_t n) { return (void *)0; }

stdio.c:

#include <stdio.h> #include <common.h> ushort *screen_mem; int colour = 0x0F; int xpos = 0, ypos = 0; int numcols = 80, numrows = 25; void init_video() {} size_t strlen(char *str) { return 0; } void cls() { } inline void scroll() { } inline void newline() { } void writech(char c) { } void putch(char c) { } void puts(char *str) { } void set_text_colour(unsigned char f, unsigned char b){ }

gdt.c:

#include <gdt.h> struct gdt_entry gdt[3]; struct gdt_ptr gdtp; void gdt_set_gate(int n, ulong base, ulong limit, uchar access, uchar gran) { } void gdt_install() { }

gdt.asm:

global gdt_reset gdt_reset: ret gdt_reset2: ret

include / common.h:

#ifndef __COMMON_H #define __COMMON_H typedef unsigned short ushort; typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; typedef int size_t; void *memcpy(void *dst, const void *src, size_t n); void *memset(void *dst, const char val, size_t n); void *memsetw(void *dst, const ushort val, size_t n); void *memseti(void *dst, const int val, size_t n); #endif

include / stdio.h:

#ifndef __STDIO_H #define __STDIO_H #include <common.h> void cls(); void writech(char c); void putch(char c); void puts(char *str); void set_text_colour(uchar f, uchar b); void init_video(); size_t strlen(char *str); #endif

incluye / gdt.h:

#ifndef __GDT_H #define __GDT_H #include <common.h> struct gdt_entry { ushort limit_low; ushort base_low; uchar base_middle; uchar access; uchar granularity; uchar base_high; } __attribute__((packed)); struct gdt_ptr { ushort limit; uint base; } __attribute__((packed)); void gdt_set_gate(int n, ulong base, ulong limit, uchar access, uchar gran); void gdt_install(); extern void gdt_reset(); #endif

Salida de "objdump -t" de una lib compartida que incluye todos los archivos .o (excepto el kernel_loader, de ahí el símbolo _start indefinido.

> i586-elf-objdump -t libos.so.1.0.1 libos.so.1.0.1: file format elf32-i386 SYMBOL TABLE: 08048080 l d .text 00000000 .text 08048162 l d .rodata 00000000 .rodata 08049180 l d .data 00000000 .data 0804918c l d .bss 00000000 .bss 00000000 l d .stab 00000000 .stab 00000000 l d .stabstr 00000000 .stabstr 00000000 l d .comment 00000000 .comment 00000000 l df *ABS* 00000000 main.c 00000000 l df *ABS* 00000000 stdio.c 00000000 l df *ABS* 00000000 common.c 00000000 l df *ABS* 00000000 gdt.c 00000000 l df *ABS* 00000000 gdt.asm 08048161 l .text 00000000 gdt_reset2 08049180 g O .data 00000004 colour 08048125 g F .text 00000014 memsetw 0804918c g O .bss 00000004 xpos 08049188 g O .data 00000004 numrows 08048158 g F .text 00000005 gdt_install 08048108 g F .text 0000000a memcpy 080480ee g F .text 00000005 puts 08049198 g O .bss 00000018 gdt 08049194 g O .bss 00000004 screen_mem 080480e0 g F .text 0000000e putch 08048144 g F .text 00000014 gdt_set_gate 00000000 *UND* 00000000 _start 08048160 g .text 00000000 gdt_reset 080480b4 g F .text 00000005 init_video 080480c8 g F .text 00000005 scroll 0804918c g *ABS* 00000000 __bss_start 08048112 g F .text 00000013 memset 08048080 g F .text 00000033 main 080480f3 g F .text 00000014 set_text_colour 080480cd g F .text 00000005 newline 08049190 g O .bss 00000004 ypos 080491b0 g O .bss 00000006 gdtp 0804918c g *ABS* 00000000 _edata 080491b8 g *ABS* 00000000 _end 080480c3 g F .text 00000005 cls 080480b9 g F .text 0000000a strlen 08048139 g F .text 0000000a memseti 08049184 g O .data 00000004 numcols 080480d2 g F .text 0000000e writech


El orden de los archivos en la línea de comando parece importar con el enlazador GNU. Coloque el archivo .o que contiene el punto de entrada ( kernel_loader.o ) primero en la línea de comando, luego los objetos a los que hace referencia directamente, luego los objetos a los que hacen referencia esos objetos (y que aún no están en la línea de cmd), etc. ., o es posible que el enlazador pierda algunos archivos.


Esto suena como un problema de referencia circular en la línea de enlace. El enlazador recorre los archivos objeto en orden y "recuerda" cualquier elemento externo no resuelto. Sin embargo, también puede descartar cualquier archivo de objeto que no tenga referencias a ellos. Si dos o más archivos de objeto se referencian entre sí (causando una referencia circular), es posible que el vinculador no pueda rastrear las entidades no resueltas.

Intenta duplicar partes de la línea de enlace y luego acota lo que necesites.

i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o / stdio.o common.o gdt.o gdt_asm.o


Hay otra pregunta SO (puede ser similar / idéntica, no estoy seguro) que cubre algo de esto. ¿Eso ofrece alguna ayuda?


He visto problemas similares varias veces y, en cierto momento, justo antes de volverme completamente loco, empiezo a buscar cosas invisibles que podrían terminar en los nombres. Bytes no ASCII o caracteres ASCII no imprimibles que podrían haberse colado en su código fuente y haberse adjuntado al primer código visto después de gdt_install();

Es posible que desee intentar agregar un comentario o una macro vacía (o a do{}while(0) ) entre su llamada a gdt_install() y la siguiente línea de código real. Tal vez incluso coloque el cursor en el nombre de la función y realice una copia de seguridad justo antes del primer carácter de ese nombre de función y comience a escribir lo que decida agregar allí. Si es algo causado por la presencia de gdt_install(); entonces algo más que se arroje allí debería forzar un error diferente.

Si aún no lo hizo, le conviene ver la salida del preprocesador del archivo con la llamada a gdt_install() y su salida de ensamblaje.

Si nada de eso produce algo interesante, cambie el nombre de gdt_install y vea si eso cambia algo. He visto algunos casos en los que los errores del compilador y / o del enlazador pueden producir algo extraño como este. Tal vez un error en una tabla hash utilizada como una tabla de símbolos (tal vez incluso en la tabla hash del archivo elf).

Espero que lo descubras.


Sospecho que quizás la combinación de las tablas de símbolos de vinculación del objeto generado por nasm y los objetos generados por gcc / gas podrían estar arruinando algo.

¿Podría intentar reemplazar la llamada a gtd_install con una llamada a una función corta en línea que contenga ensamblado en línea que llame o salte a gtd_install y que resida en el mismo archivo que la llamada actual a gtd_install ?

Otra cosa que me gtd_install a la mente es que si gtd_install está escrito en lenguaje ensamblador, entonces es posible que no sea 100% sintácticamente correcto. Nunca he visto algo como esto, pero solo pensando que podría ser posible que los límites de gtd_install (particularmente el final) o su tamaño no estén determinados correctamente por el ensamblador, y eso es solo tener resultados aleatorios.

A excepción de que creo que vas a tener que ir a la gente de binutils y pedirles ayuda directamente.


Tu escribiste. " I''ve implemented my own psuedo-stdio functions (puts, putch...) the functions match exactly ... " ¿Estás usando algo en la libc estándar? Si no lo está, debe agregar -nostdlib a su línea de comando. He visto cosas extrañas cuando intenté anular las funciones en la libc estándar.