Windows X64汇编入门(1)
tankaiha

最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助。我也是刚接触这方面知识,文中肯定有错误之处,大家多指正。
文章的标题包含了本文的四方面主要内容:
(1)Windows:本文是在windows环境下的汇编程序设计,调试环境为Windows Vista 64位版,调用的均为windows API。
(2)X64:本文讨论的是x64汇编,这里的x64表示AMD64和Intel的EM64T,而不包括IA64。至于三者间的区别,可自行搜索。
(3)汇编:顾名思义,本文讨论的编程语言是汇编,其它高级语言的64位编程均不属于讨论范畴。
(4)入门:既是入门,便不会很全。其一,文中有很多知识仅仅点到为止,更深入的学习留待日后努力。其二,便于类似我这样刚接触x64汇编的新手入门。
        本文所有代码的调试环境:Windows Vista x64,Intel Core 2 Duo。

1.        建立开发环境
1.1        编译器的选择
    对应于不同的x64汇编工具,开发环境也有所不同。最普遍的要算微软的MASM,在x64环境中,相应的编译器已经更名为ml64.exe,随Visual Studio 2005一起发布。因此,如果你是微软的忠实fans,直接安装VS2005既可。运行时,只需打开相应的64位命令行窗口(图1),便可以用ml64进行编译了。

第二个推荐的编译器是GoASM,共包含三个文件:GoASM编译器、GoLINK链接器和GoRC资源编译器,且自带了Include目录。它的最大好外是小,不用为了学习64位汇编安装几个G 的VS。因此,本文的代码就在GoASM下编译。

第三个Yasm,因为不熟,所以不再赘述,感兴趣的朋友自行测试吧。
不同的编译器,语法会有一定差别,这在下面再说。

1.2        IDE的选择
    搜遍了Internet也没有找到支持asm64的IDE,甚至连个Editor都没有。因此,最简单的方法是自行修改EditPlus的masm语法文件,这也是我采用的方法,至少可以得到语法高亮。当然,如果你懒得动手,那就用notepad吧。
    没有IDE,每次编译时都要手动输入不少参数和选项,做个批处理就行了。

1.3        硬件与操作系统
    硬件要求就是64位的CPU。操作系统也必须是64位的,如果在64位的CPU上安装了32位的操作系统,就算编译成功也无法运行程序。

2.        寄存器的改变
    汇编是直接与寄存器打交道的语言,因此硬件对语言影响很大。先来看看x64与x32相比在硬件上多了什么,变了什么(图2)。

X64多了8个通用寄存器:R8、R9、R10、R11、R12、R13、R14、R15,当然,它们都是64位的。另外还增加了8个128位XMM寄存器,不过通常用不着。
    X32中原有的寄存器在X64中均为扩展为64位,且名称的第一个字母从E改为R。不过我们还是可以在64位程序中调用32位的寄存器,如RAX(64位)、EAX(低32)、AX(低16位)、AL(低8位)、AH(8到15位),相应的有R8、R8D、R8W和R8B。不过不要在程序中使用如AH之类的寄存器,因为在AMD的CPU上这种用法会与某些指令产生冲突。

3.        第一个x64汇编程序
    本节,我们开始编写自己的第一个x64汇编程序。在这之前,先讲一下calling convention的改变。
3.1        API调用方式
    把Calling convention放在第一个讲,代表它的重要性。在32位汇编中,我们调用一个API时,采用的是stdcall,它有两个特点:一是所有参数入栈,通过椎栈传递;二是被调用的API负责栈指针(ESP)的恢复,我们在调用MessageBox后不用add esp,14h,因为MessageBox已经恢复过了。
而在x64汇编中,两方面都发生了变化。一是前四个参数分析通过四个寄存器传递:RCX、RDX、R8、R9,如果还有更多的参数,才通过椎栈传递。二是调用者负责椎栈空间的分配与回收。
    下面给出一段代码,功能是显示一个简单的MessageBox,注意对RSP的操作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

;示例代码1.asm

;语法:GoASM

DATA SECTION

text     db 'Hello x64!', 0

caption  db 'My First x64 Application', 0

CODE SECTION

START:

sub rsp,28h

xor r9d,r9d

lea r8, caption

lea rdx, text

xor rcx,rcx

