于关u-boot中的.balignl 16,0xdeadbeef的理解

先对版权问题做一个申明大笑,文章转自  http://haoyeren.blog.sohu.com/84511571.html  但对作者的文章进行了梳理,可以让读者的理解一步到位。

最近在分析u-boot的源代码,看到这一行:

.balignl 16,0xdeadbeef

不理解了,不知道为什么要这样写,0xdeadbeef,明显是个单词组,写在这里有何意义呢?然后在查阅了众多资料的时候才晃然大悟。

下面我一步步来说明:

首先要弄明白 .balignl  的意思,这个其实应该算是一个伪操作符,伪操作符的意思就是机器码里,并没有一个汇编指令与其对应,是编译器来实现其功能的。.balignl 是 .balign 的变体,.balign 的意思是,在以当前地址开始,地址计数器必须是以第一个参数为整数倍的地址为尾,紧挨着这个前面记录一个一定长度的信息,信息的长度由指令名结合第一个参数决定,信息内容为第二个参数。

.balign 8, 0xde

它的意思就是在以当前地址开始,在地址为 8 的倍数的位置的前面填入一个字节内容为0xde的内容。如果当前地址正好是8的倍数,则没有东西被写入到内存。( 为什么是填入一个字节的内容呢,这是由 .balign 里的 n 决定的 )

那么以此类推,.balignw则表示第二个参数存入的内容长度为一个字长,即两个字节(16位),所以一般有这样的形式出现:

.balignw 4,0x368d

它的意思就是在以当前地址开始,在地址为 4 的倍数的位置的前面填入2个字节内容为 0x368d 的内容。如果当前地址正好是 4 的倍数,则没有东西被写入到内存。为什么是填入2个字节的内容呢,这是由 .baligw 里的 w 决定的 )

因为现在填入的内容为16位了,那就存在以下几种情况

1.当前地址没有偏移就满足了以4为倍数的地址

2.当前地址偏移了1个字节就满足了要求

3.当前地址偏移了2个字节就满足了要求

4.当然地址编移了3个字节就满足了要求

当没有偏移的时候,地址中间肯定没有办法填上信息;
当偏移1个字节的时候,地址中间空隙不够,所以填入的数值,是末定义,也就是说,填入的什么值,不清楚;
当偏移为2个字节的时候,地址中间的空隙正好填入手面的数据,所以就填上了;
当偏移为3个字节的时候,地址中间的空隙大于所要填的内容。手册上给的定义是末定义,在我的理解,其实这个未定义,是指这三个偏移的地址整体的内容是末知的。但是其中必定含有要填的2个字节,只是另一个被填充的字节内容不知道而已

所以以此类推,

.balignl,这个指令用来填与一个字,即内容长度为一个字,即4个字节的长度

.balignl  16  , 0xdeadbeef 

它的意思就是在以当前地址开始,在地址为 16 的倍数的位置的前面填入一个字节内容为0xdeadbeef 的内容。如果当前地址正好是 16 的倍数,则没有东西被写入到内存。为什么是填入4个字节的内容呢,这是由 .baligl 里的 l 决定的 )

那0xdeadbeef是什么意思呢?经过我查找才发现,类似这样的值很多,像0xabababab,它的作用大概就是为内存做标记,有点儿像个小旗子,插在那里,表示从这个位置往后,就是干什么的内存,这个位置往前,禁止访问。

其实关于.balignl 16,0xdeadbeef 这句,就是想在某个位置插入0xdeadbeef这个特殊的内存值。16是16个字(一个字是4个字节),但是这个16的由来是什么样子的呢?

( 博客的留言中,某位网友提问,举了个pc为0x00000007地址,这是不可能的。因为ARM920T处理器核心,支持32位与16位两种指令长度,16位的指令叫thumb指令集,由于我使用的是32位指令集,所以一切都是以32位指令集进行说明。既然是32位指令集,所以一条指令就占32位,即4字节,所以在调试器中,地址的显示也是4字节一跳的,所以pc的值,也是4字节一跳的,并不存在可能pc的值为0x00000007的情况,呵呵。)

这个地方偏移量填16,是因为

