用户手册是Yasm汇编Endv

本文档的用户手册是Yasm汇编。它是介绍和通用所有Yasm用户参考。

1.介绍

Yasmbsd许可下是一个汇编程序,而设计的,以便支持多个汇编程序语法(例如NASM,GNU等)除了多个输出对象格式和多个指令集。其模块化的体系结构允许额外的对象格式,添加调试格式和语法相对容易。

Yasm2001年开始生活的重写NASMNetwidex86汇编在BSD许可。自那时以来,它已经达到和超过NASM的功能,结合特性,比如支持64位AMD64架构,解析GNU语法,并生成刺穿,DWARF2CodeView8调试信息。

2.许可证

Yasm许可2-clause下3条款“修订”BSD许可,但有一个例外:::矢量模块使用的主线版本的Yasm实现独立于机器大整数和浮点支持下triple-licensed艺术许可证GPL,LGPL。“yasm-nextgen”代码使用一个完全不同的bsd许可下实现,因此在BSD-equivalent许可证。提供的许可证的全文Yasm源分布。

这个用户手册2-clauseBSD许可下的。

3所示。材料覆盖在这本书

这本书的目的是成为Yasm的用户手册,作为一个介绍和通用的参考。虽然提到Yasm在各个部分的实现(通常是解释背后的原因错误或不寻常的方面各种特性),这本书将不进入深度解释Yasm工作;Yasm深入讨论的内部,看到的Yasm汇编程序的设计和实现。

我一部分。使用Yasm

所说yasm简介

yasm(-f格式][-o输出文件][其他选项…){infile}

1.2描述。

的yasm命令组装文件infile并将输出到文件输出文件如果指定。如果输出文件没有指定,yasm将获得一个默认输出文件的名字从其输入文件的名称,通常通过添加什么.o或.obj,或通过删除所有扩展原始二进制文件。如果做不到这一点,将输出文件的名字yasm.out。

如果叫一个infile“-”,yasm组装的标准输入,输出到文件输出文件,或yasm.out如果没有输出文件都是确定的。

如果在执行过程中发现的错误或警告,Yasm输出错误消息stderr(通常终端)。如果没有遇到错误或警告,Yasm不输出任何信息。

选择1.3。

许多选项可以在两种形式之一:破折号后面跟着一个字母,或者两个破折号,后跟一个长选项名称。按字母顺序列出选项。

1.3.1。一般选择

1.3.1.1。——一个拱或——拱=拱:选择目标架构

1.3.1.2。-f格式或——oformat=格式:选择对象格式

1.3.1.3。-g调试或——dformat=调试:选择调试格式

1.3.1.4。-h或——帮助:打印选项的摘要

打印的摘要调用选项。所有其他选项都被忽略,没有生成输出文件。

1.3.1.5。-l列表或——lformat=列表文件格式:选择列表

选择输出的格式/样式列表文件。列表文件通常混杂的原始机器生成的汇编代码。默认列表格式是“nasm”,模仿nasm列表文件格式。打印可用列表的列表文件格式到标准输出,使用“帮助”列表。

1.3.1.6。-llistfile或——列表=listfile:指定文件名列表

指定输出文件列表的名称。如果不使用此选项,没有生成文件列表。

1.3.1.7。-m机或——机器=机:选择目标计算机体系结构

1.3.1.8。-o文件名或——objfile=文件名对象:指定文件名

指定输出文件的名称,覆盖任何Yasm生成的缺省名称。

1.3.1.9。-p解析器或——解析器=解析器:选择解析器

1.3.1.10。-rpreproc或——preproc=preproc:选择预处理器

选择预处理器上使用输入文件之前将它传递给解析器。预处理器通常提供宏观功能,不包括在主要的解析器。默认的预处理是“nasm”,这是一个进口版本实际nasm的预处理器。“原始”预处理器也可以,只是跳过的预处理步骤,直接输入文件传递给解析器。打印列表可用的预处理器到标准输出,使用“帮助”preproc。

1.3.1.11。——版本:Yasm版本

这个选项会导致Yasm打印的版本号Yasm以及许可证总结到标准输出。所有其他选项都被忽略,没有生成输出文件。

1.3.2。警告选项

-w选项有两个相反的形式:-w叫什么名字和-Wno-的名字。这里只显示了非默认形式。

警告选项在命令行上给出的顺序处理,如果-w紧随其后的是-Worphan-labels,所有的警告都是关闭的除了orphan-labels。

1.3.2.1。-w:抑制所有的警告消息

这个选项会导致Yasm抑制所有警告消息。正如上面所讨论的,这个选项可以指定其他选项重新启用警告紧随其后。

1.3.2.2。-Werror:将警告视为错误

这个选项会导致Yasm对所有的警告和错误。通常警告不防止生成的对象文件,不会导致失败的退出状态yasm,而错误。这个选项让警告相当于错误的这种行为。

1.3.2.3。-Wno-unrecognized-char:不要警告未识别的输入字符

导致Yasm不警告无法识别的字符输入。通常Yasm将生成一个警告任何非ascii字符输入文件中找到。

1.3.2.4。-Worphan-labels末尾:警告标签上缺少冒号

当使用NASM-compatible解析器,使Yasm警告标签发现独自一行末尾没有冒号。虽然这些是合法的标签在NASM中语法,他们可能是无意的,由于拼写错误或宏定义命令。

1.3.2.5。-x风格:改变错误/警告报告风格

选择一个特定的输出样式错误和警告消息。默认是“gnu”风格,模仿的输出海湾合作委员会。的“vc”风格也可以模仿微软VisualStudio的编译器的输出。

这个选项是可用的,这样Yasm将更自然地集成到IDE环境等VisualStudio或Emacs,允许IDE正确认识到错误/警告信息等,并链接到的违规行源代码。

1.3.3。预处理器的选择

虽然理论上这些预处理选项将影响任何预处理器,目前唯一的预处理器在Yasmnasm预处理器。

1.3.3.1。-d宏(=价值):预定义宏

预定义一个单行的宏。值是可选的(如果没有赋值,宏仍然是定义,但是一个空值)。

1.3.3.2。-e或——preproc-only:只有进行预处理

停止组装后的预处理阶段;预处理输出发送到指定的输出名称或,如果没有指定输出名称,标准输出。不产生目标文件。

1.3.3.3。-我路径:添加包含文件路径

添加目录路径包括文件的搜索路径。搜索路径默认为只包括源文件所在的目录。

1.3.3.4。-p文件名:Pre-include文件

Pre-includes文件文件名,使它看起来好像文件名返回输入。可以用于将多行宏的-d不能支持。

1.3.3.5。-u宏:未定义一个宏

1.4。支持目标架构

x86

“x86体系结构支持ia-32指令集和衍生品(包括16位和non-Intel指令)和AMD64指令集。它由两台机器:“x86”(ia-32和衍生品)和“AMD64”(AMD64和衍生品)。默认的机器“x86架构的x86机器。

1.5。支持解析器(语法)

Yasm解析汇编程序语法如下:

nasm

气体

1.6。支持对象格式

“本”对象格式生成一个扁平格式,non-relocatable二进制文件。它是适合生产DOS。COM可执行文件或引导块之类的东西。它只支持3部分,这些部分都写在一个预定义的输出文件。

coff

COFF对象格式是一个年长的浮动对象格式用于旧的Unix和兼容系统,以及(最近)DJGPPDOS开发系统。

dbg

“dbg”对象格式不是“真正的”对象格式,其创建的输出文件简单地描述的顺序调用它Yasm和最终的对象和人类可读的文本格式符号表信息(在一个正常的对象格式会加工成对象格式的特定的二进制表示)。这个对象格式不是为了真正的使用,而是用于调试Yasm内部。

精灵

ELF对象格式真的有三种口味:并且借助elf32””(32位的目标),“elf64”(64位目标),和“elfx32”(x32目标)。精灵是一个标准的对象格式常用的现代Unix和兼容的系统(例如Linux,FreeBSD)。精灵已经复杂的支持浮动和共享对象。

男子气概

Mach-O对象格式真的有两种味道:“macho32”(32位的目标)和“macho64”(对于64位目标)。Mach-O用作对象格式在MacOSxYasm目前只支持x86和AMD64指令集,它只能为基于英特尔处理器的mac电脑上生成Mach-O对象。

rdf

RDOFF2对象格式是一个简单的多节格式NASM的最初设计。它支持段引用但不是关于引用。它的主要目的是简单和简约的标题为便于加载和链接。一个完整的工具链(链接器、图书管理员和装入器)与NASM分布。

win32

Win32对象生成对象文件格式兼容微软编译器(例如VisualStudio)的32位x86Windows平台。COFF的对象格式本身是一个扩展的版本。

win64

Win64对象生成对象文件格式兼容微软编译器,目标64位Windows平台“x64”。这种格式非常类似于win32对象格式,但64位生成对象。

xdf

XDF对象本质上是一个简化版的COFF格式。这是一个多节浮动格式,支持64位的物理和虚拟地址。

1.7。支持调试格式

cv8

CV8调试格式使用MicrosoftVisualStudio2005(8.0版)和是完全非法的,虽然之前CodeView格式有强烈的相似之处。Yasm支持CV8调试格式目前限于生成程序行号信息(允许一定程度的源代码级调试)。CV8调试信息存储在.debug$S和.debug$TWin64对象的部分文件。

dwarf2

矮2是一个复杂的调试格式,记录调试信息的标准。创建它在刺穿了克服缺点,允许更详细的和紧凑的描述数据结构,数据变量的运动,在C等复杂的语言结构。调试信息存储在部分(就像正常的程序部分)在对象文件。Yasm支持完整的直通DWARF2调试信息(如从一个C编译器),也可以生成程序行号信息。

“零”调试格式是一个占位符,它将没有调试信息添加到输出文件。

刺穿了

刺穿了调试格式是一个糟糕的记录,半标准COFF和ELF目标文件格式的调试信息。调试信息存储对象文件的符号表的一部分,因此在复杂性和范围是有限的。尽管如此,刺穿了是一种常见的调试格式在旧的Unix和兼容系统,以及DJGPP。

第二章。VSYASM——Yasm微软VisualStudio2010

表的内容

构建系统中使用微软VisualStudio2010是基于MSBUILD,微软专门构建管理工具,这一变化要求外部工具集成到开发环境以一种新的方式。VSYASM了促进Yasm集成VisualStudio2010在一个健壮的和有效的方式。VSYASM和其他版本之间的主要区别是,它能够组装多个源代码文件在一个命令行。

当组装单个文件VSYASM一样正常的行为yasm工具。在这种情况下,唯一的变化是,VSYASM不仅仅提供预处理模式。

的-e文件命令行开关可以用来发送错误报告文件,在这种情况下,这个文件还包括用于调用VSYASM命令行。这提供了一种方法来检查VSYASM被称为正确VisualStudio构建过程的控制。

2.1。集成的步骤

首先,VSYASM可执行文件(vsyasm.exe)应该被添加到VisualStudio目录C工具。这通常是:

C:\ProgramFiles(x86)\MicrosoftVisualStudio10.0\VC\bin

其次,三个文件—vsyasm.xml,vsyasm.props和vsyasm.targets——应该添加到项目的项目目录中使用VSYASM(另一个将在稍后解释)。

第三,添加Yasm支持项目在IDE中打开项目后,在解决方案资源管理器中右键单击项目并选择“构建自定义…”。如果vsyasm作为一个可选项在结果列表中你可以选择它,如果没有,使用“找到现有…”按钮,导航到结果文件对话vsyasm.targets你把在项目目录,将它添加到列表中选择它,然后从列表中选择它。

一旦你这样做了,在解决方案资源管理器中右键单击该项目并选择“属性”会弹出一个对话,一个新项“Yasm汇编程序”,将允许您配置Yasm构建任何汇编文件添加到项目中。

2.2。替代集成步骤

如果你有使用VSYASM的很多项目,你可以把上面提到的三个文件放到MSBUILD的构建定制目录通常是在:

C:\ProgramFiles(x86)\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations

VSYASM将总是可用在构建自定义对话。一个替代的方法是把这些文件放在一个方便的位置,然后将这个位置的路径添加到“构建自定义搜索路径”项下“vc++项目设置”在VisualStudio2010中选择对话。

2.3。使用VSYASM

在VisualStudio项目汇编源代码文件,Yasm设置中的“Yasm汇编程序”项中输入的项目属性对话。可用的物品符合那些Yasm上可用的命令行和主要是自我解释但一项——“对象文件名”——确实需要进一步解释。

如果“对象文件名”项指的是一个目录(默认),MSBUILD将收集所有的汇编文件在项目一起作为一个批处理和多个文件中调用VSYASM模式。为了装配文件一次有必要改变输出的名字文件例如,如“$(IntDir)%(文件名).obj”。

第二部分。NASM语法

书的这一部分文档中的章节NASM-compatible语法接受Yasm“nasm”解析器和预处理器。

3.1。NASM源代码行布局

NASM使用反斜杠(\)行连续字符;如果一行与反斜杠结束,下一行被认为是backslash-ended线的一部分。

NASM的地方没有限制内的空白行:标签可能有空白之前,或指令可能没有空间在他们面前,或任何东西。的冒号后一个标签也是可选的。注意,这意味着,如果你打算代码lodsb独自一行,和类型lodab偶然,那仍然是一个有效的源代码行这只定义一个标签。NASM运行命令行选项-w+orphan-labels将导致它提醒你如果你定义一个标签单独在一行末尾没有冒号。

指令字段可能包含任何机器指令:奔腾和P6指令,FPU指令,MMX指令甚至非法指令都是支持的。指令可能前缀锁,代表,REPE/REPZ或REPNE/REPNZ在通常的方式。显式地址大小和operand-size前缀系,A32,O16和O32被提供。您还可以使用一个段寄存器的名称作为一个指令前缀:编码esmovbx,斧头相当于编码mov[es:bx),斧头。我们建议后者语法,因为它与其他语言的句法特征是一致的,但等指令LODSB,没有操作数和需要段覆盖,没有干净的句法方法除了进行eslodsb。

一条指令不需要用一个前缀:前缀等CS,A32,锁或REPE可以出现在一行本身,NASM只会生成前缀字节。

为浮点指令,NASM接受广泛的语法:您可以使用two-operand形式像MASM支持实现,或者您可以使用NASM的本机single-operand形式在大多数情况下。例如,您可以代码:

fadd相约;这集st0:=st0+相约

faddst0,相约;这也是如此

fadd相约,st0;这集相约:=相约+st0

fadd相约;这也是如此

几乎所有的浮点指令引用内存必须使用前缀双字,QWORD,TWORD,DDQWORD,或OWORD表明什么大小的((内存操作数)),它是指。

3.2伪指令。

伪指令的东西,虽然不是真正的x86机器指令,用于教学领域还是因为这是最方便的地方。当前的伪指令是DB,DW,DD,DQ,DT,DDQ,做,未初始化的同行RESB,RESW,RESD,RESQ,休息,RESDDQ,资源,INCBIN命令,装备的命令,次前缀。

3.2.1之上。DB和朋友:宣布初始化数据

db0x55;只是x55字节0

