基本asm(basic asm) vs 扩展asm(extend asm)

  • 名词
    • clobbers =clobbering registers= (asm汇编中)modified registers = (asm汇编中)值被修改了的寄存器
  • 背景
    • asm的写法,历史上有多种写法的
    • AT&T 的asm汇编写法 是其中一种
      • -》属于老旧的写法
    • 现在多数是:GNU/GCC的asm的写法

basic asm vs extend asm

  • 基本asm=basic asm:直接一行行的写汇编代码
    • 优点
      • 可以放在(C)函数外
        • 放在文件顶部,作为全局(汇编)函数
          • 方便其他文件直接调用
    • 缺点:
      • 编译器(gcc)并不知道汇编内部的逻辑
        • 无法(帮直接汇编的你)做相关的优化和处理
    • 说明:
      • naked的函数,仅支持基本asm
  • 扩展asm=Extended Asm:带指定输入输出等寄存器的汇编代码
    • 一般来说生成代码会:更小、更安全、更高效
      • 支持运算符operands:指定 输入寄存器,输出寄存器、受影响的寄存器(clobbered register)
    • 缺点
      • 只能内嵌在(C)函数中

建议

  • 如果可以,尽量不要用:内嵌汇编
  • 如果要用汇编:尽量不用basic asm,尽量用extend asm
    • 原因
      • 扩展 asm 允许程序员为 asm 指定输入和输出以及它修改的寄存器(clobbers),而基本 asm 则没有。
      • 关于 asm 代码可以覆盖哪些寄存器,不同的 C 编译器使用不同的语义。 gcc 假设没有寄存器被修改。如果您的 asm 修改寄存器而不通知编译器(这需要使用扩展 asm),则会导致未定义的行为。
      • 破坏寄存器(基本 asm 不支持)可以提供比 push/pop 更好的性能。
      • 一些编译器会在调用任何 asm(gcc 称之为“内存”clobber)之前自动将寄存器刷新到内存中。但是 gcc 的基本 asm 不这样做。如果你的 asm 需要这个,你需要在扩展 asm 中使用“内存”clobber。
      • gcc 正在考虑改变基本 asm 的长期语义。它可能很快就会开始破坏一切,而不是不破坏任何东西。这可能会修复现有代码中的细微错误。但是,这有(很小的)机会会导致现有的、正确的功能代码出现问题。此外,这也可能会引入性能问题,因为某些/所有寄存器的内容(即使是您的 asm 不使用的)可能需要围绕您的 asm 语句保存/重新加载。为了“面向未来”您的代码针对这些类型的更改,请使用扩展的 asm 并准确指定需要破坏的内容。
      • 由于 gcc 的基本 asm 没有输入、输出或破坏这一事实,优化器很难在生成的代码中始终如一地定位基本 asm。

results matching ""

    No results matching ""