What is non-aligned access? (ARM/Keil)

非 Y 不嫁゛ 提交于 2019-11-29 04:53:57

The issue is that the address you use for a 32-bit (4-byte) memory operation must be aligned to a 4-byte boundary. This means the address must be a multiple of 4, or if you prefer, the bottom two bits of the address must be zero.

In this case, the closest 4-byte aligned addresses would be 0x7F7F7F7C or 0x7F7F7F80.

Similarly, LDRH/STRH require 2-byte alignment, whereas LDRB/STRB can operate anywhere (1-byte alignment == unaligned).

In general the compiler/assembler takes care of making sure your variables are aligned correctly for the size they are - you should only run into this if you're generating addresses yourself (as per the question).

When we talk about decades we talk about the 70's or 80s, etc. We dont talk about the 62s or the 94s. 70, 80, 90 are numbers that are aligned on tens. 10 to the power 1. centuries are things aligned on 10 to the power 2, 100s. the 1900s the 1400s, etc. Or think of it as that many number of zeros at the end of the number.

Same for addressing bytes. With a single year being the smallest unit in the example above a byte is the smallest unit when we talk about memory addresses, a bit is smaller yes but we dont address bits individually. We address bytes. Like years above, any individual year can be talked about 1971, 1436, etc. Same with an address 0x1234, 0x21. but when we want to start doing 16 bit accesses using an 8 bit addressing scheme that is like talking about decades, 2 to the power 1 so units of 2 0,2,4,6,8 are ALIGNED address for accessing 2 to the power of 1 number of bytes (one 16 bit number, 2 bytes). if we want to do a 32 bit access that is a 4 byte access or 2 to the power 2, like centuries above we need two zeros at the end of the address 0x0, 0x4, 0x8, and so on (a 4 is 100 binary, an 8 is 1000 binary 0xC is 1100 binary, two zeros at the end). And so on 64 bit accesses are 8 bytes or 2 to the power of 3 number of bytes so an aligned address has 3 zeros at the end anything without 3 zeros at the end is unaligned.

Your 32 bit access above uses an address that ends in 0x7F which in binary is 01111111 the last two bits are 11 which is not zeros, so that is not an aligned access.

What does arm or mips or any other computer do when you do an unaligned access, some trap an exception and not let you do it some swizzle the data around in a way you wouldnt expect, and some just let you do it. And some like the newer arms can be configured at runtime for different responses, newer arms can let you have that x86 like experience.

Unfortunately there are too many x86's and to many bad programming habits that have come out of the x86 not expressing the penalty more, there is definitely a penalty on an x86 for using unaligned accesses, the penalty is performance. arm and mips and others prefer to just kill your program with an exception as a very harsh penalty but a good one because it teaches you not to do that.

If you have something at that address then you should probably access it using smaller transfer sizes (four individual byte transfers or two byte and one halfword) and the combine the bytes together into a 32 bit number if you really need it as a 32 bit number.

Some platforms will not allow unaligned access to memory, as you have noticed. Reads and writes are expected to be aligned on N byte boundaries. I don't know your platform, but let's assume we require 4-byte alignment.

You have an address 0x7F7F7F7F. 0x7F7F7F7F % 4 == 3, i.e., you have a remainder and this address is not aligned on a four byte boundary. Unaligned access on many platforms will be slower than aligned access (you may want to look at how C pads structures), but some architectures simply do not allow it at all.

So, if you're going to be plopping data down at fixed addresses, make sure said address begins at an N byte boundary (where N is 4 for LDR on an ARM 7). Your compiler will synthesize aligned access for you, but not if you're hardcoding your addresses (obviously).

From some quick reading, it seems that unaligned accesses are in fact allowed on ARM7, but there is a caveat. From the link below:

Further, unaligned accesses are only allowed to regions marked as Normal memory type, and unaligned access support must be enabled by setting the SCTLR.A bit in the system control coprocessor. Attempts to perform unaligned accesses when not allowed will cause an alignment fault (data abort).

Further reading: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html

Everything above is correct but i am not sure that the code you show will do what you really want: I guess you define correctly LABEL which is word aligned so why to load an hex address as the place you want to store. Maybe you just want to store the value x'7F7F7F7F' at the memory place LABEL. In this case you will have to write STR R0, [R1]

shreekant

check the data type.

eg Suppose you have declared an array as unsigned int V1[25][25]; and you have extern it as extern int (*V1)[22];

suppose you are using function that returns this as,

unsigned long func()
   {`unsigned long k;
      return (V1[0][0]+k);   //you will get an error.'

   }

to avoid this use same data type in extern as extern unsigned int V1[25][25].

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!