1、间隔符。可用空格或Tab,一个多个均可,无顺序。
2、注释。段注释和C语言的相同,都是/*...*/。而行注释就因TARGET不同而不同了。X86机上,使用“#”。ARM行注释采用“;”或者“@”。
3、符号。符号由字母、数字、(_ . $)这三种组合而成的一个或者多个字符组成。注意不要以数字开头,没有长度限制,大小写敏感。符号以不在字符集内的字符分割,或者是以文件开头分割。
4、语句。支持空行,其他和X86下的汇编类似,以newline(“\n”)结束。
5、常量。包含字符常量、字符串、数字常量等。关于数字常量,以“0X”或“0x”开头表示16进制,以“0B”或“0b”开头表示二进制,以“0”开头表示八进制,以非零开头表示十进制。十进制和八进制容易出错了。还是直接使用16进制好。如果使用十进制,注意开头不能为0。
.abort
该指令的作用是立即停止汇编。这么做是为了与其他汇编器兼容。最初的想法是汇编语言源程序将被传送到汇编器。如果源程序的发送者退出,它可以使用此指令告诉as也退出。有一天.abort将不受支持。
.ABORT(COFF)
当生成COFF输出时,as接受此指令作为.abort的同义词。
.align abs-expr, abs-expr, abs-expr
将位置计数器(在当前子段中)填充到特定存储边界。第一个表达式(必须是绝对的)是所需的对齐,如下所述。
第二个表达式(也是绝对的)给出填充值存储在填充字节中。它(和逗号)可以省略。如果省略,则填充字节通常为零。但是,在大多数系统上,如果该部分被标记为包含代码并且省略了填充值,则该空间将填充无操作指令。
第三个表达式也是绝对的,也是可选的。如果存在,则是此对齐指令应跳过的最大字节数。如果进行对齐将需要跳过比指定的最大值更多的字节,则根本不会进行对齐。您可以完全省略填充值(第二个参数),只需在所需的对齐后使用两个逗号;如果您希望在适当的时候使用无操作指令填充对齐,这可能很有用。
指定所需对齐的方式因系统而异。对于arc,hppa,使用ELF的i386,iq2000,m68k,or1k,s390,sparc,tic4x,tic80和xtensa,第一个表达式是以字节为单位的对齐请求。例如 '.align 8'使位置计数器前进,直到它是8的倍数。如果位置计数器已经是8的倍数,则不需要进行任何更改。对于tic54x,第一个表达式是word中的对齐请求。
对于其他系统,包括ppc,使用a.out格式的i386,arm和strongarm,它是位置计数器在前进后必须具有的低位零位数。例如 '.align 3'使位置计数器前进,直到它为8的倍数。如果位置计数器已经是8的倍数,则不需要进行任何更改。
这种不一致是由于各种本地汇编程序对GAS必须模拟的这些系统的不同行为。GAS也提供了.balign和.p2align指令,后面描述,其中有在所有体系结构一致的行为(但具体到GAS)。
.ascii "string"
.ascii期望用逗号分隔的零个或多个字符串文字(请参阅字符串)。它将每个字符串(没有自动尾随零字节)组合成连续的地址。
.asciz "string"
.asciz就像.ascii,但每个字符串后跟一个零字节。其中的'z'代表“零”。
.balign[wl] abs-expr, abs-expr, abs-expr
将位置计数器(在当前子部分中)填充到特定存储边界。第一个表达式(必须是绝对的)是以字节为单位的对齐请求。例如 '.balign 8'使位置计数器前进,直到它是8的倍数。如果位置计数器已经是8的倍数,则不需要进行任何更改。
第二个表达式(也是绝对的)给出填充值存储在填充字节中。它(和逗号)可以省略。如果省略,则填充字节通常为零。但是,在大多数系统上,如果该部分被标记为包含代码并且省略了填充值,则该空间将填充无操作指令。
第三个表达式也是绝对的,也是可选的。如果存在,则是此对齐指令应跳过的最大字节数。如果进行对齐将需要跳过比指定的最大值更多的字节,则根本不进行对齐。您可以完全省略填充值(第二个参数),只需在所需的对齐后使用两个逗号; 如果您希望在适当的时候使用无操作指令填充对齐,这可能很有用。
在.balignw和.balignl指令是变体的 .balign指令。该.balignw指令将填充模式视为双字节字值。该.balignl指令把填充图案为四个字节长字值。例如,.balignw 4, 0x368d将对齐到4的倍数。如果它跳过两个字节,它们将填入值0x368d(字节的确切位置取决于处理器的字节顺序)。如果它跳过1或3个字节,则填充值未定义。
.bundle_align_mode abs-expr
.bundle_align_mode启用或禁用对齐的指令包模式。
.bundle_lock和.bundle_unlock
在.bundle_lock和指令.bundle_unlock指令允许在指令束填充明确的控制。这些指令仅.bundle_align_mode在用于启用对齐指令包模式时有效。如果它们在.bundle_align_mode完全没有被使用时出现,或者在最后一个指令是.bundle_align_mode 0时出现,则会出错。
.byte expressions
.byte期望零或多个表达式,以逗号分隔。每个表达式都汇编到下一个字节中。
CFI 指令
7.10.1 .cfi_sections section_list
.cfi_sections可用于指定CFI指令是否应发出.eh_frame部分和/或.debug_frame部分。如果section_list是.eh_frame,.eh_frame被发射,如果section_list是.debug_frame,.debug_frame被发射。要发射两者,同时使用.eh_frame,.debug_frame。如果不使用此指令,则默认为.cfi_sections .eh_frame。
在支持紧凑展开表的目标上,可以通过指定.eh_frame_entry而不是生成这些表来生成.eh_frame。
某些目标可能支持其他名称,例如.c6xabi.exidx目标使用的名称。
如果CFI生成尚未启动,则可以使用相同或不同的参数重复.cfi_sections指令。但是,一旦CFI生成开始,分区列表是固定的,任何重新定义它的尝试都会导致错误。
7.10.2 .cfi_startproc [simple]
.cfi_startproc在每个函数的开头使用,在.eh_frame中应该有一个条目。它初始化一些内部数据结构。别忘了关闭这个功能.cfi_endproc。
除非.cfi_startproc与参数simple一起使用, 它还会发出一些与体系结构相关的初始CFI指令。
7.10.3 .cfi_endproc
.cfi_endproc在函数的末尾使用,它关闭以前由.cfi_startproc打开的展开项,并将其发送到.eh_frame。
7.10.4 .cfi_personality encoding [, exp]
. cfi_personality 定义了个性规律及其编码。编码必须是一个常量,以确定如何编码个性。如果是255(DW_EH_PE_omit),则不存在第二个参数,否则第二个参数应为常量或符号名称。在使用间接编码时,所提供的符号应该是可以从其加载个性的位置,而不是个性常规本身。默认值为.cfi_startproc是cfi_personality 0xff, 没有个性习惯。
7.10.5 .cfi_personality_id id
cfi_personality_id定义了一个个性例程,其索引定义为紧凑的展开格式。仅在生成紧凑EH帧时有效(即.cfi_sections eh_frame_entry)。
7.10.6 .cfi_fde_data [opcode1 [, …]]
cfi_fde_data用于描述用于当前函数的紧凑展开操作码。如果足够小且没有LSDA,或者在.gnu.extab节中,则会在.eh_frame_entry节中内联发出这些内容。仅在生成紧凑EH帧时有效(即.cfi_sections eh_frame_entry)。
7.10.7 .cfi_lsda encoding [, exp]
.cfi_lsda定义LSDA及其编码。编码必须是确定如何编码LSDA的常量。如果是255(DW_EH_PE_omit),则不存在第二个参数,否则第二个参数应为常量或符号名称。默认值为.cfi_startproc紧跟cfi_lsda 0xff,即不存在LSDA。
7.10.8 .cfi_inline_lsda [align]
.cfi_inline_lsda标记LSDA数据节的开始,并切换到相应的.gnu.extab节。前面必须有一个包含.cfi_lsda指令的CFI块。仅在生成紧凑EH帧时有效(即.cfi_sections eh_frame_entry)。
此时将生成表头和展开操作码,以便紧接着LSDA数据。.cfi_lsda指令引用的符号仍应在使用基于回退FDE的编码时定义。LSDA数据由节指令终止。
可选对齐参数指定所需的对齐方式。对齐方式指定为2的幂,与.p2align指令相同。
7.10.9 .cfi_def_cfa register, offset
.cfi_def_cfa定义了一个计算CFA的规则:从寄存器中取地址并添加偏移量。
7.10.10 .cfi_def_cfa_register register
.cfi_def_cfa_register修改计算CFA的规则。从现在起注册将使用而不是旧的。偏移量保持不变。
7.10.11 .cfi_def_cfa_offset offset
.cfi_def_cfa_offset修改计算CFA的规则。寄存器保持不变,但偏移量是新的。注意,它是将被添加到定义的寄存器中以计算CFA地址的绝对偏移量。
7.10.12 .cfi_adjust_cfa_offset offset
与.cfi_def_cfa_offset相同, 但偏移量是从上一个偏移量中加/减的相对值。
7.10.13 .cfi_offset register, offset
寄存器的先前值保存在从CFA的偏移量偏移处。
7.10.14 .cfi_val_offset register, offset
寄存器的先前值是CFA+偏移量。
7.10.15 .cfi_rel_offset register, offset
寄存器的先前值保存在偏离当前CFA寄存器的偏移量处。这被转换为.cfi_offset使用来自CFA的CFA寄存器的已知位移。这通常更容易使用,因为该数字将与它注释的代码相匹配。
7.10.16 .cfi_register register1, register2
寄存器1的先前值保存在寄存器寄存器2中。
7.10.17 .cfi_restore register
.cfi_restore在执行所有由.cfi_startproc添加的初始指令之后,寄存器的规则现在与函数开头的规则相同。
7.10.18 .cfi_undefined register
从现在开始,寄存器的先前值无法再恢复。
7.10.19 .cfi_same_value register
寄存器的当前值与前一帧中的相同,即不需要恢复。
7.10.20 .cfi_remember_state和.cfi_restore_state
.cfi_remember_state将每个寄存器的规则集推送到隐式堆栈,同时将.cfi_restore_state它们从堆栈中弹出并将它们放在当前行中。这对于.cfi_*由于程序的控制流而需要撤消多个指令的情况很有用。例如,我们可以有类似的东西(假设CFA是rbp的值):
je label
popq %rbx
.cfi_restore %rbx
popq %r12
.cfi_restore %r12
popq %rbp
.cfi_restore %rbp
.cfi_def_cfa %rsp,8
ret
label:
/* Do something else */
在这里,我们希望.cfi指令只影响与标签之前的指令对应的行。这意味着,我们必须在标签之后添加多个.cfi指令,以重新创建寄存器的原始保存位置,并将CFA重新设置为"限制性"的值。这将是笨拙的, 并导致更大的二进制大小。相反, 我们可以这样写:
je label
popq %rbx
.cfi_remember_state
.cfi_restore %rbx
popq %r12
.cfi_restore %r12
popq %rbp
.cfi_restore %rbp
.cfi_def_cfa %rsp,8
ret
label:
.cfi_restore_state
/* Do something else */
这样,后面的指令规则label将与第一个之前的规则相同,.cfi_restore而不必使用多个.cfi指令。
7.10.21 .cfi_return_column register
更改返回列寄存器,即返回地址直接在寄存器中,或者可以通过寄存器规则访问。
7.10.22 .cfi_signal_frame
将当前功能标记为信号蹦床。
7.10.23 .cfi_window_save
SPARC注册窗口已保存。
7.10.24 .cfi_escape expression [,...]
允许用户向展开信息添加任意字节。可以使用它来添加特定于操作系统的CFI操作码,或者GAS尚不支持的通用CFI操作码。
7.10.25 .cfi_val_encoded_addr register, encoding, label
寄存器的当前值是label。label的值将根据编码在输出文件中编码;有关此编码的详细信息,参见.cfi_personality说明。
将寄存器等同于固定标签的用处可能仅限于返回地址寄存器。在这里,标记一个只有一个返回地址的代码段是有用的,该代码段由直接分支到达,并且内存或另一个寄存器中不存在返回地址的副本。
.comm symbol, length
.comm声明一个名为symbol的通用符号。链接时,一个目标文件中的公共符号可以与另一个目标文件中的相同名称的已定义或公共符号合并。
.data subsection
.data告诉as将以下语句汇编到数据小节编号子节的末尾(这是一个绝对表达式)。如果省略subsection,则默认为零。
.dc[size] expressions
.dc指令期望用逗号分隔零个或多个表达式。评估这些表达式并将其值插入当前节。发出值的大小取决于.dc指令的后缀 :
'.a'
发出N位值,其中N是目标系统上地址的大小。
'.b'
发出8位值。
'.d'
发出双精度浮点值。
'.l'
发出32位值。
'.s'
发出单精度浮点值。
'.w'
发出16位值。注意 - 即使在.word指令将发出32位值的目标上也是如此。
'.x'
发出长双精度浮点值。
如果没有使用后缀,则假设是'.w' 。
字节排序与目标有关,浮点值的大小和格式也是如此。
.dcb[size] number [,fill]
该指令发出fill的number个副本,每个size字节。number和fill都是绝对表达式。如果省略逗号和填充,则假定填充为零。如果省略了逗号和fill,则假定fill为零。size后缀(如果存在) 必须是下列值之一:
'.b'
发出单字节值。