as汇编命令

汇编命令是指示汇编器操作方式的伪指令。汇编命令用于要求汇编器为变量分配空间、确定程序开始地址、指定当前汇编的区、修改位置计数器值等。所有汇编命令的名称都以"."开始,其余是字符,并且大小写无关。但是通常都使用小写字符。下面我们给出一些常用汇编命令的说明。

1..align abs-expr1, abs-expr2, abs-expr3

.align是存储对齐汇编命令,用于在当前子区中把位置计数器值设置(增加)到下一个指定存储边界处。第1个绝对值表达式abs-expr1(Absolute Expression)指定要求的边界对齐值。对于使用a.out格式目标文件的80×86系统,该表达式值是位置计数器值增加后其二进制值最右面0值位的个数,即是2的幂值。例如,".align 3"表示把位置计数器值增加到8的倍数上。如果位置计数器值本身就是8的倍数,那么就无需改变。但是对于使用ELF格式的80×86系统,该表达式值直接就是要求对齐的字节数。例如".align 8"就是把位置计数器值增加到8的倍数上。

第2个表达式给出用于对齐而填充的字节值。该表达式与其前面的逗号可以省略。若省略,则填充字节值是0。第3个可选表达式abs-expr3用于指示对齐操作允许填充跳过的最大字节数。如果对齐操作要求跳过的字节数大于这个最大值,那么该对齐操作就被取消。若想省略第 2个参数,可以在第1和第3个参数之间使用两个逗号。

2..ascii "string"…

从位置计数器所指当前位置为字符串分配空间并存储字符串,可使用逗号分开写出多个字符串。例如,".ascii "Hello world!", "My assembler""。该汇编命令会让as把这些字符串汇编在连续的地址位置处,每个字符串后面不会自动添加0(NULL)字节。

3..asciz "string"…

该汇编命令与".ascii"类似,但是每个字符串后面会自动添加NULL字符。

4..byte expressions

该汇编命令定义0个或多个用逗号分开的字节值。每个表达式的值是1字节。

5..comm symbol, length

在bss区中声明一个命名的公共区域。在ld链接过程中,某个目标文件中的一个公共符号会与其他目标文件中同名的公共符号合并。如果ld没有找到一个符号的定义,而只是一个或多个公共符号,那么ld就会分配指定长度length字节的未初始化内存。length必须是一个绝对值表达式,如果ld找到多个长度不同但同名的公共符号,ld就会分配长度最大的空间。

6..data subsection

该汇编命令通知as把随后的语句汇编到编号为subsection的data子区中。如果省略编号,则默认使用编号0。编号必须是绝对值表达式。

7..desc symbol, abs-expr

用绝对表达式的值设置符号symbol的描述符字段n_desc的16位值。仅用于a.out格式的目标文件。参见有关include/a.out.h文件的说明。

8..fill repeat, size, value

该汇编命令会产生数个(repeat个)大小为size字节的重复拷贝。大小值size可以为0或某个值,但是若 size大于8,则限定为8。每个重复字节内容取自一个8字节数。高4字节为0,低4字节是数值value。这3个参数值都是绝对值,size和 value是可选的。如果第2个逗号和value省略,value默认为0值;如果后两个参数都省略,则size默认为1。

9..global symbol (或者.globl symbol)

该汇编命令会使得链接器ld能看见符号symbol。如果在我们的目标文件中定义了符号symbol,那么它的值将能被链接过程中的其他目标文件使用。若目标文件中没有定义该符号,那么它的属性将从链接过程中其他目标文件的同名符号中获得。这是通过设置符号 symbol类型字段中的外部位N_EXT来做到的。参见include/a.out.h文件中的说明。

10..int expressions

该汇编命令在某个区中设置0个或多个整数值(80386系统为4B,同.long)。每个用逗号分开的表达式的值就是运行时刻的值,如".int 1234, 567, 0x89AB"。

11..lcomm symbol, length

为符号symbol指定的局部公共区域保留长度为length字节的空间。所在的区和符号symbol的值是新的局部公共块的值。分配的地址在bss区中,因此在运行时刻这些字节值被清零。由于符号symbol没有被声明为全局的,因此链接器ld看不见。