call MessageBoxA

add rsp,28h

ret

这段代码是在GoASM中编译,指令部分GoASM与ML64差不多,关键是一些宏的定义有差别。比如masm中的.code,在这里就成了CODE SECTION。下面再说区别,先编译。GoASM中编译分两步:
(1)        编译:goasm /x64 1.asm
(2)        链接:golink 1.obj user32.dll
    如果一些正常,命令行中应显示图3的内容。

运行一下,我们的第一个64位windows程序就运行了。

GoASM还有一个特点是支持宏:ARG和INVOKE,使用这两个宏可以免除程序员自己对椎栈进行操作。不过初学吗,还是从基础掌握比较好。下面的一段代码相同的功能的MASM代码,注意看看区别。ML64至今仍不支持宏,所以每一步工作都要自己做。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

;示例代码2.asm

;语法:ML64

extrn MessageBoxA: proc

.data

text     db 'Hello x64!', 0

caption  db 'My First x64 Application', 0

.code

Main proc

sub rsp,28h

xor r9d,r9d

lea r8, caption

lea rdx, text

xor rcx,rcx

call MessageBoxA

add rsp,28h

ret

Main ENDP

end

编译这段代码的命令行是:ml64 2.asm /link /subsystem:windows /entry:Main user32.lib。如果正常,应该如图5显示那样。

很有意思吧,在64位系统下,我们仍然调用user32的API。可能是名称用习惯了,微软自己都懒得改了吧。

3.2        64位的椎栈
    代码中还有一处值得注意,那就是sub rsp,28h和add rsp,28h。28h这个数值是怎么来的呢?
首先,x64中椎栈被扩展为64位;其次,我们在调用MessageBoxA时,要给四个参数外加一个返回地址留空间,因此8(位)*5=40=28h。
    另外一些小问题要注意,AMD64不支持push 32bit寄存器的指令,最好的方法就是push和pop都用64位寄存器。EM64T如何?看了下Intel的开发手册,各个指令都分三种情况:纯32位、纯64位和32与64位混合。下面是手册的片段:

Opcode*      Instruction        64-Bit Mode       Compat/Leg Mode      Description
FF /6         PUSH r/m16         Valid                 Valid            Push r/m16.
FF /6         PUSH r/m32         N.E.                  Valid            Push r/m32.
FF /6         PUSH r/m64         Valid                  N.E.           Push r/m64.
Default operand size 64-bits.

没别的好方法,使用中多注意,尽量在64位程序中保用64位寄存器。

4.        一些参考资料
    写完了第一个hello world,本文就此打住。本还想写一些内容,但掌握不深,留待下回吧。感觉有些资料不得不在第一篇文章中放出来,因为它们是现有学习x64汇编的最好教材了,文中很多代码和知识点也来自于这些资料。
(1)《Moving to Windows x64》,出自:http://www.ntcore.com/Files/vista_x64.htm
(2)GoASM的帮助文档,目前最好的64位汇编教程。出自:www.jorgon.freeserve.co.uk
(3)《开始进行 64 位 Windows 系统编程之前需要了解的所有信息》,出自:http://www.microsoft.com/china/MSDN/library/Windev/64bit/issuesx64.mspx
(4)来自CodeGurus的两篇文章
《Assembler & Win64》,
http://www.codegurus.be/codegurus/Programming/assembler&win64_en.htm
《bout RIP relative addressing》
http://www.codegurus.be/codegurus/Programming/riprelativeaddressing_en.htm
(5)AMD开发手册
(6)Intel开发手册,注意是新的《ntel® 64 and IA-32 Architectures software Developer’s Manual》