db0x550x560x57;连续三个字节

db'a',0x55;字符常量就可以了

10db‘你好’,13日,“美元”,所以是字符串常量

dw0x1234;0x340x12

dw'a',0x410x00(它只是一个数字)

dw“ab”;0x410×(字符常数)

dw“abc”;0x410×0x430x00(字符串)

dd0x12345678;0x780x5600x12x34

dq0x1122334455667788;0x880x770x660x550x440x330将0x11

ddq0x112233445566778899aabbccddeeff00

;0x000xff0xeexdd0xcc0xbb0xaa0x99

;0x880x770x660x550x440x330将0x11

和以前一样做0x112233445566778899aabbccddeeff00;

dd1.234567e20;浮点常量

dq1.234567e20;双精度浮点数

dt1.234567e20;给出自由浮动

DT不接受数字常量作为操作数,DDQ不接受浮点数常量作为操作数。任何尺寸大于DD不接受字符串作为操作数。

例如:

缓冲区:resb64;储备64字节

wordvar:resw1;储备一个字

realarrayresq10;十实数数组

3.2.3。INCBIN:包括外部的二进制文件

INCBIN包括一个二进制文件逐字到输出文件。这可以方便(例如)包括图形和声音数据直接进入游戏可执行文件。然而,推荐使用这只小件的数据。它可以调用其中的一个方法:

incbin”文件。dat”;包含整个文件

incbin”文件。dat",1024年,跳过第一个1024字节

incbin”文件。dat",1024年,1024年,跳过第一个1024年

实际上,包括最多512

3.2.4。装备的:定义常量

装备的定义一个符号一个给定的常数的值:当装备的源线,必须包含一个标签。的作用装备的是定义给定的标签名称(只)操作数的值。这个定义是绝对的,不能改变。举个例子,

db消息“hello,world”

美元msglen装备的消息

3.2.5。次:重复指令或数据

的次前缀多次导致指令进行组装。这部分是NASM的等效的DUPMASM-compatible汇编、语法支持的代码

zerobuf:*64分贝0

或类似的事情,但是次比这更多功能。的参数次不仅仅是一个数字常量,但是一个数字表达式,所以你能做的事情

缓冲区:db“hello,world”

乘以64美元+缓冲db''

这将存储足够的空间的总长度吗缓冲到64。最后,次可以应用于普通的指令,所以你可以代码微不足道它展开循环:

乘以100movsb

请注意,没有有效的区别乘以100resb1和resb100,除了后者将快100倍的组装将汇编程序的内部结构。

还请注意,次不能适用于宏:原因是次处理后的宏观阶段,它允许的参数次包含表达式等64美元+缓冲如上所述。重复多一行代码,或一个复杂的宏,使用预处理器%代表指令。

3.3。有效的地址

一个有效地址是引用内存的任何指令的操作数。有效的地址,在NASM中,有一个非常简单的语法:他们由一个表达式评估所需的地址,封闭方括号。例如:

wordvardw123

movax,[wordvar]

movax,wordvar+1

movax,[西文wordvar+bx):

任何不符合这个简单的系统不是一个有效的内存引用在NASM中,例如es:wordvar(软)。

更复杂的有效地址,如涉及多个寄存器,在完全相同的方式工作:

moveax,(ebx*2+连成一片+偏移量)

movax,bp+di+8

NASM就是这样做的能力代数在这些有效的地址,这样的东西不一定看法律非常好:

moveax,(ebx*5),组装(ebx*4+ebx)

moveax,label1*2-label2;即[label1+(label1-label2)]

某些形式的有效地址有一个以上的组装形式;在大多数这样的情况下NASM将产生最小的形式。例如,有不同的组装形式为32位的有效地址(eax*2+0)和[eax+eax],NASM通常会生成后者,因为前者需要4个字节来存储一个零偏移量。

NASM提示机制,这将导致[eax+ebx]和[ebx+eax]生成不同的操作码;这是偶尔有用,因为(esi+ebp)和(ebp+应急服务国际公司)有不同的默认段寄存器。

前面的段落中描述的形式也很有用,如果你试图在一个32位访问数据从在16位代码段。特别是,如果您需要访问数据与一个已知的抵消比适合在一个16位值大,如果你不指定,它是一个dword抵消,NASM将导致高抵消损失。

同样,NASM将分裂(eax*2)成[eax+eax]因为允许缺席和空间偏移量字段得救;事实上,它也会分裂(eax*2+偏移量)成(eax+eax+偏移量)。你可以通过使用打击这种行为NOSPLIT关键字:(nospliteax*2)将迫使(eax*2+0)生成。

3.3.1。64位的位移

在位64模式,位移,在很大程度上,仍然是32位,扩展之前使用标志。除了是一个mov指令的限制形式:之间的艾尔,斧头,EAX,或递交寄存器和一个64位的绝对地址(有效地址不允许注册,地址不能RIP-relative)。在NASM中语法,需要使用64位的绝对形式QWORD。在NASM中语法的例子:

moveax,[1];32位,符号扩展

mov,[rax-1];32位,符号扩展

mov,[qword0x1122334455667788];64位绝对的

mov,[0x1122334455667788];截断32位(警告)

3.3.2。把相对寻址

在64位模式下,一种新的有效的解决可以更容易编写位置无关代码。任何内存可以参考把相对(把是指令指针寄存器,它包含的地址位置紧跟当前指令)。

在NASM中语法,有两种方法可以指定RIP-relative寻址:

movdword(rip+10),1

存储值1十字节后的指令。10也可以是象征性的常数,并将以同样的方式对待。另一方面,

movdword[symb关于撕裂),1

存储值1到符号的地址symb。这是明显不同的行为:

movdwordsymb+撕裂,1

将结束的指令的地址,添加的地址吗symb,那么存储值1。如果symb这是一个变量,会吗不存储值1到symb变量!

Yasm还支持以下语法RIP-relative寻址。的REL关键字使它产生把相对地址,腹肌关键字使它产生非把相对地址:

movrel信谊,伸展;RIP-relative

movabs信谊,伸展,没有RIP-relative

默认rel

mov(对称),rbx;RIP-relative

movabs信谊,rbx;不是RIP-relative(显式重写)

mov[rbx+1],rbx;不是RIP-relative(寄存器使用)

mov[fs:信谊],rbx;不是RIP-relative(fs或gs使用)

movds:信谊,rbx;RIP-relative(段,但不是fs或gs)

movrel信谊,rbx;RIP-relative(冗余覆盖)

默认的腹肌

mov(对称),rbx;不是RIP-relative

movabs信谊,rbx;不是RIP-relative

mov[rbx+1],rbx;不是RIP-relative

mov[fs:信谊],rbx;不是RIP-relative

movds:信谊,rbx;不是RIP-relative

movrel信谊,rbx;RIP-relative(显式重写)

3.4。直接操作数

直接操作数在NASM中可能是8位,16位,32位,甚至64位大小。眼前的大小可以直接通过使用指定的字节,词,或双字关键词,分别。

64位操作数仅限于直接64位寄存器指令在移动位64模式。对于所有其他指令在64位模式下,立即值仍然是32位,他们的价值符号扩展到32位的目标寄存器之前被使用。例外是mov指令,可以把一个64位的直接目标是一个64位的寄存器。

所有未分级立即值位64在Yasm默认32位大小一致性。为了得到一个64位的直接与一个标签,显式地指定大小的QWORD关键字。使用的方便性,Yasm还将试图识别64位值和自动改变大小64位这些情况。

在NASM中语法的例子:

添加递交1;优化签署了8位

添加伸展,dword1;迫使大小32位

添加伸展,0xffffffff;符号扩展32位

添加递交1;同上

加伸展,0xffffffffffffffff;截断32位(警告)

moveax,1;5字节

mov伸展,1、5字节(32位)签署的优化

mov伸展,qword1;10字节(64位)

movrbx,0x1234567890abcdef;10字节

movrcx,0xffffffff;10个字节(32位)签署不符合

mov连成一片,1;5字节,相当于上面

movrcx,信谊;5字节,32位大小默认符号

movrcx,qwordsym;10字节,覆盖默认大小

谨慎的用户使用NASM和Yasm2。x:movreg64的处理,未分级立即YasmNASM2之间是不同的。x;YASM遵循上述行为,NASM2。x是以下几点:

添加伸展,0xffffffff;符号扩展32位立即

添加伸展,0xffffffffffffffff;截断32位(警告)

添加伸展,信谊;符号扩展32位立即

立即moveax,1、5字节(32位)

mov递交1;10字节立即(64位)

movrbx,0x1234567890abcdef;10字节的指令

movrcx,0xffffffff;10字节的指令

立即mov连成一片,对称;5字节(32位)

movrcx,信谊;10字节(64位直接)

movrcx,qwordsym;10字节,同上

3.5.常量

NASM理解四个不同类型的常数:数字、字符、字符串和浮点。

3.5.1。数字常量

一些例子:

movax,100;小数

movax,0a2h;十六进制

movax,$0a2;又十六进制:0是必需的

再次movax,0xa2;十六进制

movax,777q;八进制

movax,777o;八进制

movax,10010011b,二进制

3.5.2。字符常量

字符常量由四字符括在单引号或双引号。NASM的类型引用没有区别,当然,除了周围不断允许双引号和单引号出现在它,反之亦然。

一个常数与多个字符将安排低位优先顺序记住:如果你的代码

moveax,“abcd”

然后不断生成的不是0x61626364,但0x64636261,所以,如果你被存储到内存的值,它将阅读abcd而不是dcba。这也是可以理解的字符常量奔腾的感觉CPUID指令。

3.5.3。字符串常量

字符串常量只接受一些伪指令,即DB家庭和INCBIN。

字符串常量看起来像一个字符常数,只长。视为一个连接的最大大小字符常量的条件。所以以下是等价的:

db‘你好’,字符串常量

db‘h’,‘e’,‘l’,‘l’,‘o’;等效字符常量

和下面的也相当于:

ddninechars,双字串常数

dd“9”,“字符”,“年代”,变成了三个双字

dbninechars,0,0,0,真的是这样的

注意,当作为操作数db,一个常数“ab”被视为一个字符串常量尽管是足够短字符常量,否则吗db“ab”会有同样的效果db'a',这将是愚蠢的。同样,三或四字符常量是被当作字符串操作数时dw。

3.5.4。浮点型常量

dw-0.5;IEEE一半精度

dd1.2;一个简单的

dq-1。e10,10000000000

dq-1。e+10;1.e10的同义词

dq-1。平台以及;0.0000000001

dt3.141592653589793238462;π

NASM无法编译时算术浮点常量。这是因为NASM被设计成便携式——尽管它总是生成代码运行在x86处理器,汇编程序本身可以在任何系统上运行的ANSIC编译器。因此,汇编程序不能保证的浮点单元处理的能力英特尔数字格式,所以NASM能够做浮动算术它必须包括自己的成套浮点例程,这将大大增加很少好处的汇编程序的大小。

3.6.表达式

表达式在NASM中在语法与C是相似的。

NASM支持两种特殊标记表达式,允许计算涉及当前装配位置:美元和$$令牌。美元评估到组装线的位置开始时包含表达式;所以你可以编写一个无限循环使用人民币美元。$$评估当前的开始部分,所以你可以告诉你是多么遥远的部分使用($-$$)。

算术运营商提供的NASM列出,递增的顺序优先级。

3.6.1。|:按位或运算符

的|运营商提供了位,或者所执行的完全一样或机器指令。按位或NASM支持的优先级运算符。

操作。^:按位异或运算符

^提供了按位异或操作。

3.6.3。&:按位与运算符

&提供了位和操作。

3.6.4。<<和>>:移位操作符

<<给出了一个向左移位,正如它在c5<<3评估5*8,或40。>>给出了一个向右移位,在NASM中,这种转变总是无符号,从左端位转移充满了零而不是符号扩展之前的最高位。

3.6.5。+和------:加法和减法运算符

的+和------运营商做的很普通加法和减法。

3.6.6。*,/,//,%和%%:乘法和除法

*是乘法运算符。/和//都是除法运算符:/是无符号除法和//是部门签字。同样的,%和%%提供无符号和签署模运算符。

NASMANSIC一样,没有提供担保的合理的操作签名模运算符。

自%性格是广泛使用的宏观预处理器,您应该确保签署和无符号模运算符都是紧随其后的是空白。

3.6.7。一元操作符:+,------,~和赛格

3.6.8。赛格和关于

在编写大型16位程序时,必须分成多个段,它常常需要能够参考段地址的符号的一部分。NASM支持赛格操作符来执行这个函数。

的赛格操作符返回首选段的一个符号,定义为段基础的相对偏移的象征意义。因此代码

movax,凹陷的象征

mov,斧头

movbx,象征

将负载es:bx使用有效的指针的象征象征。

东西可以比这更复杂:因为16位段组织可能会重叠,你可能会偶尔想引用一些符号使用不同的段基地从首选之一。NASM让你做到这一点,通过使用关于(参照)关键字。所以你能做的事情

movax,weird_seg;weird_seg段基地

关于movbx,象征weird_seg

加载es:bx不同,但功能等同,指针的象征象征。

调用(赛格过程):过程

叫weird_seg:(过程关于weird_seg)

(包括括号是为了清楚起见,显示意图解析上述指令。他们在实践中则不需要。)

NASM支持的语法叫得过程作为第一个上面的用法的同义词。无条件转移指令作品相同调用在这些例子中。

dw的象征,凹陷的象征

NASM支持没有方便的同义词,尽管你可以发明一个使用宏处理器。

3.7。严格的:抑制优化

当装配优化器设置为2级或更高,NASM使用大小说明符(字节,词,双字,QWORD,或TWORD),但会给他们尽可能最小的大小。关键字严格的可以用来抑制优化和力量发出的一个特定的操作数指定的大小。例如,优化器,16位模式,

推动dword33

三个字节编码66621,而

推动严格dword33

6个字节进行编码,一个完整的字直接操作数216668000000。

3.8。关键表达式

NASM的局限性在于,它是一个双行程汇编;与TASM和其他人不同,它总是会做两个大会通过。因此不能应付复杂到需要源文件,三个或更多传球。

第一遍是用来确定所有组装的代码和数据的大小,所以第二步,当生成的所有代码,知道所有的符号地址指的代码。所以NASM无法处理的一件事是代码的值,其大小取决于一个象征宣布后的代码问题。例如,

*(标签-美元)db0

标签:db“我在哪儿”

的参数次在这种情况下可以同样合法评估任何东西;NASM将拒绝这个例子,因为它不能告诉的大小次当它第一次见到它。它将同样坚定拒绝slightlyparadoxical代码

(标签-$+1)db0

标签:db“现在我在哪儿”

在这任何值次参数是由定义错了!

NASM拒绝这些例子通过称为概念关键表达式,这是定义为一个表达式的值是需要在第一遍可计算的,因此必须只取决于符号定义。的参数的次前缀是一个关键的表情;出于同样的原因,参数RESB伪指令的家庭也关键表达式。

关键表达式可以出现在其他上下文:考虑下面的代码。

movax,symbol1

symbol2symbol1装备

symbol2:

