Подтвердить что ты не робот

Как добавить вызов функции, чтобы другие символы стали undefined при связывании?

Я надеюсь, что кто-то сможет помочь устранить проблему, которая, по моему мнению, является проблемой компоновщика script.

У меня возникает странная проблема после добавления вызова к новой функции. Однако без вызова функции мои объектные файлы ссылаются правильно, однако при добавлении нового вызова функции я получаю ссылку undefined на символ из другого объектного файла (я проверял, что он действительно присутствует с использованием objdump).

Также странно, если присутствует вызов функции, если я сначала свяжу все объектные файлы с помощью ld -r (чтобы получить перемещаемый вывод), а затем используя мою ссылку script, ссылок undefined нет, но кажется ссылка script игнорируется, поскольку выходной двоичный файл не имеет правильной точки входа.

Мой (кросс-компилятор) ld версия:

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

Мои попытки доказать наличие "отсутствующего" символа:

> 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'

N.B. (когда я создал этот вывод, я использовал имя файла gdt.bin для сборщика ассемблеров nasm, это просто еще один файл .o).

Я вижу символ, который "отсутствует" в соответствующем объектном файле:

i586-elf-objdump -ht stdio.o
    stdio.o: формат файла 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

И объектный файл с неразрешенной ссылкой:

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

Моя ссылка script (не уверен, что это будет актуально):

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 = .;
}

Если я прокомментирую вызов putch в main.c, я вместо этого получаю undefined ссылки на puts... если я удалю вызов gdt_install, никаких ошибок!

gdt_install находится в файле C, но gdt_install вызывает функцию, определенную в 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

Чтобы попытаться и дальше диагностировать причину, я играл вокруг попытки воссоздать ошибки. Если я переведу вызов функции gdt_install() в определенное место в исходном коде, я не получаю никаких ошибок, и все работает нормально:

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;
}

Если я переведу вызов выше первого вызова puts(), я получаю undefined ссылки для 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'

Затем, если я переведу вызов выше putch(), он вызывает ссылку undefined putch (которая была там, где я первоначально имел вызов):

...
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'

И, наконец, над init_video() вызывает ссылку undefined на 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'

Что вызывает эта ошибка? Он, как вызов gdt_install, как-то "развращает" другие символы... Я не мог найти никакой ссылки на него в каких-либо документах, но есть ли способ, которым вызов функции gdt_install может привести к перерасходу, "границе" линкера, развращению другой код?

Кто-нибудь сталкивался с такой проблемой или имел какие-либо идеи относительно дальнейшего расследования? Я опубликовал на форуме osdev: http://forum.osdev.org/viewtopic.php?f=1&t=22227, но не имел большой удачи.

Спасибо

Edit:

Я не уверен, что это актуально, но если я опускаю ссылку script при связывании, все предыдущие ошибки исчезают... (хотя, тогда мой загрузчик не может вызвать ядро, так как он не понимает двоичные файлы эльфа).

В соответствии с запросом здесь файл main.c до и после предварительной обработки и дизассемблирован из скомпилированного файла main.o.

перед предварительной обработкой:

#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;
}

После предварительной обработки:

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;
}

Изменить еще раз:

Спасибо, что предложили -g3 дать более хороший результат разборки:

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    

И теперь новый вывод из чистого make:

$ 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

Изменить 3

В соответствии с запросом здесь вывод nm -s на 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

Изменить 4 В соответствии с запросом здесь представлены все исходные файлы. Я загрузил файлы в zip, чтобы: http://www.owenstephens.co.uk/media/files/kernel.zip Спасибо за постоянный интерес и помощь, это очень ценится!

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 [email protected]

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 [email protected]

kernel32.bin: $(ALL) $(INCLUDES)
    $(LD) $(LFLAGS) -o [email protected] -\( $(ALL) -\)

clean:
    rm -f $(ALL) kernel32.bin

Ссылка script:

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 = .;
}

main.c:

#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

включают в себя /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

включают в себя /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

включают в себя /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

