align

今决定认真分析一下u-boot的代码,但一开始就被“.balignl 16 0xdeadbeef”这条语句难住了,还好,google了一下,找到了《分析了一下 align 的用法》这篇文章,作者写得很好,看完后,我根据自己的实验结果,做了适当的更改,以让自己看起来更明白,把它记录如下:
.align 就是用来对齐的,究竟怎么对齐,有啥情况?下面分析一下
(一)
$vim align1.s
在新建的文件编辑以下代码:
 
_start:
    b reset
    .byte 0x55
    .byte 0xaa
reset:
    ldr r0, =0x53000000
保存后,执行如下命令:
$arm-linux-as align1.s -o align1.o
这样的话有的编译器可能会报错,但我的编译器没有报错,虽然没有报错,但反汇编的结果显示,运行时肯定会出问题。
执行如下命令:
$arm-linux-objdump -d align1.o
显示如下:
 00000000 <_start>:
   0: ea000000  b  4  <_start+0x4>
   4: 0453aa55  ldreqb s1, [r3], -#2645
00000006 <reset>:
   6: e3a00453  mov r0, #1392508928 ; 0x53000000
 
很明显,跳转语句应该跳到0x06处,而它却跳到0x04处,我们分析一下。首先,ARM指令都是32位的,这里要求4字节(一个word)对齐,b reset 指令占了4个字节,接着我们用 .byte 指令定义2个常数,因为这里是 byte 类型,所以只占了八位,两个数据,一共占16位。由于连接器内部有一个程序地址计数指针,里面保存着当前的地址,这地址指针是连接器内部工作需要的,我们不需要理会,只需要了解有这么一个机制。假如_start从0x00,第一条指令占4个byte,然后连续分配2个byte,当前地址指针应该是 0x06,那么问题来了,下条指令,也就是标号 reset 处的ldr指令,是一条ARM指令,这要求是 4个字节对齐的,当前的地址为 0x06,并不能满足这个要求,所以编译器自动将地址指针跳到0x04。
 
解决办法很简单,我们只需要加一条 .align 指令,问题就解决了
_start:
    b reset
    .byte 0x55
    .byte 0xaa
    .align
reset:
    ldr r0, =0x53000000
 
 
编译结果是:
00000000 <_start>:
   0: ea000000  b 8 <reset>
   4: 0000aa55  andeq sl, r0, r5, asr sl
00000008 <reset>:
   8: e3a00453  mov r0, #1392508928 ; 0x53000000
 
在两个 .byte 指令后自动补零,直到满足地址要求为止。这里就是将地址累加到 0x08符合ARM指令要求,所以在这里写入下条指令。这是基本内容,下面研究一下其他
 
(二).align 5
这里只是一个例子,重点想说的是 这个 .align 5 后面的 5 究竟是什么意思? uboot里面就有这指令。我们继续做做试验,看看编译结果是什么
 
_start:
    b reset
   
    .align 5
    .byte 0x55
   
    .align 5
    .byte 0xaa
   
    .align
reset:
    ldr r0, =0x53000000
 
编译结果:
00000000 <_start>:
   0: ea00000f  b 44 <reset>
 ...
  20: 00000055  andeq r0, r0, r5, asr r0
 ...
  40: 000000aa  andeq r0, r0, sl, lsr #1
00000044 <reset>:
  44: e3a00453  mov r0, #1392508928 ; 0x53000000
我们发现这编译结果有点意思,这地址分配一下子上去了,但是也不难,分析一下就OK,看那个 20 和 40 ,这里是十六进制,也就是 32 和 64了。那么很容易可以联想到,这里做的是幂运算,也就是 .align 5 对齐的地址为 2^5 = 32,之前的地址全部补零。
(三).balignl 16,0xdeadbeef
_start:
    b reset
   
    .balignl 16,0xdeadbeef
   
reset:
    ldr r0, =0x53000000
 
在看uboot的时候还有这么一个语句,查了半天as的手册才找到,囧,不过稍微做了一下实现,觉得又不是很难,我们看看结果:
00000000 <_start>:
   0: ea000002  b 10 <reset>
   4: deadbeef  cdple 14, 10, cr11, cr13, cr15, {7}
   8: deadbeef  cdple 14, 10, cr11, cr13, cr15, {7}
   c: deadbeef  cdple 14, 10, cr11, cr13, cr15, {7}
00000010 <reset>:
  10: e3a00453  mov r0, #1392508928 ; 0x53000000
可以看出,这指令就是将 deadbeef字符串填进去,一共填到地址为16对齐的地方为指,上面可以看到,这里填到 0x10 也就是 16了。
### ALIGN 方法概述 ALIGN 是一种用于对齐不同组件的方法,在不同的上下文中具有特定的应用场景。在编程领域,特别是在 Jetpack Compose 中,`Modifier.align()` 方法被广泛应用于布局调整和位置控制[^2]。 #### 使用范围 `Modifier.align()` 方法主要用于 Column、Row 和 Box 布局作用域内。如果尝试在这些容器之外使用 `align` 方法,则会出现编译错误:“Cannot access 'BoxScopeInstance': it is internal”。这是因为该方法的设计初衷是为了限定其仅能在指定的作用域中生效,从而确保布局逻辑的一致性和可维护性。 以下是正确的使用方式: ```kotlin import androidx.compose.foundation.layout.* import androidx.compose.runtime.* @Composable fun AlignExample() { Box(modifier = Modifier.size(200.dp)) { Text( text = "Aligned to Bottom End", modifier = Modifier .background(Color.LightGray) .align(Alignment.BottomEnd) // 正确的 align 调用 ) } } ``` 上述代码展示了如何通过 `Modifier.align()` 将子组件相对于父级 Box 进行精确的位置调整。注意,此方法无法脱离 Box 或其他支持 Alignment 的容器独立运行。 --- ### 技术背景与应用场景 除了 UI 开发中的具体实现外,“ALIGN”作为一个概念还可能涉及数据科学、机器学习以及自然语言处理等领域。例如,在某些研究论文或框架设计中,“alignment” 可指代模型参数之间的校准过程或者多模态特征的空间映射关系。然而,这种语义下的 ALIGN 并不直接对应于编程语法层面的操作[^3]。 对于 IT 上下文而言,理解 `align` 函数的核心在于掌握其适用环境及其约束条件。只有遵循官方文档推荐的最佳实践才能避免潜在陷阱并充分利用这一工具带来的灵活性优势。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值