Output from arbitrary dereferenced pointer

微笑、不失礼 提交于 2019-12-01 08:20:34

After suspecting memory alignment I did a quick google =)

http://awayitworks.blogspot.co.nz/2010/02/arm-memory-alignment.html

Stated in that article:

Till ARMv4 architecture, it’s assumed that address given for fetching contents is memory aligned...a 32-bit data fetch should have address aligned to 32-bit and so on. As guessed correctly the problem is only for 32-bit and 16-bit data fetching. ARM ignores lower 2-bits of address if the data fetch is 32-bit, and ignores lower 1-bit if data fetch is 16-bit. So, in all if the address is not properly aligned then data fetch will be erroneous.

Note the last sentence =)

If you require the behaviour that you expected on x86, you'll have to explicitly build the integers from chars, ie (assuming little-endian):

// Endian-specific
inline unsigned long ulong_at( const char *p ) {
    return ((unsigned long)p[0])
         | (((unsigned long)p[1]) << 8)
         | (((unsigned long)p[2]) << 16)
         | (((unsigned long)p[3]) << 24);
}

Or perhaps:

// Architecture-specific
inline unsigned long ulong_at( const char *p ) {
    unsigned long val;
    char *v = (char*)&val;
    v[0] = p[0];
    v[1] = p[1];
    v[2] = p[2];
    v[3] = p[3];
    return val;
}

If you want to fetch a four-byte word from memory, the address should be a multiple of four.

Misaligned access is generally a bad idea on any architecture. Some will throw a SEGFAULT, others will transparently handle the fault and — very slowly — synthesise the correct value by fetching the two words containing the desired value and stitching them together. It appears (though I'm not an expert) that ARM is fetching the four-byte slot that the pointer occupies and rotating the result so that the LSB of the register matches the pointer.

The problem is that you are dereferencing a non-aligned pointer, which, depending on the hardware, may be undefined. Many architectures assume that a long* will be aligned to 32 bits of memory, that is, be divisible by 4. If it is not, the result is undefined.

In general, C doesn't guarantee what happens when you cast one pointer type to another.

Endianness doesn't explain this behavior. It seems the ARM processor doesn't allow four-byte memory accesses not aligned a four-byte boundary, and the output indicates that the processor read the memory as though it was subjected to a rightward bitwise rotation of 8 bits per byte accessed past the four-byte boundary. See this Wikipedia article for more information on memory alignment.

In fact, on some architectures, a bus error may occur if you attempt to perform an unaligned memory access of this kind.

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