.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:
引用文檔來(lái)自:ARM Assembly Language Tools v17.6.0.STS User's Guide
這三個(gè)指令都可以定義一個(gè)全局的符號(hào),可以被其他的程序使用,
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在當(dāng)前module定義,可以被其他文件訪問(wèn),這個(gè)符號(hào)也會(huì)被存在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指令說(shuō)明這個(gè)符號(hào)在當(dāng)前module中使用,但是在別的module中定義,鏈接器最終會(huì)在鏈接的時(shí)候找到其定義
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.)
如果一個(gè)global symbol被多次定義,assembler會(huì)提醒一個(gè)多次定義的錯(cuò)誤,.ref指令不管modules用不用
這個(gè)symbol,都會(huì)在符號(hào)表里創(chuàng)建一個(gè)entry,.global的話只會(huì)在用到這個(gè)symbol的時(shí)候才創(chuàng)建.
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不管用不用到,符號(hào)表里都有一個(gè)符號(hào)的entry,global定義的則只會(huì)在使用到的時(shí)候才會(huì)創(chuàng)建一個(gè)entry
A symbol can be declared global for either of two reasons:
出于以下兩種原因聲明一個(gè).global符號(hào)
? 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沒(méi)有定義在當(dāng)前文件,(包括macro, copy, and include files)
.global和.ref告訴assembler symbol定義在別的module,防止assembler產(chǎn)生一個(gè)引用錯(cuò)誤,鏈接的時(shí)候,linker會(huì)在別的module查找該符號(hào)的定義
? 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定義在了當(dāng)前文件,通過(guò)上述兩個(gè)命令就可以在其他文件中使用這個(gè)symbol
- 以下是一個(gè)例子
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定義了一個(gè) 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
file2.lst
file3.lst
file4.lst
以下是在linux主機(jī)下的一個(gè)實(shí)際的例子
1.S
.global X, Y, Z
ADD R0, R0, #0x56
.word X
.end
2.S
.global X, Y, Z
#.extern X, Y, Z
.set X, 1
.set Y, 2
.set Z, 3
.end
Makefile
objs := 1.o 2.o
all:$(objs)
arm-linux-ld -o exam_elf $^
arm-linux-objdump -D -m arm exam_elf > exam.dis
%.o:%.S
arm-linux-gcc -c -o $@ $<
clean:
rm *.o *.dis exam*
.global相當(dāng)于c 語(yǔ)言里面聲明一個(gè)變量為全局變量,有點(diǎn)類似于c里面的extern,1.Sl里面的.global可以去掉,make的時(shí)候也不會(huì)報(bào)錯(cuò)
反匯編出來(lái)的文件在add指令后的地址確實(shí)存放的是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不能取消,雖然能夠通過(guò)編譯,但是鏈接的時(shí)候,提示找不到X這個(gè)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這個(gè)symbol不加上global的時(shí)候,make的時(shí)候會(huì)有一個(gè)警告
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:要訪問(wèn)的協(xié)處理器寄存器號(hào):pn,例如p15.
opcode1
is a 3-bit coprocessor-specific opcode.這個(gè)一般在協(xié)處理器文檔有規(guī)定.參考哪個(gè)文檔選取值
opcode2
is an optional 3-bit coprocessor-specific opcode這個(gè)是可選的
Rt
is an ARM source register. Rt must not be PC. r0,r1等等寄存器了
CRn, CRm
are coprocessor registers. 例如cp15寄存器下的0號(hào),1號(hào)寄存器.
The opcode_1, opcode_2, and CRm fields should be zero, except when the values specified are used to select the desired operations
0號(hào)寄存器有兩個(gè),肯定有不同的訪問(wèn)方法,取決于opcode_2的值
CRn表示要訪問(wèn)p15寄存器里的哪一個(gè)寄存器
注意事項(xiàng):
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設(shè)置成任何值(除了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).
以下摘自arm 體系架構(gòu)手冊(cè)
A2.10.5 Configuration and control
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>{^};
功能:從一片連續(xù)的內(nèi)存單元讀取數(shù)據(jù)到各個(gè)寄存器中衙熔,內(nèi)存單元的起始地址為基址寄存器Rn的值运沦,各個(gè)寄存器由寄存
LDMIA R1!,{R2-R7,R12} ;將R1指向的若干個(gè)存儲(chǔ)單元中的數(shù)據(jù)讀寫到R2~R7、R12中碗殷,然后R1自加4 *寄存器的個(gè)數(shù),
器列表regs表示谈撒。
該指令一般用于多個(gè)寄存器數(shù)據(jù)的出棧蚕捉。
type字段種類:
IA:每次傳送后地址加1律胀。
IB:每次傳送前地址加1贝乎。
DA:每次傳送后地址減1情连。
DB:每次傳送前地址減1。
FD:滿遞減堆棧览效。
ED:空遞減堆棧却舀。
FA:滿遞增堆棧。
EA:空遞增堆棧朽肥。
堆棧尋址的命令LDMFA/STMFA禁筏、LDMEA/STMEA持钉、LDMFD/STMFD衡招、LDMED/STMED。
LDM和STM表示多寄存器尋址每强,即一次可以傳送多個(gè)寄存器值始腾。
LDM:一次裝載多個(gè),這里用來(lái)出棧空执。
STM:一次存儲(chǔ)多個(gè)浪箭,這里用來(lái)入棧。
STMIA R1!,{R2-R7,R12} ;將寄存器R2~R7辨绊、R12的值保存到R1指向的存儲(chǔ)單元中奶栖,然后R1自加4 *寄存器的個(gè)數(shù)
F/E表示指針指向的位置
F:full滿堆棧,表示堆棧指針指向最后一個(gè)入棧的有效數(shù)據(jù)項(xiàng)门坷。
E:empty空堆棧宣鄙,表示堆棧指針指向下一個(gè)要放入的空地址。
A/D表示堆棧的生長(zhǎng)方式
A:堆棧向高地址生長(zhǎng)默蚌,即遞增堆棧冻晤。
D:堆棧向低地址生長(zhǎng),即遞減堆棧绸吸。
注意:有一個(gè)約定鼻弧,編號(hào)低的寄存器在存儲(chǔ)數(shù)據(jù)或者加載數(shù)據(jù)時(shí)對(duì)應(yīng)于存儲(chǔ)器的低地址。
FD锦茁、ED攘轩、FA和EA指定是滿棧還是空棧,是升序棧還是降序棧码俩,用于堆棧尋址撑刺。
一個(gè)滿棧的棧指針指向上次寫的最后一個(gè)數(shù)據(jù)單元.
空棧的棧指針指向第一個(gè)空閑單元。
一個(gè)降序棧是在內(nèi)存中反向增長(zhǎng)而升序棧在內(nèi)存中正向增長(zhǎng)握玛。
{!}:若選用了此后綴够傍,則當(dāng)指令執(zhí)行完畢后甫菠,將最后的地址寫入基址寄存器。
{^}:當(dāng)regs中不包含PC時(shí)冕屯,該后綴用于指示指令所用的寄存器為用戶模式下的寄存器寂诱,
否則指示指令執(zhí)行時(shí),將寄存器SPSR的值復(fù)制到CPSR中安聘。
//注意:有一個(gè)約定痰洒,編號(hào)低的寄存器在存儲(chǔ)數(shù)據(jù)或者加載數(shù)據(jù)時(shí)對(duì)應(yīng)于存儲(chǔ)器的低地址
ldr sp, =0x1000---存放的是0x1,0x2
LDMIA SP!,{r2-r3}--執(zhí)行完之后r2 = 0x1,r3 = 0x2,去掉感嘆號(hào)!,sp寄存器的值不會(huì)發(fā)生改變,仍然是r2 = 0x1,r3 = 0x2
再來(lái)看另外一個(gè)例子
ldr sp, =0x1000,0xffc存放0x1,0x1000存放0x2
LDMDA SP,{R2-r3} r2 = 0x1,r3 = 0x2
__lookup_processor_type:
adr r3, 3f
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標(biāo)號(hào)都是絕對(duì)地址
關(guān)于arm寄存器的介紹
寄存器名字
Reg# APCS 意義
R0 a1 工作寄存器
R1 a2 "
R2 a3 "
R3 a4 "
R4 v1 必須保護(hù)
R5 v2 "
R6 v3 "
R7 v4 "
R8 v5 "
R9 v6 "
R10 sl 棧限制
R11 fp 楨指針
R12 ip 內(nèi)部過(guò)程調(diào)用寄存器
R13 sp 棧指針
R14 lr 連接寄存器
R15 pc 程序計(jì)數(shù)器
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芯片手冊(cè)
THE PROGRAM STATUS REGISTERS
)
詳細(xì)的指令解釋可參考:ARM Architecture Reference Manual.pdf
MSR 通用寄存器到程序狀態(tài)寄存器的數(shù)據(jù)傳送指令 ,mrs是相反的作用.
格式:MSR{<cond>} CPSR/SPSR_<field>,<op1>;
功能:用于將寄存器Rd的值傳送到程序狀態(tài)寄存器中。
<field>:用來(lái)設(shè)置狀態(tài)寄存器中需要操作的位浴韭。 這些域的介紹參看
ARM Architecture Reference Manual.pdf
A3.10 Status register access instructions
32位的狀態(tài)寄存器可以分為4個(gè)域:
位[31:24]為條件標(biāo)志位域丘喻,用f表示。
位[23:16]為狀態(tài)位域念颈,用s表示泉粉。
位[15:8]為擴(kuò)展位域,用x表示榴芳。
位[7:0]為控制位域嗡靡,用c表示。
例:
MSR CPSR_f,R0 ;用R0的值修改CPSR的條件標(biāo)志域
MSR CPSR_fsxc,#5; CPSR的值修改為5
實(shí)際運(yùn)用的例子:
msr cpsr_c, #0xd2 參看The mode bits那張圖
ldr sp, =0x31000000
msr cpsr_c, #0xdf
ldr sp, =0x34000000
關(guān)于arm寄存器的介紹
寄存器名字
Reg# APCS 意義
R0 a1 工作寄存器
R1 a2 "
R2 a3 "
R3 a4 "
R4 v1 必須保護(hù)
R5 v2 "
R6 v3 "
R7 v4 "
R8 v5 "
R9 v6 "
R10 sl 棧限制
R11 fp 楨指針
R12 ip 內(nèi)部過(guò)程調(diào)用寄存器
R13 sp 棧指針
R14 lr 連接寄存器
R15 pc 程序計(jì)數(shù)器
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芯片手冊(cè)
THE PROGRAM STATUS REGISTERS
)
A2.5.8 The T and J bits的參考
ARM Architecture Reference Manual.pdf
A2.5.6 The interrupt disable bits
mode bit各個(gè)對(duì)應(yīng)值的相關(guān)參考,其他各個(gè)位均可參考ARM Architecture Reference Manual,這里就不一一列出來(lái).
bic指令語(yǔ)法
BIC{<cond>}{S} <Rd>, <Rn>, <shifter_operand>
Rd = Rn AND NOT shifter_operand
bit 位清除指令
格式:BIC{<cond>}{S} <Rd>,<Rn>,<op2>;
功能:Rd=Rn AND (!op2) 用于清除寄存器Rn中的某些位窟感,并把結(jié)果存放到目的寄存器Rd中
例:
BIC R0,R0,#5 ;R0中第0位和第2位清0讨彼,其余位不變
ORR 邏輯或指令
格式:ORR{<cond>}{S} <Rd>,<Rn>,<op2>;
功能:Rd=Rn OR op2 一般用于設(shè)置Rn的特定幾位。
例:
ORR R0,R0,#5 ;R0的第0位和第2位設(shè)置為1柿祈,其余位不變
adr指令參考(adr是偽指令,反匯編的時(shí)候會(huì)被替換成別的指令)
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指令是位置無(wú)關(guān)的,取得_start標(biāo)號(hào)的地址,依賴于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計(jì)算其相對(duì)于PC的地址,存入rd寄存器-----
Syntax
ADR{cond}{.W} Rd,label
where:
cond
is an optional condition code.
.W
is an optional instruction width specifier.
Rd
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指令是位置無(wú)關(guān)指令------
Use the ADRL pseudo-instruction to assemble a wider range of effective addresses.
------ ADRL可以尋址更遠(yuǎn)------
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] ;把內(nèi)存中地址為Rn的字?jǐn)?shù)據(jù)裝入寄存器Rd中
LDR Rd,[Rn,Rm] ;將內(nèi)存中地址為Rn+Rm的字?jǐn)?shù)據(jù)裝入寄存器Rd中
LDR Rd,[Rn,#index] ;將內(nèi)存中地址為Rn+index的字?jǐn)?shù)據(jù)裝入Rd中
LDR Rd,[Rn,Rm,LSL#5] ;將內(nèi)存中地址為Rn+Rm×32的字?jǐn)?shù)據(jù)裝入Rd
LDR Rd,[Rn,Rm]! ;將內(nèi)存中地址為Rn+Rm的字?jǐn)?shù)據(jù)裝入Rd,并將新地址Rn+Rm寫入Rn
LDR Rd,[Rn,#index]! ;將內(nèi)存中地址為Rn+index的字?jǐn)?shù)據(jù)裝入Rd媳危,并將新地址Rn+index寫入Rn
LDR Rd,[Rn,Rm荞彼,LSL#5]! ;將內(nèi)存中地址為Rn+Rm×32的字?jǐn)?shù)據(jù)裝入Rd,并將新地址Rn+Rm×32寫入Rn
LDR Rd,[Rn],Rm ;將內(nèi)存中地址為Rn的字?jǐn)?shù)據(jù)裝入寄存器Rd待笑,并將新地址Rn+Rm寫入Rn
LDR Rd,[Rn],#index ;將內(nèi)存中地址為Rn的字?jǐn)?shù)據(jù)裝入寄存器Rd鸣皂,并將新地址Rn+index寫入Rn
LDR Rd,[Rn],Rm,LSL#5 ;將內(nèi)存中地址為Rn的字?jǐn)?shù)據(jù)裝入寄存器Rd,并將新地址Rn+Rm×32寫入Rn
STR指令
STR(或STR、STRB寞缝、STRBT癌压、STRH、STRT) <Rd>,<addr>;
功能:將寄存器數(shù)據(jù)寫入到內(nèi)存中
尋址方式:Rn:基址寄存器荆陆。Rm:變址寄存器滩届。Index:偏移量,12位的無(wú)符號(hào)數(shù)被啼。
STR Rd,[Rn] ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn內(nèi)存中
STR Rd,[Rn,Rm] ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn+Rm的內(nèi)存中
STR Rd,[Rn,#index] ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn+index內(nèi)存中
STR Rd,[Rn,Rm,LSL#5] ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn+Rm×32內(nèi)存中
STR Rd,[Rn,Rm]! ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn+Rm的內(nèi)存中
STR Rd,[Rn,#index]! ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn+index的內(nèi)存中帜消,并將新地址Rn+index寫入Rn
STR Rd,[Rn,Rm,LSL#5]! ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn+Rm×32的內(nèi)存中浓体,并將新地址Rn+Rm×32寫入Rn
STR Rd,[Rn],Rm ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn的內(nèi)存中泡挺,并將新地址Rn+Rm寫入Rn
STR Rd,[Rn],#index ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn的內(nèi)存中,并將新地址Rn+index寫入Rn
STR Rd,[Rn],Rm,LSL#5 ;將寄存器Rd中的字?jǐn)?shù)據(jù)寫入到內(nèi)存中地址為Rn的內(nèi)存中命浴,并將新地址Rn+Rm×32寫入Rn