汇编 | Java | C# | Delphi | C/C++ |

Windows X64汇编入门(1)

indows X64汇编入门(1)【转载】

内容来自dedecms


作 者:tankaiha
链 接:http://bbs.pediy.com/showthread.php?t=43967

 

copyright dedecms

最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助。我也是刚接触这方面知识,文中肯定有错误之处,大家多指正。
文章的标题包含了本文的四方面主要内容:
(1)Windows:本文是在windows环境下的汇编程序设计,调试环境为Windows Vista 64位版,调用的均为windowsAPI。
(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)。

dedecms.com




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,如果还有更多的参数,才通过椎栈传递。二是调用者负责椎栈空间的分配与回收。
copyright dedecms

下面给出一段代码,功能是显示一个简单的MessageBox,注意对RSP的操作: 内容来自dedecms

代码:

copyright dedecms

;示例代码1.asm 织梦好,好织梦

;语法:GoASM

dedecms.com

DATA SECTION 内容来自dedecms

textdb 'Hello x64!', 0

内容来自dedecms

captiondb 'My First x64Application', 0

织梦内容管理系统

  dedecms.com

CODE SECTION 本文来自织梦

START: 本文来自织梦

subrsp,28h

dedecms.com

xorr9d,r9d

copyright dedecms

lear8, caption 织梦内容管理系统

leardx, text

内容来自dedecms

xorrcx,rcx copyright dedecms

callMessageBoxA

copyright dedecms

addrsp,28h 内容来自dedecms

ret 内容来自dedecms

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


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


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

代码:

织梦好,好织梦

;示例代码2.asm

本文来自织梦

;语法:ML64 copyright dedecms

extrnMessageBoxA: proc 内容来自dedecms

  织梦内容管理系统

.data dedecms.com

textdb 'Hello x64!', 0 本文来自织梦

captiondb 'My First x64Application', 0

本文来自织梦

  织梦内容管理系统

.code 内容来自dedecms

Main proc 织梦内容管理系统

subrsp,28h dedecms.com

xorr9d,r9d

织梦内容管理系统

lear8, caption 织梦好,好织梦

leardx, text

dedecms.com

xorrcx,rcx

内容来自dedecms

callMessageBoxA 织梦好,好织梦

addrsp,28h 织梦好,好织梦

ret

copyright dedecms

  织梦好,好织梦

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》 织梦好,好织梦