在64位平台上运行的32位汇编代码

时间:2011-01-31 23:07:15

标签: linux assembly 32bit-64bit

我正在通过Jonathan Barlett撰写的名为Programming from the Ground Up的书来学习x86汇编语言。最近我将我的系统更新到64位平台,并且出现了汇编代码语法的问题,pushl指令更加具体。我花了一些时间在x86_64 isa上寻找信息,但我认为最好完成学习x86的基础知识。为了做到这一点,我想知道是否有一种方法将旧语法组装成64位对象,或类似的东西。或者有重大变化使这不可能? 我正在使用Ubuntu 10.10和GNU便携式汇编程序。

反正。如果您在x86_64或其与其前任之间的差异中指出一本好书或任何信息来源,那将会很不错。

编辑:谢谢!我得到了我需要的东西。这两个答案都很有用。别担心,我很期待放开X86。

2 个答案:

答案 0 :(得分:3)

Linux使用指定的x86_64 ABI here。您可以做的最好的事情是读取与您所在地区最相关的ABI位。这里有一些想到的东西:

  • 与x86不同,x86_64上只有一个调用约定;两个,如果你算上微软Windows再次完全不同的事实。
  • 在x86中,函数的参数通常在堆栈上传递。在x86_64中,前几个用于整数类型的寄存器rdirsirdxrcxr8r9
  • 内存地址类型均为QWORD,因此,如果您使用带有AT& T语法的完整寄存器(r10等),则需要movqaddq

现在,x86_64的部分设计是它与x86向后兼容,即如果操作系统设置正确,则能够执行x86代码。所以,例如这样做没有错:

nasm -felf32 myprog.asm
gcc -o myprog -m32 myprog.o

然而,请注意;您开始依赖其他可用代码的次数越多,您需要的32位副本就越多。请注意,这基本上完全使用32位模式的代码,完成调用约定和所有内容。简而言之,它也应该在32位机器上执行。正如Jerry所说(+1),你无法在64位模式下使用32位约定编译32位汇编。您必须遵守64位ABI。

当然,除此之外,您可以在日常工作中使用eax这样的寄存器,只要知道它会影响整个rax或者更确切地说是`eax的一半。

答案 1 :(得分:2)

在汇编语言级别的32位和64位操作之间存在足够的差异,您几乎肯定不会只想尝试将32位代码视为64位代码,并希望最好的,或类似的东西。

当你像编写汇编语言一样“靠近金属”工作时,通常是出于某种原因 - 你通常不会/不会/不会欣赏汇编程序试图猜测你到底是什么打算,并修改您的代码以适应。在某些情况下,你只是失去了优势(例如,速度)而在其他情况下,它可能会破坏你完全正在做的事情(例如,当它/如果它的符号将某些东西延伸到64位而应该实际上是零延伸的话)。