12..long expressions

含义与.int相同。

13..octa bignums

这个汇编命令指定0个或多个用逗号分开的16B大数(.byte, .word, .long, .quad, .octa 分别对应1、2、4、8和16字节数)。

14..org new_lc, fill

这个汇编命令会把当前区的位置计数器设置为值new_lc。new_lc是一个绝对值(表达式),或者是具有相同区作为子区的表达式,即不能使用.org跨越各区。如果new_lc的区不对,那么.org就不会起作用。请注意,位置计数器是基于区的,即以每个区作为计数起点。

当位置计数器值增长时,所跳跃过的字节将被填入值fill。该值必须是绝对值。如果省略了逗号和fill,则fill默认为0值。

15..quad bignums

这个汇编命令指定0个或多个用逗号分开的8B大数bignum。如果大数放不进8B中,则取低8B。

16..short expressions (同.word expressions)

这个汇编命令指定某个区中0个或多个用逗号分开的2字节数。对于每个表达式,在运行时刻都会产生一个16位的值。

17..space size, fill

该汇编命令产生size个字节,每个字节填值fill。这个参数为绝对值。如果省略了逗号和fill,那么fill的默认值就是0。

18..string "string"

定义一个或多个用逗号分开的字符串。在字符串中可以使用转义字符。每个字符串都自动附加一个NULL字符结尾。例如,".string "/n/nStarting", "other strings""。

19..text subsection

通知as把随后的语句汇编进编号为subsection的子区中。如果省略了编号subsection,则使用默认编号值0。

20..word expressions

对于32位机器,该汇编命令含义与.short相同。

/**************************************************************
*    以上摘抄自《Linux内核完全剖析》,下面是自己的一些常见补遗    *
**************************************************************/

b0..def name
开始定义调试符号,遇到.endef伪指令就结束调式符号定义块。

b1..dim
由编译器生成的辅助调试信息,放在符号表中,此命令仅允许在.def .endef块中使用。

b2..double flounums
.double后面跟零个或者多个用逗号分割的双精度浮点数,在x86,x86_64上是64位长度的双精度浮点数。

b3..else
条件汇编命令之一,作为.if命令的否定分支块的开始。

b4..elseif
条件汇编命令之一,作为.if命令的有条件的否定分支块的开始。

b5..end
文件结尾标记,出现在此命令后的任何信息都会被汇编器忽略。

b6..endef
结束由.def命令定义的调式符号块。

b7..endfunc
函数定义结束标记。

b7.endif
条件汇编命令之一,结束由最近的.if .elseif开始条件编译块。

b8..equ symbol, expression
这个命令把symbol的值设置为expression,同.set命令相同。HPPA机上格式为 "symbol .equ expression" ;Z80机上格式为 "symbol equ expression",而且当symbol已经定义的时候会产生错误。

b9..equiv symbol, expression
类似.equ,但是在symbol已经定义的时候会产生一个错误。

b10. .equv symbol, expression
类似.equiv,但是不是对expression立即求值并赋给symbol,而是每次使用symbol的时候实时计算expression的值。

b11..err
当汇编器遇到这个命令的时候,会打印一个错误消息,而且除非汇编时使用 -Z参数,汇编器不会生成目标文件,可以用来在条件汇编/编译时发出错误消息。

b12..error "string"
类似于.err,但错误消息变成了后面的string字符串,如果没有指定string,使用默认错误提示".error directive invoked in source file"。

b13..exitm
提前从当前的宏定义退出。

b14..extern
此命令可以用在源程序中但会被忽略(为了和其他汇编器兼容)。as汇编器会把所有的未定义符号当作外部符号。

b15..fail expression
当expression大于等于500,打印一条警告消息;否则打印错误消息。消息中包含express的值,很奇怪的命令,大概在一些复杂的条件汇编中用到。

b16..file string
此命令通告as准备开启一个新文件,string是新文件名,可以使用双引号引起来,也可以不用。但是当规定一个空文件名是,一定要用""才行。此命令已过时,仅为了和老版本兼容,不要使用。
.file fileno filename
dwarf2调试信息使用的命令,fileno是文件名列表的如口,是一个正整数。filename是C风格字符串字面常量。

