selph
selph
发布于 2021-12-30 / 3213 阅读
1
1

使用VS2022编写x64汇编程序

创建x64项目

创建汇编项目的方法与之前写x86汇编的是一样的:

创建汇编项目:

  • 新建C++控制台项目,名字随便起
  • 选中项目右键“生成依赖性”,“生成自定义”,选择MASM生成规则
  • 右击右边的资源管理器中的源文件,添加,新建项,新建一个.asm后缀的新文件
  • 选中项目右键–属性–链接器–系统–子系统选<控制台(SUBSYSTEM:CONSOLE)>
  • 选中项目右键–属性–链接器–高级–入口点–填写 “main”
  • 写代码运行即可

调试汇编程序:

  • 右击项目名称,选择重新生成,然后点上面工作栏的本地Windows调试器即可
  • 可进行断点执行
  • 通过调试窗口中可将寄存器显示调出来

第一个程序

x64汇编程序和x86汇编程序的写法倒是有区别,x64汇编第一个程序:

extrn MessageBoxA: proc

;64位没有 .model 宏指令,不能指定内存模型和调用约定

.data
text     db 'Hello World', 0
caption  db 'Selph First x64 Application', 0

.code
main proc
	sub rsp,28h		; 函数调用前需要预留影子空间,对齐rsp
	xor r9d,r9d
	lea r8, caption
	lea rdx, text
	xor rcx,rcx
	call MessageBoxA	; 函数调用使用fastcall
	add rsp,28h
main ENDP
END				; 最后直接end,不用指明符号

WinAPI在64位要注意的点

以下内容来自:《汇编语言64位Windows API使用简述》,链接见文末参考资料

  • 输入与输出句柄是 64 位的。

  • 调用系统函数前,主调程序必须保留至少 32 字节的影子空间,其方法是将堆栈指针(RSP)寄存器减去 32。这使得系统函数能利用这个空间保存 RCX、RDX、R8 和 R9 寄存器的临时副本。

  • 调用系统函数时,RSP 需对齐 16 字节地址边界(基本上,任何十六进制地址的最低位数字都是 0)。幸运的是,Win64 API 似乎没有强制执行这条规则,而且在应用程序中对堆栈对齐进行精确控制往往是比较困难的。

  • 系统调用返回后,主调方必须回复 RSP 的初始值,方法是加上在函数调用前减去的数值。如果是在子程序中调用 Win64 API,那么这一点非常重要,因为在执行 RET 指令时,ESP 最终须指向子程序的返回地址。

  • 整数参数利用 64 位寄存器传递。

  • 不允许使用 INVOKE。取而代之,前 4 个参数要按照从左到右的顺序,依次放入这 4 个寄存器:RCX、RDX、R8 和 R9。其他参数则压入运行时堆栈。

  • 系统函数用 RAX 存放返回的 64 位整数值。

参考资料

Windows X64汇编入门_ayang1986的专栏-CSDN博客_win64汇编

使用 Visual Studio 2017 写纯 64 位汇编(intel 风格)_Alisebeast的博客-CSDN博客

汇编语言64位Windows API使用简述 (biancheng.net)


评论