views:

193

answers:

4

Hello people!

This is currently a homework project that me and my teammate are stuck on. We haven't been given much of an introduction into Assembly, and this is supposed to be our first homework exercise. The task is to create a program that converts 0xAABBCCDD into 0xDDCCBBAA.

I'm not looking for an answer, as that would defeat the purpose, but we are getting severely frustrated over the difficulty of this stupid thing. We think we have a good start in creating a viable solution, but we just cannot come up with the rest of the program.

First, we mask every single tupel (aa), (bb), (cc), (dd) into a different register:

LDR R0, LittleEndian    // 0xAABBCCDD
AND R1, R0, #0xFF000000 // 0xAA
AND R2, R0, #0x00FF0000 // 0xBB
AND R3, R0, #0x0000FF00 // 0xCC
AND R4, R0, #0x000000FF // 0xDD

Then we try to re-align them into the R0 register, but hell if we could come up with a good solution...

Our best effort came from:

ORR R0, R1, LSL #24 
ORR R0, R2, LSL #8
ORR R0, R3, LSR #8
ORR R0, R4, LSR #24

which produced 0xBBBBCCDD for some odd reason; we really don't know.

Any hints would be greatly appreciated. Again, we are asking for help, but not for a solution.

Cheers!

+3  A: 

Your code looks good so far.

Your mistake is, that you have reversed the meaning of LSL and LSR.

Take R0 for example:

AND R1, R0, #0xFF000000 // 0xAA

The result of this operation does not generate 0xAA. It generates 0xAA000000.

The second instruction that processes R1:

ORR R0, R1, LSL #24 

Will shift the data out of the register. There is simply no space left of the top 8 bits.

If otoh you shift the data to the right like this:

ORR R0, R1, LSR #24 

The data ends up in the lowest byte. Where you want it to be. That should give you enough help to get your homework done. :-)

Nils Pipenbrinck
Thanks for your support! I did have personally another question, if you don't mind. The #24 represents 2^n, in this case 2^24, right? But if we only have 0x00000000 = 8 bits in total, then we're really doing overkill and writing #24 isn't necessary, or?
SoulBeaver
@SoulBeaver: No, you have 8 "nibbles" (hex digits), each of which is 4 bits. `0xAABBCCDD` is 32 bits wide.
Stephen Canon
+3  A: 

I think you need to do (ARM a bit rusty):

MOV R0, R1, LSR #24 
ORR R0, R2, LSR #8
ORR R0, R3, LSL #8
ORR R0, R4, LSL #24

That is, MOV in the first instruction as you don't want anything from the old R0 to affect the new value.

I can't see any way to make this more 'hint' like as you've effectively done all the work anyway.

Charles Bailey
Do you think you could elaborate a little more on the workings of this code? Why was it necessary to first MOV the entire thing out of the way?
SoulBeaver
Well, if you've still got the original value of R0 in R0 and you merely 'or' the new bytes into R0, then rather than having just the re-positioned bytes R0 will orred with the original value of R0 producing an incorrect result.
Charles Bailey
Thanks for the explanation! Helped a lot ^^
SoulBeaver
+1  A: 

Also, it looks like you may not have cleared out the R0 register (set it to all zero bits) before using ORR to move the bits back.

Greg Hewgill
+3  A: 

On ARMv6 and above, you can just use the rev instruction, but I assume that you're not allowed to do that for whatever reason.

As to why you got the result you did, I've gone through your code and commented the actual values of the registers being operated upon:

LDR R0, LittleEndian    // r0 = 0xAABBCCDD
AND R1, R0, #0xFF000000 // r1 = 0xAA000000
AND R2, R0, #0x00FF0000 // r2 = 0x00BB0000
AND R3, R0, #0x0000FF00 // r3 = 0x0000CC00
AND R4, R0, #0x000000FF // r4 = 0x000000DD

ORR R0, R1, LSL #24     // r0 = 0xAABBCCDD | 0x00000000 = 0xAABBCCDD
ORR R0, R2, LSL #8      // r0 = 0xAABBCCDD | 0xBB000000 = 0xBBBBCCDD
ORR R0, R3, LSR #8      // r0 = 0xBBBBCCDD | 0x000000CC = 0xBBBBCCDD
ORR R0, R4, LSR #24     // r0 = 0xBBBBCCDD | 0x00000000 = 0xBBBBCCDD

What's happening here is that you have your shift directions backwards; instead of left shifting 0xAA000000 by 24, you want to right shift it by 24, giving 0x000000AA. Furthermore, you never zeroed out the contents of r0, which you would also need to do for this approach to work. If you fix these problems, your code will work as intended (though there are more compact ways to accomplish the same task).

Stephen Canon