内容简介:3. 汇编编程基础3.1. 可用的汇编器X86指令集有几个汇编器可用,但目前它们没有一个好到被一致推荐。汇编程序员处在x86汇编没有统一语法的不幸境地之中。不同的汇编器使用不同的语法变体。最常用的汇编器有如下。
3. 汇编编程基础
3.1. 可用的汇编器
X86指令集有几个汇编器可用,但目前它们没有一个好到被一致推荐。汇编 程序员 处在x86汇编没有统一语法的不幸境地之中。不同的汇编器使用不同的语法变体。最常用的汇编器有如下。
MASM
这个Microsoft汇编器包括在Microsoft C++编译器中。有时可以通过下载Microsoft Windows驱动套装(WDK),或平台软件开发套装(SDK),或作为免费Visual C++精简版的扩展,获得免费版本。在Windows世界里,MASM已经成为事实上的标准许多年,大多数Windows编译器的汇编输出使用MASM语法。MASM有许多先进的语言特性。由于继承自用于8086处理器的最早期汇编器,语法有点凌乱且不一致。Microsoft仍然在维护MASM,以对Windows提供一套完整的开发工具,但这显然无利可图,MASM的维护被保持在最低限度。新指令集仍然被定期添加,但64位版本有几个缺陷。更新的版本仅在安装了编译器时可以运行,且仅在Windows XP或更新系统上。版本6与更早的版本可以运行在任何系统上,包括使用Windows模拟器的Linux。这样的版本在网上流传。
GAS
Gnu汇编器是包括在大多数Linux,BSD及Mac OS X发布的Gnu Binutils包的部分。Gnu编译器产生的汇编输出,在链接前经过Gnu汇编器。传统上,Gnu汇编器使用对机器生成代码工作良好的AT&T语法,但它产生的汇编对人非常不方便。AT&T语法中操作数的次序,与所有其他x86汇编器,以及Intel与AMD公布的指令文档给出的,都不一样。它使用各种前缀,像%与$来说明操作数类型。Gnu汇编器对所有x86平台都可用。
幸运地,更新版本的Gnu汇编器有一个使用Intel语法的选项。Gnu-Intel语法几乎与MASM语法完全相同。Gnu-Intel语法仅定义了指令代码的语法,没有指示、函数、宏等。指示仍然使用旧的Gnu-AT&T语法。指定.intel_syntax noprefix来使用Intel语法。在离开C或C++代码中的内联汇编时,指定.att_syntax prefix返回AT&T语法。
NASM
NASM是一个免费、开源的汇编器,支持多个平台与目标文件格式。相比MASM语法,其语法更清晰、更一贯。NASM定期更新指令集。NASM比MASM有更少的高级特性,但对大多数目的,它已足够。我将推荐NASM作为一个非常好的多平台汇编器。
YASM
YASM非常类似于NASM,使用完全相同的语法。在某些时期,YASM是第一个支持新指令集的,在其他时期是NASM。YASM与NASM可互换使用。
FASM
FASM汇编器是另一个开源的多平台汇编器。其语法不与其他汇编器兼容。FASM本身以汇编写就——一个诱人的想法,但不幸的是,这使得它的开发与维护不那么有效率。
WASM
WASM汇编器包含在Open Watcom C++编译器中。其语法类似MASM,但有些不同。没有紧跟时代。
JWASM
JWASM是WASM的进一步开发。它完全与MASM语法兼容,包括先进的宏与高级指示。如果要求MASM语法,JWASM是一个好的选择。JWASM可用一个称为Easy Code的集成开发环境(IDE)。
TASM
Borland Turbo汇编器包含在CodeGear C++ Builder里。它与MASM语法兼容,除了一些较新的语法补充。TASM不再维护,但仍然可用。它过时了,不支持当前的指令集。
GOASM
GoAsm是用于32与64位Windows的免费汇编器,包括资源编译器,链接器与调试器。其语法类似于MASM,但不完全兼容。目前,它没有支持最新的指令集。一个称为Easy Code的集成开发环境(IDE)也是可用的。
HLA
High Level Assembler实际上是一个支持类似汇编语句,产生汇编输出的高级语言编译器。在发明它的时候,这可能是一个好主意,但今天最好的C++编译器都支持固有函数,我相信不再需要HLA。
内联汇编
Microsoft与Intel C++编译器支持使用MASM语法子集的内联汇编。只要在汇编代码中插入名字,访问C++变量、函数及标签是可能的。这很容易,但不支持C++寄存器变量。参考第29页。
Gnu编译器支持可访问所有指令以及Gnu汇编器Intel与AT&T语法形式指示的内联汇编。从汇编访问C++变量,使用相当复杂的方法。
用于 Linux 与Mac系统的Intel编译器支持Microsoft与Gnu形式的内联汇编。
C++ 中的固有函数
这是组合低级代码与高级代码最新以及最便利的方式。固有函数是机器指令的高级语言表示。例如,可以通过调用等效于向量加法汇编指令的固有函数,在C++中进行一个向量加法。另外,定义一个带有重载+操作符的向量类,使只要通过写+就能进行向量加法,是可能的。Microsoft,Intel,Gnu与Clang编译器都支持固有函数。参考第27页与手册1《优化C++软件》。
选择哪个汇编器?
在大多数情形里,最简单的解决方案是在C++代码中使用固有函数。编译器可以负责大部分优化,使程序员可以集中精力在选择最好的算法,并把数据组织为向量。系统程序员可以通过使用固有函数访问系统指令,无需使用汇编语言。
在真正需要低级编程时,比如在高度优化的函数库或设备驱动中,你可以使用汇编器。
最好使用一个与你使用的C++编译器兼容的汇编器。这使你可以使用这个编译器把C++翻译为汇编,进一步优化汇编代码,然后汇编之。如果汇编器与编译器产生的语法不兼容,那么可以通过这个编译器产生一个目标文件,把目标文件反汇编为你需要的汇编语法。Objconv反汇编器支持几个不同的语法方言。
对许多用途,NASM汇编器都是好的选择,因为它支持许多平台与目标文件格式,它有良好的维护,经常更新到最新的指令集。
本手册中的例子使用MASM语法,除非另外指出。MASM语法在msdn.microsoft.com上的《Microsoft Macro Assembler Reference》中描述。
各种语法手册、编程手册与论坛的链接,参考 www.agner.org/optimize 。
-
- 寄存器集与基本指令
16 位模式中的寄存器
通用与整数寄存器
完整寄存器比特 0 - 15 |
部分寄存器比特 8 - 15 |
部分寄存器比特 0 - 7 |
AX |
AH |
AL |
BX |
BH |
BL |
CX |
CH |
CL |
DX |
DH |
DL |
SI |
||
DI |
||
BP |
||
SP |
||
Flags |
||
IP |
表3.1. 16位模式中的通用寄存器
如果微处理器与操作系统支持,在16位模式中,32位寄存器也可用。不应该使用ESP的高位字,因为在中断期间,它不会被保存。
浮点寄存器
完整寄存器,比特 0 - 79 |
ST(0) |
ST(1) |
ST(2) |
ST(3) |
ST(4) |
ST(5) |
ST(6) |
ST(7) |
表3.2. 浮点栈寄存器
如果微处理器支持,MMX寄存器可能可用。如果微处理器与操作系统支持,XMM寄存器可能可用。
段寄存器
完整寄存器,比特 0 - 15 |
CS |
DS |
ES |
SS |
表3.3. 16位模式中的段寄存器
寄存器FS与GS可能可用。
32 位模式中的寄存器
通用与整数寄存器
完整寄存器比特 0 - 31 |
部分寄存器比特 0 - 15 |
部分寄存器比特 8 - 15 |
部分寄存器比特 0 - 7 |
EAX |
AX |
AH |
AL |
EBX |
BX |
BH |
BL |
ECX |
CX |
CH |
CL |
EDX |
DX |
DH |
DL |
ESI |
SI |
||
EDI |
DI |
||
EBP |
BP |
||
ESP |
SP |
||
EFlags |
Flags |
||
EIP |
IP |
表3.4. 32位模式中的通用寄存器
浮点与64 位向量寄存器
完整寄存器,比特 0 - 79 |
部分寄存器,比特 0 - 63 |
ST(0) |
MM0 |
ST(1) |
MM1 |
ST(2) |
MM2 |
ST(3) |
MM3 |
ST(4) |
MM4 |
ST(5) |
MM5 |
ST(6) |
MM6 |
ST(7) |
MM7 |
表3.5. 浮点与MMX寄存器
如果微处理器支持,MMX寄存器才可用。ST与MMX寄存器不能用在代码的同一部分。使用MMX寄存器的代码部分,与使用ST寄存器的后续部分,必须通过EMMS指令隔开。
128 与256 位整数与浮点向量寄存器
完整或部分寄存器 比特 0 - 127 |
完整或部分寄存器 比特 0 - 255 |
完整 比特 0 - 511 |
XMM0 |
YMM0 |
ZMM0 |
XMM1 |
YMM1 |
ZMM1 |
XMM2 |
YMM2 |
ZMM2 |
XMM3 |
YMM3 |
ZMM3 |
XMM4 |
YMM4 |
ZMM4 |
XMM5 |
YMM5 |
ZMM5 |
XMM6 |
YMM6 |
ZMM6 |
XMM7 |
YMM7 |
ZMM7 |
表3.6. 32位模式中的XMM,YMM与ZMM寄存器
仅在微处理器与操作系统都支持,XMM才可用。对单精度或双精度,标量浮点指令分别仅使用XMM寄存器的32或64位。仅在处理器与操作系统都支持AVX指令集时,YMM寄存器才可用。仅处理器支持AVX-521指令集时,ZMM寄存器可用。
段寄存器
完整寄存器,比特 0 - 15 |
CS |
DS |
ES |
FS |
GS |
SS |
表3.7. 32位模式中的段寄存器
64 位模式中的寄存器
通用与整数寄存器
完整寄存器 比特 0 - 63 |
部分寄存器 比特 0 - 31 |
部分寄存器 比特 0 - 15 |
部分寄存器 比特 8 - 15 |
部分寄存器 比特 0 - 7 |
RAX |
EAX |
AX |
AH |
AL |
RBX |
EBX |
BX |
BH |
BL |
RCX |
ECX |
CX |
CH |
CL |
RDX |
EDX |
DX |
DH |
DL |
RSI |
ESI |
SI |
SIL |
|
RDI |
EDI |
DI |
DIL |
|
RBP |
EBP |
BP |
BPL |
|
RSP |
ESP |
SP |
SPL |
|
R8 |
R8D |
R8W |
R8B |
|
R9 |
R9D |
R9W |
R9B |
|
R10 |
R10D |
R10W |
R10B |
|
R11 |
R11D |
R11W |
R11B |
|
R12 |
R12D |
R12W |
R12B |
|
R13 |
R13D |
R13W |
R13B |
|
R14 |
R14D |
R14W |
R14B |
|
R15 |
R15D |
R15W |
R15B |
|
RFlags |
Flags |
|||
RIP |
表3.8. 64位模式中的寄存器
高8位寄存器AH,BH,CH,DH仅可以用在没有REX前缀的指令中。注意修改一个32位部分寄存器将寄存器余下部分(比特32 ~ 63)置零,但修改一个8位或16位部分寄存器不会影响该寄存器余下部分。这可由以下序列来展示:
; Example 3.1. 8, 16, 32 and 64 bit registers
mov rax, 1111111111111111H ; rax = 1111111111111111H
mov eax, 22222222H ; rax = 0000000022222222H
mov ax, 3333H ; rax = 0000000022223333H
mov al, 44H ; rax = 0000000022223344H
这个不一致有一个很好的理由。将寄存器不使用的部分置零,比不改变它更高效,因为这消除了对之前值的一个假依赖。但重置寄存器未使用部分的原则不能扩展到16位及8位部分寄存器,因为这将破坏与32位及16位模式的前向兼容。
唯一可以有64位立即数的指令是MOV。其他整数指令仅能有32位符号扩展操作数,例如:
; Example 3.2. Immediate operands, full and sign extended
mov rax, 1111111111111111H ; Full 64 bit immediate operand
mov rax, -1 ; 32 bit sign-extended operand
mov eax, 0ffffffffH ; 32 bit zero-extended operand
add rax, 1 ; 8 bit sign-extended operand
add rax, 100H ; 32 bit sign-extended operand
add eax, 100H ; 32 bit operand. result is zero-extended
mov rbx, 100000000H ; 64 bit immediate operand
add rax, rbx ; Use an extra register if big operand
使用16位符号扩展操作数是不可能的。如果需要向一个64位寄存器加一个立即数,如果这个值太大,不能放入32位符号扩展操作数,必须首先将这个值移入另一个寄存器。
浮点与64 位向量寄存器
完整寄存器,比特 0 - 79 |
部分寄存器,比特 0 - 63 |
ST(0) |
MM0 |
ST(1) |
MM1 |
ST(2) |
MM2 |
ST(3) |
MM3 |
ST(4) |
MM4 |
ST(5) |
MM5 |
ST(6) |
MM6 |
ST(7) |
MM7 |
表3.9. 浮点与MMX寄存器
ST与MMX寄存器不能用在代码的同一个部分。使用MMX寄存器的代码部分必须通过一条EMMS指令与使用ST寄存器的后续部分隔开。对64位Windows,ST与MMX寄存器不能用在设备驱动中。
128 位与256 位整数与浮点向量寄存器
完整或部分寄存器 比特 0 - 127 |
完整或部分寄存器 比特 0 - 255 |
完整寄存器 比特 0 - 511 |
XMM0 |
YMM0 |
ZMM0 |
XMM1 |
YMM1 |
ZMM1 |
XMM2 |
YMM2 |
ZMM2 |
XMM3 |
YMM3 |
ZMM3 |
XMM4 |
YMM4 |
ZMM4 |
XMM5 |
YMM5 |
ZMM5 |
XMM6 |
YMM6 |
ZMM6 |
XMM7 |
YMM7 |
ZMM7 |
XMM8 |
YMM8 |
ZMM8 |
XMM9 |
YMM9 |
ZMM9 |
XMM10 |
YMM10 |
ZMM10 |
XMM11 |
YMM11 |
ZMM11 |
XMM12 |
YMM12 |
ZMM12 |
XMM13 |
YMM13 |
ZMM13 |
XMM14 |
YMM14 |
ZMM14 |
XMM15 |
YMM15 |
ZMM15 |
ZMM16 |
||
ZMM17 |
||
ZMM18 |
||
ZMM19 |
||
ZMM20 |
||
ZMM21 |
||
ZMM22 |
||
ZMM23 |
||
ZMM24 |
||
ZMM25 |
||
ZMM26 |
||
ZMM27 |
||
ZMM28 |
||
ZMM29 |
||
ZMM30 |
||
ZMM31 |
表3.10. 64位模式中的XMM,YMM与ZMM寄存器
对单精度或双精度,标量浮点指令仅分别使用XMM寄存器的32或64位。仅当处理器与操作系统支持AVX指令集时,YMM寄存器才可用。仅当处理器支持AVX512指令集时,ZMM寄存器才可用。在处理器与汇编器都支持AVX512时,才可能使用XMM16-31与YMM16-32。
段寄存器
完整寄存器,比特 0 - 15 |
CS |
FS |
GS |
表3.11. 64位模式中的段寄存器
段寄存器仅用于特殊目的。
以上所述就是小编给大家介绍的《[译]优化汇编例程(2)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- iOS汇编入门教程(一)ARM64汇编基础
- iOS 汇编入门教程(一):ARM64 汇编基础
- iOS汇编入门教程(三)汇编中的 Section 与数据存取
- iOS汇编入门教程(二)在Xcode工程中嵌入汇编代码
- 汇编语言8086笔记
- python编程(反汇编)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
黑客攻防技术宝典(第2版)
[英] Dafydd Stuttard、[英] Marcus Pinto / 石华耀、傅志红 / 人民邮电出版社 / 2012-6-26 / 99.00元
内容简介: Web应用无处不在,安全隐患如影随形。承载着丰富功能与用途的Web应用程序中布满了各种漏洞,攻击者能够利用这些漏洞盗取用户资料,实施诈骗,破坏其他系统等。近年来,一些公司的网络系统频频遭受攻击,导致用户信息泄露,造成不良影响。因此,如何确保Web应用程序的安全,已成为摆在人们眼前亟待解决的问题。 本书是Web安全领域专家的经验结晶,系统阐述了如何针对Web应用程序展开攻击与......一起来看看 《黑客攻防技术宝典(第2版)》 这本书的介绍吧!