在第一次通过,NASM无法确定的价值symbol1,因为symbol1定义等于什么symbol2NASM尚未看到。在第二步中,因此,当它遇到movax,symbol1,它不能生成的代码,因为它仍然不知道的价值symbol1。下一行,就会看到装备的又能够确定的价值symbol1,但那时就太晚了。

moveax,ebx+偏移量

抵消装备的10

NASM中,通过一个,必须计算指令的大小moveax,ebx+偏移量不知道的价值抵消。它没有办法知道抵消足够小,适合1字节偏移量字段,因此它可以生成一个短形式的有效地址编码;它知道,在通过一个,抵消在代码段可能是一个象征,它可能需要完整的四字节形式。所以不得不计算指令的大小,以适应一个四字节地址部分。在通过两个,这个决定,现在不得不尊重它并保持指令大,所以在这种情况下生成的代码不是一样小。这个问题可以通过定义来解决抵消前使用它,或通过迫使字节大小的有效地址编码(字节ebx+偏移量)。

3.9。当地的标签

NASM给符号开始的特殊待遇时期。一个标签开始被当作一个单一的时期当地的标签,这意味着它与前面的非本地标签。举个例子:

label1;一些代码

。循环;更多的代码

jne.loop

受潮湿腐烂

label2;一些代码

在上面的代码片段中,JNE立即指令跳线之前,因为这两个定义的.loop是分开的每一个与前面的非本地标签。

NASM更进一步,在允许访问本地标签代码的其他部分。这是通过的定义当地一个标签在前面的非本地标签:第一个定义.loop以上是定义一个符号label1.loop,第二个定义了一个称为象征label2.loop。所以,如果你真的需要,你可以写

label3;更多的代码

,更多的

jmplabel1.loop

有时是有用的——在一个宏,例如,能够定义一个标签,可以从任何地方引用但不干扰正常local-label机制。这样一个标签不能非本地,因为它会干扰后续的定义,和引用,当地地方标签;不能因为定义的宏,它不知道标签的全名。NASM因此介绍第三种类型的标签,这只可能是有用的在宏定义:如果一个标签开头的特殊前缀..@,那么它无助于当地标签机制。所以你可以代码

label1:;非本地标签

。本地:,这是真的label1.local

..@foo:,这是一个特殊的符号

label2:;另一个非本地标签

。本地:,这是真的label2.local

人民币..@foo;这将跳三行

NASM有能力定义其他特殊符号开头一段双:例如,开始..用于指定入口点的吗obj输出格式。

第四章。NASM预处理器

NASM包含一个强大的宏处理器,支持有条件的组装、多层次的文件包含,两种形式的宏观(单行和多行),和一个额外的宏观权力的“上下文堆栈”机制。预处理器指令所有从一开始%的迹象。

预处理程序崩溃所有行最后一个反斜杠(\)字符到一行。因此:

%定义THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO\

THIS_VALUE

将像一个单行的宏没有backslash-newline序列。

4.1。单行的宏

以下4.4.1。正常的方法:%定义

单行的宏定义使用%定义预处理器指令。定义工作类似于C,所以你能做的事情

%定义ctrl0x1f&

%定义参数(a,b)(()+()*(b))

movbyte[参数(ebx)],ctrl'D'

这将扩大到

movbyte[(2)+(2)*(ebx)],0x1f&'D'

%定义(x)1+b(x)

%定义b(x)2*x

movax,(8)

将评估预期的方式movax,1+2*8,即使宏b没有定义时定义一个。

宏定义%定义是区分大小写:在%定义foo酒吧,只有喷火将扩大酒吧:喷火或喷火不会。通过使用%idefine而不是%定义(“我”代表“不敏感”),您可以定义的所有情况下变异宏,这样%idefinefoo酒吧会导致喷火,喷火,喷火,喷火等等所有扩展酒吧。

有一个机制,检测宏调用时发生的前一个扩张的宏观,防范循环引用,无限循环。如果发生这种情况,预处理器只会扩大宏的第一次出现。因此,如果你的代码

%定义(x)1+(x)

movax,(3)

宏(3)将扩大一次,成为1+(3),然后没有进一步扩张。这种行为可以是有用的。

你可以超载单行的宏:如果你写

%定义foo(x)1+x

%定义foo(x,y)1+x*y

预处理器能够处理两种类型的宏调用,通过计算参数传递,所以foo(3)将成为1+3而foo(ebx,2)将成为1+ebx*2。然而,如果您定义

%定义foo酒吧

然后其他的定义喷火将被接受:不带参数宏禁止相同的名称作为一个宏的定义与参数,反之亦然。

这并不阻止单行的宏重新定义:你可以很好地定义一个宏

然后重新定义在相同的源文件

%定义foo巴兹

4.1.2。提高%定义:%xdefine

有参考嵌入式单行的宏观解决当时嵌入,而不是调用宏扩展时,你需要一个不同的机制来提供的%定义。解决方案是使用%xdefine,或者它不区分大小写%xidefine。

假设你有下面的代码:

%定义isTrue1

%定义isFalseisTrue

%定义isTrue0

val1:dbisFalse

val2:dbisFalse

在这种情况下,val1=0,然后呢val2=1。这是因为,当一个单行的宏定义使用%定义,它是只有当它被称为扩展。作为isFalse扩大到isTrue,扩张的当前值isTrue。它被称为是0,第一次和第二次是1。

如果你想要isFalse扩大价值分配给嵌入式宏isTrue在那个时候,isFalse被定义,您需要更改使用上面的代码吗%xdefine。

%xdefineisTrue1

%xdefineisFalseisTrue

%xdefineisTrue0

现在,每一次isFalse被调用时,它扩大到1,这就是嵌入式宏isTrue扩展到的时候isFalse被定义。

4.1.3。连接一行宏观标记:%+

作为一个例子,考虑以下:

%定义BDASTART400h;BIOS数据区域的开始

structBIOSDA;它的结构

。COM1addrRESW1

。COM2addrRESW1

,..等等

endstruc

现在,如果我们需要访问tBIOSDA的元素在不同的地方,我们可以得到:

movax,BDASTART+tBIOSDA.COM1addr

movbx,BDASTART+tBIOSDA.COM2addr

这将变得很丑(乏味)如果使用在许多地方,可以显著缩小,通过使用以下宏:

;宏观BIOS变量的访问他们的名字(从tBDA):

%定义BDA(x)BDASTART+tBIOSDA。%+x

现在上面的代码可以写成:

movax,BDA(COM1addr)

movbx,BDA(COM2addr)

使用这个特性,我们可以简化引用大量的宏(反过来,减少打字错误)。

4.1.4。它通过宏:%undef

单行的宏可以删除的%undef命令。例如,下列顺序:

%undeffoo

moveax,foo

将扩大指令moveax,foo后,因为%undef宏喷火不再是定义。

4.1.5。预处理器变量:%分配

另一种方式来定义通过单行的宏%分配命令(和它的不区分大小写的%iassign,它不同于%分配以完全相同的方式%idefine不同于%定义)。

%分配用于定义单行的宏,不带任何参数,数值。这个值可以指定一个表达式的形式,它将评估一次,当%分配处理指令。

就像%定义宏定义使用%分配可以界定之后,你可以做吗

%分配我+1

增量的数值宏。

4.2。字符串处理在宏

通常是有用的在宏能够处理字符串。NASM支持两个简单的字符串处理宏观运营商可以构造更复杂的操作。

4.2.1。准备字符串长度:%strlen

的%strlen宏就像%分配宏,它创建(或重新定义)一个宏的数值。不同之处在于,%strlen数值是一个字符串的长度。使用的一个例子是:

%strlencharcnt'我的字符串

在这个例子中,charcnt将获得的价值,就像一个吗%分配已经被使用。在这个例子中,“我的字符串”是一个文字字符串,但它也可以是一个单行的宏,它扩大到一个字符串,如以下示例:

%定义sometext“我的字符串”

%strlencharcntsometext

在第一种情况下,这将导致charcnt被分配的值8。

4.2.2。子:%的子串

单个字母字符串可以提取使用%的子串。其使用的一个例子可能是更有用的描述:

%substrmychar“xyz”1;相当于%定义mychar“x”

%substrmychar“xyz”2;相当于%定义mychar‘y’

%substrmychar“xyz”3;相当于%定义mychar'z'

4.3。多行宏

多行宏更像的一种宏观MASM和TASM:实现一个多行宏定义在NASM中看起来是这样的。

%宏观前言1

推动ebp

movebp,特别是

子esp,%1

%endmacro

这个定义了一个c函数序言作为一个宏:所以你会调用宏的调用等

myfunc:序言12

这将扩大到三行代码

myfunc:推动ebp

子esp,12

数量1宏名称%的宏行定义了宏的参数个数序言期望获得。的使用%1在宏定义是指宏调用的第一个参数。随着宏观多个参数,后续的参数将被称为%2,%3等等。

多行宏,单行的宏,等区分大小写,除非你使用替代指令定义它们%imacro。

如果你需要通过一个逗号部分多行宏的参数,你可以通过将整个参数包含在括号。所以你可以代码之类的东西

%宏观傻2

%2:db%1

愚蠢的“a”,letter_a;letter_a:db'a'

愚蠢的“ab”string_ab;string_ab:db“ab”

愚蠢的{13日10},crlf;crlf:10db13日

4.3.1。重载多行宏

与单行的宏,可以重载多行宏定义相同的宏名多次与不同数量的参数。这一次,不例外是为宏不带参数。所以你可以定义

%宏观序言0

定义函数的另一种形式的序幕分配没有本地堆栈空间。

但是,有时候您可能想要“超负荷”机器指令;例如,您可能需要定义

%宏观推2

推动%1

推动%2

这样你可以代码

推动ebx;这一行不是一个宏调用

推动eax,连成一片,但是这个是

4.3.2。Macro-Local标签

NASM允许您定义标签在一个多行宏定义等方式让他们当地的宏调用:所以调用相同的宏观多次每次都将使用一个不同的标签。这可以通过加前缀%%标签的名字。所以你可以发明一个执行一个指令受潮湿腐烂如果Z国旗由这样做:

%宏观retz0

jnz%%跳过

%%跳过:

4.3.3。贪婪的宏参数

有时是有用的定义一个宏块整个命令行成一个参数定义,可能后提取一个或两个小参数的前面。一个例子可能是一个宏来编写一个文本字符串在ms-dos文件,您可能希望能够编写

writefile(文件句柄),“你好,世界”,13日10

NASM允许您定义一个宏的最后一个参数贪婪的,也就是说,如果您调用宏比预计更多的参数,定义的所有多余的参数集总进入最后一个逗号分开。所以如果你代码:

%宏writefile2+

jmp%%endstr

%%str:db%2

%%endstr:

movdx,%%str

mov残雪,%%endstr-%%str

movbx,%1

mov啊,0x40

int0x21

然后调用的例子writefile以上将按预期工作:第一个逗号前的文本(文件句柄)作为第一个宏观参数和扩大%1是指,所有随后的文本集中到%2后,把db。

贪婪的宏观性质是NASM使用的表示+签署后的参数依赖%的宏线。

如果你定义一个贪婪的宏,你实际上是告诉NASM如何扩大宏任何指定的参数的数量与实际数量无穷;在这种情况下,例如,NASM现在知道当它看到调用该做什么writefile2、3、4或更多的参数。NASM重载时将考虑这个宏,并将不允许您定义的另一种形式writefile采取4参数(例如)。

当然,上面的宏可以被实现为一个贪婪的宏,在这种情况下,它必须看起来像

writefile(文件句柄),{10}“hello,world”,13日

NASM提供机制(宏观参数)(逗号),你选择哪一个你更喜欢每个宏定义。

4.3.4。默认宏参数

NASM还允许您定义一个多行宏了范围容许的参数计算。如果你这样做,您可以指定默认值省略参数。举个例子:

%宏观死0-1”痛苦的程序死亡发生。”

writefile2,%1

x4c01movax,0

一般来说,你提供一个最小和最大数量的这种类型的宏参数;所需的最小数量的参数然后在宏调用,然后你提供可选的默认值。所以如果一个宏定义开始

%1-3宏观foobareax,(ebx+2)

然后它可以称为一至三个参数,和%1总是来自宏调用。%2宏调用,如果未指定,默认eax,%3如果没有指定默认的(ebx+2)。

这种违约机制可以结合greedy-parameter机制;因此,死宏观上可以更强大和更有用,通过改变的第一行定义

%宏观死0-1+“痛苦的程序死亡发生。”,13日10

4.3.5。%0柜台:宏参数

4.3.6。%旋转:旋转宏参数

Unixshell程序员都熟悉转变shell命令,允许参数传递给shell脚本(引用1美元,2美元等等)要搬到一个地方,留下的,以前引用的论点2美元可用的1美元和之前引用的论点1美元不再可用。

NASM提供了一个类似的机制,在形式的%旋转。顾名思义,它不同于Unix转变在不丢失参数:参数旋转的左端参数列表出现在右边,反之亦然。

%旋转与一个数字参数被调用(这可能是一个表达式)。宏观参数旋转的留下的很多地方。如果参数%旋转是负的,宏观参数向右旋转。

所以一双宏的保存和恢复的一组寄存器可能工作如下:

%宏观multipush1-*

%代表%0

%旋转1

%endrep

这个宏调用推指令在它的每个参数反过来,从左到右。它首先将第一个参数,%1,然后调用%旋转向左移动一个地方的所有争论,现在原来的第二个参数是可用的%1。这个过程重复多次有参数(通过提供实现%0作为参数,%代表)导致每个参数反过来推动。

还请注意使用*作为最大的参数计算,表明没有上限参数的数量你可以供应multipush宏。

这将是方便,使用这个宏时,有一个流行等价的,没有需要给定的参数在相反的顺序。理想情况下,你会写multipush宏调用,然后复制粘贴到流行需要做些什么,和改变的名字叫做宏multipop,宏会照顾弹出注册以相反的顺序从一个推动。

这可以通过以下定义:

%宏观multipop1-*

流行%1

这个宏开始旋转它的参数的一个地方正确的,所以原来的去年参数显示为%1。这是那么突然,参数是旋转的,所以变成了倒数第二个论点%1。因此,参数在相反的顺序遍历。

4.3.7。连接宏参数

%宏观keytab_entry2

keypos%1装备keytab美元

db%2

keytab:

keytab_entryF1,128+1

keytab_entryF2,128+2

keytab_entry回报,13

keytab美元keyposF1装备

db128+1

keytab美元keyposF2装备

db128+2

keytab美元keyposReturn装备

db13

您可以简单地将文本的另一端一个宏观参数,通过编写%1foo。

如果你需要添加一个数字一个宏观参数,例如定义标签foo1和foo2当的参数传递喷火,你不能代码%11因为这是作为第十一个宏观参数。相反,您必须的代码%{1}1将单独的第一1(给宏观参数的数量)从第二(文字文本连接到参数)。

为4.3.8。码作为宏观参数条件

NASM能给特殊待遇宏观参数包含一个条件代码。首先,您可以参考宏观参数%1通过另一种语法%+1,通知NASM这个宏参数应该包含一个条件代码,并将导致预处理器报告一个错误消息,如果宏观叫做一个参数不一个有效的状态码。

