EQU:其作用类似于 C 语言中的# define
Expression_name EQU Expression
此后程序中凡需要用到该表达式指出,就可以用表达式名来代替了。可见,EQU的引入提高了程序的可读性,也使其容易修改。
上始终的表达式可以是任何有效的操作数格式,可以是任何可求出常数值的表达式,也可以是任何有效的助记符。举例如下:
CONSTANT EQU 256 数值赋以符号名
DATA EQU HEIGHT+12 地址表达式赋以符号名
ALPAHA EQU 7
EQU不是指令集,而是伪指令,一般我们常使用的MASM5.0以上都常用这个伪指令。它不是80X86的指令集合。而汇编在第一次扫描时只扫描了指令,而将伪指令中的东西作为“动态内容”作了标记而已。所以在第一次扫描所得到的清单中是没有看到它占用内存的。所以不会计算其中的数据的。而第二次扫描才能得到。
指令集是属于机器CPU的,因有的,一个类型CPU就有这样一个指令集。而伪指令则是由汇编软件提供的,比如MASM5.0中提供了EQU的伪指令,那么汇编时是由于MASM5.0进行运算的。而计算空间时所得到的清单文件是关于指令的,所以伪指令并没有计算在内。
不同类型的CPU会有不同的指令集,不管你使用什么样的汇编软件,同一个类型 的CPU指令集是不会变的!而伪指令是由汇编软件提供,不同的汇编软件有不同的伪指令集。
CPU的发展和软件的发展都有一个基础,因此出现了向下兼容的现象。80386与80286相比,只在80286指令集的基础上增加了几个指令而成的。而软件也是,MASM6.0只是在5.0部分伪指令集的基础上增加了几条伪指令而已。但6.0却还有一大进步就是将5。0中的两次扫描一次完成。也就是说6.0只有一次扫描。而5.0却是两次扫描。
===================================================================
AREA:
语法格式:
—ASSOC=section。指定与本段相关的ELF段。任何时候连接section段也必须包括sectionname段。
— COMDEF 属性:该属性定义一个通用的段,该段可以包含代码或数据。在各源文件中,同名的COMDEF段必须相同。
通常可以用AREA伪操作将程序分为多个ELF格式的段。段名称可以相同,这时这些同名的段被放在同一个ELF段中。一个大的程序可以包括多个代码段和数据段,一个汇编语言程序至少要包含一个段。
===================================================================
SPACE
===================================================================
PRESERVE8:
字节对齐关键词,以前用ADS编译器的时候可以不用,但是后来的keil编译器时需要加上(譬如用周立功模板时,将ADS工程转到keil工程时就必须加上)。
指定当前文件堆栈8字节对齐
REQUIRE8
PRESERVE8
链接器检查要求堆栈八字节对齐的任何代码是否仅由保持堆栈八字节对齐的代码直接或间接地调用。
语法
REQUIRE8 {bool
} PRESERVE8 {bool
} 其中:
bool
是一个可选布尔常数,取值为{TRUE}
或 {FALSE}
。
用法
如果您的代码保持堆栈八字节对齐,在需要时,可使用 PRESERVE8
PRESERVE8 {FALSE}
Note
如果您省略 PRESERVE8
PRESERVE8
{FALSE}
,汇编程序会检查修改 sp 的指令,以决定是否设置 PRES8 编译属性。 ARM 建议明确指定 PRESERVE8
。
您可以通过以下形式启用警告:
armasm --diag_warning 1546
您将会收到类似以下警告:
"test.s", line 37: Warning: A1546W: Stack pointer update potentially
37 00000044
THUMB:告诉汇编器下面是32为的Thumb指令,如果需要汇编器将插入位以保证对齐
CODE16、CODE32
===================================================================
EXPORT(或GLOBAL)
===================================================================
DCD(或DCDU)
5 ,
6 ;分配一片连续的字存储单元并初始化。
===================================================================
汇编控制( Assembly Control )伪指令
X:LOR:Y 表示将X和Y做逻辑或的操作。
:LNOT:Y 表示将Y做逻辑非的操作。
X:LEOR:Y 表示将X和Y做逻辑异或的操作。
:LNOT: 逻辑预算符
:DEF:
IF
;如果宏判断是否定义NO_CRP #ifndef
;自定义只读代码段
CRP_Key
;加密等级见上注释
===================================================================
PROC
过程的类型有两种:
ldr只能在当前PC的4KB范围内跳转
B只能在当前PC的32M范围内跳转
label标号实际上就是个地址
eg:
合法: ldr r1,[r2] |
ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。比如想把数据从内存中某处读取到寄存器中,只能使用ldr
比如:ldr r0, 0x12345678
就是把0x12345678这个地址中的值存放到r0中。
而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。
x86中没有ldr这种指令,因为x86的mov指令可以将数据从内存中移动到寄存器中。
另外还有一个就是ldr伪指令,虽然ldr伪指令和ARM的ldr指令很像,但是作用不太一样。ldr伪指令可以在立即数前加上=,以表示把一个地址写到某寄存器中,比如:
ldr r0, =0x12345678
这样,就把0x12345678这个地址写到r0中了。所以,ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为mov指令的。
===================================================================
BX{<cond>} <Rm>
<cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。
<Rm>该寄存器中为跳转的目标地址。当<Rm>寄存器的bit[0]为0时,目标地址处的指令为ARM指令;
当<Rm>寄存器的bit[0]为1时,目标地址处的指令为Thumb指令。
ARM指令是字对齐(指令的地址后两位为[1:0]=0b00),Thumb是半字对齐(指令的地址后两位为[1:0]=0bx0,x为0或1)。指令的地址的最后一位必为0。
===================================================================
__main函数的作用
1.1
1.2
图 1.1
__main()是编译系统提供的一个函数,负责完成库函数的初始化和初始化应用程序执行环境,最后自动跳转到main()。所以说,前者是库函数,后者就是我们自己编写的main()主函数;
===================================================================
===================================================================
__user_initial_stackheap()
· r0
· r1
· r2
· r3
===================================================================
BX
如果LR的值不是0xffffxxxx类型的,则PC跳至LR[31:1],而根据LR[0:0]则决定跳转后处理器进入的状态。如果LR[0:0]=1,则进入Thumb状态,否则进入ARM状态。
在CM3中,如果以0xffff开头则有特殊的含义,命名为EXC_RETURN,它指示正在从异常返回,并决定返回的方式,在《Cortex-M3权威指南》中有重点介绍
===================================================================
__initial_sp
通过定义一个等于堆栈顶部的符号 __initial_sp
__initial_sp EQU 0x100000 ; equal to the top of the stack
__heap_base
过分别定义符号__heap_base
和 __heap_limit
来指定堆的开头和末尾。 完成后,您可以按通常方式使用堆函数。
__heap_limit
必须指向堆区中最后一个字节后面的字节。
EXPORT __heap_base
__heap_base EQU 0x400000 ; equal to the start of the heap
EXPORT __heap_limit
__heap_limit EQU 0x800000 ; equal to the end of the heap
===================================================================
;这个函数中,EXPORT
Default_Handler PROC
WAKEUP_IRQHandler
CAN_IRQHandler
__user_initial_stackheap
====
http://blog.sina.com.cn/s/blog_6b94d5680100s89x.html