汇编语言到底有多不可移植?

8
我知道在任何程序中编写汇编代码或添加汇编代码都会影响其可移植性。但是,影响有多大呢?我的意思是,现在基本上所有的PC都是x86或x64,对吗?所以,如果我将汇编代码嵌入C程序中,为什么它不会在任何地方编译呢?
这种不可移植性的概念是否只是指当您深入了解特定处理器的特殊问题,从代码中挤出每一滴性能时?
如果我没记错的话,PC游戏“过山车大亨”几乎完全是用汇编语言编写的。那么……它到底有多不可移植?
4个回答

17
除了处理器本身外,当然还有其他考虑因素:您的目标平台上的调用约定是什么?如何将struct值传递给其他(例如:API)函数?哪些寄存器可能被调用方破坏?哪些寄存器保证为调用方所保留?如何进行系统调用?操作系统在进程启动时为您准备的内存布局是什么?

1
+1,虽然我猜调用约定和数据结构都不会有影响,除非你的程序与其他进程交互。至于内存布局——如果您将程序与目标平台的标准C库链接,并使用其malloc()等函数呢? - Carson Myers
@Carson: 函数的调用约定也很重要,因为您可能想要能够从混合汇编中调用用C编写的函数,反之亦然。 - unwind
FASM在Windows和Linux之间具有良好的可移植性。我不知道其他汇编器如何。 - Imagist
2
一旦您访问操作系统的API,就会与其他进程进行交互。我认为如果没有这个,您无法编写任何有趣的程序。 - Nathan Fellman

11

移植汇编代码时,还存在操作系统间ABI的差异问题。将C程序从Unix移植到Windows(甚至是从Linux移植到OpenBSD)可能只需要重新编译,但对于汇编程序来说,你可能会发现一些被调用者保存的寄存器变为了调用者保存的寄存器,或者浮点参数的传递方式也有所不同。

这不仅仅是理论上的问题,例如PowerPC版本的Linux和Mac OS X中的寄存器r2。实际上这个问题可能并不太糟糕,例如AMD在其64位指令集发布时同时发布了一个“推荐”的ABI。


9
如果您认为“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问题。
因此,您可以看到这可能变得任意复杂。

1
一个例子:Linux支持十几种,如果不是更多的CPU架构。另一个例子是苹果Unix生态系统:Cocoa代码可能在最新的Mac上处理x86,在旧的Mac上处理PPC,在iPhone上处理ARM。 - mouviciel
1
说得好 - 尽管我所说的“PC”并不是指Windows,而是指普通个人电脑(你可能会在任何人家里找到的),而不是服务器,排除Xbox和嵌入式系统等。 - Carson Myers
我认为你的意思是“PC=Windows”,否则你就不会做出“一切都是x86或x64”的假设了 :-) - Gunther Piez
英特尔为了保持向后兼容性,会采取很多努力,包括修复bug。如果某个操作码有问题,可以确保规范将被更改,而不是未来的行为。如果没有问题,将添加一种模式位以允许您使用有问题的操作码。 - Nathan Fellman

3

汇编语言是直接为特定处理器编写指令,这意味着如果x86永远存在,你的代码在某种程度上是可移植的。

但即使现在,ARM处理器也正在回归(即下一代网络书),我确信如果处理器在明年不改变,它们将会越来越流行。

我认为,由于设计原因,汇编语言并不具备可移植性。


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