在Linux vs Mac上将C汇编为ARM64时的不同说明
如果我将AC文件编译到ARM64组件中,我会获得不同的说明(不仅是不同的语法和指令 - 例如.cfi_def_cfa
vs .cfi_def_cfa_offset
)苹果。如果ISA是相同的,为什么这是如此?我知道会有不同的目标二进制格式(ELF/MACH-O),但是我期望将相同的说明汇编为不同的对象。这是因为Apple使用Apple Clang可能与AARCH64 GCC工具链内部的处理情况不同?
有什么方法可以使用相同的说明执行?
输入文件(fib.c):
int fib(int n)
{
if (n <= 1)
return 1;
return fib(n - 1) + fib(n - 2);
}
Mac(在Mac mini上使用GCC -S FIB.C -O FIB.S
):
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 11, 0 sdk_version 12, 1
.globl _fib ; -- Begin function fib
.p2align 2
_fib: ; @fib
.cfi_startproc
; %bb.0:
sub sp, sp, #32 ; =32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16 ; =16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
str w0, [sp, #8]
ldr w8, [sp, #8]
subs w8, w8, #1 ; =1
b.gt LBB0_2
; %bb.1:
mov w8, #1
stur w8, [x29, #-4]
b LBB0_3
LBB0_2:
ldr w8, [sp, #8]
subs w0, w8, #1 ; =1
bl _fib
str w0, [sp, #4] ; 4-byte Folded Spill
ldr w8, [sp, #8]
subs w0, w8, #2 ; =2
bl _fib
mov x8, x0
ldr w0, [sp, #4] ; 4-byte Folded Reload
add w8, w0, w8
stur w8, [x29, #-4]
LBB0_3:
ldur w0, [x29, #-4]
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32 ; =32
ret
.cfi_endproc
; -- End function
.subsections_via_symbols
Linux(在Ubuntu上使用aarch64 -linux -gnu汇总-gcc -s fib.c -o fib.s
):
.arch armv8-a
.file "fib.c"
.text
.align 2
.global fib
.type fib, %function
fib:
.LFB0:
.cfi_startproc
stp x29, x30, [sp, -48]!
.cfi_def_cfa_offset 48
.cfi_offset 29, -48
.cfi_offset 30, -40
mov x29, sp
str x19, [sp, 16]
.cfi_offset 19, -32
str w0, [sp, 44]
ldr w0, [sp, 44]
cmp w0, 1
bgt .L2
mov w0, 1
b .L3
.L2:
ldr w0, [sp, 44]
sub w0, w0, #1
bl fib
mov w19, w0
ldr w0, [sp, 44]
sub w0, w0, #1
bl fib
add w0, w19, w0
.L3:
ldr x19, [sp, 16]
ldp x29, x30, [sp], 48
.cfi_restore 30
.cfi_restore 29
.cfi_restore 19
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE0:
.size fib, .-fib
.ident "GCC: (Ubuntu 11.2.0-17ubuntu1) 11.2.0"
.section .note.GNU-stack,"",@progbits
If I compile a c file into ARM64 assembly I get different instructions (not only a different syntax and directives - eg .cfi_def_cfa
vs .cfi_def_cfa_offset
) depending on whether I compile on linux or mac. Why is this if the ISA is the same? I know there will be different target binary formats (ELF/Mach-O), but I was expecting identical instructions that would then be compiled into different objects. Is this because apple use apple clang which may process things differently from the internals of the aarch64 gcc toolchain?
Is there any way to enforce using the same instructions?
Input file (fib.c):
int fib(int n)
{
if (n <= 1)
return 1;
return fib(n - 1) + fib(n - 2);
}
Mac (compiled on a mac mini with gcc -S fib.c -o fib.s
):
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 11, 0 sdk_version 12, 1
.globl _fib ; -- Begin function fib
.p2align 2
_fib: ; @fib
.cfi_startproc
; %bb.0:
sub sp, sp, #32 ; =32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16 ; =16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
str w0, [sp, #8]
ldr w8, [sp, #8]
subs w8, w8, #1 ; =1
b.gt LBB0_2
; %bb.1:
mov w8, #1
stur w8, [x29, #-4]
b LBB0_3
LBB0_2:
ldr w8, [sp, #8]
subs w0, w8, #1 ; =1
bl _fib
str w0, [sp, #4] ; 4-byte Folded Spill
ldr w8, [sp, #8]
subs w0, w8, #2 ; =2
bl _fib
mov x8, x0
ldr w0, [sp, #4] ; 4-byte Folded Reload
add w8, w0, w8
stur w8, [x29, #-4]
LBB0_3:
ldur w0, [x29, #-4]
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32 ; =32
ret
.cfi_endproc
; -- End function
.subsections_via_symbols
Linux (compiled on ubuntu with aarch64-linux-gnu-gcc -S fib.c -o fib.s
):
.arch armv8-a
.file "fib.c"
.text
.align 2
.global fib
.type fib, %function
fib:
.LFB0:
.cfi_startproc
stp x29, x30, [sp, -48]!
.cfi_def_cfa_offset 48
.cfi_offset 29, -48
.cfi_offset 30, -40
mov x29, sp
str x19, [sp, 16]
.cfi_offset 19, -32
str w0, [sp, 44]
ldr w0, [sp, 44]
cmp w0, 1
bgt .L2
mov w0, 1
b .L3
.L2:
ldr w0, [sp, 44]
sub w0, w0, #1
bl fib
mov w19, w0
ldr w0, [sp, 44]
sub w0, w0, #1
bl fib
add w0, w19, w0
.L3:
ldr x19, [sp, 16]
ldp x29, x30, [sp], 48
.cfi_restore 30
.cfi_restore 29
.cfi_restore 19
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE0:
.size fib, .-fib
.ident "GCC: (Ubuntu 11.2.0-17ubuntu1) 11.2.0"
.section .note.GNU-stack,"",@progbits
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Mac上的GCC
实际上是clang
,除非您安装了实际的GCC软件包。(他们这样做是因为某些MakeFiles使用
CC = GCC
而不是CC = CC
,并且它确实接受了几乎所有相同的选项。使用gcc -v -v 找出答案
。
两个完全不同的编译器使不同优化的ASM 毫不奇怪。他们有不同的内部设备和转换,以从C来源制造ASM,例如Clang通过LLVM-IR,GCC穿过Gimple和RTL。
通过启用优化,对于足够简单的代码,他们倾向于同意是否只有一个好选择(除寄存器号码之外),但是一旦事情变得足够复杂,可以变得不乏味(例如优化迭代中的双重恢复功能),就会有空间每个人都做出不同的选择。
同一编译器的不同版本 /选项也是如此。
gcc
on a Mac is actuallyclang
, unless you install an actual GCC package.(They do this because some Makefiles use
CC=gcc
instead ofCC=cc
, and it does accept almost all the same options. Usegcc -v
to find out.)Or we can tell from looking at the asm output:
LBB0_3
label naming is indicative of LLVM, numbering by function and then basic-block within function.It's not surprising that two totally different compilers make different un-optimized asm. They have different internals and transformations they go through to make asm from C source, e.g. clang going through LLVM-IR, GCC going through GIMPLE and RTL.
With optimization enabled, for simple enough code they tend to agree if there's only one good choice (other than register numbers), but once things get complex enough to be non-trivial (like optimizing a doubly-recursive function into iterative) there's room for each one to make different choices.
Same is true across different versions / options of the same compiler, too.