Связывание скомпилированной сборки и файла C с помощью ld - PullRequest
0 голосов
/ 06 февраля 2020

Я скомпилировал эти программы:

  BITS 16
extern _main
start:
      mov ax, 07C0h 
      add ax, 288
      mov ss, ax 
      mov sp, 4096

      mov ax, 07C0h 
      mov ds, ax 

      mov si, text_string 
      call print_string 

      jmp $

      text_string db 'Calling Main Script'
      call _main

print_string:
      mov ah, 0Eh 

.repeat:
      lodsb 
      cmp al, 0
      je .done 
      int 10h
      jmp .repeat 

.done:
      ret 

      times 510-($-$$) db 0
      dw 0xAA55

и это в качестве теста, просто чтобы попытаться связать их

int main()
{
  return 0;
}

обе программы компилируются полностью самостоятельно, используя: gcc -Wall -m32 main.c nasm -f elf bootloader.asm однако я не могу связать их, используя: ld bootloader.o main.o -lc -I /lib/Id-linux.so.2, и я получаю эту ошибку:

ld: i386 architecture of input file `bootloader.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `main.o' is incompatible with i386:x86-64 output
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
ld: bootloader.o: file class ELFCLASS32 incompatible with ELFCLASS64
ld: final link failed: file in wrong format

Любая помощь будет отличной, спасибо

Ответы [ 2 ]

0 голосов
/ 06 февраля 2020

G CC по умолчанию уже динамически связывается с libc, поэтому, если вы хотите связать вручную, используя ld, убедитесь, что ваш исполняемый файл ELF static, вы можете передать с флагом -static.

gcc -o <filename> <filename>.c -static -Wall -m32 затем связать с ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o <filename> -lc <filename>.o

Я полагаю, поскольку ассемблер, такой как NASM, статически (автономно без libc), вы можете сделать ELF dynamici c исполняемым непосредственно с libc Вы можете передать с флагом -dynamic-linker.

Например:

x86

nasm -f elf32 -o <filename>.o <filename>.asm
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o <filename> -lc <filename>.o

x86_64

nasm -f elf64 -o <filename>.o <filename>.asm
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o <filename> -lc <filename>.o
0 голосов
/ 06 февраля 2020

В случае, если вы просто хотите выполнить простое программирование на ассемблере на своем P C, на самом деле вам не нужен 16-битный код и вы не хотите погружаться в загрузчики и разработку ОС, вы можете начать работу намного легче, написание 32-битного (IA32) или 64-битного (AMD64) кода приложения. Вместо прерываний B IOS вы будете использовать (Linux) системные вызовы .

Примером "hello world" для i386 будет:

.section .text._start
.global _start
.type  _start, %function

_start:
    mov $4, %eax
    mov $1, %ebx
    mov $message, %ecx
    mov $14, %edx

    int $0x80

    mov $1, %eax
    xor %ebx, %ebx
    int $0x80

.section .rodata.message
.type message, %object
message:
    .ascii "Hello, World!\n"

Сборка, связывание и выполнение через

as --32 test32.S -o test32.o && ld -m elf_i386 test32.o -o test32 && ./test32

То же самое для AMD64:

.section .text._start
.global _start
.type  _start, %function

_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $14, %rdx

    syscall

    mov $0x3c, %rax
    xor %rdi, %rdi
    syscall

.section .rodata.message
.type message, %object
message:
    .ascii "Hello, World!\n"

Сборка, связывание и выполнение через

as --64 test64.S -o test64.o && ld -m elf_x86_64 test64.o -o test64 && ./test64

Просто для удовольствия то же самое для ARM (32 бита):

.syntax unified
.arch armv6
.arm

.section .text._start
.global _start
.type  _start, %function

_start:
    movs r7, #4
    movs r0, #1
    ldr r1, =#message
    movs r2, #14
    svc #0

    movs r7, #1
    movs r0, #0
    svc #0

    .ltorg

.section .rodata.message
.type message, %object
message:
    .ascii "Hello, World!\n"

Собрать, связать и выполнить через (например, на Raspberry PI или Beaglebone):

as testarm.S -o testarm.o && ld testarm.o -o testarm && ./testarm
...