Вывод "objdump -t" в общую библиотеку, включающую все файлы .o(кроме kernel_loader, следовательно, символ undefined _start.

> 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
4b9b3361

Ответ 1

Это звучит как проблема с круговой ссылкой на линии ссылки. Компилятор проходит через объектные файлы по порядку и "запоминает" любые нерешенные внешние. Однако он также может отбрасывать любые объектные файлы, которые не имеют ссылок на них. Если два или более объектных файла ссылаются друг на друга (вызывая циклическую ссылку), компоновщик может не отслеживать неразрешенные объекты.

Попробуйте дублировать части линии ссылок, а затем сузите их до нужных вам.

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

Ответ 2

Порядок файлов в командной строке, по-видимому, имеет значение с помощью компоновщика GNU. Поместите файл .o, содержащий точку входа (kernel_loader.o), сначала в командной строке, затем любые объекты, которые он непосредственно ссылается, а затем объекты, на которые ссылаются эти объекты (и которые еще не находятся в CMD-линии) и т.д., или возможно, что компоновщик пропустит некоторые файлы.

Ответ 3

Есть другой вопрос SO (может быть похожим/идентичным, я не уверен), который охватывает некоторые из них. Помогает ли эта помощь?

Ответ 4

Я видел подобные проблемы несколько раз и в определенный момент, перед тем, как я начинаю безумно безумно, я начинаю искать невидимые вещи, которые могут оказаться в именах. Не-ASCII-байты или непечатаемые символы ASCII, которые могли проникнуть в ваш исходный код и привязаны к первому коду, увиденному после gdt_install();

Возможно, вам захочется добавить комментарий или пустой макрос (или do{}while(0)) между вашим вызовом gdt_install() и следующей реальной строкой кода. Возможно, даже доведите курсор до имени функции и верните ее до первого символа имени этой функции и начните вводить то, что вы решили добавить туда. Если это что-то, вызванное присутствием gdt_install();, тогда что-то другое, забрасываемое туда, должно вызвать другую ошибку.

Если вы еще этого не сделали, вы можете просмотреть вывод препроцессора файла с вызовом gdt_install(), а также его вывод сборки.

Если ничто из этого не вызывает ничего интересного, измените имя gdt_install и посмотрите, не изменит ли это что-либо. Я видел несколько примеров, когда ошибки в компиляторе и/или компоновщике могут создавать нечто странное. Возможно, ошибка в хеш-таблице, используемой в качестве таблицы символов (возможно, даже в хэш-таблице файла эльфа).

Надеюсь, вы это поймете.

Ответ 5

какая-то дикая догадка, возможно, ваша функция ассемблера, которая называется (и, возможно, встроенная) в gdt_install, испортила то, что происходит после нее. (этот прыжок в конце до ret необычен, никогда не видел этого)

Является ли ваш gdt_install в том же компиляционном блоке, где и у вас есть вызов? Используете ли вы -O[12] для компиляции? Является ли вызов вложенным? Как выглядит ассемблер, создаваемый компилятором для стороны вызова?

Вы пытались скомпилировать с помощью -O0 -g или -fno-inline (или как этот параметр вызывается)?

Ответ 6

Ты написал. "I've implemented my own psuedo-stdio functions (puts, putch...) the functions match exactly ..." Вы используете что-нибудь в стандартном libc? Если вы этого не сделаете, добавьте -nostdlib в свою командную строку. Я видел странные вещи, когда я пытался переопределить функции в стандартном libc.

Ответ 7

Я подозреваю, что, возможно, объединение таблиц связующих символов из созданного объекта nasm и объектов, генерируемых gcc/gas, могло бы что-то испортить.

Не могли бы вы попытаться заменить вызов на gtd_install вызовом короткой встроенной функции, содержащей встроенную сборку, которая вызывает или переходит на gtd_install и находится в том же файле, что и текущий вызов gtd_install?

Еще одна вещь, которая появилась у меня в голове, заключается в том, что если gtd_install написано на ассемблере, то возможно, что она не будет на 100% синтаксически правильной. Я никогда не видел ничего подобного, но просто думал, что возможно, что границы gtd_install (особенно конец) или его размер неправильно определены ассемблером, и это просто имеет случайные результаты.

Убедившись, что я думаю, что вам придется пойти к людям binutils и попросить их о помощи напрямую.