[转]关于U-BOOT中.balignl 16…
来源:互联网 发布:电力数据网 编辑:程序博客网 时间:2024/06/10 07:45
.balignl 16,0xdeadbeef
首先要弄明白.balignl的意思,这其实应该算是一个伪操作符,伪操作符的意思就是机器码里,并没有一个汇编指令与其对应,是由编译器来实现其功能的。
.balign是意思是:以当前地址为开始开始,找到第一次出现的以第一个参数为整数倍的地址,并将其作为结束地址,
在这个结束地址前面存储一个字节长度的数据,存储内容正是第二个参数。如果当前地址正好是第一个参数的倍数,则没有数据被写入到内存。
.balign 8,0xde这条指令的含义可以用下图表示:
图解:以当前地址为开始开始,找到第一次出现的以8为整数倍的地址,并将其作为结束地址,在这个结束地址前面存储一个字节长度的数据0xde。
如果当前地址正好是8的倍数,则没有数据被写入到内存。
以此类推,.balignw则表示第二个参数存入的内容长度为2字节:
因为现在填入的内容为2个字节,那就存在以下几种情况:
分析一下这四种情况:
以此类推,.balignl,这个指令用来填与一个字,即4个字节的长度
仔细分析一下就知道,对于.balignl 16,0xdeadbeef,如果想要0xdeadbeef一定填到当前地址后面某个部分,当前地址偏移量就必须为4字节,这样才能保证在任何情况下,偏移的地址所留的空隙刚好填入所要填的内容。
注意:0xdeadbeef是什么意思?
类似这样的值很多,像0xabababab,它们的作用就是为内存做标记,插在那里,就表示从这个位置往后的一段有特殊作用的内存,而这个位置往前,禁止访问。
看了上面转载的博文,算是有豁然开朗了,下面再转一篇博文,是对这条命令进行的验证,算是对上面自己理解的一个实践。
转自:http://www.liweifan.com/2012/01/11/assembly-embedded-system-balignl-arm/
-
-
- #include
- #include
- #include
-
-
-
-
- .globl
_start - _start:
b start_code -
ldr pc, _undefined_instruction -
ldr pc, _software_interrupt -
ldr pc, _prefetch_abort -
ldr pc, _data_abort -
ldr pc, _not_used -
ldr pc, _irq -
ldr pc, _fiq -
- _undefined_instruction:
.word undefined_instruction - _software_interrupt:
.word software_interrupt - _prefetch_abort:
.word prefetch_abort - _data_abort:
.word data_abort - _not_used:
.word not_used - _irq:
.word irq - _fiq:
.word fiq -
-
.balignl 16,0xdeadbeef
问题出在58行,.balignl
balignl有几个“近亲”,具体看下面截图:
四种功能基本相同,不同之处在于填充时的字节数。.align和.balign是1个字节1个字节的填充,.balignw是2个字节2个字节的填充,而.balignl一次填充4个字节。
我们以balignl为例说明,它的完整指令格式为: .balignl {alignment} {,fill} {,max}。
第一个参数alignment为一个正整数,对齐时要以alignment的值的整数倍为结束地址,以当前地址为起始地址,进行字节填充,比如当前地址为20,而alignment的值我们设定为16,那么字节填充自20开始,结束于20后第一个16的倍数地址处,即32处。
第二个参数fill即我们选定的,用来填充的数值。balignl模式下,最大为4字节,不够4字节系统会自动补够4字节,此参数可选,不标则采用默认值0。
第三个参数max也是可选项,默认值为alignment。若对齐时偏移量大于max,则不偏移。同上例,从16--32,偏移量为16,如果max我们设置为8,那么该偏移不进行。
为了能更容易理解,我们实际操作下。
将start.S拷贝至任意目录,保留58行前以及start_code段的代码(大约在117~124行),方便起见,我直接贴出裁剪后的代码:
-
-
- #include
- #include
- #include
-
-
-
-
- .globl
_start - _start:
b start_code -
ldr pc, _undefined_instruction -
ldr pc, _software_interrupt -
ldr pc, _prefetch_abort -
ldr pc, _data_abort -
ldr pc, _not_used -
ldr pc, _irq -
ldr pc, _fiq -
- _undefined_instruction:
.word undefined_instruction - _software_interrupt:
.word software_interrupt - _prefetch_abort:
.word prefetch_abort - _data_abort:
.word data_abort - _not_used:
.word not_used - _irq:
.word irq - _fiq:
.word fiq -
-
.balignl 16,0xdeadbeef -
- start_code:
-
-
mrs r0, cpsr -
bic r0, r0, #0x1f -
orr r0, r0, #0xd3 -
msr cpsr, r0
OK,首先我们将58行屏蔽掉,然后在59行添加代码:
58:
@.balignl 16,0xdeadbeef 59:
.byte 0x11
保存后,用linux上的交叉编译器来编译下,看看什么效果:
eleven@eleven-desktop:~/workspace$
arm-linux-as start.S -o start.o start.S: Assembler messages:
start.S:41: Error: misaligned branch destination
提示边界对齐出错,这说明arm编译器没有自动帮我们对齐。添加的 .byte 0x11只占用了1字节,导致其后的全部指令地址都没有对齐,而arm的指令要求32位对齐,不然无法寻址。所以41行处跳转去start_code时出现了问题,start_code此时的存储地址不是4字节的整数倍,当然无法寻址了。
要解决这个问题,这里我们就需要手动对齐了。在59行后添加如下代码:
.align 4,0x12
保存后再编译就顺利通过了。为了能更清楚知道它的作用,我们来看看反汇编代码:
- eleven@eleven-desktop:~/workspace$
arm-linux-objdump -d start.o -
- start.o:
file format elf32-littlearm -
- Disassembly
of section .text: -
- 00000000
<_start>: -
0: ea00000e b 40 -
4: e59ff014 ldr pc, [pc, #20] ; 20 <_undefined_instruction> -
8: e59ff014 ldr pc, [pc, #20] ; 24 <_software_interrupt> -
c: e59ff014 ldr pc, [pc, #20] ; 28 <_prefetch_abort> -
10: e59ff014 ldr pc, [pc, #20] ; 2c <_data_abort> -
14: e59ff014 ldr pc, [pc, #20] ; 30 <_not_used> -
18: e59ff014 ldr pc, [pc, #20] ; 34 <_irq> -
1c: e59ff014 ldr pc, [pc, #20] ; 38 <_fiq> -
- 00000020
<_undefined_instruction>: -
20: 00000000 .word 0x00000000 -
- 00000024
<_software_interrupt>: -
24: 00000000 .word 0x00000000 -
- 00000028
<_prefetch_abort>: -
28: 00000000 .word 0x00000000 -
- 0000002c
<_data_abort>: -
2c: 00000000 .word 0x00000000 -
- 00000030
<_not_used>: -
30: 00000000 .word 0x00000000 -
- 00000034
<_irq>: -
34: 00000000 .word 0x00000000 -
- 00000038
<_fiq>: -
38: 00000000 .word 0x00000000 -
3c: 121212ee .word 0x121212ee -
- 00000040
: -
40: e10f0000 mrs r0, CPSR -
44: e3c0001f bic r0, r0, #31 ; 0x1f -
48: e38000d3 orr r0, r0, #211 ; 0xd3 -
4c: e129f000 msr CPSR_fc, r0
仔细看37行处,align4,0x12的作用体现出来了吧?为了能够4字节对齐,添加了0x121212共3字节,这样就保证了start_code开始处的地址为4字节的倍数。
接下来我们将刚刚添加的代码删除掉,恢复至start.S刚裁剪完后的状态(不要忘记将58行处的屏蔽去掉)。之后做如下改动(红色部分为改动部位):
- .globl
_start //不占用内存空间 - _start:
b //占用4字节start_code -
ldr pc, _undefined_instruction -
ldr pc, _software_interrupt -
ldr pc, _prefetch_abort -
ldr pc, _data_abort -
ldr pc, _not_used -
ldr pc, _irq - @
ldr pc, _fiq -
- _undefined_instruction:
.word //占用4字节undefined_instruction - _software_interrupt:
.word software_interrupt - _prefetch_abort:
.word prefetch_abort - _data_abort:
.word data_abort - _not_used:
.word not_used - _irq:
.word irq - @_fiq:
.word fiq -
-
.balignl 16,0xdeadbeef
上面一共占用内存为 4字节x7 + 4字节x6 =52字节。离52最近的16的整数倍地址为64,中间差了12个字节,对齐时需要填充3次的0xdeadbeef,下面我们验证下,看推断对不对。
编译之后再进行反汇编,有如下显示:
- eleven@eleven-desktop:~/workspace$
arm-linux-objdump -d start.o -
- start.o:
file format elf32-littlearm -
- Disassembly
of section .text: -
- 00000000
<_start>: -
0: ea00000e b 40 -
4: e59ff010 ldr pc, [pc, #16] ; 1c <_undefined_instruction> -
8: e59ff010 ldr pc, [pc, #16] ; 20 <_software_interrupt> -
c: e59ff010 ldr pc, [pc, #16] ; 24 <_prefetch_abort> -
10: e59ff010 ldr pc, [pc, #16] ; 28 <_data_abort> -
14: e59ff010 ldr pc, [pc, #16] ; 2c <_not_used> -
18: e59ff010 ldr pc, [pc, #16] ; 30 <_irq> -
- 0000001c
<_undefined_instruction>: -
1c: 00000000 .word 0x00000000 -
- 00000020
<_software_interrupt>: -
20: 00000000 .word 0x00000000 -
- 00000024
<_prefetch_abort>: -
24: 00000000 .word 0x00000000 -
- 00000028
<_data_abort>: -
28: 00000000 .word 0x00000000 -
- 0000002c
<_not_used>: -
2c: 00000000 .word 0x00000000 -
- 00000030
<_irq>: -
30: 00000000 .word 0x00000000 -
34: deadbeef .word 0xdeadbeef -
38: deadbeef .word 0xdeadbeef -
3c: deadbeef .word 0xdeadbeef -
- 00000040
: -
40: e10f0000 mrs r0, CPSR -
44: e3c0001f bic r0, r0, #31 ; 0x1f -
48: e38000d3 orr r0, r0, #211 ; 0xd3 -
4c: e129f000 msr CPSR_fc, r0
.balignl
网上查阅,找到了两种答案:
1.类似这样的值很多,像0xabababab,它们的作用就是为内存做标记,插在那里,就表示从这个位置往后的一段有特殊作用的内存,而这个位置往前,禁止访问。
2.正如deadbeef一样,其实是作者故意搞笑,无任何实际意义。
- [转]关于U-BOOT中.balignl 16…
- 关于U-BOOT中.balignl 16,0xdeadbeef的理解
- 关于u-boot中的.balignl 16,0xdeadbeef的理解
- 关于u-boot中的.balignl 16,0xdeadbeef的理解
- 关于u-boot中的.balignl 16,0xdeadbeef 的理解
- 关于u-boot中的.balignl 16,0xdeadbeef的理解
- 关于U-Boot中的u-boot中的.balignl 16,0xdeadbeef
- U-boot .balignl 16,0xdeadbeef浅析
- 关于u-boot start.s文件中指令 .balignl 16,0xdeadbeef
- 关于u-boot start.s文件中指令 .balignl 16,0xdeadbeef
- u-boot中的.balignl 16,0xdeadbeef的理解
- u-boot中的.balignl 16,0xdeadbeef的理解
- u-boot中的.balignl 16,0xdeadbeef的理解
- u-boot中的.balignl 16,0xdeadbeef的理解
- u-boot中的.balignl 16,0xdeadbeef的理解
- u-boot中的.balignl 16,0xdeadbeef的理解
- U-boot 中的 .balignl 16 0xdeadbeef 说明
- u-boot中的.balignl 16,0xdeadbeef的理解
- 安装使用SSH Secure She…
- ubuntu系统根目录下各个目录用途说…
- linux符号链接命令ln详解
- ARM汇编: ldr与mov 、 b与bl
- ARM平台下ldr和bl跳转的区别
- [转]关于U-BOOT中.balignl 16…
- linux中/etc/inittab文件分析
- Python2.7下安装Scrapy框架
- 关于弹出窗实例
- upper_bound无法用在结构体重
- jvm内存溢出和内存泄漏的区别
- stm32的bootloader和APP
- ajax调用controller
- AndroidStudio插件GsonFormat之Json快速转换JavaBean