b17. .float flonums
.float等同于.single,后面跟零个或者多个用逗号分割的单精度浮点数,在x86,x86_64上是32位长度的单精度浮点数。

b18..func name[,label]
.func发出一个调试信息来指名函数 name,除非使用开启调试的方式汇编,这条命令将被忽略。目前仅支持 –gstabs[+]。label是函数入口点,如果省略name则使用预定的引导符。引导符视目标而定,可能是’_’也可能是空的。当前的as版本下,所有函数被定义为无返回值。函数体必须使用.endfunc来结束。

b19. .hidden names
这是一条关于elf文件中符号可见度的命令,用来取消符号names的缺省可见度,并设置其可见度为hiden,使得names对其他部分不见。其他可见度设置指令有.internal .protected。

b20..hword expressions
本命令后跟零个或多个expression,并生成同样数量的16位整数。其行为与.short和某些架构下的.word相同。

b21..if absolute expression
.if 标志着一段代码的开始,这段代码只有在参数absolute experession(必须是一个独立的表达式)不为0时才进行汇编。这段条件汇编代码必须使用.endif标志结束。另外,可以使用.else来标记一个代码块,这个代码块与前面那段代码只有一个会进行汇编。 如果您需要检查数个汇编条件,可以在使用.elseif命令,以避免在.else代码块中进行if/else语句块的嵌套。
同样可以使用下面.if的变体:
.ifdef symbol
如果指定的符号symbol已经定义过,汇编下面那段代码。
.ifc string1,string2
如果两个字符串相同的话,汇编下面那段代码。 字符串可以可选地使用单引号。如果不使用引号则第1个字符串在逗号处结束。第2个字符串在本行末结束。包含空白的字符串应该使用引号标注。字符串比较时是区分大小写的。

.ifeq absolute expression
如果参数的值为0,汇编下面那段代码。

.ifeqs string1,string2
这是.ifc的另一种形式,字符串必须使用双引号标注。

.ifge absolute expression
如果参数的值大于等于0,汇编下面那段代码。

.ifgt absolute expression
如果参数的值大于0,汇编下面那段代码。

.ifle absolute expression
如果参数的值小于等于0,汇编下面那段代码。

.iflt absolute expression
如果参数的值小于0,汇编下面那段代码。

.ifnc string1,string2.
类似与.ifc,不过使用反向的测试: 如果两个字符串不相等的话,汇编下面那段代码。
.ifndef symbol
.ifnotdef symbol
如果指定的符号symbol不曾被定义过,汇编下面那段代码。 上面两种写法是等效的。

.ifne absolute expression
如果参数的值为不等于0,汇编下面那段代码。 (换句话说, 这是.if的另一种写法).

.ifnes string1,string2
类似与.ifeqs,不过使用反向的测试: 如果两个字符串不相等的话,汇编下面那段代码。

b22. .include "file"
本命令提供在源程序中指定点引入支撑文件的手段。file中的代码如同紧跟.include后一样被汇编。当引入文件汇编结束,继续汇编原来的文件。您可以使用命令行选项参数“-I”来控制搜索路径。文件名必须使用引号来标注。

b23..internal names
这是一条与ELF可见度相关的命令,用来取消符号names的缺省可见度,并将其可见度设置为internal,使得对其他部分不可见。另外,符号还必须经过处理器的特别的处理。

b24..line line-number
更改逻辑行号,参数line-number必须是个纯粹的表达式。本命令后的下一行将被赋予此逻辑行号。因此在当前行之前任何其他的语句(在语句分隔符后)的逻辑行号将被视作line-number – 1。以后 as将不在支持这条命令:只是为了兼容现存的汇编器而接受本命令。
Warning: 在为AMD29K目标机器配置的as中,不能使用本指令。在这种场合可以使用.ln命令。
尽管这是与a. out或b. out目标代码格式相关的命令,在生成COFF输出时as仍然接受它,并且如果‘.line’出现在.def/endef之外的话,就把它视为‘.ln’命令。
如果‘.line’在.def语句块中的话,.line命令则是一条编译器使用的命令,用来为调式生成辅助符号信息。

