1 adr 指令:
ADR R4, SSA2 + 0x20 ;把语句标号SSA2的地址加上0x20赋值给R4
LDR R5,=SSA2+0x20 ;把“SSA2 + 0x20"处的地址赋值给R5.
LDR R9,#800 ;把内存表首地址定义在0x800;即把0x800赋值给R9.
LDR R5,=0x55555555 ;把地址0x55555555赋值给R5.
2 函数如果需要在其他文件中调用, 需要用到.global伪操作将函数声明为全局函数。
.global .global symbol 将symbol定义为全局标号
3
.word expression …
.4byte expression …
在对象文件中插入字(32位),内容为expression的值。可以同时插入多个,以","分隔。这个两个命令是一样的。 下面的例子在对象文件中插入8个字节内容。
.word 0xDEADBEEF ; 插入字节: 0xEF 0xBE 0xAD 0xDE
.4byte -42 ; 插入字节 0xD6 0xFF 0xFF 0xFF
.byte 0x55 ; 插入1个字节 0x55
.align ; 顺次插入3个字节: 0x00 0x00 0x00
.word 0xAA55EE11 ; 插入内容 0x11 0xEE 0x55 0xAA (小端模式)
举例:
.globl _bss_start //定义一个全局标号
_bss_start:
.word __bss_start //这句话说明_bss_start,其实就是__bss_start。 其中__bss_start实在lds文件里面定义了具体的地址,而_bss_start则是在start.S里面使用的,_bss_start作为一个全局变量,里面所放的数据就是__bss_start的地址。
4 .type:用来指定一个符号的类型是函数类型或者是对象类型, 对象类型一般是数据, 格式如下:
.type 符号, 类型描述
5 B和BL指令
B或BL指令引起处理器转移到“子程序名”处开始执行。两者的不同之处在于BL指令在转移到子程序执行之前,将其下一条指令的地址拷贝到R14(LR,链 接寄存器)。由于BL指令保存了下条指令的地址,因此使用指令“MOV PC ,LR”即可实现子程序的返回。而B指令则无法实现子程序的返回,只能实现单纯的跳转。用户在编程的时候,可根据具体应用选用合适的子程序调用语句。
6 mov 和movt
mov sp,#0; 把0赋值给sp
movt sp,#800;把800赋值给sp的高16位。
from:http://hi.baidu.com/shawpinlee/blog/item/1a4db1f297732511b07ec517.html from:http://www.gnu.org/software/binutils/manual/gas-2.9.1/html_chapter/as_toc.html 《Using as--the GNU Assembler》 GNU AS This manual is intended to describe what you need to know to use gnu as. We cover the syntax expected in source files, including notation for symbols, constants, and expressions;the directives that as understands; and of course how to invoke as. This manual also describes some of the machine-dependent features of various flavors of the assembler. On the other hand, this manual is not intended as an introduction to programming in assembly language—let alone programming in general! In a similar vein, we make no attempt to introduce the machine architecture; we do not describe the instruction set, standard mnemonics, registers or addressing modes that are standard to a particular architecture. You may want to consult the manufacturer’s machine architecture manual for this information. 二 Command-Line Options This chapter describes command-line options available in all versions of the GNU assembler; see section Machine Dependent Features , for options specific to particular machine architectures.
三 语法 1 预处理 Preprocessing The as internal preprocessor: ·adjusts and removes extra whitespace. It leaves one space or tab before the keywords on a line, and turns any other whitespace on the line into a single space. • removes all comments, replacing them with a single space, or an appropriate number of newlines. • converts character constants into the appropriate numeric values. 意思如下:as的内部预处理主要包括三个方面的工作。一是调整和去除额外的间隔符。保留每行的关键字前的一个空格或者TAB,其他任意的间隔符都转换为一个空格。二是去除所有注释,代之以一个空格,或者新行的合适的数字。三是把字符常量转换成相应的数字值。 它不能做宏处理和文件包含处理,如果你需要用,那么可以交给C 预处理器来处理。交给CPP处理的文件包含格式是不同的,需要用#include,跟C的一样(AS中用.include)。那么CPP如何识别这样的文 件呢?答案是通过后缀。man gcc可以获得, file.s Assembler code. file.S Assembler code which must be preprocessed. 这也就是在vivi的[arch/s3c2410/head.S]中扩展名为什么是大写字母S,而不是小写字母s的原因了。vivi的配置机制的结果引用就是通过#include "config.h"来完成的,对它的处理则是通过CPP完成的预处理。 2 间隔符 Whitespace 可用空格或TAB,一个多个均可,无顺序。间隔符的作用是间隔符号,增强汇编程序的可读性。如果不是字符常量,间隔符等效于一个单一的空格,原因可见预处理部分。 3 注释 Comments 有两种方式(注释经过预处理后都等效于一个空格):行注释和段注释。 段注释和C语言的相同,都是/*...*/。而行注释就因TARGET不同而不同了。现在目标S3C2410的核是ARM,行注释采用“;”或者“@”。这就是vivi中为什么那么多“@”的原因了,当然这里可以使用“;”。如果是在X86机上,则使用“#”。 4 符号 Symbols A symbol is one or more characters chosen from the set of all letters (both upper and lower case), digits and the three characters ‘_.$’. 符号由字母、数字、(_ . $)这三种组合而成的一个或者多个字符组成。注意不要以数字开头,没有长度限制,所有字母都是有意义的,也就是说大小写敏感。符号以不在字符集内的字符分割,或者是以文件开头分割。 5 语句 Statements 支持空行,其他和X86下的汇编类似,以newline(“\n”)结束。 6 常量 Constants 包含字符常量、字符串、数字常量等。 关于数字常量,以“0X”或“0x”开头表示16进制,以“0B”或“0b”开头表示二进制,以“0”开头表示八进制,以非零开头表示十进制。十进制和八进制容易出错了。还是直接使用16进制好。如果使用十进制,注意开头不能为0. 四 段和重定向 根据本文档的英文资料,粗略的理解,所谓”段“,从物理上来看,就是一段没有间隔的地址空间,在里面存放着数据,这些数据具有相同的属性,也就是段的属性,比如说RO等。所以段就是具有相同属性的数据的集合。 对于多文件工程,汇编器as将汇编程序转换成目标文件,而这些目标文件都是假定从0开始的。链接器ld把这些目标文件结合库或者启动文件整合在一起,形成 可执行文件。那么ld就需要分配最终的地址,以使得不同部分的程序不会重叠。这样虽然非常简单,但也说明了链接器的作用。同时也说明了段的含义。 链接器ld以section为单位,分派实际运行的地址,这个过程就是重定向。as所产生的目标文件至少有三个段:text、data、bss。当然,还 可以包含自定义的段,用.section定义。这些在ld是就需要根据ld scripts传递给ld,要不然,ld无法知道如何分派实际运行的地址。实际上,有些动态加载库的程序在加载执行时才会完成最终的重定向分配。这个过程 是比较复杂的,应该读一下John R. Levine的《Linkers and Loaders》,把链接和加载的过程搞清楚,同时也需要分析重定向之后的可执行文件的格式。 ld只处理四类段: (1)named sections、text section、data section(2)bss section(3)absolute section (4)undefined section 五 符号 1 labels 标签后面跟“:”,注意标签和“:”之间不要有空格。 2 赋值 可以使用“.equ .set =”。比如设置NUM为0x1000,方法如下: .equ NUM, 0x1000 NUM = 0x1000 .set NUM, 0x1000 3 符号名 关于命名规则,前面提到了。但是这里有些特殊的地方。 (1)局部符号名 Local Symbol names 局部的符号方便程序员使用临时符号。采用一种简单的定义方式“N:”,即数字加冒号。注意这里的N必须是正整数。另外提供了两种表示方式Nf和Nb。其中 Nf中的f代表forward(向前),也就是说后面遇到的第一个符号N,Nb中的b代表backward(向后),也就是说前面遇到的最近的符号N。比 较形象化,别弄混了。 Here is an example: 1: branch 1f 2: branch 1b 1: branch 2f 2: branch 1b Which is the equivalent of: label_1: branch label_3 label_2: branch label_1 label_3: branch label_4 label_4: branch label_3 这些局部变量的符号在汇编器使用之前就已经被转化为更为方便的名字,其处理机制就是维护一个符号表。符号表的组成格式如下: | L | number | C-B | ordinal number | L:固定,表示Local。除非使用-L选项,否则不会输出局部符号表。 number: 就是你定义的N。 C-B: 不常用的量,避免重复。 ordial number:用来区分,如果你定义同样的N:,就要靠这个来区分符号名了。 比如说,上面的例子中,label_1实际上为L1C-B1, label_2为L2C-B1,label_3为L1C-B2,label_2为L2C-B2。 (2)Dollar Local Labels 以N$的形式定义,Local symbol label最多在一个文件中有效,dollar local label可以在某些文件中有效,除非定义了一个同名的全局变量。 (3)Dot “.”可以表示当前地址。该符号可以被引用或者赋值。 六 表达式 - 取相反数,减 + 加法运算 / 除 == 等于 % 取余运算 不等于 左移 小于 >, >> 右移 > 大于 | 按位或 >= 大于等于 & 按位与 小于等于 ^ 按位异或 && 逻辑与 ! 按位或非 | | 逻辑或 ~ 按位取反 1. Highest Precedence * Multiplication. / Division. Truncation is the same as the C operator ‘/’ % Remainder. >> Shift Right. Same as the C operator ‘>>’. 2. Intermediate precedence | Bitwise Inclusive Or. & Bitwise And. ^ Bitwise Exclusive Or. ! Bitwise Or Not. 3. Low Precedence + Addition. If either argument is absolute, the result has the section of the other argument. You may not add together arguments from different sections. - Subtraction. If the right argument is absolute, the result has the section of the left argument. If both arguments are in the same section, the result is absolute. You may not subtract arguments from different sections. == Is Equal To Is Not Equal To Is Greater Than >= Is Greater Than Or Equal To The comparison operators can be used as infix operators. A true results has a value of -1 whereas a false result has a value of 0. Note, these operators perform signed comparisons. 4. Lowest Precedence && Logical And. || Logical Or. These two logical operations can be used to combine the results of sub expressions. Note, unlike the comparison operators a true result returns a value of 1 but a false results does still return 0. Also note that the logical or operator has a slightly lower precedence than logical and. 七 汇编命令 Assembler Directives .align 插入0-3个0x0,以便实现四字节边界对齐 .ascii "string" 定义字符串,后面不带NUL .asciz "string" 定义字符串,后面带0 .byte 定义一个字节 .word 定义一个字 .hword 定义半字 .long 等同于.int 定义整形整数 .global 定义全局变量 .section name 定义段 .end 表示汇编程序的结束 //实现条件编译 .ifdef ... .elseif ... .endif //实现定义宏 .macro macro_name param_name1, param_name2, ... ... .endm 八 机器相关特性 现在只选择ARM相关的选项。 1、立即数前可以用“#”,也可以用“$”,不过习惯上用“#”。 2、ARM Machine Directives .align expression [, expression] 这个对于ARM来说,如果第一个参数为0,则汇编器默认当作2来处理,即2字节边界对齐。其余为4字节对齐。这主要是ARM自己的汇编器的兼容性而设定的。 name .req register name 为寄存器创建一个别名,如foo .req r0 .code [16|32] 选择指令集,.code 16即thumb指令集,.code 32为arm指令集。 .thumb 等同于.code 16 .arm 等同于.code 32 .force_thumb 强制转化为thumb指令集,即使处理器不支持 .ltorg 创建一个文字池,4字节边界对齐,堆放于当前段。 .pool 等同于.ltorg 3 ARM pseudo opcodes |