我使用以下命令在ubuntu上交叉编译运行simple.s
,但得到一个错误
> arm-linux-gnueabi-as -o simple.o simple.s
> arm-linux-gnueabi-ld -o simple simple.o
> ./simple
bash: ./simple: cannot execute binary file: Exec format error
> file simple
simple: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped
> uname -m
x86_64
命令如下:
arm-linux-gnueabi-as -o simple.o simple.s
arm-linux-gnueabi-ld -o simple simple.o
./simple
我试图通过
获得二进制文件的体系结构file simple
和我的机器结构
uname -m
,发现它们是不同的。我相信为架构获得正确的二进制文件将解决这个问题。这是真的吗?
这里是simple.s
.global _start
@ comments start with the '@' character
@ the _start label is the entry point to the program
_start:
@ program code here
_exit:
@ it is usual to indent instructions with TAB
MOV R0, #65 @ arbitrary value
MOV R7, #1
SWI 0
如何解决这个问题?Thx
不能在x86_64 Linux PC上本机执行为32位ARM Linux系统编译的Linux可执行文件,因为使用不同公司设计的不同处理器,更重要的是,使用不同的指令集和不同的编程模型。
例如,如果用arm-linux-gnueabi-gcc
编译这个简单的C程序,编译器将生成以下ARM汇编代码:
add.c:
int add(int a, int b)
{
return a + b;
}
。:
.arch armv7-a
.file "add.c"
.text
.align 2
.global add
.arch armv7-a
.syntax unified
.arm
.fpu neon
.type add, %function
add:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
str r0, [fp, #-8]
str r1, [fp, #-12]
ldr r2, [fp, #-8]
ldr r3, [fp, #-12]
add r3, r2, r3
mov r0, r3
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.size add, .-add
.ident "GCC: (GNU Toolchain for the A-profile Architecture 10.2-2020.11 (arm-10.16)) 10.2.1 20201103"
.section .note.GNU-stack,"",%progbits
现在,如果使用x86_64-linux-gnu-gcc
编译它,它将生成x86_64/amd64体系结构的代码:
。:
.file "add.c"
.text
.globl add
.type add, @function
add:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
addl %edx, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size add, .-add
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
.section .note.GNU-stack,"",@progbits
可以看到,程序集是完全不同的,一旦它们被组装和链接,生成的机器码也将是完全不同的。阅读标题为">长篇大论"的部分会让你更清楚。
不同的体系结构意味着不同的CPU:arm-linux-gnueabi-as
只能在没有硬件支持的ARM CPU上编译程序,在Linux上运行浮点运算:编译器的名称中有一个提示,它是从体系结构,操作系统和ABI中构建的,它可以编译程序:
(手臂)- (linux) [gnueabi]或[x86_64] - (linux) (gnu)为例。请看这里的简短解释在GCC编译器的上下文中'目标三元组'是什么。
交叉编译是指在一台CPU #1运行os#1操作系统的计算机上,在另一台CPU #2运行os#2操作系统的计算机上编译一个程序的操作。
在你的例子中,你正在编译一个在运行Linux的32位ARM CPU上运行的程序,在运行Linux的64位Intel CPU (x86_64/amd64)上运行。
总线交叉编译不允许"交叉执行":要做到这一点,你需要使用一个模拟器,比如qemu-arm
,要么显式地使用,要么像这里解释的那样使用binfmt-support
。
如果在这个答案中有什么不清楚的地方,或者如果你认为你仍然遗漏了一个关键的信息,请随意评论或相应补充你的问题。