b25..ln line-number
‘.ln’命令等同与‘.line’.

b26..list
控制(和.nolist命令配合)是否生成汇编清单。这两个命令维护一个内部的计数器(计数器初始值为0).list命令增加计数器的值,.nolist减少计数器的值。当计数器的值大与0时将汇编列表。
缺省状态汇编列表的生成是关闭的。当您打开它的时候(使用带-a选项的命令行), 内部计数器的初始值为1。

b27..macro
本命令.macro和.endm命令允许您定义宏来生成汇编输出。例如,下面的语句定义了一个宏sum,这个宏把一个数字序列放入内存。

.macro sum from=0, to=5
.long /from
.if /to-/from
sum "(/from+1)",/to
.endif
.endm
使用上述定义,’SUM 0,5’语句就等于输入下面的汇编语句:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5

.macro macname
.macro macname macargs …
开始定义一个名为macname的宏。如果您的宏需要使用参数,则在宏的名字后指定他们的名字,参数之间用逗号或空格分隔。您可以为任意的参数提供参数的缺省值,只需要在参数后使用“=deflt”,。例如,下列都是合法的宏定义语句:
.macro comm
定义一个名为comm宏,不使用参数。
.macro plus1 p, p1
.macro plus1 p p1
两个语句都声明要定义一个名为plus1的宏,这个宏需要两个参数,在宏定义体内,使用’/p’或’/p1’来引用参数的值。
.macro reserve_str p1=0 p2
声明要定义一个名为reserve_str的宏,使用两个参数。第一个参数有缺省值,第二个没有缺省值。宏定义完成后,您可以通过‘reserve_str a, b’(宏体中‘/p1’引用a的值,‘/p2’引用b值)或通过‘reserve_str ,b’(‘/p1’使用缺省值,在此为‘0’,‘/p2’引用b的值)来调用这个宏。

当调用一个宏时,您既可以通过位置指定参数值,也可以通过关键字指定参数值。例如,‘sum 9,17’和‘sum to=17, from=9’是等价的。
.endm 标志宏定义体的结束。
.exitm 提前从当前宏定义体中退出。
/@ 这个伪变量其实是as维护的一个计数器,用来统计执行了多少个宏。您可以通过使用/@把这个数字复制到您的输出中,但仅限于在宏定义体中使用。

b28..nolist
控制(和.list命令配合)是否生成汇编列表。这两个命令维护一个内部的计数器(计数器初始值为0).list命令增加计数器的值,.nolist减少计数器的值。当计数器的值大与0时将汇编列表。

b29..p2align[wl] abs-expr, abs-expr, abs-expr
增加位置计数器(在当前的子段)使它指向规定的存储边界。第一个表达式参数(结果必须是纯粹的数字) 代表位置计数器移动后,计数器中连续为0的低序位数量。例如‘.align 3’向后移动位置指针直至8的倍数(指针的最低的3位为0)。如果地址已经是8倍数,则无需移动。
第二个表达式参数(结果必须是纯粹的数字)给出填充字节的值。用这个值填充位置计数器越过的地方。这个参数(和逗点)可以省略。如果省略它,填充字节的值通常默认为0。但在某些系统上,如果本段标识为包含代码,而填充值被省略,则使用no-op指令填充填充区。
第3个参数表达式的结果也必须是纯粹的数字,这个参数是可选的。如果存在第3个参数,它代表本对齐命令允许越过字节数的最大值。如果完成这个对齐需要跳过的字节比指定的最大值还多,则根本无法完成对齐。您可以在边界基准后简单地使用两个逗号,以省略填充值参数(第二参数);如果您想在适当的时候,对齐操作自动使用no-op指令填充,这个方法将非常奏效。
.p2alignw和.p2alignl是.p2align命令的变化形式。.p2alignw 使用2个字节来填充填充区。.p2alignl使用4字节来填充。例如,. .p2alignw 2,0x368d将地址对齐到4的倍数,如果它跳过2个字节,GAS将使用0x368d填充这2个字节(字节的准确的位置视处理器的存储方式而定)。如果它跳过1或3个字节,填充值则不明确。

