GNU ARM汇编的.balignl对齐实验

发布者:星辰小鹿最新更新时间:2016-04-20 来源: eefocus关键字:GNU  ARM汇编的  对齐实验 手机看文章 扫描二维码
随时随地手机看文章
在u-boot的start.s源文件中出现“.balignl 16 0xdeadbeef”语句,这条语句是实现地址对齐的。

.balignl与. align类似,完整的laign语句格式为:.align {alignment} {,fill} {,max}

alignment用于指定对齐方式,可能的取值为2的次幂,缺省为4。fill是填充内容,缺省用0填充。max是填充字节数最大值,如果填充字节数超过max, 不进行对齐。

下面分4种情况进行对比:

1.正常情况

.word 0x12345678
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef

此时.balignl位于的地址是0x50,恰好是16的倍数,所以不填充。如图所示:

2.填充一个字

//.word 0x12345678
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef

此时将0x12345678注释掉,.balignl位于的地址是0x4c,不是16的倍数,所以要使用0xdeadbeef进行填充。如图所示:

3.填充三个字

.word 0x12345678
.word 0x12345678
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef

此时加多一个0x12345678,使.balignl的地址位于0x54,不是16的倍数,所以要填充到0x5f,内容使用指定的0xdeadbeef。如图所示:

4.超过限制不填充

.word 0x12345678
.word 0x12345678
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef,8

此时限制填充最多8个字节,但是需要填充12个字节,所以不填充。如图所示:

 

补充:

UBOOT问题收集(1)--balignl 16, 0xdeadbeef
2011年03月27日 星期日 下午 12:57

.balignl 16,0xdeadbeef

是uboot起始文件下的start.S文件57行.

因为好奇这个代码的含义,所以百度了下:

====================================================

(http://haoyeren.blog.sohu.com/84511571.html)

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

.balign 8, 0xde

它的意思就是在以当前地址开始,在地址为8的倍数的位置的前面填入一个字节内容为0xde的内容。如果当前地址正好是8的倍数,则没有东西被写入到内存。

=======================================================

http://blog.163.com/mcu_expert/blog/static/131245153201073125947792/

关于.balignl 16,0xdeadbeef这句,功能说明没有错,就是想在某个位置插入0xdeadbeef这个特殊的内存值。错就错在我对这个16的理解上面。16是 16个字节,这是没有错的,但是这个16的由来,并不是我所理解的得至少为16个字节,才能在任何情况下保证插入这个特殊的内存值。我在此篇博客的留言中,回答某位网友的提问,举了个pc为0x00000007地址,偏移量某为8字节时,这个时候就不够4字节的内容了,以此推导出的,至少有16个字节才能保证这个特殊的内存值的插入也是完全错误的。

举个反例,如果按给那位网友的解释,那就算有16个字节的偏移量,那如果pc地址为0x0000000F时,也只有一个字符的空间,那这个deadbeef的值还是不够。以此类推,就算这个值为任意一值,按我之前解释的错误逻辑,也都是有不满足的情况的,呵呵。所以我之前的推论有误,特此更正。我现在把16这个值的由来进行说明。

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的倍数 (60到64之间都不是8的倍数,同样也不是16的倍数,所以写8和16都可行),如果写8,也正好插到64前面,也即60这个内存起始地址。如果更大一点儿的呢,那么填32也可以达到同样的效果,即.balignl 32,0xdeadbeef,道理同上。当然,不能为4,因为pc值在任何时候,都是4的倍数 (60是4的倍数),只要不为0就为4的倍数,呵呵,这个值不行,如果用了这个值,0xdeadbeef永远也插不进去,呵呵。


关键字:GNU  ARM汇编的  对齐实验 引用地址:GNU ARM汇编的.balignl对齐实验

上一篇:S3C2440 clock 工作原理
下一篇:ARM标准汇编与GNU汇编

推荐阅读最新更新时间:2024-03-16 14:51

GNU ARM汇编--(五)中断汇编之嵌套中断处理
在上篇《GNU ARM汇编--(四)中断汇编之非嵌套中断处理》中分析了最简单的中断处理的写法,再看TQ2440启动代码中的中断向量表的写法就一目了然了.今天抽时间对嵌套中断处理的学习做下整理. 嵌套中断处理的核心代码如下: view plain copy ;/* ; * ____________________________________________________________________ ; * ; * Copyright (c) 2004, Andrew N. Sloss, Chris Wright and Dominic Symes ; * All rights
[单片机]
关于ARM汇编特殊符号
先前企图全部靠自己写一个bootloader,结果尝试了下,花了4天时间查各种技术资料,写了个startup.s文件出来,写的过程中才发现,原来还有很多问题是我基本上不知道的,比如说如何进行ARM的位操作、如何将堆栈设置到RAM中、UART的波特率计算方法等问题。 在边写边查资料的过程中,我又发现了别人的一些程序我看不懂。。。因为除了EQU、DCD等我基本不用伪指令。。。 所以我开始看44B0 BootLoader的范例程序,可能是人家水平实在比较高,也可能是俺的水平确实有限,总之是有些地方看不怎么懂,特别是一些个特殊符号,现特将那些个麻烦的符号总结下: 特殊符号 | 对应指令 | 含义
[单片机]
GNU ARM汇编入门
任何汇编行都是如下结构: .macro SHIFTLEFT a, b .if b 0 MOV a, a, ASR #-b .exitm .endif MOV a, a, LSL #b .endm .rept number_of_times 循环执行.endr前的代码段number_of_times次。 (与armasm中的WEN相似) .irp param {, val_1 } {, val_2 } 循环执行.endr前的代码段,param依次取后面给出的值。 在循环执行的代码段中必须以 param 表示参数。 .endr 结束循环(与armasm中的WEND相似).
[单片机]
ARM处理器学习之GPIO操作篇(gnu link script)
1:主要内容 本文主要介绍了VMA、LMA的相关概念,gnu link script的作用和使用方法。 2:引言 我们程序员刚开始学习编写程序时,都会接触到一个 *.C 文件要经过编译、链接等过程才能变成可以执行的程序。至于这里的链接到底怎么回事,我们今天就来谈谈这方面的内容。现在,我们有这样一套ARM7的硬件开发环境,0X80000000地址开始BANK0 我们用的是NorFlash,0X40000000地址是芯片内部的RAM。我编译、链接的程序下载到0x80000000地址处。而真正运行时,一部分初始化代码在0X80000000运行,初始化完毕后,将主要工作的代码copy到内部RAM 0X40000000开始的地方运
[单片机]
ARM处理器学习之GPIO操作篇(<font color='red'>gnu</font> link script)
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
502 Bad Gateway

502 Bad Gateway


openresty
设计资源 培训 开发板 精华推荐

502 Bad Gateway

502 Bad Gateway


openresty
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

502 Bad Gateway

502 Bad Gateway


openresty
502 Bad Gateway

502 Bad Gateway


openresty
502 Bad Gateway

502 Bad Gateway


openresty
随便看看
    502 Bad Gateway

    502 Bad Gateway


    openresty
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
502 Bad Gateway

502 Bad Gateway


openresty