珠宝的故事 2018-04-12
在 Uboot 的 Start.S 中存在以下源码:
.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
那么这个 .balignl 16,0xdeadbeef (死牛肉) 的作用是什么呢?我们先从 balignl 这个伪指令说起:
.balign[wl] abs-expr, abs-expr, abs-expr 第一个参数是一个整数的绝对值,表示后面的指令对齐在它的倍数地址上。 第二个参数也是个绝对值让你指定要填充的指,随便指定,比如 0x55aa 之类的都可以。此参数可选,如果省略,那么默认就用 0 来填充了。 第三个参数也是可选的,表示为了对齐,最大只能跳过多少个字节;但是如果需要跳过更多的字节,那么这里添加的对齐就无效了。
.balignw 和 .balignl 是 .balign 的变体;它们分别表示填充 2 个字节 (word) 及填充 4 个字节 (long) 。
我们以下面的程序为例,来发现 0xdeadbeef 的奥妙。
_start: b reset nop .balignl 16, 0xdeadbeef reset: ldr r0, =0x40000000
00000000 <_start>: 0: ea000002 b 10 4: e1a00000 nop ; (mov r0, r0) 8: deadbeef cdple 14, 10, cr11, cr13, cr15, {7} c: deadbeef cdple 14, 10, cr11, cr13, cr15, {7} 00000010 <reset>: 10: e3a00101 mov r0, #1073741824 ; 0x40000000 14: e1a00000 nop ; (mov r0, r0) 18: e1a00000 nop ; (mov r0, r0) 1c: e1a00000 nop ; (mov r0, r0)
由上可见,填充了 8 个字节数据,也就是 2 个 0xdeadbeef 。这样, ld r0, =0x40000000 就对齐到 0x10 地址处,0x10 就是 16。
假如将上面的程序 .balignl 16, 0xdeadbeef 改为 .balignl 16, 0xdeadbeef, 4 ,那么反汇编则会看到下面的结果:
Disassembly of section .text: 00000000 <_start>: 0: ea000000 b 8 4: e1a00000 nop ; (mov r0, r0) 00000008 : 8: e3a00101 mov r0, #1073741824 ; 0x40000000 c: e1a00000 nop ; (mov r0, r0)
如果要以 16 字节对齐的话需要再填充 8 个字节,因为指定最大才能跳过 4 个字节来对齐,所以伪指令无效。
参考自:www.linuxidc.com/Linux/2013-03/81025.htm