zoukankan      html  css  js  c++  java
  • 关于keil编译cortexm3纯汇编时为什么问题使用align地址问题

      在编译下面一段代码时:

    STACK_TOP	EQU	0x20002000
    	AREA	Reset,CODE,READONLY
    	DCD	0x20002000
    	DCD	Start
    	ENTRY
    ;	CODE16 
    
    Start
    	ldr	r2,=Test
      	LDRD r0,r1,[r2,#4]
    	LDRD r0,r1,[r2]
    	LDRD r0,r1,[r2]
    ;	movs	r0,r0
    ;	NOP
    ;	align 4
    Test
    	DCD	0x12345678
    	END
    我发现,如果加上NOP或align4,程序就不会跑飞,否则程序就跑飞了。

      经调试发现:    如果不加NOP或align 4的话产生的Test的标号地址就会产生错误,而LDRD 指令操作的地址必须是4字节对节的,如果使用的地址不是四字节对齐,那么程序就会产生异常,所以程序就跑飞了。  那么为什么不加NOP或align 4的话Test标号地址就会产生错误呢?  来看一段手册上的话:
    也就是说DCD是需要标号地址按字对齐的,如果你没有对齐就可以看到如下的编译警告:test.asm(18): warning: A1581W: Added 2 bytes of padding at address 0x1a
    这说明编译器会自动添加两个字节来帮你对齐,数据分布情况和下面很相似:

    这说明编译器会自动添加两个字节来帮你对齐,数据分布情况和下面很相似:
    STACK_TOP	EQU	0x20002000
    	AREA	Reset,CODE,READONLY
    	DCD	0x20002000
    	DCD	Start
    	ENTRY
    ;	CODE16 
    
    Start
    	ldr	r2,=Test
      	LDRD r0,r1,[r2,#4]
    	LDRD r0,r1,[r2]
    	LDRD r0,r1,[r2]
    ;	movs	r0,r0
    ;	NOP
    ;	align 4
    Test
    	dcb	00	    ;编译器自动添加
    	dcb	00      ;编译器自动添加,而movs	r0,r0的机器码就是0x0000,会被	
    	            ;编译器翻译成movs r0,r0,不是当作数据0x0000
    	DCDU	0x12345678
    	END
    也许看来这样就完美了,但是程序依然会跑飞。原因有两点:
     1.即使加了两个字节那么Test的标号地址依然不是四字节对齐。

     2.这两个字节的零会被编译器当作指令来处理的,这也就是说Test标号会被编译器来当作代码标号来处理,看到了吧,我们的数据编译器一插手就变成代码了,实在无奈的很。再来看一段手册上的讲解:

                          

    也就是实际上LDR r2,=Test执行后,r2=Test+1这也解释了为什么不加NOP或align 4的话r2=0x8000017而加了NOP或Align 4就r2=0x8000018。那么来看一下,加nop或align 4后的效果:
    STACK_TOP	EQU	0x20002000
    	AREA	Reset,CODE,READONLY
    	DCD	0x20002000
    	DCD	Start
    	ENTRY
    ;	CODE16 
    
    Start
    	ldr	r2,=Test
      	LDRD r0,r1,[r2,#4]
    	LDRD r0,r1,[r2]
    	LDRD r0,r1,[r2]
    ;	movs	r0,r0
    	; 如果是align 4会被加两个节字的movs r0,r0(机器码为0x0000)
    	; 如果是nop 则会被加上nop的机器码(0xBF00)
    
    ;	NOP
    
    	align 4
    Test
    	DCDU	0x12345678
    	END
    需要说明的是,我总是把align 和nop 放在一块说,并不是说nop也具有对齐作用。是因为加上nop后刚好可以使Test标号地址放在4字节对齐的其他地方。在其他地方,nop也许并无此作用。
    
    
    
    
  • 相关阅读:
    VNC远程控制软件是什么?有没有更好的远程桌面控制解决方案?
    目前国内最热门的四款远程桌面控制软件
    深入Redis命令的执行过程
    深入Redis客户端(redis客户端属性、redis缓冲区、关闭redis客户端)
    Springboot拦截器的使用
    Springboot使用Undertow
    Jenkins parallel并行构建
    Jenkins使用docker构建
    Redis 的键命令、HyperLogLog 命令、脚本命令、连接命令、服务器命令
    Redis Set和ZSet常用命令
  • 原文地址:https://www.cnblogs.com/findstr/p/2803707.html
Copyright © 2011-2022 走看看