Windows X64汇编入门相关推荐

  1. x86-64汇编入门

    前言 去年在看协程相关内容的时候,通读了腾讯的libco.其中切换协程的一小段代码是用汇编实现的,当时没有去搞明白这一块.最近趁着项目空闲查阅了x64汇编的相关资料,这篇博客打算总结一下,方便以后查阅 ...

  2. Windows x64内核学习笔记(一)—— 环境与配置

    Windows x64内核学习笔记(一)-- 环境与配置 前言 新特性 基础要求 实验环境 Guest Win10配置 问题解决 参考资料 前言 之前,跟着海哥学习了windows内核的一些机制,包括 ...

  3. macOS上的汇编入门(五)——第一个汇编程序

    通过前几篇文章,我们逐步建立了学习汇编语言之前需要的基础知识.接下来,在这篇文章中,我们开始编写我们的第一个汇编程序了. 编辑器,汇编器与链接器 工欲善其事,必先利其器.我们编写汇编语言,至少需要编辑 ...

  4. Windows x64内核学习笔记(二)—— IA-32e模式

    Windows x64内核学习笔记(二)-- IA-32e模式 IA-32e模式 模式检测 强制平坦段 任务切换 中断门描述符 FS / GS 模式切换 32位程序进内核 64位程序进内核 实验:模式 ...

  5. 张赐荣 | Windows 消息处理机制 入门

    张赐荣 | Windows 消息处理机制 入门 [文 / 张赐荣] 事件驱动和消息循环 消息概述 消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按 ...

  6. Windows x64为动态代码添加unwind信息

    Windows x64为动态代码添加unwind信息 0x00 0x01 0x00 64位程序的堆栈回溯与32位差别很大,调试器和 RtlCaptureStackBackTrace 无法再使用 ebp ...

  7. Windows Azure Marketplace入门教学-利用TabLeau Public构建可视化DataMarket应用

    公告    :本博客为微软云计算中文博客  的镜像博客.   部分文章因为博客兼容性问题  ,会影响阅读体验  .如遇此情况,请访问  原博客    . 在上一篇教学Windows Azure Mar ...

  8. 用x64汇编优化8位S盒置换(三)

    2019独角兽企业重金招聘Python工程师标准>>> 在本文的上一章,S盒置换的C语言实现的最佳方案是将8位S盒扩展至16位,确定了S盒数组的大小与数据单元的大小,首先回顾相应的C ...

  9. windows x64 build c++ poco库

    编译环境及工具: vs2008 windows server 2008 x64 poco源码(可以http://pocoproject.org/获取) Windows (x86, 64-bit), Z ...

最新文章

  1. JavaBeans四个作用域 范围
  2. IDEA如何生成get和set方法
  3. java jar包冗余_paip.批处理清理java项目冗余jar的方法
  4. org.apache.catalina.LifecycleException: Failed to
  5. oracle常用用户权限,oracle创建新用户及授予常用权限
  6. scapy python_Scapy在Python脚本中
  7. 动软代码生成器连不上高版本(8.0+)的解决方法
  8. 身体指数bmi流程图_理想的身体脂肪百分比是多少?男女不同脂肪数据对照表
  9. AutoIt的录制(AU3Record)
  10. java语音实现_用JAVA实现语音交互的功能(即语音聊天室的功能)
  11. 三星量子计算机,全球首款量子手机来了,某厂商是秀肌肉还是蹭流量?
  12. 中文拼音首字母排序比较器
  13. 传统安防互联网化无插件直播分析及解决方案
  14. 为什么和平精英一直显示无法连接到服务器,和平精英无法连接到服务器解决办法...
  15. C语言中空格,空字符,字符数组结束符的区别
  16. AJAX---发送POST请求、Get请求、请求四步、解决低版本的缓存问题
  17. python爬虫王者荣耀高清皮肤大图背景故事通用爬虫
  18. 御龙在天怎么找回服务器,御龙在天手游人物找回 误删的角色如何找回
  19. 【visual studio】错误LNK 1168,无法打开 XXX.exe进行写入解决方案
  20. 59十字链表,邻接多重表,边集数组,佛洛依德的冰山理论

热门文章

  1. c++双人战争小游戏
  2. flv文件元信息(metadata)
  3. 整理形成1997—2018年31个省份人口密度
  4. C语言文件联系人管理碎片整理,深入理解C语言内存管理.docx
  5. 《PROTOTYPICAL CONTRASTIVE LEARNING OF UNSUPERVISED REPRESENTATIONS》学习笔记
  6. c++版本opencv(04.认识Mat对象-05.Mat对象创建与使用-06.遍历与访问每个像素-)
  7. 网库黄页董事长兼CEO王海波演讲
  8. do-while和while的区别
  9. jpa常用查询方法使用总结自定义sql查询
  10. MATLAB将每次运算结果循环依次写入xls文件