宏观retc%1

j%-1%%跳过

现在可以使用调用调用这个宏retc不,这将导致条件转移指令在宏扩展出来我,或retc阿宝这将使跳一个吗JPE。

的%+1macro-parameter引用是很乐意解释参数CXZ和ECXZ然而,随着代码有效条件;%1将报告一个错误如果通过这些,因为不存在逆状态码。

4.3.9。禁用清单扩张

NASM时生成一个清单文件从您的程序中,它通常会扩大通过编写多行宏宏调用清单的每一行,然后扩张。这允许您看到宏扩展指令的生成代码;然而,对于一些宏这不必要的杂波的清单。

NASM因此提供了.nolist限定符,您可以包括在一个宏定义抑制宏观的扩张在清单文件中。的.nolist限定符直接参数的数量后,像这样:

%1.nolist宏观foo

或者像这样:

1-5+%宏观酒吧。nolista,b,c,d,e,f,g,h

4.4。有条件的组装

类似于C预处理器,NASM允许组装部分的源文件只有在某些条件得到满足。这个特性的一般语法看起来像这样:

%如果<条件>

;一些代码只出现><条件是否满足

%elif

,只有出现如果不满足<条件>

其他的%

;这似乎如果<条件>和

%endif

的其他的%条款是可选的,是%elif条款。你可以有多个%elif条款。

4.1.1。%如果定义了:测试单行的宏观的存在

开始的条件汇编块线%如果定义了宏将组装后续代码,如果且仅当一个单行的宏观叫什么宏定义。如果不是,那么%elif和其他的%块(如果有的话)会被处理。

例如,当调试一个程序,您可能想要编写代码等

,执行一些功能

%ifdef调试

writefile2,“函数执行成功”,13日10

,去做别的事情

然后您可以使用命令行选项-d调试创建一个版本的程序产生调试信息,和删除选项来生成最终的发布版本的程序。

你可以测试一个宏不被定义为使用%如果未定义而不是%如果定义了。你也可以测试宏定义%elif块用%elifdef和%elifndef。

10/24/11。%ifmacro:测试多行宏观的存在

的%ifmacro指令操作一样%如果定义了指令,除了它检查的存在多行宏。

例如,你可能使用一个大型项目,没有控制宏在图书馆。您可能想要创建一个宏,一个名字,如果它不存在,如果一个人与另一个名字,名字确实存在。

的%ifmacro被认为是真实的如果定义一个宏的名称和数量的参数会导致定义冲突。例如:

%ifmacroMyMacro1-3

%的错误“MyMacro1-3”与现有的宏观引起冲突。

%宏观MyMacro1-3

;插入代码来定义宏

这将创建宏MyMacro1-3如果没有宏已经存在的冲突,并发出警告是否有定义冲突。

你可以测试使用的宏不存在%ifnmacro而不是%ifmacro。额外的测试可以执行%elif块用%elifmacro和%elifnmacro。

4.4.3。%ifctx:测试上下文堆栈

条件汇编构造%ifctxctxname将导致后续代码组装当且仅当上下文预处理程序的上下文堆栈顶部有名字吗ctxname。与%如果定义了,逆%elif形式%ifnctx,%elifctx和%elifnctx也支持。

4.4.4。%如果:测试任意数值表达式

%如果扩展了正常NASM表达式语法,通过提供一组关系运算符不通常可以在表达式。运营商=,<,>,<=,>=和<>测试平等、小于、大于、less-or-equal分别大于等于和不等于。c形式==和!=作为替代形式的支持=和<>。此外,低优先级的逻辑运算符&&,^^和||提供,供应逻辑,逻辑XORandlogical或。这些工作像C逻辑运算符(尽管C没有逻辑异或),他们总是返回0或1,和治疗任何非零输入1(这样^^例如,返回1如果一个输入为零,否则和0)。关系运算符也为真,0为假返回1。

4.4.5。%ifidn和%ifidni:测试具体文本的身份

的构造%ifidntext1text2将导致后续代码组装当且仅当吗text1和text2扩大后,单行的宏,是相同的文本。空白的差异并不算。

%ifidni类似于%ifidn,但不区分大小写的。

例如,下面的宏推一个注册或堆栈,并允许你来治疗知识产权作为一个真正的注册:

宏观pushparam%1

%ifidni%1,ip

调用%%标签

%%标签:

像大多数其他%如果结构,%ifidn是否有对应的%elifidn和否定形式%ifnidn和%elifnidn。同样的,%ifidni有同行%elifidni,%ifnidni和%elifnidni。

4.4.6。%ifid,%ifnum,%ifstr:测试令牌类型

一些宏需要执行不同的任务取决于他们是否通过一个数字,一个字符串,或一个标识符。例如,一个字符串输出宏可能希望能够应付传递一个字符串常量或现有的字符串的指针。

条件组合构建%ifid,以一个参数(可能是空白的),组装后续代码当且仅当第一个令牌参数存在,是一个标识符。%ifnum同样的工作,但测试令牌是一个数字常数;%ifstr测试是一个字符串。

%宏观writefile2-3+

%ifstr%2

%%0=3

%%str:db%2,%3

%%%%endstr:movdx,str

movdx,%2

mov残雪,%3

然后writefile宏可以应对被称为在以下两个方面:

strpointerwritefile(文件),长度

writefile(文件),“你好”,13日10

注意使用%如果在%ifstr:这是检测宏是否传递两个参数(绳子将一个字符串常量,和db%2将是足够的)或更多(在这种情况下,但前两集中在一起%3,db%2,%3需要)。

通常的%elifXXX,%ifnXXX和%elifnXXX为每个版本存在%ifid,%ifnum和%ifstr。

4.4.7。%的错误:用户定义的错误报告

预处理器指令%的错误将导致NASM报告一个错误如果它发生在组装代码。如果其他用户是要组装你的源文件,您可以确保他们正确的宏定义的代码是这样的:

%ifdefSOME_MACRO

,做一些设置

%elifdefSOME_OTHER_MACRO

,做一些不同的设置

%SOME_MACRO和SOME_OTHER_MACRO定义错误。

那么任何用户无法理解你的代码应该是组装将迅速警告他们的错误,而不必等到正在运行的程序崩溃,然后不知道出现了什么问题。

4.5。预处理程序循环

NASM的次前缀,虽然有用,不能用于调用一个多行宏观多次,因为它是由NASM处理后宏已经扩大。因此NASM提供了另一种形式的循环,这次在预处理器级别:%代表。

这些指令%代表和%endrep(%代表以一个数值参数,这可以是一个表达式;%endrep不需要参数)可以用来封装一大块代码,然后复制多次指定的预处理:

%分配我0

%代表64

公司词表+2*(我)

这将生成一个64年的序列公司指令,递增的记忆的每一个字(表)来(表+126)。

对于更复杂的终止条件,或打破一个重复循环的一部分,您可以使用%exitrep指令终止循环,像这样:

斐波那契数列:

%分配j1

%代表100

%如果j>65535

%exitrep

dwj

%分配jk+i

%分配我j

%分配jk

fib_number装备(斐波那契美元)/2

这产生一个列表的所有斐波纳契数将在16位配合。注意,仍然必须给予最大重复计数%代表。这是为了防止NASM进入一个无限循环的可能性在预处理器,它(多任务和多用户系统)通常导致逐渐用尽所有的系统内存和其他应用程序开始崩溃。

4.6。包括其他文件

再次使用,一个非常相似的语法C预处理器,NASM预处理器可以包括其他源文件到您的代码。这是通过使用%包括指令:

%包括“macros.mac”

包括文件的内容吗macros.mac源文件包含%包括指令。

标准C语言为防止文件被包含不止一次同样适用于NASM预处理:如果文件macros.mac的形式

%如果未定义MACROS_MAC

%定义MACROS_MAC

,现在定义一些宏

然后包括文件不止一次不会导致错误,因为第二次文件包含什么都不会发生,因为宏MACROS_MAC将已经被定义。

4.7。上下文堆栈

NASM预处理器提供这种级别的权力的上下文堆栈。预处理器维护一堆上下文,每一个的特点是一个名字。你添加一个新的上下文堆栈使用%推指令,移除一个使用%的流行。您可以定义标签,是当地的一个特定的上下文堆栈。

4.7.1。%推和%的流行:创建和删除背景

的%推指令是用来创建一个新的上下文并将其上下文堆栈的顶部。%推需要一个参数,即上下文的名称。例如:

%foobar推

这将一个新的上下文foobar在堆栈上。你可以有多个具有相同名称的上下文堆栈:还可以对它们进行区分。

4.7.2。Context-Local标签

就像使用%%foo定义一个标签是本地使用的特定的宏调用,使用%$foo用于定义一个标签是本地的环境上下文堆栈的顶部。因此,重复和直到上面的例子可以实现通过:

%宏观重复0

%将重复

%$开始:

%的宏,直到1

j%-1%美元开始

%的流行

例如,通过调用

mov残雪,字符串

重复

添加残雪,3

scasb

直到e

这将扫描每四字节的字节的字符串搜索艾尔。

如果您需要定义,或访问,标签本地上下文下面堆栈的顶部,你可以使用%$$foo,或%$$$foo下面的内容,等等。

4.7.3。Context-Local单行的宏

NASM预处理程序还允许您定义单行的宏是当地的一个特定的上下文,在同样的方式:

%定义%localmac3美元

单行的宏定义吗%$localmac是本地上下文堆栈顶部。当然,在随后的%推,它仍然可以被访问的名字%$$localmac。

4.7.4。%repl:重命名上下文

%推新名称

非破坏性的版本%repl新名称。

4.7.5。IFs示例使用上下文堆栈:块

这个例子使用了几乎所有的上下文堆栈功能,包括条件汇编构造%ifctx,实现一个IF语句块为一组宏。

%宏如果1

%如果推

j%-1%ifnot美元

%其他宏观0

%ifctx如果

%repl其他

jmp%$ifend

%$ifnot:

%错误”预计‘如果’‘其他’”

%宏观endif0

%elifctx其他

%$ifend:

%错误”之前预期的“如果”或“其他”endif”

此外,endif宏必须能够应对直接后的两种不同的情况下如果,或者后一个其他的。它实现,利用装配条件做不同的事情取决于上下文堆栈的顶部如果或其他的。

的其他的宏保存上下文堆栈,以有%$ifnot指的如果宏定义的是一样的endif宏,但必须改变上下文的名称endif就会知道有一个干预其他的。它通过使用%repl。

一个示例使用这些宏的样子:

cmpax,软

如果ae

cmpbx,残雪

movax,残雪

其他的

movax,软

endif

cmpax,残雪

块-如果宏处理嵌套相当令人高兴的是,通过推动另一个上下文中,描述内如果描述外,最重要的如果,因此其他的和endif总是把最后一个无与伦比的如果或其他的。

4.8。标准宏

Yasm定义了一组标准宏在NASM预处理器定义已经开始处理任何源文件。如果你真的需要一个程序组装没有预定义的宏,您可以使用%明显空一切的预处理器指令。

4.8.1。__YASM_MAJOR__等:Yasm版本

单行的宏__YASM_MAJOR__,__YASM_MINOR__,__YASM_SUBMINOR__扩大的主要、次要、子副的部分版本号的Yasm被使用。此外,__YASM_VER__扩大到Yasm版本的字符串表示__YASM_VERSION_ID__扩大到一个32位的BCD-encoded表示Yasm版本,主要版本的最重要的8位,紧随其后的是8位小版本和8位子副版本,并在最重要的8位0。例如,在Yasm0.5.1,__YASM_MAJOR__将定义为0,__YASM_MINOR__将被定义为5,__YASM_SUBMINOR__将被定义为1,__YASM_VER__将被定义为“0.5.1”,__YASM_VERSION_ID__将被定义为000050100h。

此外,一行宏__YASM_BUILD__扩大Yasm”建立“数字,通常Subversion变更集的数字。它应被视为显著低于子副版本,并且通常只用于区分Yasm夜间快照或预发布(如发行候选版)Yasm版本。

4.8.2。__FILE__和__LINE__:文件名和行号

像C预处理器,NASM预处理程序允许用户找到包含当前指令的文件名和行号。宏__FILE__扩大到一个字符串常量给当前的输入文件的名称(可能在装配的过程中如果发生改变%包括使用指令),__LINE__扩展一个数值常数输入文件中的当前行号。

例如,可以用这些宏调试信息沟通的一个宏,因为调用__LINE__在一个宏定义(单行或多行)将返回的行号宏调用,而不是定义。为了确定在一段代码崩溃发生,例如,可以编写一个程序stillhere,这是通过一个行号EAX和输出类似“155行:还在这里”。您可以编写一个宏

%宏观notdeadyet0

推动eax

moveax,__LINE__

叫stillhere

流行eax

然后胡椒与调用您的代码notdeadyet直到你找到崩溃点。

4.8.3。__YASM_OBJFMT__和__OUTPUT_FORMAT__关键字:输出对象格式

这些扩展匹配给定的选项在命令行上,即使对象格式是等价的。例如,-f精灵和-felf32是等价的32位精灵格式说明符,然后呢精灵-f-mamd64和-felf64是等价的64位精灵格式说明符,但__YASM_OBJFMT__将扩大精灵和elf32第一两种情况精灵和elf64第二两种情况。

NASM预处理器足够强大,可以实现数据结构的宏。的宏STRUC和ENDSTRUC用于定义一个结构数据类型。

STRUC需要一个参数,这是数据类型的名称。这个名字被定义为一个符号的值为零,同样也有后缀_size附加到它,然后定义为装备的给结构的大小。一次STRUC已发布,你定义的结构,而且应该定义字段使用RESB家庭的伪指令,然后调用ENDSTRUC完成的定义。

例如,定义一个结构mytype包含longword,一句话,一个字节字符串的字节,你可能的代码

strucmytype

mt_long:resd1

mt_word:resw1

mt_byte:resb1

mt_str:resb32

上述代码定义了六个符号:mt_long0(偏移量从一开始的mytype结构longword字段),mt_word4,mt_byte6,mt_str7,mytype_size39岁,mytype自己是零。

结构类型名称的原因是定义为零的副作用使结构与当地的标签机制:如果你的结构成员倾向于在一个以上的结构相同的名称,您可以定义上面的结构是这样的:

。长:resd1

。词:resw1

。字节:resb1

。str:resb32

这定义了补偿结构领域mytype.long,mytype.word,mytype.byte和mytype.str。

因为没有NASM语法内在结构的支持,不支持任何形式的时期符号来引用一个结构的元素一旦你有一个(除了上述local-label符号),所以代码等movax,[mystruc.mt_word]不是有效的。mt_word是一个常数就像任何其他常数,所以正确的语法吗movax,[mystruc+mt_word]或movax,[mystruc+mytype.word]。

mystruc:istrucmytype

123456年在mt_long,dd

在mt_worddw1024

在dbmt_byte“x”

在mt_str,db“hello,world”,13日100

iend

如果数据在结构领域需要不止一个源代码行来指定,剩下的源代码行后可以很容易地来在线。例如:

123134145156167178189年在mt_str,db