.globl _start  //不占内存
_start: b       start_code //占4字节内存
 ldr pc, _undefined_instruction //占4字节内存
 ldr pc, _software_interrupt //占4字节内存
 ldr pc, _prefetch_abort //占4字节内存
 ldr pc, _data_abort //占4字节内存
 ldr pc, _not_used //占4字节内存
 ldr pc, _irq //占4字节内存
 ldr pc, _fiq //占4字节内存

占了4x8=32字节内存。

_undefined_instruction: .word undefined_instruction //占4字节内存
_software_interrupt: .word software_interrupt //占4字节内存
_prefetch_abort: .word prefetch_abort //占4字节内存
_data_abort:  .word data_abort //占4字节内存
_not_used:  .word not_used //占4字节内存
_irq:   .word irq //占4字节内存
_fiq:   .word fiq //占4字节内存

占了4x7=28字节内存。

所以在这个.balignl 16,0xdeadbeef指令之前,一共占了4x15=60个字节的内存,所以本代码的作者当时就简单的在15这个数上,加了个1,即16,把当前指针往后移到地址为64的位置,然后在前面插上了0xdeadbeef这个特殊的值。可以写成.balignl 8,0xdeadbeef,也可以达到同样的目的。因为60不是8的倍数,但是64是8的倍数,如果写8,也正好插到64前面,也即60这个内存起始地址。如果更大一点儿的呢,那么填32也可以达到同样的效果,即.balignl 32,0xdeadbeef,道理同上。当然,不能为4,因为pc值在任何时候,都是4的倍数,只要不为0就为4的倍数,呵呵,这个值不行,如果用了这个值,0xdeadbeef永远也插不进去,呵呵。

.balignl是条伪指令,用于字节对齐的。对于S3C2440来说,它是32位处理器,要求指令必须4字节对齐。与.balignl相似的伪指令如下表所示:

四种功能基本相同,不同之处在于填充时的字节数。.align.balign1个字节1个字节的填充(区别在于对齐方式不用),.balignw2个字节2个字节的填充,而.balignl一次填充4个字节。我们以balignl为例说明,它的完整指令格式为: 

.balignl {alignment} {,fill} {,max}

第一个参数alignment为一个正整数,对齐时要以alignment的值的整数倍为结束地址(补充:这段描述摘录于别人博客,经过自己验证之后发现.align与其他三个以b开头的伪指令不同是以2^alignment的整数倍为地址,后面会加以讲解),以当前地址为起始地址,进行字节填充,比如当前地址为20,而alignment的值我们设定为16,那么字节填充自20开始,结束于20后第一个16的倍数地址处,即32处。

第二个参数fill即我们选定的,用来填充的数值。balignl模式下,最大为4字节,不够4字节系统会自动补够4字节,此参数可选,不标则采用默认值0

第三个参数max也是可选项,默认值为alignment。若对齐时偏移量大于max,则不偏移。同上例,从16--32,偏移量为16,如果max我们设置为8,那么该偏移不进行。

为了更容易理解,截取start.S最开始一部分代码做个试验,对它单独编译。文件名为test.S,代码如下:

.globl _start
_start: b reset
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 0x11223344
_software_interrupt:
.word 0x11223344
_prefetch_abort:
.word 0x11223344
_data_abort:
.word 0x11223344
_not_used:
.word 0x11223344
_irq:
.word 0x11223344
_fiq:
.word 0x11223344
_pad:
.word 0x12345678 /* now 16*4=64 */
reset:
.word 0x11003300
.global _end_vect
_end_vect:
.balignl 8,0xdeadbeef
b reset
.align 3,0x12
.align 3,0xfd

反汇编的结果如下:


text.s中 最后四句代码是

.balignl 8,0xdeadbeef   ********** 在地址为 0x44 处,即68,最接近8的倍数的是72,他会以4个字节为单位填充,填充内容为 0xdeadbeef
b reset     ********** 在地址为 0x
48 处

.align 3,0x12    ********** 在地址为 0x4c 处,即76,最接近2^3=8的倍数的是80,他会以1字节单位填充,填充单位是0x12
.align 3,0xfd   ********** 在地址为 0x50 处,即80处,满足是2^3=8的倍数,不填充。相当于该指令不存在。



以上仅仅是我个人的理解,有可能存在披露,请有更了解这块的大侠给予指正 ,您的评论是我前进的不懈动力 得意
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值