.global/.def/.ref Identify Global Symbols
Syntax .global symbol1[, ... , symboln]
.def symbol1[, ... , symboln]
.ref symbol1[, ... , symboln]
Description -----------Three directives identify global symbols that are defined externally or can be referenced externally:
引用文档来自:ARM Assembly Language Tools v17.6.0.STS User's Guide
这三个指令都可以定义一个全局的符号,可以被其他的程序使用,
The .def directive identifies a symbol that is defined in the current module and can be
accessed by other files. The assembler places this symbol in the symbol table.
.def在当前module定义,可以被其他文件访问,这个符号也会被存在symbol table里面
The .ref directive identifies a symbol that is used in the current module but is defined in another module. The linker resolves this symbol's definition at link time.
.ref指令说明这个符号在当前module中使用,但是在别的module中定义,链接器最终会在链接的时候找到其定义
The .global directive acts as a .ref or a .def, as needed.
A global symbol is defined in the same manner as any other symbol; that is, it appears
as a label or is defined by the .set, .equ, .bss, or .usect directive. If a global symbol is
defined more than once, the linker issues a multiple-definition error. (The assembler can
provide a similar multiple-definition error for local symbols.)
如果一个global symbol被多次定义,assembler会提醒一个多次定义的错误,.ref指令不管modules用不用
这个symbol,都会在符号表里创建一个entry,.global的话只会在用到这个symbol的时候才创建.
The .ref directive always creates a symbol table entry for a symbol, whether the module uses the symbol or not; .global, however, creates an entry only if the module actually uses the symbol.
.ref不管用不用到,符号表里都有一个符号的entry,global定义的则只会在使用到的时候才会创建一个entry
A symbol can be declared global for either of two reasons:
出于以下两种原因声明一个.global符号
• If the symbol is not defined in the current module (which includes macro, copy, and
include files), the .global or .ref directive tells the assembler that the symbol is defined in an external module. This prevents the assembler from issuing an unresolved reference error. At link time, the linker looks for the symbol's definition in other modules.
如果symbol没有定义在当前文件,(包括macro, copy, and include files)
.global和.ref告诉assembler symbol定义在别的module,防止assembler产生一个引用错误,链接的时候,linker会在别的module查找该符号的定义
• If the symbol is defined in the current module, the .global or .def directive declares
that the symbol and its definition can be used externally by other modules. These
types of references are resolved at link time.
如果symbol定义在了当前文件,通过上述两个命令就可以在其他文件中使用这个symbol
以下是一个例子
The file1.lst and file3.lst files are equivalent. Both files define the symbol INIT and make it available to other modules; both files use the external symbols X, Y, and Z. Also, file1.lst uses the .global directive to identify these global symbols; file3.lst uses .ref and .def to identify the symbols.
1,3定义了一个 external symbol INIT,都使用external symbol X,Y,Z
The file2.lst and file4.lst files are equivalent. Both files define the symbols X, Y, and Z and make them available to other modules; both files use the external symbol INIT. Also, file2.lst uses the .global directive to identify these global symbols; file4.lst uses .ref and.def to identify the symbols.
2,4定义了external symbol X,Y,Z
file1.lst
rm *.o *.dis exam*
.global相当于c 语言里面声明一个变量为全局变量,有点类似于c里面的extern,1.Sl里面的.global可以去掉,make的时候也不会报错
反汇编出来的文件在add指令后的地址确实存放的是0x1
exam_elf: file format elf32-littlearm
Disassembly of section .text:
00008074 <.text>:
8074: e2800056 add r0, r0, #86 ; 0x56
8078: 00000001 andeq r0, r0, r1
但是2.S里面的.global不能取消,虽然能够通过编译,但是链接的时候,提示找不到X这个symbol
arm-linux-gcc -c -o 2.o 2.S
2.S:7:5: warning: no newline at end of file
arm-linux-ld -o exam_elf 1.o 2.o
arm-linux-ld: warning: cannot find entry symbol _start; defaulting to 00008074
1.o(.text+0x4): In function `$a':
: undefined reference to `X'
make: *** [all] Error 1
_start这个symbol不加上global的时候,make的时候会有一个警告
arm-linux-ld: warning: cannot find entry symbol _start; defaulting to 00008074
<armasm_Assembler User Guide version 6.7 pdf>
MCR{cond} coproc, #opcode1, Rt, CRn, CRm{, #opcode2}
MCR: Move to Coprocessor from ARM Register,把寄存器的值放到Coprocessor
MRC:Move to ARM Register from Coprocessor,从Coprocessor读到寄存器里面去
coproc:要访问的协处理器寄存器号:pn,例如p15.
opcode1
is a 3-bit coprocessor-specific opcode.这个一般在协处理器文档有规定.参考哪个文档选取值
opcode2
is an optional 3-bit coprocessor-specific opcode这个是可选的
is an ARM source register. Rt must not be PC. r0,r1等等寄存器了
CRn, CRm
are coprocessor registers. 例如cp15寄存器下的0号,1号寄存器.
The opcode_1, opcode_2, and CRm fields should be zero, except when the values specified are used to select the desired operations
0号寄存器有两个,肯定有不同的访问方法,取决于opcode_2的值
CRn表示要访问p15寄存器里的哪一个寄存器
注意事项:
The opcode_1, opcode_2, and CRm fields should be zero, except when the values specified
are used to select the desired operations, in all instructions that access CP15. Using
other values results in unpredictable behavior
Register 0, ID code register,32bit,,opcode_2设置成任何值(除了1)表示读取device ID
MRC p15,0,Rd,c0,c0,0 ; returns ID register
This is a read-only register that returns a 32-bit device ID code.
You can access the ID code register by reading CP15 register 0 with the opcode_2 field
set to any value other than 1 (the CRm field should be zero when reading).
MCR{<cond>} p14, 7, <Rd>, CRn, CRm{, opcode_2}*
MRC{<cond>} p14, 7, <Rd>, CRn, CRm{, opcode_2}*
*opcode_2 can be omitted if opcode_2 == 0
ARM Compiler v5.06 for µVision armasm User Guide
10.41 LDM
格式:LDM{<cond>}{<type>} <Rn>{!},<regs>{^};
功能:从一片连续的内存单元读取数据到各个寄存器中,内存单元的起始地址为基址寄存器Rn的值,各个寄存器由寄存
LDMIA R1!,{R2-R7,R12} ;将R1指向的若干个存储单元中的数据读写到R2~R7、R12中,然后R1自加4 *寄存器的个数,
器列表regs表示。
该指令一般用于多个寄存器数据的出栈。
type字段种类:
IA:每次传送后地址加1。
IB:每次传送前地址加1。
DA:每次传送后地址减1。
DB:每次传送前地址减1。
FD:满递减堆栈。
ED:空递减堆栈。
FA:满递增堆栈。
EA:空递增堆栈。
堆栈寻址的命令LDMFA/STMFA、LDMEA/STMEA、LDMFD/STMFD、LDMED/STMED。
LDM和STM表示多寄存器寻址,即一次可以传送多个寄存器值。
LDM:一次装载多个,这里用来出栈。
STM:一次存储多个,这里用来入栈。
STMIA R1!,{R2-R7,R12} ;将寄存器R2~R7、R12的值保存到R1指向的存储单元中,然后R1自加4 *寄存器的个数
F/E表示指针指向的位置
F:full满堆栈,表示堆栈指针指向最后一个入栈的有效数据项。
E:empty空堆栈,表示堆栈指针指向下一个要放入的空地址。
A/D表示堆栈的生长方式
A:堆栈向高地址生长,即递增堆栈。
D:堆栈向低地址生长,即递减堆栈。
注意:有一个约定,编号低的寄存器在存储数据或者加载数据时对应于存储器的低地址。
FD、ED、FA和EA指定是满栈还是空栈,是升序栈还是降序栈,用于堆栈寻址。
一个满栈的栈指针指向上次写的最后一个数据单元.
空栈的栈指针指向第一个空闲单元。
一个降序栈是在内存中反向增长而升序栈在内存中正向增长。
{!}:若选用了此后缀,则当指令执行完毕后,将最后的地址写入基址寄存器。
{^}:当regs中不包含PC时,该后缀用于指示指令所用的寄存器为用户模式下的寄存器,
否则指示指令执行时,将寄存器SPSR的值复制到CPSR中。
//注意:有一个约定,编号低的寄存器在存储数据或者加载数据时对应于存储器的低地址
ldr sp, =0x1000---存放的是0x1,0x2
LDMIA SP!,{r2-r3}--执行完之后r2 = 0x1,r3 = 0x2,去掉感叹号!,sp寄存器的值不会发生改变,仍然是r2 = 0x1,r3 = 0x2
ldmda r3, {r5 - r7}
sub r3, r3, r7 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldmia r5, {r3, r4} @ value, mask
and r4, r4, r9 @ mask wanted bits
teq r3, r4
beq 2f
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
cmp r5, r6
blo 1b
mov r5, #0 @ unknown processor
2: mov pc, lr
.long __proc_info_begin
.long __proc_info_end
3: .long .
.long __arch_info_begin
.long __arch_info_end
代码的地址是从低地址一直排到高地址的.
r7 = . r6 = __proc_info_end, r5 = __proc_info_begin标号都是绝对地址
关于arm寄存器的介绍
寄存器名字
Reg# APCS 意义
R0 a1 工作寄存器
R1 a2 "
R2 a3 "
R3 a4 "
R4 v1 必须保护
R5 v2 "
R6 v3 "
R7 v4 "
R8 v5 "
R9 v6 "
R10 sl 栈限制
R11 fp 桢指针
R12 ip 内部过程调用寄存器
R13 sp 栈指针
R14 lr 连接寄存器
R15 pc 程序计数器
The following register names are predeclared:
r0-r15 andR0-R15
a1-a4 (argument, result, or scratch registers, synonyms for r0 to r3)
v1-v8 (variable registers, r4 to r11)
sb andSB (static base, r9)
ip andIP (intra-procedure-call scratch register, r12)
sp andSP (stack pointer, r13)
lr andLR (link register, r14)
pc andPC (program counter, r15).
CPSR寄存器介绍
格式(参考文档
ARM Architecture Reference Manual
A2.5 Program status registers
CPU三星S3C2440A芯片手册
THE PROGRAM STATUS REGISTERS
详细的指令解释可参考:ARM Architecture Reference Manual.pdf
MSR 通用寄存器到程序状态寄存器的数据传送指令 ,mrs是相反的作用.
格式:MSR{<cond>} CPSR/SPSR_<field>,<op1>;
功能:用于将寄存器Rd的值传送到程序状态寄存器中。
<field>:用来设置状态寄存器中需要操作的位。 这些域的介绍参看
ARM Architecture Reference Manual.pdf
A3.10 Status register access instructions
32位的状态寄存器可以分为4个域:
位[31:24]为条件标志位域,用f表示。
位[23:16]为状态位域,用s表示。
位[15:8]为扩展位域,用x表示。
位[7:0]为控制位域,用c表示。
MSR CPSR_f,R0 ;用R0的值修改CPSR的条件标志域
MSR CPSR_fsxc,#5; CPSR的值修改为5
实际运用的例子:
msr cpsr_c, #0xd2 参看The mode bits那张图
ldr sp, =0x31000000
msr cpsr_c, #0xdf
ldr sp, =0x34000000
关于arm寄存器的介绍
寄存器名字
Reg# APCS 意义
R0 a1 工作寄存器
R1 a2 "
R2 a3 "
R3 a4 "
R4 v1 必须保护
R5 v2 "
R6 v3 "
R7 v4 "
R8 v5 "
R9 v6 "
R10 sl 栈限制
R11 fp 桢指针
R12 ip 内部过程调用寄存器
R13 sp 栈指针
R14 lr 连接寄存器
R15 pc 程序计数器
The following register names are predeclared:
r0-r15 andR0-R15
a1-a4 (argument, result, or scratch registers, synonyms for r0 to r3)
v1-v8 (variable registers, r4 to r11)
sb andSB (static base, r9)
ip andIP (intra-procedure-call scratch register, r12)
sp andSP (stack pointer, r13)
lr andLR (link register, r14)
pc andPC (program counter, r15).
CPSR寄存器介绍
格式(参考文档
ARM Architecture Reference Manual
A2.5 Program status registers
CPU三星S3C2440A芯片手册
THE PROGRAM STATUS REGISTERS
bit 位清除指令
格式:BIC{<cond>}{S} <Rd>,<Rn>,<op2>;
功能:Rd=Rn AND (!op2) 用于清除寄存器Rn中的某些位,并把结果存放到目的寄存器Rd中
BIC R0,R0,#5 ;R0中第0位和第2位清0,其余位不变
ORR 逻辑或指令
格式:ORR{<cond>}{S} <Rd>,<Rn>,<op2>;
功能:Rd=Rn OR op2 一般用于设置Rn的特定几位。
ORR R0,R0,#5 ;R0的第0位和第2位设置为1,其余位不变
adr指令参考(adr是伪指令,反汇编的时候会被替换成别的指令)
ARM Developer Suite Assembler Guide
4.9 ARM pseudo-instructions
4.9.1 ADR ARM pseudo-instruction
ARM® Compiler v5.06 for µVision® armasm User Guide
10.11 ADR (PC-relative)
10.12 ADR (register-relative)
adr指令是位置无关的,取得_start标号的地址,依赖于pc的值加上偏移,如果pc是0.就是0+offset,如果是0x30000000就是0x30000000 + 偏移
7.5 Register-relative and PC-relative expressions
In ARM code, the value of the PC is the address of the current instruction plus 8 bytes.
ADR (PC-relative)
Generate a PC-relative address in the destination register, for a label in the current area.
----- label计算其相对于PC的地址,存入rd寄存器-----
Syntax
ADR{cond}{.W} Rd,label
where:
is an optional condition code.
is an optional instruction width specifier.
is the destination register to load.
label
is a PC-relative expression.
label must be within a limited distance of the current instruction.
Usage
ADR produces position-independent code, because the assembler generates an instruction that adds or subtracts a value to the PC.
------adr指令是位置无关指令------
Use the ADRL pseudo-instruction to assemble a wider range of effective addresses.
------ ADRL可以寻址更远------
label must evaluate to an address in the same assembler area as the ADR instruction.
If you use ADR to generate a target for a BX or BLX instruction, it is your responsibility to set the Thumb bit (bit 0) of the address if the target contains Thumb instructions
arm mode pc = current address + 8bytes
str指令
STR{<c>}{<q>} <Rt>, [<Rn> {, #+/-<imm>}] Offset: index==TRUE, wback==FALSE
STR{<c>}{<q>} <Rt>, [<Rn>, #+/-<imm>]! Pre-indexed: index==TRUE, wback==TRUE
STR{<c>}{<q>} <Rt>, [<Rn>], #+/-<imm> Post-indexed: index==FALSE, wback==TRUE
ldr指令
LDR(或LDRB、LDRBT、LDRH、LDRSB、LDRSH、LDRT、STR、STRB、STRBT、STRH、STRT) <Rd>,<addr>;
LDR Rd,[Rn] ;把内存中地址为Rn的字数据装入寄存器Rd中
LDR Rd,[Rn,Rm] ;将内存中地址为Rn+Rm的字数据装入寄存器Rd中
LDR Rd,[Rn,#index] ;将内存中地址为Rn+index的字数据装入Rd中
LDR Rd,[Rn,Rm,LSL#5] ;将内存中地址为Rn+Rm×32的字数据装入Rd
LDR Rd,[Rn,Rm]! ;将内存中地址为Rn+Rm的字数据装入Rd,并将新地址Rn+Rm写入Rn
LDR Rd,[Rn,#index]! ;将内存中地址为Rn+index的字数据装入Rd,并将新地址Rn+index写入Rn
LDR Rd,[Rn,Rm,LSL#5]! ;将内存中地址为Rn+Rm×32的字数据装入Rd,并将新地址Rn+Rm×32写入Rn
LDR Rd,[Rn],Rm ;将内存中地址为Rn的字数据装入寄存器Rd,并将新地址Rn+Rm写入Rn
LDR Rd,[Rn],#index ;将内存中地址为Rn的字数据装入寄存器Rd,并将新地址Rn+index写入Rn
LDR Rd,[Rn],Rm,LSL#5 ;将内存中地址为Rn的字数据装入寄存器Rd,并将新地址Rn+Rm×32写入Rn
STR指令
STR(或STR、STRB、STRBT、STRH、STRT) <Rd>,<addr>;
功能:将寄存器数据写入到内存中
寻址方式:Rn:基址寄存器。Rm:变址寄存器。Index:偏移量,12位的无符号数。
STR Rd,[Rn] ;将寄存器Rd中的字数据写入到内存中地址为Rn内存中
STR Rd,[Rn,Rm] ;将寄存器Rd中的字数据写入到内存中地址为Rn+Rm的内存中
STR Rd,[Rn,#index] ;将寄存器Rd中的字数据写入到内存中地址为Rn+index内存中
STR Rd,[Rn,Rm,LSL#5] ;将寄存器Rd中的字数据写入到内存中地址为Rn+Rm×32内存中
STR Rd,[Rn,Rm]! ;将寄存器Rd中的字数据写入到内存中地址为Rn+Rm的内存中
STR Rd,[Rn,#index]! ;将寄存器Rd中的字数据写入到内存中地址为Rn+index的内存中,并将新地址Rn+index写入Rn