在Mac和Linux上汇编有什么区别?

16

我一直在尝试了解如何在Mac上使用汇编语言,但据我所知,相关文档非常缺乏,大部分书籍都是针对Windows或Linux的。我以为我可以很容易地从Linux转换到Mac,但事实并非如此。

.file   "simple.c"
.text
.globl simple
.type   simple, @function
simple:
      pushl   %ebp
      movl    %esp, %ebp
      movl    8(%ebp), %edx
      movl    12(%ebp), %eax
      addl    (%edx), %eax
      movl    %eax, (%edx)
      popl    %ebp
      ret
.size   simple, .-simple
.ident  "GCC: (Ubuntu 4.3.2-1ubuntu11) 4.3.2"
.section        .note.GNU-stack,"",@progbits

看起来与这个(Mac)相当不同。

.section    __TEXT,__text,regular,pure_instructions
.globl  _simple
.align  4, 0x90
_simple:                                ## @simple
    .cfi_startproc
## BB#0:
pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    addl    (%rdi), %esi
    movl    %esi, (%rdi)
    movl    %esi, %eax
    popq    %rbp
    ret
    .cfi_endproc


.subsections_via_symbols

针对“普通”的指令和寄存器,例如pushq %rbp,我不担心。但是像.cfi_startprocLtmp2:这样“奇怪”的指令就不太好理解了,它们恰好位于机器指令的中间。

我不知道去哪里找到关于它们的信息以及它们的含义。我已经尝试了数月寻找适合初学者的良好资源,但一无所获。你有什么建议吗?


指令的格式和含义将取决于您使用的汇编语言的特定版本。与操作系统的接口也将具有类似的特点。 - user1864610
@MikeW,“flavour”是什么意思?我在哪里可以找到更多关于它的信息?我正在使用GCC,所以我假设它是GNU汇编器。 - William Oliver
差异主要是针对目标可执行文件格式或调试符号信息。 - zneak
@zneak 我在哪里可以了解与我特定的术语、要求和能力相关的信息? - William Oliver
@zneak 抱歉,OS X 方面的问题我比较熟悉。我尝试过谷歌搜索大部分相关内容,但是我找不到与我所需命令相关的具体信息。这些信息通常都嵌入在一些汇编代码中,而这些问题或示例与我想了解的内容完全无关。也许我没有使用正确的关键词进行搜索? - William Oliver
“Ltmp2:”只是一个代码标签,你可以跳转到那里(即使没有任何跳转)。我不是这方面的专家,但通过谷歌精确搜索命令“cfi_startproc”和“cfi_endproc”的名称,我得到了不错的结果(它们表示函数的开始和结束,并用于异常处理)。 - zneak
2个回答

18

首先,你正在比较32位x86汇编和64位x86-64汇编。虽然OS X的Mach-O ABI支持32位IA32,但我怀疑你想要x86-64 SysV ABI。(幸运的是,x86-64.org网站似乎又恢复了)。Mach-O x86-64模型本质上是ELF / SysV ABI的一种变体,因此即使使用不同的汇编器,用户空间代码的差异也相对较小。

.cfi指令是DWARF调试指令,在汇编中你并不一定需要它们-它们用于调用帧信息等。下面是一些最简示例:

ELF x64-64 汇编器:

    .text
    .p2align 4

    .globl  my_function
    .type   my_function,@function

my_function:
    ...
.L__some_address:

    .size    my_function,[.-my_function]

Mach-O x86-64 汇编器:

    .text
    .p2align 4

    .globl  _my_function

_my_function:
    ...
L__some_address:

除了编写一个汇编教程之外,汇编器之间的主要区别在于:Mach-O函数名称需要前导下划线,标签(目的地)使用.LL有所不同。OS X上的汇编器可以理解'.p2align'指令。.align 4, 0x90基本上执行相同的操作。

编译器生成的代码中,并非所有指令都必须用于生成有效的目标代码。它们用于生成堆栈帧(调试)和异常处理数据。有关更多信息,请参阅链接。


1
谢谢!我知道64位和32位之间的差异,但是尽管答案很简单,你会惊讶于关于指令的直接回答有多难。很高兴知道它们不会立即影响汇编。我是否可以找到确切的含义? - William Oliver
请注意,在 x86 Linux 上,.align 4 = .balign 4 = .p2align 2。而在 Mac 上,就像你所说的是.p2align 4。永远不要使用 .align,而应该始终使用其中一个明确的.balign.p2align 指令。 - Peter Cordes

0

显然,Linux代码是32位的Linux代码。请注意,64位的Linux可以运行32位和64位的代码!

Mac代码肯定是64位代码。

这是主要的区别。

".cfi_xxx"行仅是用于Mac特定文件格式的信息。


Linux 也使用带有相同指令的 DWARF .cfi 堆栈展开元数据;也许 OP 使用了编译选项,如 -fno-asynchronous-unwind-tables 来省略它们。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接