3.2.2 as汇编语法
为了维持与gcc输出汇编程序的兼容性,as汇编器使用AT&T系统V的汇编语法(下面简称为AT&T语法)。这种语法与Intel汇编程序使用的语法(简称Intel语法)很不一样,它们之间的主要区别有以下几点:
AT&T语法中立即操作数前面要加一个字符"$";寄存器操作数名前要加字符百分号"%";绝对跳转/调用(相对于与程序计数器有关的跳转/调用)操作数前面要加星号"*"。而Intel汇编语法没有这些限制。
AT&T语法与Intel语法使用的源和目的操作数次序正好相反。AT&T的源和目的操作数是从左到右"源, 目的"。例如Intel的语句add eax, 4对应AT&T的addl $4, %eax。
AT&T语法中内存操作数的长度(宽度)由操作码最后一个字符来确定。操作码后缀b、w和l分别指示内存引用宽度为8位字节(byte)、16位字(word)和32位长字(long)。Intel语法则通过在内存操作数前使用前缀byte prt、word ptr和dword ptr来达到同样目的。因此,Intel的语句mov al, byte ptr foo对应于AT&T的语句movb $foo, %al。
AT&T语法中立即形式的远跳转和远调用为ljmp/lcall $section, $offset,而Intel的是jmp/call far section:offset。同样,AT&T语法中远返回指令lret $stack-adjust对应Intel的ret far stack-adjust。
AT&T汇编器不提供对多代码段程序的支持,UNIX类操作系统要求所有代码在一个段中。
1.汇编程序预处理
as汇编器具有对汇编语言程序内置的简单预处理功能。该预处理功能会调整并删除多余的空格字符和制表符;删除所有注释语句并且使用单个空格或一些换行符替换它们;把字符常数转换成对应的数值。但是该预处理功能不会对宏定义进行处理,也没有处理包含文件的功能。如果需要这方面的功能,那么可以让汇编语言程序使用大写的后缀".S",让as使用gcc的CPP预处理功能。
由于as汇编语言程序除了使用C语言注释语句(即"/*…*/")以外,还使用"#"号作为单行注释开始字符,因此若在汇编之前不对程序执行预处理,那么程序中包含的所有以"#"号开始的指示符或命令均会被当做注释。
2.符号、语句和常数
符号(Symbol)是由字符组成的标识符,组成符号的有效字符取自大小写字符集、数字和3字符"-"、"."、"$"。符号不允许用数字字符开始,并且大小写含义不同。在as汇编程序中符号长度没有限制,并且符号中所有字符都是有效的。符号使用其他字符(如空格、换行符)或者文件的开始来界定开始和结束处。
语句(Statement)以换行符或者行分割字符";"作为结束。文件最后语句必须以换行符作为结束。
若在一行的最后使用反斜杠字符"\"(在换行符前),那么就可以让一条语句使用多行。当as读取到反斜杠加换行符时,就会忽略这两个字符。
语句由零个或多个标号(Label)开始,后面可以跟随一个确定语句类型的关键符号。标号由符号后面跟随一个冒号(":")构成。关键符号确定了语句余下部分的语义。如果该关键符号以一个"."开始,那么当前语句就是一个汇编命令(或称为伪指令、指示符)。如果关键符号以一个字母开始,那么当前语句就是一条汇编语言指令语句。因此一条语句的通用格式为:
标号: 汇编命令 注释部分(可选) 或 标号: 指令助记符 操作数1, 操作数2 注释部分(可选) |
常数是一个数字,可分为字符常数和数字常数两类。字符常数还可分为字符串和单个字符;而数字常数可分为整数、大数和浮点数。
字符串必须用双引号括住,并且其中可以使用反斜杠"\"来转义包含特殊字符。例如"\\"表示一个反斜杠字符。其中第1个反斜杠是转义指示字符,说明把第2个字符看做一个普通反斜杠字符。常用转义符序列见表3-1。反斜杠后若是其他字符,那么该反斜杠将不起作用并且as汇编器将会发出警告信息。
汇编程序中使用单个字符常数时可以写成在该字符前加一个单引号,例如"A"表示值65、"C"表示值67。表3-1中的转义码也同样可以用于单个字符常数。例如,"\\"表示一个普通反斜杠字符常数。
表3-1 as汇编器支持的转义字符序列
|
转义码< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
说明 |
|
\b |
退格符(Backspace),值为0x08 |
|
\f |
换页符(FormFeed),值为0x0C |
|
\n |
换行符(Newline),值为0x0A |
|
\r |
回车符(Carriage-Return),值为0x0D |
|
\NNN |
3个八进制数表示的字符代码 |
|
\xNN... |
16进制数表示的字符代码 |
|
\\ |
表示一个反斜杠字符 |
|
\" |
表示字符串中的一个双引号'"' |
整数数字常数有4种表示方法,即使用0b或0B开始的二进制数(0~1)、以0开始的八进制数(0~7)、以非0数字开始的十进制数(0~9)和使用0x或0X开头的十六进制数(0~9a~fA~F)。若要表示负数,只需在前面添加负号" "。
大数(Bignum)是位数超过32位二进制位的数,其表示方法与整数的相同。汇编程序中对浮点常数的表示方法与C语言中的基本一样。由于内核代码中几乎不用浮点数,因此这里不再对其进行说明。