190100db,0

根据个人口味不同,你也可以省略的部分的代码在结构领域完全一致,并开始下一行:

在mt_str

db“hello,world”

10db13日,0

4.8.6。对齐和ALIGNB:数据对齐

的对齐和ALIGNB宏提供一种方便的方式来调整代码或数据在一个词,longword、段落或其他边界。的语法对齐和ALIGNB宏是

4,对齐4字节边界对齐

对齐16;16字节边界对齐

nop对齐16日,相当于前一行

对齐8,db0;垫0而不是空操作

4,对齐resb1;BSS对齐到4

alignb4,相当于前一行

宏都需要他们的第一个参数是2的幂,它们都计算出所需要的额外字节数使当前节的长度的倍数,两个孩子的权力,和输出NOP填补或应用次第二个参数来执行对齐前缀。

如果没有指定第二个参数,默认对齐是NOP和默认值ALIGNB是RESB1。对齐对待一个NOP论点特别通过生成最大NOP填补指令(不一定NOP操作码)电流位设置,而ALIGNB的第二个参数。否则,这两个宏指定第二个参数时是等价的。通常情况下,你可以使用对齐在代码和数据部分ALIGNB在BSS部分,不需要第二个参数除了特殊用途。

对齐和ALIGNB,简单的宏,执行没有错误检查:他们不能提醒你如果第一个参数不能是2的幂,或者如果他们的第二个参数生成多个字节的代码。在每一种情况下,他们会静静地做错误的事情。

ALIGNB(或对齐的第二个参数RESB1)可以使用在结构定义:

strucmytype2

alignb2

alignb4

这将确保成员结构合理对齐相对于结构的基础。

最后一个警告:ALIGNB相对于的开始工作部分地址空间的开始,而不是最终的可执行文件。调整到16位边界时,部分只能保证你在4字节边界对齐的,例如,是浪费精力。再次,Yasm不检查部分的排列特征是明智的使用ALIGNB。对齐更聪明,做调整部分对齐最大指定对齐。

第五章。NASM汇编指令

NASM,尽管它试图避免汇编类似MASM和TASM实现的官僚主义仍然是被迫支持几指令。这些都是本章中描述。

NASM的指令有两种类型:用户级指令和原始的指令。通常,每个指令都有一个用户级表单和一个基本形式。在几乎所有情况下,我们建议用户使用用户级形式的指令,这被实现为宏调用原始的形式。

原始的指令包含在方括号;用户级指令。

5.1。指定目标处理器模式

5.1.1。位

的位指令指定Yasm是否应该用于生成代码运行在一个处理器操作在16位模式中,32位模式还是64位模式。语法16位,32位,或位64。

在大多数情况下,你不应该需要使用位明确。的coff,elf32,macho32,win32对象格式,它被设计用于32位操作系统,所有导致Yasm默认选择32位模式。的elf64,macho64,win64对象格式,设计用于在64位操作系统,都导致Yasm默认选择64位模式。的xdf你对象格式允许您指定每一段定义USE16,USE32,或USE64相应Yasm将其操作模式,所以使用位指令再次不必要的。

最可能使用的原因位指令是编写32位或64位代码在一个平坦的二进制文件;这是因为本对象格式默认为16位模式预期它最常用于写DOScom项目,DOS。系统设备驱动程序和引导加载程序软件。

你做不需要指定32位仅仅为了使用32位指令在一个16位DOS程序;如果你这样做,汇编程序生成正确的代码,因为它将会编写代码针对32位平台上运行一个16位。然而,它是需要指定位64使用64位指令和寄存器;这样做是为了让这些指令的使用和在32位或16位程序注册名字,尽管这样的使用将会产生一个警告。

当Yasm16位模式,说明哪些使用32位数据前缀0x66字节,这些指的32位地址0x67前缀。在32位模式,反过来也是如此:32位指令不需要前缀,而指令使用16位数据需要一个0x66这些工作需要一个0x6716位地址。

当Yasm位64模式中,32位指令通常不需要前缀,大多数使用64位的寄存器或数据大小需要雷克斯前缀。在必要时Yasm自动插入雷克斯前缀。还有8更普遍和SSE寄存器,并不再支持16位寻址。默认的地址大小是64位,32位寻址可以选择0x67前缀。默认操作数的大小仍然是32位,然而,0x66前缀选择16位操作数的大小。雷克斯前缀可以用来选择64位操作数的大小,并访问新的寄存器。几条指令有一个默认的64位操作数的大小。

雷克斯使用前缀时,处理器不知道如何解决啊,黑洞,CH或DH(高8位遗留)寄存器。相反,它可以访问的低8位SP,英国石油公司如果,迪注册为SPL,底保,银,迪勒分别,但只有当雷克斯使用前缀。

的位指令有一个完全等价的原始形式,(16位),(32位),(64位)。用户级以外的形式是一个没有宏观功能调用原始的形式。

5.1.2中。USE16,USE32,USE64

的USE16,USE32,USE64指令可以代替使用16位,32位,位64分别为兼容其他装配工。

5.2。默认的:改变汇编的违约

的默认的指令改变了汇编程序默认值。通常,Yasm默认模式,预计程序员显式地指定最直接的特性。然而,有时这是不可取的,如果某种行为非常commmonly使用。

特殊处理的FS和GS覆盖是由于这样的事实,这些部分是唯一的部分可以有非0的基地地址在64位模式下,因此通常用作线程指针或其他特殊功能。与一个非零基础地址,生成把相对地址这些形式将极为混乱。其他段寄存器等DS总是有基地址0,所以RIP-relative访问仍然是有意义的。

默认REL被禁用,默认的腹肌。汇编程序的默认模式启动默认的腹肌。

5.3。改变和定义部分

5.3.1。部分和段

