简体   繁体   English

ARM程序集 - 转换字节序

[英]ARM Assembly - Converting Endianness

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. 任务是创建一个将0xAABBCCDD转换为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: 首先,我们将每个tupel(aa),(bb),(cc),(dd)掩盖到不同的寄存器中:

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... 然后我们尝试将它们重新对齐到R0寄存器中,但是如果我们能够提出一个好的解决方案呢......

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; 因某些奇怪的原因产生0xBBBBCCDD; we really don't know. 我们真的不知道。

Any hints would be greatly appreciated. 任何提示将不胜感激。 Again, we are asking for help, but not for a solution. 我们再次寻求帮助,但不是寻求解决方案。

Cheers! 干杯!

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. 在ARMv6及更高版本上,您可以只使用rev指令,但我认为不允许您出于任何原因这样做。

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 . 而不是将0xAA000000 24,你想要将它右移 24,得到0x000000AA Furthermore, you never zeroed out the contents of r0 , which you would also need to do for this approach to work. 此外,您从未将r0的内容归零,您还需要为此方法工作。 If you fix these problems, your code will work as intended (though there are more compact ways to accomplish the same task). 如果您解决了这些问题,您的代码将按预期工作(尽管有更紧凑的方法来完成相同的任务)。

Your code looks good so far. 到目前为止你的代码看起来不错

Your mistake is, that you have reversed the meaning of LSL and LSR. 你的错误是,你已经颠倒了LSL和LSR的含义。

Take R0 for example: 以R0为例:

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

The result of this operation does not generate 0xAA. 此操作的结果不会生成0xAA。 It generates 0xAA000000. 它生成0xAA000000。

The second instruction that processes R1: 处理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. 前8位没有剩余空间。

If otoh you shift the data to the right like this: 如果otoh你将数据移到右边,如下所示:

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. 这应该会给你足够的帮助来完成你的功课。 :-) :-)

I think you need to do (ARM a bit rusty): 我认为你需要这样做(ARM有点生疏):

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. 也就是说, MOV在第一条指令中,因为您不希望旧R0任何内容影响新值。

I can't see any way to make this more 'hint' like as you've effectively done all the work anyway. 我无法看到任何方式让你更加“暗示”,就像你已经有效地完成了所有的工作一样。

While the question is rather old i've wanted to add my suggestion for the code, because it just needs 6 instructions instead of 8. It also needs only 3 Registers instead of 5. This should be the best solution for anything before armv6 (which has the rev instruction). 虽然问题相当陈旧,但我想添加我对代码的建议,因为它只需要6个指令而不是8个。它也只需要3个寄存器而不是5个。这应该是armv6之前的任何东西的最佳解决方案有rev指令)。

// We're starting with r0 = 4321
mov r2, r0, lsr #24             // r2 = 0004
and r1, r0, #16711680           // r1 = 0300
orr r2, r2, r0, lsl #24         // r2 = 1004
orr r2, r2, r1, lsr #8          // r2 = 1034
and r0, r0, #65280              // r0 = 0020
orr r0, r2, r0, lsl #8          // r0 = 1234

此外,在使用ORR移回位之前,您可能还没有清除R0寄存器(将其设置为所有零位)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM