汇编语言:如何将数组列表粘贴到单词中?

时间:2016-09-12 18:51:04

标签: assembly arm

我该怎么做 将四个字节的数组合并为一个32位。第一项应该进入 最重要的蚕食结果。将结果存储在32位变量结果中。

输入: [LIST] = 0xC,0x2,0x6,0x9 (每个项目都是一个字节,使用DCB来定义字节类型的变量)

输出: [结果] = 0x0C020609

编辑答案:

ADD R1, R0
MOV R1, R1, LSL #8
ADD R0, R0, #8
ADD R1, R0
MOV R1, R1, LSL #8
ADD R0, R0, #8
ADD R1, R0
MOV R1, R1, LSL #8
ADD R0, R0, #8
ADD R1, R0

2 个答案:

答案 0 :(得分:1)

您所描述的与将4个连续字节视为以big-endian字节顺序存储的32位整数相同。

根据gcc(在Godbolt compiler explorer上),从big-endian到ARM-native endby的字节交换的最佳方法是使用ARM为此目的明确提供的指令:

rev   r0, r0 
#include <stdint.h>
#include <endian.h>
#include <string.h>

// type-punning with unions is an alternative to memcpy from a char array to an int
union be_bytes {
  uint32_t be_word;
  char bytes[4];
};

uint32_t be_bytes_to_native( char *array ) {
  union be_bytes tmp;
  memcpy(tmp.bytes, array, 4);   // memcpy since we take a char* arg instead of a union be_bytes * arg.
  //  I *think* (union be_bytes*)array would be safe, but I'm not 100% sure.

  // GNU C and many other compilers guarantee that writing one union member and reading another is safe.  ISO C doesn't, so this technically isn't portable.
  return be32toh(tmp.be_word);   // from endian.h, uses compiler builtins, inline asm, or some C shift and mask instructions.
}

编译到

be_bytes_to_native:
    ldr     r0, [r0]  @ unaligned
    rev     r0, r0
    bx      lr

如果没有REV指令,@ dwelch对Endianness conversion in ARM的回答建议在ARM中进行字节交换32位值的4指令序列:

  eor r3,r1,r1, ror #16
  bic r3,r3,#0x00FF0000
  mov r0,r1,ror #8
  eor r0,r0,r3, lsr #8

请注意这是如何将桶形移位器与MOV以外的指令结合使用的。我仍然不确定你的代码中应该是ADD R0, R0, #8(r0 + = 8)。

答案 1 :(得分:0)

*result* = 0
for each *byte* from *list*:
    shift *result* 4 bits left  ; move previous values to make room for next one
    AND *byte* with mask to keep only lower 4 bits (0x0F)room
    OR *masked byte* to *result* ("add" would work too, as all is masked properly)
done.

编辑后关于您的代码:
我很确定它会做出与你想要的不同的事情,但我不确定这是哪种CPU /方言,让我想起ARM。

如果LDR R0,=LIST一次性获取所有4个字节,那就很聪明。

但是你用MSB屏蔽R0(所以你知道你的平台的字节顺序,这个是第一个?)并将其存储在R1中(从某种意义上说,将第一个字节提取到R1进入MSB位置)。

然后你将4添加到R0(对我没有任何意义,破坏最后一个字节值)。然后你将第二个字节提取到R1(覆盖R1的前一个值)等等......

最后你存储到R1和RESULT第四个字节值+ 12(结果= 0x00000015)。

顺便说一下,您应该编译代码,并在某些调试器中进行调试,看看您做了什么,您将以更快的速度学习。只是在纸上猜测,当你拥有真正的硬件几乎是免费的?我不得不在纸上编码,因为我每周只能访问一次实际硬件3小时,所以我几乎没有时间将代码重新键入计算机,运行它,看着它崩溃(我当时都不知道调试器),我还有一周的文书工作来弄清楚发生了什么,修复它,再试一次......

但是今天你可以简单地将它输入机器,编译,并逐步指令进入它。可以更容易。