的部分指令(((段)是一个完全等价的同义词)变化的输出文件您编写的代码将被组装成。在某些对象文件格式,部分的数量和名称是固定的;另一方面,用户可能多达他们希望。因此部分有时可能会给一个错误消息,也可能定义一个新的部分,如果你想切换到(还)不存在的部分。

5.3.2。标准化的部分名称

Unix对象格式,和本对象格式,所有的支持标准化的部分名称。text,.data和.bss代码、数据和uninitialised-data部分。的obj相比之下,格式不承认这些部分名称是特殊的,甚至会剥的主要时期的任何部分的名字有一个。

5.3.3。__SECT__宏

的部分指令的不寻常之处在于,它的用户级函数形式不同于原始的形式。原始的形式,(部分xyz),只需切换当前目标部分的。用户级形式,部分xyz然而,首先定义了单行的宏__SECT__是原始的(部分)指令它问题,然后问题。因此,用户级指令

部分。

扩大到两行

%定义__SECT__(部分。text)

(部分。text)

用户可能会发现它有用的利用自己的宏。例如,writefileNASM手册中定义的宏可以有效地重写在接下来的更复杂的形式:

(.data部分)

__SECT__

5.4。绝对:定义绝对标签

的绝对指令可以被认为是另一种形式部分:它导致后续代码是针对没有物理部分,但在假想的部分从给定的绝对地址。唯一可以使用在这种模式下的指令RESB家庭。

绝对使用如下:

绝对0x1a

kbuf_chrresw1

kbuf_freeresw1

kbufresw16

这个例子描述了一个部分的PCBIOS数据区域,在段地址0x40:上面的代码定义了kbuf_chr0x1a,kbuf_free0x1c,kbuf0x1e。

用户级的形式绝对,像这样的部分,重新定义__SECT__宏调用时。

STRUC和ENDSTRUC被定义为宏使用哪一个绝对(还有__SECT__)。

org100h;它是一个。COM程序

jmp设置,设置代码

,居民TSR是这里的一部分

设置:,现在写的代码安装临时避难所

绝对的设置

runtimevar1resw1

runtimevar2resd20

tsr_end:

这定义了一些变量“之上”的设置代码,这样设置后运行结束之后,它拿起可以重用为数据存储空间的临时避难所。象征“tsr_end”可以用来计算的总大小的一部分需要居民的临时避难所。

5.5。走读生:导入符号

的走读生你喜欢的指令需要尽可能多的参数。每一个参数是一个符号的名称:

走读生_printf

走读生_sscanf,_fscanf

走读生_variable:关于dgroup

的原始形式走读生不同于用户级形式只有在它一次只能带一个参数:支持多种参数预处理器级别的实现。

5.6。全球:输出符号

的全球指令申请必须出现一个标志之前符号的定义。

全球使用相同的语法走读生,除了必须引用符号是在同一模块中定义全球指令。例如:

全球_main

_main:;一些代码

全球,就像走读生,允许对象格式定义私有扩展通过冒号。的精灵对象格式,例如,允许您指定全球数据项是否函数或数据:

全球hashlookup:函数,散列表:数据

就像走读生的原始形式全球不同于用户级形式只有在它一次只能带一个参数。

5.7。常见的:定义常见的数据区域

常见intvar4

相似的函数吗

全球intvar

部分.bss

intvarresd1

所不同的是,如果一个以上的模块定义了共同变量,然后在链接时这些变量合并后的和引用,intvar在所有模块都指向同一块内存。

就像全球和走读生,常见的支持对象格式特定的扩展。例如,obj格式允许无论远近,常见的变量和精灵格式允许您指定的对齐要求一个共同的变量:

常见commvar4:附近;在OBJ工作

常见intarray100:4;在精灵:4字节对齐

再次,像走读生和全球的原始形式常见的不同于用户级形式只有在它一次只能带一个参数。

5.8。CPUCPU:定义依赖关系

所有选择都不区分大小写。说明将使只有适用于选定的cpu或更低。

第三部分。气体的语法

本书的章节在这部分文档GNU兼容语法接受Yasm“气”解析器。

第六章。TBD

写的。

第四部分。对象的格式

书的这一部分文档中的章节Yasm对各种对象文件格式的支持。

第七章。本:平面形式的二进制输出

的本“对象格式”并不产生对象文件:产生的输出文件只包含部分数据;不生成标题或搬迁。输出可以被认为是“纯二进制”,用于操作系统和引导加载程序开发、生成ms-doscom可执行程序和。系统设备驱动程序,为嵌入式目标环境(如创建图像。快闪记忆体)。

当使用x86体系结构,本对象格式开始Yasm16位模式。为了编写本地32位或64位的代码,一个显式的32位或位64指令分别是必需的。

本产生一个输出文件没有扩展默认情况下,它只是条扩展从输入文件名称。因此输入文件的默认输出文件名foo.asm仅仅是喷火。

7.1。ORG起源:二进制

本提供了ORG指令在NASM中语法允许设置输出文件的内存地址是最初加载。的ORG指令只能使用一次(输出文件只能最初加载到一个位置)。如果ORG没有指定,ORG0在默认情况下使用。

当结合多个部分,ORG也有违约的影响LMA的第一部分ORG价值的输出文件尽可能小。如果这不是所需的行为,通过显式地指定一个LMA部分开始或遵循限定符的部分指令。

7.2。本扩展部分指令

的本对象格式允许使用任意名称的多个部分。它还扩展了部分(或段)指令允许复杂的排序段的输出文件或初始加载地址(也称为LMA)和最终的执行地址(虚拟地址或VMA)。

的的影响是执行地址。Yasm计算绝对内存引用假设在一个部分程序代码在VMA而被执行。另一方面,LMA指定一段在哪里最初加载,以及它的位置在输出文件中。

通常,VMALMA一样。然而,他们可能会有所不同,如果程序或另一段代码副本(凡)执行前一节。在嵌入式系统中一个典型的例子是一段代码存储在ROM中,但快复制到RAM之前执行。另一个例子是覆盖:部分加载到不同的文件位置的需求相同的执行位置。

表7.1。本部分属性

属性

显示部分

progbits

存储在磁盘映像,而在负荷分配和初始化。

nobits

分配和初始化加载(progbits相反)。指定的progbits或nobits可能只有一个,他们是相互排斥的属性。

开始=地址

LMA开始地址。如果LMA对齐约束,它是针对所提供的地址和检查如果发出的一个警告地址不符合一致性约束。

遵循=sectname

应该遵循的部分命名sectname在输出文件中(LMA)。如果LMA一致性约束,它是受人尊敬和插入一个缺口,部分满足一致性要求。注意,LMA重叠是不允许的,通常只有一个部分可能遵循另一个。

对齐=n

需要一个LMA对齐的n字节。的值n必须是2的幂。如果未指定LMA对齐默认为4。

音速启动=地址

有一个VMA开始吗地址。如果VMA一致性约束,它是针对所提供的地址和检查如果发出的一个警告地址不符合一致性约束。

vfollows=sectname

应该遵循的部分命名sectname在输出文件中(VMA)。如果VMA一致性约束,这是尊重和插入一个缺口,部分满足一致性要求。VMA允许重叠,所以多个部分可能遵循另一个(可能是有用的在覆盖的情况下)。

valign=n

需要一个VMA对齐的n字节。的值n必须是2的幂。影响规律排列LMA对齐,如果未指定默认值。

只有一个开始或遵循可能为一段指定;同样的限制适用于音速启动和vfollows。

通过使用除非另有说明遵循或开始,默认Yasm假定的隐式排序的顺序输入文件的各个部分中。一段名为。text总是第一个部分。任何代码之前,是显式的部分指令进入。text部分。的。text部分属性可能会被给予一个明确的部分。指令与属性。

除非另有说明,Yasm默认设置VMALMA=。如果指定只是“valign,Yasm需要LMA和对齐到所需的对齐。这可能推动下面的影响“VMAsnon-LMA地址,以避免VMA重叠。

Yasm对待nobits部分在一个特殊的方式以减少输出文件的大小。作为nobits部分可以0-sizedLMA领域,但不能如果位于两个其他部分(由于VMA=LMA默认),Yasm移动nobits部分与未指明的LMA输出文件,在那里他们可以保存有0LMA大小,因此在输出文件中不占用任何空间。如果这种行为不需要,nobits部分LMA(就像一个progbits部分)可以指定使用遵循或开始部分属性。

7.3。本特殊的符号

为了方便编写代码,自己从一个位置复制到另一个(例如从LMA到VMA执行期间),本对象格式提供了一些特殊的符号定义的每一个部分。每个特殊符号开始部分。其次是部分名称。支持的特殊本符号:

部分。sectname.start

设置为命名的LMA地址部分sectname。

部分。sectname.vstart

设置为VMA地址的部分命名sectname。

部分。sectname长处

将部分的长度命名sectname。长度被认为是运行时,因此“nobits部分”长度是他们的运行时,而不是0。

7.4。映射文件

可能生成地图文件本通过使用(地图)指令。地图文件名可以指定命令行选项(——mapfile=文件名)或(地图)指令。如果要求但没有地图输出文件名,地图默认输出到标准输出。

如果没有(地图)指令中给出了输入文件,没有地图生成输出。如果(地图)没有选择,给出一个简短的地图生成。的(地图)指令接收以下选项来控制映射文件中包含什么内容。可以指定多个选项。以外的任何选项,下面是解释为输出文件名。

短暂的

部分,段

包括一个章节的详细清单,包括VMA和LMA对齐,任何“跟随”设置,以及VMA和LMA的部分开始地址和长度。

符号

包括一个详细清单的所有装备的价值观和VMA和LMA符号位置,按截面分组。

所有

所有的上面。

第八章。coff:通用对象文件格式

第9章。elf32:可执行文件和可链接32位对象文件格式

可执行和可链接对象格式是许多操作系统包括的主要对象格式FreeBSD和GNU/Linux。它出现在三种形式:

Yasm只有直接支持浮动对象文件。其他工具,如GNU链接器ld,帮助把浮动对象文件转化为另一种格式。Yasm支持32位和64位精灵的生成文件,调用elf32和elf64。一个额外的格式,称为elfx32,是一个32位精灵文件,支持64位执行(指令和寄存器),而限制指针大小为32位。

Yasm默认为32位当输出模式elf32对象的格式。

9.1。调试格式支持

9.2。精灵的部分

表9.1。精灵部分属性

alloc

在运行时被加载到内存中。这是对代码和数据部分,假为元数据部分。

执行

已经许可运行可执行代码。

在运行时是可写的。

需要一个内存对齐的n字节。的值n必须是2的幂。

在NASM中语法、属性nobits提供一个别名noprogbits。

表9.2。精灵标准部分

部分

对齐

.bss

4

.data

.rodata

。text

16

.comment

0

未知的

1

9.3。精灵的指示

精灵增加了额外的汇编指令定义弱符号(弱),设置符号大小(大小),并表明是否符号是专门一个函数或一个对象(类型)。精灵还增加了一个指令,协助识别源文件或版本,鉴别。

设备上装。鉴别:添加文件识别

的鉴别指令允许任意的字符串数据添加到一个ELF对象文件,将被保存在对象和可执行文件,但不会加载到内存中的数据.data部分。它通常用于储蓄版本控制关键字等信息工具cvs或svn成文件,源创建对象的修改可以阅读使用鉴别大多数Unix系统上发现的命令。

该指令将一个或多个字符串参数。每个参数保存在0-terminated字符串序列.comment部分对象的文件。多种用途的鉴别指令是合法的,字符串将被保存到.comment节源文件中给出的顺序。

在NASM中语法,没有提供包装宏鉴别,所以它必须用方括号。示例使用在NASM中语法:

(识别“Id”美元)

9.3.2。大小:设置符号大小

精灵的符号表的存储大小的能力的象征。这是常用的函数或数据对象。虽然可以直接对特定的大小常见的符号,大小指令可以指定任何符号的大小,包括当地的象征。

指令接受两个参数,第一个参数是符号的名称,和第二个是大小。可能是一个常量或表达式。例子:

函数:

指标:最终

大小funcfunc.end-func

9.3.3。类型:设置符号类型

指令接受两个参数,第一个参数是符号的名称,和第二个是符号类型。符号类型必须函数或对象。一个无法识别的类型会导致生成一个警告。使用的例子:

类型函数函数

.data部分

vardd4

类型变量对象

9.3.4。弱:创建软弱的象征

这个功能主要是有用的库,希望提供常用功能但不与用户程序发生冲突。例如,libc有一个系统调用(函数)称为“读”。然而,实现一个线程的进程在用户空间使用POSIX线程,libpthread需要提供一个函数也称为“读”,它提供了一个阻塞接口,程序员,但实际上确实非阻塞调用内核。允许一个应用程序与libc和libpthread(共享通用代码),libc需要其版本的系统调用与non-weak名称如“_sys_read”称为“读”的弱符号。如果一个应用程序对有关libc,链接器找不到non-weak象征“读”,所以它将使用弱者。如果相同的应用程序对libc有关和libpthread,那么链接将链接“读”调用libpthread象征,忽略libc的弱者,不管库链接订单。如果使用libcnon-weak名称,“读”功能程序最终可能取决于各种各样的因素;软弱的象征是一种告诉链接器符号是resolution-wise那么重要。

的弱指令需要一个参数,宣布弱符号名称。例子:

weakfunc:

strongfunc:

弱weakfunc

全球strongfunc

9.4。精灵的扩展全球指令

您可以指定一个全局变量是否是一个函数或一个数据对象通过向一个冒号和一词的名称函数或数据。(((对象)是同义词数据)。例如:

出口全球的象征hashlookup作为一个函数,哈希表作为一个数据对象。

可选地,您可以控制的精灵能见度的象征。能见度的添加一个关键词:默认的,内部,隐藏的,或受保护的。默认值是默认的,当然。例如,hashlookup隐藏:

全球hashlookup:隐藏功能

全球散列表:数据(散列表。结束-散列表)

散列表:

db,一次;一些数据

全球散列表

哈希表对象类型

大小hashtablehashtable。——散列表

9.5。精灵的扩展常见的指令

精灵也允许您指定对齐要求共同的变量。这是通过把数量(必须是2的幂)共同的变量的名称和大小后,(像往常一样)用冒号分开。例如,一个双字将受益于4字节对齐的数组:

常见dwordarray128:4

9.6。elf32特殊符号和关于

ELF规范包含足够的特性允许位置无关代码编写(PIC),这使得精灵共享库非常灵活。然而,这也意味着Yasm必须能够生成各种奇怪的迁移类型在ELF对象文件中,如果它是一个可以编写汇编程序照片。

因为精灵不支持segment-base引用关于运营商不用于其正常目的;因此Yasmelf32利用输出格式关于不同的目的,即PIC-specific搬迁类型。

elf32定义五个特殊符号,您可以使用右边的关于运营商获取图片迁移类型。他们是..gotpc,..gotoff,..了,..plt和.信谊。它们的功能进行了总结:

..gotpc

指的是符号标记使用全局偏移表基地关于..gotpc最终会让距离当前的开始部分全局偏移表。(((_GLOBAL_OFFSET_TABLE_)是标准的名称指象征了)。所以你将需要添加$$结果得到的真实地址。

..gotoff

指的是在一个位置使用你自己的部分关于..gotoff会给的距离到达指定位置,以便增加的地址有会给你想要的真正的地址位置。

..了

指外部或全局符号使用关于..了导致链接器建立一个条目在的包含了地址的象征,并参考了距离的开始要进入,所以您可以添加的地址,负载产生的地址和最终的地址的象征。

..plt

指一个过程名称使用关于..plt导致建立一个链接过程符号链接表条目,并参考提供的地址PLT条目。你只能使用在上下文通常会生成一个PC-relative搬迁(即作为目的地调用或无条件转移指令),因为精灵不包含搬迁绝对引用PLT条目类型。

.信谊

指的是使用符号名关于……信谊导致Yasm写一个普通的搬迁,而是让搬迁相对于部分的开始,然后添加偏移量的符号,它将编写一个搬迁记录直接针对问题的象征。的区别是一个必要的动态链接器的特点。

第十章。elf64:可执行文件和可链接格式64位对象文件

Yasm默认为位64当输出模式elf64对象的格式。

10.1。elf64特殊符号和关于

的主要区别elf32和elf64(除了64位支持)是共享库的差异处理和位置无关代码。作为位64允许使用的把相对寻址,大多数变量访问可以相对于RIP,允许简单的共享库的搬迁到不同的内存地址。

虽然RIP-relative寻址可用,它不能处理所有可能的变量访问模式,所以仍然需要有特殊符号,如elf32。与elf32,elf64利用输出格式关于为利用PIC-specific搬迁类型。

elf64定义了四个特殊符号,您可以使用右边的关于运营商获取图片迁移类型。他们是..gotpcrel,..了,..plt和.信谊。它们的功能进行了总结:

..gotpcrel

虽然RIP-relative寻址允许您编码指令指针相对数据参考喷火与(relfoo),有时需要编码RIP-relative引用指针linker-generated象征符号foo;这是使用关于..gotpcrel,如。[relfoo关于..gotpcrel]。不同于elf32,这个搬迁,加上RIP-relative寻址,可以加载一个地址的((全局偏移表))使用一个单一的指令。注意,因为RIP-relative引用仅限于一个签署了32位的位移,有大小可以通过这种方法仅限于2GB。

就像在elf32,指外部或全局符号使用关于..了导致链接器建立一个条目在的包含了地址的象征,并参考了距离的开始要进入,所以您可以添加的地址,负载产生的地址和最终的地址的象征。

就像在elf32,指的是一个过程名称使用关于..plt导致建立一个链接过程符号链接表条目,并参考提供的地址PLT条目。你只能使用在上下文通常会生成一个PC-relative搬迁(即作为目的地调用或无条件转移指令),因为精灵不包含搬迁绝对引用PLT条目类型。

就像在elf32,指的是一个符号名的使用关于……信谊导致Yasm写一个普通的搬迁,而是让搬迁相对于部分的开始,然后添加偏移量的符号,它将编写一个搬迁记录直接针对问题的象征。的区别是一个必要的动态链接器的特点。

第十一章。elfx32:精灵32位64位处理器对象文件

Yasm默认为位64当输出模式elfx32对象的格式。

11.1。elfx32特殊符号和关于

由于RIP-relative寻址的可用性,elfx32共享库处理和独立于位置的代码基本上是相同的elf64。

就像在elf64,elfx32定义了四个特殊符号,您可以使用右边的关于运营商获取图片迁移类型。他们是..gotpcrel,..了,..plt和.信谊和有相同的功能,因为他们做的elf64。它们的功能进行了总结:

虽然RIP-relative寻址允许您编码指令指针相对数据参考喷火与(relfoo),有时需要编码RIP-relative引用指针linker-generated象征符号foo;这是使用关于..gotpcrel,如。[relfoo关于..gotpcrel]。就像在elf64,这个搬迁,加上RIP-relative寻址,可以加载一个地址的((全局偏移表))使用一个单一的指令。注意,因为RIP-relative引用仅限于一个签署了32位的位移,有大小可以通过这种方法仅限于2GB。

就像在elf64,指外部或全局符号使用关于..了导致链接器建立一个条目在的包含了地址的象征,并参考了距离的开始要进入,所以您可以添加的地址,负载产生的地址和最终的地址的象征。

就像在elf64,指的是一个过程名称使用关于..plt导致建立一个链接过程符号链接表条目,并参考提供的地址PLT条目。你只能使用在上下文通常会生成一个PC-relative搬迁(即作为目的地调用或无条件转移指令),因为精灵不包含搬迁绝对引用PLT条目类型。

就像在elf64,指的是一个符号名的使用关于……信谊导致Yasm写一个普通的搬迁,而是让搬迁相对于部分的开始,然后添加偏移量的符号,它将编写一个搬迁记录直接针对问题的象征。的区别是一个必要的动态链接器的特点。

第十二章。macho32:32位马赫对象文件格式

第13章。macho64:马赫64位对象文件格式

第14章。rdf:浮动动态对象文件格式

第15章。win32:微软Win32对象文件

的win32对象格式生成微软Win32对象文件用于32位本地WindowsXP和Vista平台。使用这个对象格式生成的对象文件可能与32位微软连接器等VisualStudio生成32位PE可执行文件。

的win32对象格式提供了一个默认的输出文件名扩展.obj。

注意,尽管微软说Win32对象文件遵循COFF(通用对象文件格式)标准,MicrosoftWin32产生的对象文件编译器不兼容COFF连接器等DJGPP,反之亦然。这是由于不同的意见在精确的语义PC-relative搬迁。生产适合DJGPPCOFF文件,使用coff输出格式;反之,coff格式不产生目标文件,Win32连接器能产生正确的输出。

15.1。win32扩展部分指令

可用的限定符是:

代码或文本

定义了部分代码部分。这标志着部分可读和可执行文件,但没有可写的,还指示链接器,部分代码的类型。

数据或bss

rdata

信息

指定的对齐需求部分。您可以指定的最高分数为8192:Win32对象文件格式包含不要求更大的部分对齐。如果没有显式地指定对齐,默认值是16字节对齐的代码部分,8字节对齐rdata部分和4字节对齐的数据(BSS)部分。信息部分的默认对齐方式1字节(没有对齐),虽然价值并不重要。的定位必须是2的幂。

默认值由Yasm如果不指定上述限定符是:

部分。对齐文本代码=16

部分。数据数据对齐=4

部分。rdatardata对齐=8

部分。rodatardata对齐=8

部分。rdatardata对齐=8美元

部分。bssbss对齐=4

部分。drectve信息

部分.comment信息

其他部分的名字是默认处理。text。

15.2。win32:安全结构化异常处理

其他改进在WindowsXPSP2和WindowsServer2003微软推出了“安全的概念结构化异常处理。“总的想法是收集处理程序入口点在指定只读表,每个入口点验证之前对这个表异常控制被传递到处理程序。为了创建一个可执行的安全异常处理程序表,链接器命令行上的每个对象文件必须包含一个特殊符号命名@feat.00。如果任何对象文件传递给链接器没有这个符号,然后从可执行异常处理程序表省略,因此运行时检查为应用程序不会被执行。默认情况下,表省略默默地从可执行文件如果发生这种情况,因此可以很容易被忽视。用户可以指示链接器拒绝通过产生一个可执行的没有这个表/safeseh命令行选项。

版本1.1.0,Yasm补充说这种特殊的符号win32对象文件,所以它的输出不无法链接/safeseh。

15.1.Win32例子safeseh例子

走读生_MessageBoxA@16

safeseh处理程序,处理程序注册为“安全处理程序”

处理程序:

推动DWORD1;MB_OKCANCEL

把字标题

推动DWORD文本

把字0

叫_MessageBoxA@16

子eax,1;顺便说一句适合作为返回值

,因为异常处理程序

_main:

把字处理程序

推动DWORD[fs:0]

movDWORD[fs:0],esp;异常处理程序

xoreax,eax

moveax,DWORD[eax];导致异常

字流行[fs:0];解除异常处理程序

添加esp,4

文本:db”可以重新抛出,取消生成核心转储”,0

标题:dbSEGV,0

db/defaultlib:user32。lib/defaultlib:msvcrt。自由的

如果应用程序有一个安全的异常处理程序表,试图执行任何程序未注册的异常处理程序将导致立即终止。因此重要的是要登记每个异常处理程序的入口点safeseh指令。

所有提到的链接器在这部分参考微软链接器版本7。x和。的存在@feat.00符号和数据安全的异常处理程序表因为没有向后不兼容,因此“safeseh”生成对象文件仍然可以由链接器版本或非微软早些时候连接器连接起来。

第十六章。win64:PE32+(微软Win64)对象文件

的win64或x64对象格式生成微软Win64对象文件的64位本地使用WindowsXPx64(和Vistax64)平台。使用这个对象格式生成的对象文件可能与64位微软连接器等VisualStudio2005和2008年以生产64位PE32+可执行文件。

win64提供了一个默认的输出文件名扩展.obj。

16.1。win64扩展部分指令

16.2。win64结构化异常处理

大多数函数,利用堆栈的64位版本的Windows必须支持异常处理,即使他们没有内部使用的设施。这是因为这些操作系统定位异常处理程序通过使用这一过程被称为“栈”,取决于功能提供数据,描述了他们如何使用堆栈。

当发生异常栈是“解除”工作向后通过函数调用链异常事件前确定功能是否具有适当的异常处理程序或他们是否有保存的非易失性寄存器的值需要恢复为了重建的执行上下文中的下一个更高的功能链。这个过程取决于编译器和汇编程序提供“解除数据”功能。

以下部分详述的机制可用Yasm满足这些需求,从而允许函数写在汇编程序中使用的编码惯例遵守64位版本的Windows。这些YasmMASM。实现中提供设备遵循这些

16.2.1。约定x64堆栈、寄存器和功能参数

图16.1。x64调用协定

前四个整数函数参数传递(从左到右顺序)寄存器RCX,RDX,R8和R9机型。进一步的整数参数传递到栈上推在右到左的顺序(向左参数在低地址)。栈空间是分配给四个寄存器参数(“影子空间”),但他们的价值观并不存储由调用函数调用的函数必须这样做,如果必要的。调用函数有效地拥有这个空间,可以使用它为任何目的,因此,在返回调用函数不能依靠其内容。注册参数占据最低有效位的寄存器和影子空间必须分配给四个寄存器参数,即使被调用的函数没有这么多参数。

前四个浮点参数传入XMM0XMM3。当混合整数和浮点参数时,参数和寄存器之间的通信是没有改变。因此一个整数参数在两个浮点的R8RCX和RDX未使用。

当它们通过值,结构和工会的尺寸8,16、32或64位传递相同大小的整数。数组和更大的结构和工会作为指针传递给调用函数的内存分配和分配。

寄存器伸展,RCX,RDX、R8R9机型,R10,R11是挥发性的,可以自由使用的调用函数没有保存它们的值(但是请注意,一些可用于传递参数)。由于功能不能指望这些寄存器保存调用其他函数。

寄存器RBXRBP,肢体重复性劳损症,RDIR12,R13,R14、R15和XMM6XMM15非易失性,必须保存和恢复功能,使用它们。

除了浮点值,返回XMM0,函数返回值,适合在递交的64位返回。一些128位值也传入XMM0但较大的值返回调用程序在内存中分配的,并指出通过一个额外的“隐藏”函数参数,成为第一个参数和推动其他参数。这个指针值也必须返回给调用程序在调用的程序返回时递交。

16.2.2。类型的函数

函数分配堆栈空间,调用其他函数,非易失性寄存器保存或使用异常处理被称为“帧函数”;其他功能被称为“叶功能”。

帧函数使用一个区域在堆栈上称为“堆栈帧”和有一个定义的序言中设置。通常他们在影子的位置保存寄存器参数(如果需要的话),他们使用的任何非易失性寄存器保存,为局部变量分配堆栈空间,并建立一个注册为一个堆栈帧指针。他们还必须有一个或多个定义的尾声,免费的任何分配堆栈空间和恢复非易失性寄存器之前返回到调用函数。

除非动态分配堆栈空间,一个框架函数必须保持16字节对齐的堆栈指针,同时在其序言和后记外代码(在调用其他函数除外)。一帧函数动态地分配堆栈空间必须首先需要分配任何固定的堆栈空间,然后分配和建立一个索引寄存器访问该地区。这个区域的较低的基地址必须是16字节对齐的,必须提供注册而不管函数本身使得显式地使用它。然后自由离开函数堆栈对齐在执行期间虽然必须重建16字节对齐如果或当它调用其他函数。

叶功能不需要定义序言或后记但他们不能调用其他函数;也不能改变任何非易失性寄存器和堆栈指针(这意味着他们不保持16字节的堆栈对齐在执行期间)。不过,它们可以退出,跳转到另一个框架或叶的入口点函数提供了相应的堆参数是兼容的。

表16.1。功能结构化异常处理规则

功能需求或可以:

帧与帧指针寄存器函数

框架没有帧指针寄存器函数

叶函数

序言和后记(s)

是的

没有

使用异常处理

到栈上分配空间

保存或寄存器推压入堆栈

使用非易失性寄存器(在保存)

使用动态堆栈分配

在函数体改变堆栈指针

在函数体对齐堆栈指针

使跳到其他功能

16.2.3。框架功能结构

已经表明,帧函数必须有一个良好定义的结构包括序言和一个或多个尾声,每个特定的形式。一个函数中的代码不属于它的序言或其一个或多个结语将把这里称为函数的身体。

一个典型的功能序言的形式:

mov负责+8,rcx,参数存储在影子空间如果有必要

推动r14;保存任何要使用非易失性寄存器

推动r13;

子负责,大小;如果需要为局部变量分配堆栈

lear13[偏差+负责];用r13帧指针偏移

当一个帧指针需要程序员可以选择使用哪个寄存器(“偏见”将在稍后解释)。虽然它没有用于访问分配空间,它必须分配在序言和执行期间保持不变的主体功能。

匹配的结语是:

lea负责,r13-bias;这不是官方后记的一部分

添加负责,大小;官方结语从这里开始

流行r13

流行r14

也可以使用以下规定,已经建立了一个帧指针寄存器:

lea负责,[r13+size-bias]

这是只允许两种形式的尾声。它必须与一个开始添加负责,常量指令或与lea负责,(const+fp_register);第一个表单可以使用有或没有一个帧指针寄存器但第二种形式要求。这些指令然后其次是零个或多个8字节寄存器持久性有机污染物和返回指令(可替换为一组有限的跳转指令如微软文档中所述)。结语形式高度受限,因为这允许例外调度代码来定位他们不需要解除数据除了提供序言。

每个函数的位置和数据长度的序幕,在任何固定堆栈分配和任何非易失性寄存器保存在对象代码是记录在特殊的部分。Yasm提供宏创建这些数据,现在将描述(例子的方式使用它们)。

16.2.4。堆栈框架的细节

有两种类型的堆栈帧,在创建解除数据需要考虑。

图16.2。x64详细的堆栈帧

为了让最大数量的数据访问单个字节偏移量\+127(-128)从帧指针寄存器,它是正常的,以抵消其价值对分配的中心区域(之前介绍的“偏见”)。帧指针寄存器的身份,这抵消必须16字节的倍数,记录在解除数据允许堆栈帧基地址计算帧寄存器中的值。

16.2.5。Yasm为解除操作原语

这是低水平设施Yasm提供创建解除数据。

proc_frame的名字

生成一个函数表条目.pdata和解除信息.xdata一个函数的结构化异常处理数据。

[pushreg注册]

为指定的非易失性寄存器生成解除数据。只使用非易失性整数寄存器;易失性寄存器使用(allocstack8)代替。

[setframe注册,抵消]

生成解除数据寄存器和堆栈帧偏移量。偏移量必须16的倍数和小于或等于240。

[allocstack大小]

生成撤销堆栈空间的数据。尺寸必须是8的倍数。

[savereg注册,抵消]

生成解除指定的寄存器和数据抵消;必须积极抵消8的倍数的基础相对于过程的框架。

[savexmm128注册,抵消]

生成解除数据指定XMM寄存器和抵消;必须积极抵消16的倍数的基础相对于过程的框架。

[pushframe代码]

生成解除40或48字节的数据(使用一个可选的错误代码)框架用于存储硬件的结果异常或中断。

(endprolog)

信号的序言,必须在第一个255字节的函数。

endproc_frame

用在函数开始的结束proc_frame。

例16.1。Win64解除原语

PROC_FRAME样本

db0x48;发出雷克斯前缀,使热修补

推动rbp;拯救未来的帧指针

[pushregrbp];创建解除数据rbp寄存器推

子负责,0x40;分配堆栈空间

[]allocstack0x40;创建解除数据堆栈分配

learbp,[负责+0x20];分配帧指针的偏见32

[setframerbp,0x20);在rbp创建解除一帧数据寄存器

xmm7movdqa(rbp),节省非易失性寄存器XMM

[savexmm128xmm7,0x20);创建解除XMM寄存器保存数据

mov(rbp+0x18),肢体重复性劳损症;保存肢体重复性劳损症

[saveregrsi,0x38];创建解除数据保存肢体重复性劳损症

mov负责+0x10,rdi;拯救rdi

(saveregrdi0x10);创建rdi的解除数据保存

;我们可以改变堆栈指针之外的开场白,因为我们

,有一个帧指针。如果我们没有一个这将是非法的。

;帧指针是必要的因为这个堆栈指针修改。

子负责,0x60;我们可以自由修改堆栈指针

mov伸展,0;我们可以解除这个访问违例

mov伸展,伸展

movdqaxmm7(rbp);恢复寄存器没有保存

movrsi(rbp+0x18);推动;这不是的一部分

movrdi[rbp-0x10];官方跋

lea负责,(rbp+0x20),这是官方的尾声

流行rbp

ENDPROC_FRAME

16.2.6。Yasm宏正式栈操作

生成一个函数表条目.pdata和解除信息.xdata。

alloc_stackn

分配一个堆栈区n字节。

save_reg注册,疯狂的

节省了非易失性寄存器注册在抵消疯狂的在堆栈上。

push_reg注册

将非易失性寄存器注册在堆栈上。

rex_push_reg注册

将非易失性寄存器注册在堆栈上使用一个2字节指令。

save_xmm128注册,疯狂的

节省了非易失性寄存器XMM注册在抵消疯狂的在堆栈上。

set_frame注册,疯狂的

设置框架注册注册来抵消疯狂的在堆栈上。

push_eflags

推动eflags寄存器

push_rex_eflags

推动eflags寄存器使用一个2字节指令(允许热修补)。

push_frame代码

推动一个40字节帧和一个可选的8字节错误代码压入堆栈。

end_prologue,end_prolog

结束函数序言(这是另一种选择(endprolog))。

使用的职能之一proc_frame。

例16.2。Win64解除宏

PROC_FRAME样本;开始的序幕

rex_push_regrbp;推动未来的帧指针

alloc_stack0x40;分配64字节的堆栈空间

set_framerbp,0x20;设置一个框架注册(负责+32)

save_xmm128xmm70x20;节省xmm7,肢体重复性劳损症和rdi到本地堆栈空间

save_reg肢体重复性劳损症,0x38;放松基地地址:[rsp_after_entry-72]

save_regrdi,0x10;框架寄存器值:[rsp_after_entry-40]

END_PROLOGUE

子负责,0x60;我们现在可以改变堆栈指针

mov伸展,0;解除这个访问违例

mov伸展,伸展,因为我们有一个帧指针

movdqaxmm7(rbp);恢复寄存器,没救了

movrsi(rbp+0x18);推动(而不是官方跋的一部分)

movrdi[rbp-0x10]

lea负责(rbp+0x20),官方的尾声

第十七章。xdf:扩展动态对象的格式

第五部分。调试格式

书的这一部分文档中的章节Yasm对各种调试格式的支持。

第18章。cv8:VC8CodeView调试格式

19章。dwarf2:DWARF2调试格式

第20章。刺穿了:刺穿了调试格式

第六部分架构。

书的这一部分文档中的章节Yasm对各种指令集架构的支持。

21章。x86体系结构

的x86架构的通用名称是多供应商16位,32位,最近64位架构。最初由英特尔的8086系列CPU,英特尔在80386年扩展到32位的CPU,并延长AMDOpteron64位,Athlon64CPU。而在2007年,英特尔和AMD是最高的x86处理器体积制造商,许多其他供应商也生产x86处理器。通常制造商已经交换专利权(或复制)主要架构的改进,但也有一些独特的功能出现在许多的实现。

21.1。说明

x86体系结构有一个可变的指令大小,允许适度的代码压缩,同时允许非常复杂的操作数组合以及一个非常大的和许多扩展指令集的大小。指令一般变化从零到三个操作数只有一个内存操作数允许的。

21.1.1。NOP填充

表21.1。x86NOP填充模式

CPU

填充

任何

16位短空操作

32

没有,或少于686

32位短空操作(没有长空操作)

686或最新的英特尔处理器

英特尔指南,使用长空操作

转K6或更新的AMD处理器

AMDK10指南,使用长空操作

64年

没有一个

表21.2。x86NOPCPU指令选项

的名字

描述

basicnop

intelnop

amdnop

21.2。执行模式和扩展

x86在许多方面已经扩展在整个历史进程中,剩下的大多是向后兼容的同时添加执行模式和大扩展指令集。现代x86处理器可以在四种主要模式:16位真正的模式中,16位保护模式,32位保护模式,和64位长模式。的主要区别真实和保护模式的处理部分:在实模式段直接寻址内存16字节的页面,而在保护模式片段而不是索引到描述符表,其中包含的物理基础和大小。32位保护模式允许分页和虚拟内存,以及一个32位的,而不是一个16位的偏移量。

16位和32位的操作模式都允许使用16位和32位寄存器通过设置操作和指令前缀地址大小16位或32位,与活跃的操作模式设置默认操作规模和“其他”大小被标记为一个前缀。这些操作和地址大小也影响直接操作数的大小:例如,一个与一个32位的指令操作的大小和立即操作数将有一个32位值的编码指令,除了优化等符号扩展8位值。

与16位和32位模式不同的是,64位长模式更多的是一种打破“遗留”的模式。长模式废止几个指令。也是唯一的64位寄存器可用模式;64位寄存器不能从16位或32位访问模式。与其他模式,大多数编码值模式是有限大小32位长。一个小的子集MOV指令允许64位编码值,但在其他值大于32位指令必须来自一个寄存器。部分原因是这个限制,也由于浮动的广泛使用共享库,长模式还增加了一个新的寻址模式:把相对。

21.2.1。CPU的选择

表21.3。x86处理器功能标志

FPU

浮点单元(FPU)指令

MMX

MMXSIMD指令

上交所

流SIMD扩展(SSE)指令

SSE2

流SIMD指令扩展2

SSE3

流SIMD指令扩展3

SSSE3

补充流SIMD指令扩展3

SSE4.1

流SIMD扩展4,彭林子集(47个指令)

SSE4.2

流SIMD扩展4,Nehalem子集(7指令)

SSE4

所有流SIMD指令扩展4(SSE4.1和SSE4.2)

SSE4a

4流SIMD扩展(AMD)

SSE5

流SIMD扩展5

XSAVE

XSAVE指令

AVX

先进的矢量扩展指令

菲利普-马萨

延时指令

AES

高级加密标准说明

CLMUL,PCLMULQDQ

PCLMULQDQ指令

3dnow

3dnow!指令

新瑞仕

Cyrix-specific指令

AMD

比转K6AMD-specific指令(旧)

多发性骨髓瘤

系统管理模式指令

普罗特,保护

只保护模式指令

Undoc,无证

非法指令

奥林匹克广播服务公司,过时了

过时的指令

我感到,特权

特权指令

支持向量机

安全虚拟机指令

挂锁

通过挂锁指令

EM64T

英特尔EM64T或更好的指令(不一定仅64位)

表21.4。x86处理器的名字

功能标志

8086年

我感到

英特尔8086年

186年,80186年,i186

英特尔80186年

286年,80286年,i286

英特尔80286年

386年,80386年,i386

多发性骨髓瘤,普罗特,我感到

英特尔80386年

486年,80486年,i486

FPU,多发性骨髓瘤,普罗特,我感到

英特尔80486年

586年,i586奔腾,P5

英特尔奔腾

686年,i686P6、PProPentiumPro

P2,Pentium2、Pentium-2PentiumII,奔腾ii

MMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔奔腾II

P3、Pentium3奔腾3、PentiumIIIpentiumiii,卡特迈

上交所、MMXFPU,多发性骨髓瘤,普罗特,我感到

英特尔奔腾III

P4、Pentium4奔腾4,PentiumIVWilliamette奔腾iv

SSE2、SSEMMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔奔腾4

IA64,安腾ia-64

英特尔安腾(x86)

转K6

3dnowMMX,FPU,多发性骨髓瘤,普罗特,我感到

AMD转K6

速龙,K7

上交所,3dnowMMX,FPU,多发性骨髓瘤,普罗特,我感到

的AMDAthlon

锤,抓奏的,皓龙处理器、Athlon64速龙-64

SSE2、上交所、3dnowMMX,FPU,多发性骨髓瘤,普罗特,我感到

AMDAthlon64和皓龙处理器

普莱斯考特

SSE3SSE2,上交所MMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔代号普雷斯科特

Conroe,嵌件

SSSE3、SSE3SSE2、SSEMMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔代号Conroe

彭林

SSE4.1、SSSE3SSE3SSE2,SSE,MMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔代号彭林

Nehalem,Corei7

XSAVE、SSE4.2SSE4.1、SSSE3SSE3,SSE2,上交所,MMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔代号Nehalem

Westmere

CLMUL,AES、XSAVESSE4.2、SSE4.1SSSE3,SSE3,SSE2,上交所,MMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔代号Westmere

Sandybridge

AES,AVX,CLMULXSAVE、SSE4.2SSE4.1,SSSE3,SSE3,SSE2,上交所,MMX,FPU,多发性骨髓瘤,普罗特,我感到

英特尔代号桑迪大桥

威尼斯

SSE3SSE2,上交所、3dnowMMX,FPU,多发性骨髓瘤,普罗特,我感到

AMD代号威尼斯

Family10hK10、杰出人才

SSE4a、SSE3SSE2SSE,3dnow,MMX,FPU,多发性骨髓瘤,普罗特,我感到

AMD代号K10

推土机

SSE5、SSE4aSSE3SSE2,SSE,3dnowMMX,FPU,多发性骨髓瘤,普罗特,我感到

AMD代号推土机

默认为最新的处理器CPU设置和所有特性标志启用;例如x86指令的处理器,包括所有的指令集扩展和64位指令。

21.3。寄存器

64位x86寄存器设置由16个通用寄存器,其中只有8个16位和32位模式下可用。8个16位寄存器是核心斧头,BX,残雪,DX,如果,迪,英国石油公司,SP。最重要的8位的第一个四个寄存器可通过艾尔,提单,CL,戴斯。莱纳姆:在所有的执行模式。在64位模式下,最重要的8位其他四个寄存器也可访问;这些命名银,迪勒,SPL,底保。最重要的8位前四16位寄存器也可用,虽然有一些限制时,可以用在64位模式;这些都是命名啊,黑洞,CH,DH。

80386年扩展这些寄存器为32位,同时保留所有的16位和8位的名字在16位模式下可用。用添加一个新的扩展寄存器E前缀,因此核心八32位寄存器命名EAX,EBX,连成一片,EDX,应急服务国际公司,EDI,EBP,ESP。最初的8位和16位寄存器名称映射到最不重要的部分32位寄存器。

64位长模式进一步扩展这些寄存器的规模通过添加64位R16位的名字前缀;因此,基地8个64位寄存器命名递交,RBX等。长模式还添加了八个额外的寄存器指定数值r8通过r15。最重要的32位的寄存器都可以通过d后缀(r8d通过r15d),最重要的16位通过w后缀(r8w通过r15w),并通过一个最重要的8位b后缀(r8b通过r15b)。

THE END
1.图书标签制作图书标签制作厂家品牌图片热帖阿里巴巴1688为您优选227条图书标签制作热销货源,包括图书标签制作厂家,品牌,高清大图,论坛热帖。找,逛,买,挑图书标签制作,品质爆款货源批发价,上1688图书标签制作主题频道。https://www.1688.com/zhuti/-CDBCCAE9B1EAC7A9D6C6D7F7.html
2.VB编写的多标签窗口源码学校图书标签怎样编写资源【标题解析】 "VB编写的多标签窗口源码"这一标题揭示了主要知识点是关于使用Visual Basic(VB)编程语言开发的一个具有多标签界面的应用程序。VB是一种面向对象的编程语言,常用于创建Windows桌面应用程序。多标签窗口通常指的是在同一个应用程序窗口中可以有多个独立的工作区域,每个区域称为一个标签页,用户可以通过切换https://download.csdn.net/download/taily_duan/8500595
3.血脂高了怎么吃犀文图书编写2015年版下载资料名称:血脂高了怎么吃 犀文图书编写 2015年版 英文名称: 文件大小:27.19 MB 标准类型:行业图书 标准语言:中文版 授权形式:免费 文件类型:PDF文档 下载次数:3185 加入收藏 标签:资料介绍 血脂高了怎么吃 作者:犀文图书编写出版时间: 2015年版内容简介控制血脂是患者必打的持久战,《血脂高了怎么吃》分两http://360read.cn/showinfo-145-982923.html
4.防白水安全技术说明书MSDS标签要素: 象形图: 警示词:警告 危险性说明: H302 吞咽有害 H312 皮肤接触有害 H315 造成皮肤刺激 H319 造成严重眼刺激 H332 吸入有害 防范说明: 预防措施: —— P264 作业后彻底清洗。 —— P270 使用本产品时不要进食、饮 水或吸烟。 —— P280 戴防护手套/穿防护服/戴防 护眼罩/戴防护面具。 http://minghg.cn/a/xinwenzhongxin/jishuzhishi/1073.html
5.网页***与网站建设书?(网页***与网站建设书哪个好)网页设计与 *** 的图书一 作者:詹青龙,郭永灿 主编 出版社:清华大学出版社有限公司 出版时间: 2010-1-1 开本: 16开 定价:29.00 本书从网页设计与 *** 的实际需要出发,全面、系统地介绍网页设计与 *** 的基础知识、网页编辑软件Dreamweaver CS4等内容,还提供了一个完整的网站规划、网页设计与 *** 的实例。http://www.yyggzy.com/articles/835f899156.html
6.第一次见这种透明的便签纸,用它给课本做标注不脏书不留胶学习用品评论 还没有人评论过,快来抢首评 发布 第一次见这种透明的便签纸,用它给课本做标注不脏书不留胶学习用品 文具安利 便利贴 文具用品 拳击那点事 发布于:江西省 2024.12.16 00:00 +1 首赞 收藏 第一次见这种透明的便签纸,用它给课本做标注不脏书不留胶学习用品 文具安利 便利贴 文具用品 推荐https://www.sohu.com/a/838108581_100114195
7.学位论文撰写指南积累材料的方法:(1)查找图书文献资料 (2)查找报刊论文资料 (3)利用三次文献(三次文献指综述、述评、书评、评论、年鉴、手册、百科全书等) (4)利用其他工具书和向专家请教。 4、选择材料的原则 (1)、 选择能突出主题的材料 (2)、 选择典型的材料 http://lib.jiangnan.edu.cn/old/fw/xkfwjxkgy/xwlwzxzn.htm
8.标签转换站RFID馆员工作站/标签转换站用于对RFID图书进行快速的借还、续借、预约、缴费等操作,提高图书馆工作人员的工作效率。 可与图书馆采用的图书自动化管理系统无缝连接,协调工作。 具有读取RFID图书标签、编写图书标签、改写图书标签的能力。 可识读读者证,可进行人工办理读者证。 可进行图书编目及RFID图书标签转换,检测修改http://www.ftzn.net/view/2.html
9.印刷的详细工艺流程(精选9篇)[3]《设计与工艺》编写组编著.设计与工艺[M].北京.高等教育出版社出版1997.7 篇4:报业印刷的流程之美 应用 成效显著 我国目前推广应用的数字化工作流程有两种模式,一是全数字化工作流程,即CIP3工作流程;另一种是印前数字化工作流程,其又包括以CTP为基础的数字化工作流程、基于大幅面激光照排机的数字化工作流程和https://www.360wenmi.com/f/fileqb8329x6.html
10.AdobePremiereProCC2017经典教程图书目录: 详情 本书由Adobe公司编写,是Adobe Premiere Pro CC软件的正规学习用书。全书共分为18课,每课都围绕着具体的例子讲解,步骤详细,重点明确,手把手教你进行实际操作。全书是一个有机的整体,通过大量富有创意的项目,详细地介绍视频编辑的流程和细节,帮助您快速掌握软件的使用。 https://www.epubit.com/bookDetails?id=N37977
11.用java制作导航栏javawebhtml顶部导航菜单十六、书城项目第五阶段——编写图书模块 001-MVC概念 002-编写图书模块的数据库表 003-编写图书模块的JavaBean 004-编写图书模块的Dao和测试Dao 005-编写图书模块的Service和测试Service 006-编写图书模块的Web层和页面联调测试 (1)实现获取图书信息功能 https://blog.51cto.com/u_12204/8600591
12.图书管理员的左右手——馆员工作站条码RFID馆员工作站用于流通部门对粘贴有RFID标签的流通文献进行快速的借还操作(含续借、预约、付费等功能)提高工作人员的流通文献借还工作效率。 馆员工作站的特点 1.标签转换:将图书条码转换成RFID标签数据 2.可对RFID标签非接触式地进行阅读,有读取RFID图书标签、编写图书标签、改写图书标签的能力。 https://www.163.com/dy/article/HI9KL95U05538X2R.html
13.豆瓣图书标签:词典本书是国内第一部集切口之大成的词典.原名为《全国各界切口大词典》,开本为15Cm×11.5Cm,现据上海东陆图书公司1924年版影印出版。 何谓“切口”?其 牛津高阶英汉双解词典(第四版) 霍恩比 / 李北达 / 商务印书馆 / 1997-8 / 88.00 9.3(2140人评价) https://book.douban.com/tag/%E8%AF%8D%E5%85%B8
14.电子商务网站建设图书简介 书名: 电子商务网站建设 作者:刘芳,黄国庆 ISBN:7512103808,9787512103801 出版社:北京交通大学出版社 出版日期: 2010年10月1日 页数:191 开本:16开 定价:¥24.00 内容简介 《电子商务网站建没》采用任务驱动模式编写,以具体的电子商务网站为实例,将实例细分为具体的任务。同时每个任务按照“任务介绍→任务https://baike.sogou.com/v5852534.htm
15.合理使用规范范文11篇(全文)6.药师应积极开展用药监护工作。应严格新药审批制度,并认真贯彻执行;开展好合理用药咨询工作,编写资料,宣传合理用药知识,加强信息交流,为临床提供合理用药参考。经常进行药物利用评价,特别是抗生素合理应用调查分析,监督合理用药执行情况。 7.发挥临床药师在合理用药中的作用和地位。临床药师应坚持下临床,参与医师药物治疗,https://www.99xueshu.com/w/ikeyq5ramrti.html
16.食品卫生安全教育教案(通用15篇)作为一名无私奉献的老师,有必要进行细致的教案准备工作,编写教案有利于我们弄通教材内容,进而选择科学、恰当的教学方法。来参考自己需要的教案吧!下面是小编帮大家整理的食品卫生安全教育教案,欢迎阅读与收藏。 食品卫生安全教育教案 1 教学目的 1、通过活动,让学生了解当前的食品安全现状; https://m.ruiwen.com/anquanjiaoan/5402022.html
17.UL认证6.测试结束后会怎样?一旦产品测试结束,你的项目工程师会通知你产品是否符合UL的要求。对于符合UL要求的产品,项目工程师会根据测试数据编写一本正式的报告。测试数据也将用于跟踪服务并作为跟踪服务细则的基础部分。跟踪服务细则是一本详细描述了经UL测试符合UL要求产品的结构的文件。UL的现场代表将用此文件作为指导来实https://www.360doc.cn/article/2297179_112095427.html
18.图书推荐:《动物医院工作流程手册》中国宠物医师网《动物医院工作流程手册》分步骤地详细介绍了怎样准备和实施必要的工作,并且在书后附有总结简表以助于读者快速查找他们所需要的内容。中国宠物医师网R `OF-A|Z9s0? (q mTJ$Rd#}0 ·内容全面,从专业性指导和办公室工作到实验室操作技术和动物护理都有介绍。*@ bw9sJ7Q UF3j+q0 中国宠物http://www.petdr.cn/news/html/05/n-1205.html
19.死侍3:X已标记2024pdfepubmobi电子书图书标签: 漫画 美漫 Marvel 漫威 死侍 美国 想读,一定很精彩! 我想读这本书 死侍3:X已标记 2024 pdf epub mobi 电子书 图书描述 死侍想加入X战警,他不会让任何人阻挠他——即使是X战警也不行! 死侍和靶眼达成协议,他隐姓埋名在海上漂泊。然而,做一个蹩脚的海盗并没能填补死侍的空虚,他陷入了深切的自我https://onlinetoolsland.com/books/27147366
20.学校教师管理工作总结(精选13篇)认真编写教案,并不断归纳总结经验教训。注重课堂教学效果,针对学生特点,以愉快式教学为主,坚持以学生为主体,教师为主导、教学实效为主线,注重讲练结合。在教学中注意抓住重点,突破难点。在作业批改上,认真及时,力求做到全批全改,重在订正,及时了解学生的学习情况,以便在辅导中做到有的放矢。在教学过程中尊重孩子的https://mip.oh100.com/a/202211/5687089.html
21.中班社会活动《垃圾分类》教案(通用17篇)电脑课件、不同色的塑料桶或唐瓷桶四个(红、绿、蓝、白)、分类标签(金属、玻璃、塑料,有机物)、一袋准备扔掉的垃圾(纸盒、玻璃瓶、塑料袋、果皮果壳、易拉罐等物)。图书、照片等。 三、活动过程: 1、出示垃圾筒,引导幼儿讨论: 这是什么?什么是垃圾?垃圾有没有用?如果我们的周围都是垃圾,生活会变得怎么样?https://www.jy135.com/jiaoan/1014962.html
22.北塔小学校园图书馆智能流转管理物品采购竞争性谈判公告具备借书、还书、查询/续借功能,可同时识别多本贴有RFID标签的图书。人机交互界面简单易懂,硬件设备安全可靠。 1台 2 RFID标签转换装置(馆员工作站不含PC机) 馆员工作站所包含的模块有条形码扫描枪,RFID读写器,IC卡读写器,标签转换系统。 1.可对一个RFID标签非接触式地进行阅读,有读取RFID图书标签、编写https://www.bidcenter.com.cn/newscontent-146057323-1.html
23.广州道宽智能科技有限公司该设备还应根据需要能够通过扫描图书条码对RFID标签进行编写,进行简单的加工工作。同时可以数据加工,图书借还等功能。 智能图书借还柜 智能图书借还柜是一个全新的图书管理服务模式,利用了RFID技术的便利,能灵活部署在社区、校园、超市、机场、车站等各种公共场所,可实现传统图书馆提供读者的文献借阅/归还,办理图书馆证http://www.gzdkzn.com/