最近断断续续接触了些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.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至今仍不支持宏,所以每一步工作都要自己做。

代码:
;示例代码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)的更多相关文章

  1. Windows x64汇编函数调用约定

    最近在写一些字符串函数的优化,用到x64汇编,我也是第一次接触,故跟大家分享一下. x86:又名 x32 ,表示 Intel x86 架构,即 Intel 的32位 80386 汇编指令集. x64: ...

  2. 深入理解Windows X64调试

    随着64位操作系统的普及,都开始大力进军x64,X64下的调试机制也发生了改变,与x86相比,添加了许多自己的新特性,之前学习了Windows x64的调试机制,这里本着“拿来主义”的原则与大家分享. ...

  3. Kinect for Windows SDK开发入门(15):进阶指引 下

    Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...

  4. mpusher 源码编译 for windows X64

    mpusher 源码编译 for windows X64 对于java我是小白,通过一步步的摸索,将经验总结下来,给更多码友提供入门的帮助.一个人的摸索是很困难的,本教程感谢 [MPush开源消息推送 ...

  5. x64汇编第一讲,Vs系列配置x64环境与x86环境

    目录 x64汇编环境配置 一丶x64环境配置 1.1 VS系列编译器配置X64Asm开发环境. 二丶Vs配置X86汇编环境. x64汇编环境配置 一丶x64环境配置 现在windows系统都是64位了 ...

  6. Oracle Fusion Applications (11.1.8) Media Pack and Oracle Application Development Framework 11g (11.1.1.7.2) for Microsoft Windows x64 (64-bit)

    Oracle Fusion Applications (11.1.8) Media Pack for Microsoft Windows x64 (64-bit) 重新搜索   常见问题    提示  ...

  7. [转]判断程序是否运行在 Windows x64 系统下

    以下功能代码判断是否运行在 Windows x64 下.本例使用 Windows API 函数 IsWow64Process,具体请参考MSDN文档:http://msdn.microsoft.com ...

  8. Windows X64 Patch Guard

    先简单介绍下PatchGuard ,摘自百度百科 PatchGuard就是Windows Vista的内核保护系统,防止任何非授权软件试图“修改”Windows内核,也就是说,Vista内核的新型金钟 ...

  9. OGG-00782 - OGG 11.2.1.0.2 FOR Windows x64 Microsoft SQL Server

    OS ENV:主机名:           WIN-NO42QRNPMFAOS 名称:          Microsoft Windows Server 2008 R2 Datacenter OS ...

随机推荐

  1. Jenkins的授权和访问控制

    默认的Jenkins不包含任何的安全检查,任何人可以修改Jenkins设置,job和启动build等.显然地在大规模的公司需要多个部门一起协调工作的时候,没有任何安全检查会带来很多的问题. 在系统管理 ...

  2. NOIP2018初赛 解题报告(C++普及)

    第24届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 竞赛时间:2018 年 10 月 13 日 14:30~16:30 选手注意: 1.试题纸共有 7 页,答题纸共有 2 页,满分 100 ...

  3. MySQL开发技巧

    MySQL基础表和数据 如何进行行列转换 行转列 场景:报表统计(sum()).汇总显示表数据:select * from score; 希望达到的效果 cross join SQL如下: selec ...

  4. CSU - 2058 跳一跳

    Description 冰弦非常热衷于过气微信小游戏"跳一跳",现在给出了他每次游戏时的一些信息,请你帮他计算一下每局游戏的得分. 跳一跳的游戏规则如下: 玩家操控一个小棋子,在形 ...

  5. 美团客户端响应式框架EasyReact开源啦

    前言 EasyReact 是一款基于响应式编程范式的客户端开发框架,开发者可以使用此框架轻松地解决客户端的异步问题. 目前 EasyReact 已在美团和大众点评客户端的部分业务中进行了实践,并且持续 ...

  6. splice() 的用法

    splice splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素: var arr = ['Microsoft', 'Apple', ' ...

  7. JavaScript数据类型学习脑图:

  8. 递归与分治策略之循环赛日程表Java实现

    递归与分治策略之循环赛日程表 一.问题描述 设有n=2^k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次: (2)每个选手一天只能参赛一 ...

  9. 压缩的问题-----WriteUp

    原题:http://ctf5.shiyanbar.com/crypto/winrar/ 526172211A0700CF907300000D0000000000000056947424965E 006 ...

  10. BZOJ2716 KD-Tree

    好久没写博客了 回去赶了好久文化课 颓欲见长 突然翻到fc爷的KD-Tree板子 来切了到裸题 对于一开始的数据我们可以先预处理 具体的排序方式见板子 其实就是我们对每次选定的一块选一个维度来排序啦 ...