b30..previous
这是一个ELF段堆栈操作命令。
本命令交换当前段(及其子段)和最近访问过的段(及其子段)。多个连续的.previous命令将使当前位置两个段(及其子段)之间反复切换。
用段堆栈的术语来说,本命令使当前段和堆顶段交换位置。

b31..popsection
这是一个ELF段堆栈操作命令。
本命令用堆栈顶段(及其子段)替代当前段(及其子段)。堆栈顶段出栈。

b32..print string
as会在标准输出上打印string。string必须使用双引号。

b33..protected names
这是一条ELF可见度的相关命令,用来取消符号names的可见度缺省值,并设置为protected。这个可见度意味着:在定义此符号的部件内对此符号的任何访问,都必须解析到这个部件内的定义体。即使其他部件中存在一个正常情况下比此优先的定义体。

b34..psize lines , columns
当生成清单列表时,使用本命令声明每页的行数—还可以可选地声明列数。
如果您不使用本命令,清单列表的行数为默认的60行。可以省略逗号和列参数:默认值为200列。
当指定的行数过多的话,as会产生进纸操作。(如果您确实需要一个进纸动作,可以使用.eject命令)

b35..pushsection name , subsection
本命令是一个ELF段堆栈操作命令。
本命令与.section命令是等价的。它将当前段(及子段)推入段堆栈的顶部。并使用name和subsection来替代当前段和子段。

b36..rept count
汇编.rept和.endr之间的语句count次。
如, 汇编下列语句:
.rept 3
.long 0
.endr
与下列语句是等价的:
.long 0
.long 0
.long 0

b37.sbttl "subheading"
当生成汇编清单时,使用subheading作为标题(第3行,紧跟在标题行之后)。
本命令对清单的后续页起作用,如果它位于当前页的前10行内,则对当前页也起作用。

b38..scl class
设置一个符号的存储类型值(storage-class value)。本命令只能在.def/.endef之间使用。符号的存储类型可以表明符号是static类型或是external类型,或者进一步记录符号的调试信息。
‘.scl’命令主要与在COFF输出有关,当生成b.out输出格式时,as接受本命令,但忽略本命令。

b39..section name
(COFF 版本)
使用.section命令将后续的代码汇编进一个定名为name的段。
本命令只能在目标格式真正支持任意命名段时使用;例如,汇编一个a.out目标格式时,即使name是一个标准的a.out段名,本命令也不被接受。
当目标格式为COFF时,.section命令的使用为下面某一种格式:
.section name[, "flags"]
.section name[, subsegment]
如可选参数使用了引号,它将被视为该段的标志(flags)。每个标记是单个的字符。下列是认可的标志。
b bss 段 (未初始化的数据)
n 未装入内存的段
w 可写的段
d 数据段
r 只读段
x 代码段 (executable section)
s 共享段 (目标为PE格式有意义)
如果本命令没有指定标志,则依靠段名来确定标志缺省值。如果该段名没有使用标准段名,则默认该段已装入内存并且可写。注意在使用n和w标志组合时,不是增加这组属性,而是删除该段的属性。所以如果只存在这两个标志,就代表该段没有指定任何标志。
如果本命令的可选参数没有使用引号,参数将被视为子段的编号。(参见 4.4 [Sub-Sections], 25页)。

(ELF 版本)
本命令是ELF的段堆栈操作命令之一。
当目标格式为ELF时,.section命令应如下使用:
.section name [, "flags"[, @type]]
可选参数flags是被引号包围的字符串,可以由下列字符的任意组合:
a 可分配的段(allocatable)
w 可写段
x 代码段
可选的参数type可以包含下列的任一常量:
@progbits 包含数据的段
@nobits 不包含数据的段(只占用空间的段)
如果本命令没有指定标志,则依靠段名来确定标志缺省值。如果段名不是标准的段名,则默认的该段不包含上述标志:该段不可分配内存,不可写,不可执行。该段是包含数据的段。
当目标格式为ELF时,as还支持另一种形式的.section命令,以便兼容Solaris的汇编器:
.section "name"[, flags…]
注意段名是使用引号包围的,可能存在一系列由逗号分隔分隔的标志:
#alloc 可分配的段(section is allocatable)
#write 可写的段
#execinstr 可执行的段
本命令将(用段名为name的段)替代当前段和子段。被替换的段将被推入段堆栈。参见gas的测试套件目录gas/testsuite/gas/elf,可以找到一些本命令和其他段堆栈操作命令的例子。

