内联汇编之64位程序

sohot

发布日期: 2019-01-03 10:50:43 浏览量: 1085
评分:
star star star star star star star star star star
*转载请注明来自write-bug.com

背景

内联汇编是指在 C/C++ 代码中嵌入的汇编代码,与全部是汇编的汇编源文件不同,它们被嵌入到 C/C++ 的大环境中。内联汇编方式两个作用,一是程序的某些关键代码直接用汇编语言编写,可提高代码的执行效率;二是有些操作无法通过高级语言实现,或者实现起来很困难,必须借助汇编语言达到目的。

32 位程序和 64 位程序下使用内联汇编的方式,有很大的差别。现在,我们对此分别进行介绍。本篇文章主要介绍的是在 64 位程序中使用内联汇编。

VS2013中添加并编译 .asm 文件步骤

在 64 位程序中,已经不能使用关键字 __asm 来添加汇编代码,而应把汇编代码全部写在 .asm 文件中,然后,再将 .asm 包含到项目中编译链接。现在,我们就先来讲解如何使用 VS2013 添加并编译 .asm 文件的步骤。

注意,以下演示实现从 x86 模式,即 Win32 模式下开始,如果从 x64 模式开始,在设置 .asm 文件的“自定义生成工具”的时候会卡死或者无反应。从 Win32 模式开始设置后,再新建 x64 模式,并从 Win32 模式复制设置,这样就可以成功对 .asm 文件设置“自定义生成工具”。

首先,我们在本地上新建一个 .asm 格式的文件 “myasm.asm”之后,右击项目工程并选择“添加” —> “现有项”,然后选择我们新创建的“myasm.asm”文件,添加到工程中:

然后,我们选中“myasm.asm”文件,并右击选择“属性”:

在“myasm.asm属性页”中,设置 从生成中排除 为“否”,设置 项类型 为“自定义生成工具”,然后,点击“应用”。这时,在窗口左侧就会生成“自定义生成工具”的扩展栏。如果是从 x64 模式下设置的,在一步,会没有反应或者卡死。所以,一定要从 Win32 模式开始,再创建 x64 模式,并把 Win32 的设置复制到 x64 模式中,便可以解决这个问题。

接着,我们开始新建 x64 模式,因为我们要开发的是 64 位程序。我们选中项目工程,以此选择 “属性” —> “配置属性” —> “配置管理器” —> “活动解决方案平台”选择“新建”。这时,就会来到“新建解决方案平台”页面。我们选择“x64”,并从 Win32 中复制设置,创建新的项目平台,点击“确定”。这时,就可以使用 x64 模式编译 64 位程序了。

然后,我们继续对 .asm 文件进行设置,将其包含到项目工程中来编译链接。选中“myasm.asm”文件,右击选择“属性”,来到“myasm.asm”属性页进行设置。在 命令行 中输入“ml64 /c %(fileName).asm”,在 输出 中输入“%(fileName).obj”,其它保持默认即可,点击“确定”即可完成设置。

经过上述几个步骤,我们成功为 x64 程序添加 .asm 文件并设置包含到项目工程中编译链接。接下来,我们就开始讲解如何在 .asm 文件中写汇编代码了。

实现原理

对于 64 位程序在 .asm 中写代码,需要遵循以下几个规则:

  • 会变文件 .asm 文件必须以关键字 .CODE 开始,关键字 END 结束,大小写都可以。
  1. .code
  2. ; 此处写汇编指令代码
  3. end
  • 所有的汇编代码以函数方式组织在一起。也就是说,我们要将汇编代码封装成一个个汇编函数。要注意 64 位汇编中的函数声明以及调用约定:
  1. .code
  2. ; _MyAdd是汇编函数
  3. _MyAdd proc
  4. ; 此处写汇编函数的代码
  5. _MyAdd endp
  6. end

其中, _MyAsm 是汇编函数的名称,proc 是汇编函数的关键字,endp 是汇编函数的结尾关键字。

要注意和 32 位汇编函数的区别:32 位汇编函数调用约定 __stdcall,所有参数从右到左依次入栈,通过压栈传递参数。64 位汇编函数的调用约定 __fastcall,前 4 个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈。

编码实现

myasm.asm

  1. .code
  2. _MyAdd proc
  3. xor rax, rax
  4. mov rax, rcx
  5. add rax, rdx
  6. add rax, r8
  7. add rax, r9
  8. ret
  9. _MyAdd endp
  10. end

ASM_64_Test.cpp

  1. extern "C" ULONGLONG _MyAdd(ULONGLONG a1, ULONGLONG a2, ULONGLONG a3, ULONGLONG a4);
  2. int _tmain(int argc, _TCHAR* argv[])
  3. {
  4. ULONGLONG a1 = 1;
  5. ULONGLONG a2 = 2;
  6. ULONGLONG a3 = 3;
  7. ULONGLONG a4 = 4;
  8. ULONGLONG b = _MyAdd(a1, a2, a3, a4);
  9. printf("b=%d\n", b);
  10. system("pause");
  11. return 0;
  12. }

程序测试

我们直接运行程序,成功显示正确的计算结果:

然后,我们查看 RAX、RCX、RDX、R8、R9 这 5 个寄存器里的值,和上述我们讲解的相一致:

总结

要特别注意一点就是,如果你使用 VS2013 开发环境,或者你使用其它的开发环境也遇到这样一个问题就是:在 x64 模式下,添加 .asm 文件,并设置在 .asm 属性页 中设置“自定义生成工具”后,界面出现卡死、无反应现象。可以尝试下面的解决方法:

  • 首先,不要在 x64 模式下面进行设置 .asm 属性页。更换到 x86 模式,即 Win32 模式下,然后再在 .asm 属性页 中设置“自定义生成工具”,这时可以正常设置。

  • 然后,在在 .asm 属性页 中设置“自定义生成工具”,这时,我们再“新建” x64 的解决方案平台,从 Win32 中复制设置。

那么,这时,我们就可以在 x64 下正常对“自定义生成工具”进行设置了。

同时,也要要注意和 32 位汇编函数的区别:32 位汇编函数调用约定 __stdcall,所有参数从右到左依次入栈,通过压栈传递参数。64 位汇编函数的调用约定 __fastcall,前 4 个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download ASM_64_Test.7z ( 143.47kb, 7次下载 )

发送私信

我想要你幸福,但我希望我是你幸福的原因

15
文章数
11
评论数
最近文章
eject