gnu arm asm汇编

.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

file1

file2.lst

file2

file3.lst

file3

file4.lst

file4

以下是在linux主机下的一个实际的例子
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相当于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这个是可选的
    Rt
    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).
Register 0, ID code

以下摘自arm 体系架构手册
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>{^};
功能:从一片连续的内存单元读取数据到各个寄存器中,内存单元的起始地址为基址寄存器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
0x1000处内存数据
上述代码执行完的效果

再来看另外一个例子

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标号都是绝对地址

关于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寄存器介绍


格式(参考文档

  1. ARM Architecture Reference Manual
    A2.5 Program status registers
  2. 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寄存器介绍


格式(参考文档

  1. ARM Architecture Reference Manual
    A2.5 Program status registers
  2. CPU三星S3C2440A芯片手册
    THE PROGRAM STATUS REGISTERS
    )
ARM Architecture Reference Manual
CPU三星S3C2440A芯片手册

A2.5.8 The T and J bits的参考


A2.5.8 The T and J bits

ARM Architecture Reference Manual.pdf
A2.5.6 The interrupt disable bits


中断bit的参考

mode bit各个对应值的相关参考,其他各个位均可参考ARM Architecture Reference Manual,这里就不一一列出来.

The mode bits

bic指令语法
  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中的某些位,并把结果存放到目的寄存器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 + 偏移


adr指令反汇编
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:
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指令是位置无关指令------
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 
STR Rd,[Rn,Rm,LSL#5]! ;将寄存器Rd中的字数据写入到内存中地址为Rn+Rm×32的内存中,并将新地址Rn+Rm×32写入Rn 
STR Rd,[Rn],Rm          ;将寄存器Rd中的字数据写入到内存中地址为Rn的内存中,并将新地址Rn+Rm写入Rn 
STR Rd,[Rn],#index     ;将寄存器Rd中的字数据写入到内存中地址为Rn的内存中,并将新地址Rn+index写入Rn 
STR Rd,[Rn],Rm,LSL#5   ;将寄存器Rd中的字数据写入到内存中地址为Rn的内存中,并将新地址Rn+Rm×32写入Rn 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容