b40..set symbol, expression
同.equ命令

b41..single flonums
同.float

b42.size
.size(COFF 版本)
本命令一般由编译器生成,以在符号表中加入辅助调试信息。本命令只能在.def/.endef命令对之间使用。
本命令只在生成COFF格式的输出文件有意义。当as生成b.out时,as接受本命令但忽略之。

.size name , expression(ELF 版本)
本命令经常用来设置符号name的内存大小。内存大小的单位是字节, 通过计算参数expression得到,参数expression中可以使用标签进行计算。本命令常用来设置函数符号的长度。

b43.skip size , fill
本命令生成size个字节,每个字节的值都是fill。参数size和fill都必须是纯粹的表达式。如果省略逗号和fill,则默认fill的值为0。这与’.space’相同。

b44..struct expression
切换到独立地址段,并用expression设定段的偏移量,expression必须是个纯粹的表达式。您可以如下使用:
.struct 0
field1:
.struct field1 + 4
field2:
.struct field2 + 4
field3:

定义符号field1的值为0,符号field2的值为4,符号field3的值为8。这段汇编程序将保存在独立地址段中,在进行下一步汇编前,您需要使用一个某种类型的.section命令,以切换到相应的段。

b45..subsection name
本命令是一个ELF段堆栈操作命令。
本命令用name子段替换当前子段。当前段并不改变。被替换的子段入段堆栈,成为段堆栈的新栈顶。

b46..tag structname
本命令由编译器生成,用来在符号表中增加调试辅助的信息。本命令只允许在.def/.endef语句对内使用。标饰(tags)常用来连接符号表中的结构定义和该结构实例。
‘.tag’只能在生成COFF格式的输出文件时使用。当as生成b.out格式的输出文件时,接受本命令但忽略之。

b47..title "heading"
当生成汇编清单时,把heading作为标题使用(标题在第2行,紧跟在源文件名和页号后)。
如果这个命令出现在某页的前10行中,它不但作用影响到后续的页,也同样影响到当前页。

b48..type int (COFF 版本)
本命令紧允许在.def/.endef 命令对之间使用,把整数int作为类型属性记录进符号表表项。
‘.type’只和COFF格式的输出有关,当as配置生成b.out输出格式时,as接受本命令但忽略之。

.type name , type description (ELF 版本)
本命令经常用来设置符号name的类型(属性)为函数符号或是目标符号两者之一。type description部分允许使用5种不同的语法,以兼容众多的汇编器。这些语法是:

.type <name>,#function
.type <name>,#object

.type <name>,@function
.type <name>,@object

.type <name>,%function
.type <name>,%object

.type <name>,"function"
.type <name>,"object"

.type <name> STT_FUNCTION
.type <name> STT_OBJECT

b49..val addr
本命令只能在.def/.endef命令对之间使用,把addr的地址作为值属性存入符号表的表项中。
‘.val’命令只能在COFF输出时使用;当as被配置成生成b.out输出时,接受本命令但忽略之。

b50..version "string"
本命令创建一个.note段,并把一个NT VERSION类型ELF格式的note放入该.note段。Note的名字被设置为string。

b51..weak names
本命令设置names中每个符号(由逗号分隔)的weak属性。如果这些符号尚不存在,则创建这些符号。

以上资料来自info as。翻译成中文版,但是不全。


相关博文

This entry was posted in 硬件与汇编 and tagged . Bookmark the permalink.

4 Responses to as汇编命令

  1. kshaoye says:

    一头雾水地路过[e08]

    • davelv says:

      回复 kshaoye:
      as汇编器用的伪指令的一个合集。
      从别人书上抄了一些,然后自己照着as的info文件翻译了一些。

  2. Fleurer says:

    支持D大!

kshaoye进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注