使用 ld 链接已编译的程序集和 C 文件
Linking a compiled assembly and C file with ld
我编译了这些程序:
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
这是一个测试,只是为了尝试 link他们
int main()
{
return 0;
}
两者都可以使用以下方法自行编译:
gcc -Wall -m32 main.c
nasm -f elf bootloader.asm
但是我不能 link 他们使用:
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
如有帮助将不胜感激
如果您只是想在 PC 上进行一些简单的汇编编程,实际上不需要 16 位代码,并且不想深入研究引导加载程序和 OS 开发,您可以开始很多通过编写 32 位 (IA32) 或 64 位 (AMD64) 应用程序代码更容易。您可以使用 (Linux) system calls.
而不是 BIOS 中断
i386 的示例 "hello world" 为:
.section .text._start
.global _start
.type _start, %function
_start:
mov , %eax
mov , %ebx
mov $message, %ecx
mov , %edx
int [=10=]x80
mov , %eax
xor %ebx, %ebx
int [=10=]x80
.section .rodata.message
.type message, %object
message:
.ascii "Hello, World!\n"
Assemble, link 并通过
执行
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 , %rax
mov , %rdi
mov $message, %rsi
mov , %rdx
syscall
mov [=12=]x3c, %rax
xor %rdi, %rdi
syscall
.section .rodata.message
.type message, %object
message:
.ascii "Hello, World!\n"
Assemble, link 并通过
执行
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"
Assemble、link 并通过(例如在 Raspberry PI 或 Beaglebone 上执行):
as testarm.S -o testarm.o && ld testarm.o -o testarm && ./testarm
GCC 默认情况下已经动态 linking libc
,所以如果你想 linking 手动使用 ld
,确保你的 ELF 可执行 [=14] =], 你可以通过 -static
标志。
gcc -o <filename> <filename>.c -static -Wall -m32
然后 link 和 ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o <filename> -lc <filename>.o
我想,因为像 NASM 这样的汇编器有静态的(没有 libc
的独立)你可以直接用 libc
使 ELF 动态可执行,你可以用 -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
我编译了这些程序:
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
这是一个测试,只是为了尝试 link他们
int main()
{
return 0;
}
两者都可以使用以下方法自行编译:
gcc -Wall -m32 main.c
nasm -f elf bootloader.asm
但是我不能 link 他们使用:
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
如有帮助将不胜感激
如果您只是想在 PC 上进行一些简单的汇编编程,实际上不需要 16 位代码,并且不想深入研究引导加载程序和 OS 开发,您可以开始很多通过编写 32 位 (IA32) 或 64 位 (AMD64) 应用程序代码更容易。您可以使用 (Linux) system calls.
而不是 BIOS 中断i386 的示例 "hello world" 为:
.section .text._start
.global _start
.type _start, %function
_start:
mov , %eax
mov , %ebx
mov $message, %ecx
mov , %edx
int [=10=]x80
mov , %eax
xor %ebx, %ebx
int [=10=]x80
.section .rodata.message
.type message, %object
message:
.ascii "Hello, World!\n"
Assemble, link 并通过
执行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 , %rax
mov , %rdi
mov $message, %rsi
mov , %rdx
syscall
mov [=12=]x3c, %rax
xor %rdi, %rdi
syscall
.section .rodata.message
.type message, %object
message:
.ascii "Hello, World!\n"
Assemble, link 并通过
执行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"
Assemble、link 并通过(例如在 Raspberry PI 或 Beaglebone 上执行):
as testarm.S -o testarm.o && ld testarm.o -o testarm && ./testarm
GCC 默认情况下已经动态 linking libc
,所以如果你想 linking 手动使用 ld
,确保你的 ELF 可执行 [=14] =], 你可以通过 -static
标志。
gcc -o <filename> <filename>.c -static -Wall -m32
然后 link 和 ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o <filename> -lc <filename>.o
我想,因为像 NASM 这样的汇编器有静态的(没有 libc
的独立)你可以直接用 libc
使 ELF 动态可执行,你可以用 -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