基本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:直接一行行的写汇编代码
- 扩展asm=Extended Asm:带指定输入输出等寄存器的汇编代码
- 一般来说生成代码会:更小、更安全、更高效
- 支持运算符operands:指定 输入寄存器,输出寄存器、受影响的寄存器(clobbered register)
- 缺点
建议
- 如果可以,尽量不要用:内嵌汇编
- 如果要用汇编:尽量不用
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。