我知道在程序集中编写任何东西,或者将程序集添加到任何程序都会损害其可移植性.但是,有多糟糕?我的意思是,这些天基本上所有PC都是x86或x64,对吗?那么,如果我将汇编嵌入到C程序中,为什么不管它到哪里都不能编译?
当您真正深入了解特定处理器的特定怪癖,从一段代码中挤出每一滴性能时,这种不可移植性的概念是否只是指的?
如果我没记错的话,PC游戏"过山车大亨"几乎完全用汇编语言写成.那么......它真的有多么难以置信?
除了处理器本身,当然还有其他一些注意事项:目标平台上的调用约定是什么?如何将struct
值传递给其他(例如:API)函数?哪些寄存器可能被被调用者破坏?保证为呼叫者保留哪些内容?如何进行系统调用?操作系统在进程启动时为您准备的内存布局是什么?
移植组件,还存在ABI的问题,从OS到OS不等.将C程序从Unix移植到Windows(甚至从Linux移植到OpenBSD)可能是一个简单的重新编译,但对于汇编程序,您可能会发现一些被调用者保存寄存器变为调用者保存,或者浮点参数是通过不同.
这不仅仅是理论上的,即.注册Linux和Mac OS X的PowerPC版本的r2.实际上问题可能不会太糟糕,例如AMD在其64位指令集的同时发布了"推荐的"ABI.
如果您认为"PC == Windows",那么将汇编程序添加到C程序并不会造成太大损害.如果你进入Unix世界,你将拥有许多不同的CPU:PS3或XBox中的PPC,旧Mac和许多功能强大的服务器.对于许多小型设备,您将拥有ARM.嵌入式设备(占当今绝大多数安装的CPU)通常使用自己的自定义CPU和特殊的指令集.
因此,虽然今天许多PC都能够运行英特尔代码,但这只占所有CPU的一小部分.
也就是说,x86代码并不总是相同的.汇编代码有两个主要原因:您需要访问特殊功能(如中断寄存器)或者您希望优化代码.在第一种情况下,代码非常便携.在后一种情况下,每个CPU都有点不同.他们中的一些人有SSE.但SSE很快被SSE2取代,后者被SSE3和SSE4取代.AMD拥有自己的品牌.很快,将有AVX.在操作码级别上,每个版本的CPU都有不同的时序.
更糟糕的是,一些操作码具有在CPU的特定步进中修复的错误.最重要的是,某些操作码在某些版本的CPU上比在其他版本上快得多.
接下来,您需要将此汇编代码与C部分接口.这通常意味着您需要处理ABI问题.
所以你可以看到这可能变得任意复杂.