IAR下的汇编/单片机启动代码汇编
1、
IAR汇编指令SFB和SFE
SFB Segment begin 段开始
语法格式
SFB(segment [{+|-} offset])
参数
segment: 可重定位段的段名, 必须在SFB使用前已定义
offset : 从开始地址的偏移, 是一个可选参数, 当偏移量省略时, 可以不添加小括号
描述
SFB 右边可以接受一个操作数, 而且这个操作数必须是一个可重位段的段名.
这个操作符计算段的首字节地址. 这个操作发生在连接时.
例
NAME demo
RSEG CODE
start: DC16 SFB(CODE)
即使上面的代码和多个其他的模块进行连接, start标号处仍被置为段的首字节地址
语法格式
SFE (segment [{+|-} offset])
参数
segment: 可重定位段的段名, 必须在SFB使用前已定义
offset : 从开始地址的偏移, 是一个可选参数, 当偏移量省略时, 可以不添加小括号
描述
SFE在其右边接收一个操作数. 操作数必须是一个可重定位段的段名. SFE操作符将段起始地址和段大小相加. 这个操作在连接时发生.
SFE accepts a single operand to its right. The operand must be the name of a relocatable segment. The operator evaluates to the segment start address plus the segment size. This evaluation takes place at linking time.
例
NAME demo
RSEG CODE
end: DC16 SFE(CODE)
即使当上面的代码被和多个模块想连接时, end标号仍然会被置为段最后一个字节的地址. Even if the above code is linked with many other modules, end will still be set to the address of the last byte of the segment.
段MY_SEGMENT的大小可以通过以下方式计算而得:
SFE(MY_SEGMENT)-SFB(MY_SEGMENT)
--------------------------------------------------------------------------------
arm中的几种跳转
arm汇编的跳转指令无非是b和ldr。但是如果没有足够理解,别人灵活的用一下你就犯晕了。
首先我们要知道两者的两个本质区别:
1、b是位置无关的,ldr不是位置无关的。
2、b的范围只能是+—32MB,而ldr是4GB。
在arm的启动汇编的中断向量表是必然用跳转指令的,但是就是这里也有很多实现形式:
方式1:
B InitReset ; 0x00 Reset handler
undefvec:
B undefvec ; 0x04 Undefined Instruction
swivec:
B swivec ; 0x08 Software Interrupt
pabtvec:
B pabtvec ; 0x0C Prefetch Abort
dabtvec:
B dabtvec ; 0x10 Data Abort
rsvdvec:
B rsvdvec ; 0x14 reserved
irqvec:
B IRQ_Handler_Entry ; 0x18 IRQ
这个我很容易理解,实现的标号油InitReset和IRQ_Handler_Entry,其他没有实现的在原地跳转。
方式二:
LDR pc, =resetHandler ; Reset
LDR pc, Undefined_Addr ; Undefined instructions
LDR pc, SWI_Addr ; Software interrupt (SWI/SYS)
LDR pc, Prefetch_Addr ; Prefetch abort
LDR pc, Abort_Addr ; Data abort
B . ; RESERVED
LDR pc, =irqHandler ; IRQ
LDR pc, FIQ_Addr ; FIQ
LDR PC,[PC,#0x18]
Undefined_Addr: DCD Undefined_Handler
SWI_Addr: DCD SWI_Handler
Prefetch_Addr: DCD Prefetch_Handler
Abort_Addr: DCD Abort_Handler
FIQ_Addr: DCD FIQ_Handler
我们注意到两种ldr
一种LDR PC,=label,这时把LDR当做伪指令,他要被翻译成:
LDR PC,[PC,offset_to_label2]
label2:DCD resetHandler
这种label是在程序中标记的了,如resetHandler和irqHandler
还有一种LDR PC,label,这时直接把label地址内存内容copy到PC中
这种label都是 label:DCD label2 ,这些label2可以在任何地方实现
我们来理解b和ldr两者的不同
1,b是位置无关,因为他的跳转都是相对PC来的,而ldr不是位置无关的,因为他的跳转是根据DCD里面的值,这个值是连接的时候确定的,他是跟连接地址有关的
2,b的范围只能是32M,是因为指令里面给偏移的空间只有24bit,而ldr是一个32bit的DCD,所以他是32bit的
注意:像上面方式二
LDR pc, =resetHandler ; Reset
。
。
。
resetHandler:
....
....
如果运行地址是0,那么LDR pc, =resetHandler还在以基址为0的空间运行
但是执行完了,假设装载地址是0x3000000,所以resetHandler的基址不是0,而是0x30000000
所以resetHandler标号以后的指令应该存在以0x3000000为基址的空间,pc跳过去了
这种技巧在at91的remap模式经常用到
-----------------------------------------------
IAR汇编单片机启动代 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)