Assembly 如何在ARM组件中屏蔽字节?

Assembly 如何在ARM组件中屏蔽字节?,assembly,arm,Assembly,Arm,我有一个32位(十六进制)字0xaabbccdd,必须交换2。和3。字节。最后,它应该看起来像0xaaccbbdd 如何“屏蔽”第2和第3字节,以便首先将它们加载到寄存器r1和r2并交换它们。。 我也知道我必须使用lsl和lsr命令,但不知道如何开始 对不起,我的英语不好。希望有人能帮我 问候,, sebastian在ARM组装中,这不是一项简单的任务,因为您无法轻松使用32位常量。您必须分解所有屏蔽字节的操作,每个操作使用8位常量(这些常量也可以旋转) 您可以使用and指令屏蔽字节2和字节3,

我有一个32位(十六进制)字0xaabbccdd,必须交换2。和3。字节。最后,它应该看起来像0xaaccbbdd

如何“屏蔽”第2和第3字节,以便首先将它们加载到寄存器r1和r2并交换它们。。 我也知道我必须使用lsl和lsr命令,但不知道如何开始

对不起,我的英语不好。希望有人能帮我

问候,,
sebastian

在ARM组装中,这不是一项简单的任务,因为您无法轻松使用32位常量。您必须分解所有屏蔽字节的操作,每个操作使用8位常量(这些常量也可以旋转)

您可以使用and指令屏蔽字节2和字节3,稍后再进行移位。在ARM汇编程序中,大多数指令都有一个移位是免费的,所以移位到位并与其他位合并通常最终成为一条指令

下面是一些执行中间字节交换的未经测试的代码(ARMv4,而不是thumb指令集):

逐行翻译成以下c代码:

int swap (int R0)
{
  int R2,R3;
  R2 = R0 & 0x00ff0000;
  R3 = R0 & 0x0000ff00;
  R0 = R0 & 0xff00ffff;
  R0 = R0 & 0xffff00ff;
  R0 |= (R2>>8);
  R0 |= (R3<<8);
  return R0;
}

您可以使用指针交换两个字节

static union {
 BYTE   BBuf[4];
 WORD   WWBuf[2];
 DWORD  DWBuf;
}swap;

unsigned char *a;
unsigned char *b;
swap.DWBuf = 0xaabbccdd;

a = &swap.BBuf[1];
b = &swap.BBuf[2];

*a ^= *b;
*b ^= *a;
*a ^= *b;
现在结果是

swap.DWbuf == 0xaaccbbdd;

嗯,不知道发生了什么,它在我真正开始之前就提交了我的答案

起初我不认为只有两个寄存器就可以做到这一点,但后来我决定我可以做到。这些解决方案仅为寄存器,无内存(ldr r0除外,=可替换为四条指令)。如果使用内存和hmmm,两个寄存器可能可以减少指令的数量,str、bic、bic、ldrb、orr lsl、ldrb、orr lsl。好的,我只用一条指令就完成了,但是你需要内存位置,存储和加载的成本周期,所以我需要相同的内存量和更多的周期来使用内存。其他人可能有一些好把戏。我认为一些较新的内核有一个endian交换指令,这将使它更加容易

.globl midswap
midswap:
    mov r2,r0,lsl #8      ;@ r2 = BBCCDDAA
    mov r3,r0,lsr #8      ;@ r3 = DDAABBCC (this might drag a sign bit, dont care)
    and r2,r2,#0x00FF0000 ;@ r2 = 00CC0000
    and r3,r3,#0x0000FF00 ;@ r3 = 0000BB00
    bic r0,r0,#0x00FF0000 ;@ r0 = AA00CCDD
    bic r0,r0,#0x0000FF00 ;@ r0 = AA0000DD
    orr r0,r0,r2          ;@ r0 = AACC00DD
    orr r0,r0,r3          ;@ r0 = AACCBBDD
    bx lr ;@ or mov pc,lr for older arm cores


.globl tworegs
tworegs:
    mov r2,r0,ror #8       ;@ r2 = DDAABBCC
    bic r2,r2,#0xFF000000  ;@ r2 = 00AABBCC
    bic r2,r2,#0x00FF0000  ;@ r2 = 0000BBCC
    orr r2,r2,ror #16      ;@ r2 = BBCCBBCC
    bic r2,r2,#0xFF000000  ;@ r2 = 00CCBBCC
    bic r2,r2,#0x000000FF  ;@ r2 = 00CCBB00
    bic r0,r0,#0x00FF0000  ;@ r0 = AA00CCDD
    bic r0,r0,#0x0000FF00  ;@ r0 = AA0000DD
    orr r0,r0,r2           ;@ r0 = AACCBBDD
    bx lr

testfun:
    ldr r0,=0xAABBCCDD
    bl midswap

在过去的日子里,我们在很大程度上依靠提高采收率来进行这种欺骗

你可以在4个周期内完成

首先,我们需要这样一个事实:A^(A^B)=B

我们从0xAABBCCDD开始,我们想要0xAACCBBDD。 要到达那里,我们需要0x00EEEE00^0xAABBCCDD, 其中EE=BB^CC

现在,我们需要几个周期来构建00EE00:

eor     r1,r0,r0,lsr #8
and     r1,r1,#0xFF00
orr     r1,r1,r1,lsl #8
eor     r0,r0,r1
在c中:


这将适用于任何32位ARM内核。

您可以使用BFI和UBFX吗?它们将使您的工作更轻松。

呃,在第一个示例中,这不是使用32位常量吗?令人困惑。是的,这些是32位常量,但如果你仔细看,它们的常量中只使用了8个连续位。手臂可以做8位,但这些位置可以自由旋转到你想要的位置。汇编程序足够聪明,可以为您编码常量;例如,0x1fe不是可表示的立即数,但0x3fc是。
.globl midswap
midswap:
    mov r2,r0,lsl #8      ;@ r2 = BBCCDDAA
    mov r3,r0,lsr #8      ;@ r3 = DDAABBCC (this might drag a sign bit, dont care)
    and r2,r2,#0x00FF0000 ;@ r2 = 00CC0000
    and r3,r3,#0x0000FF00 ;@ r3 = 0000BB00
    bic r0,r0,#0x00FF0000 ;@ r0 = AA00CCDD
    bic r0,r0,#0x0000FF00 ;@ r0 = AA0000DD
    orr r0,r0,r2          ;@ r0 = AACC00DD
    orr r0,r0,r3          ;@ r0 = AACCBBDD
    bx lr ;@ or mov pc,lr for older arm cores


.globl tworegs
tworegs:
    mov r2,r0,ror #8       ;@ r2 = DDAABBCC
    bic r2,r2,#0xFF000000  ;@ r2 = 00AABBCC
    bic r2,r2,#0x00FF0000  ;@ r2 = 0000BBCC
    orr r2,r2,ror #16      ;@ r2 = BBCCBBCC
    bic r2,r2,#0xFF000000  ;@ r2 = 00CCBBCC
    bic r2,r2,#0x000000FF  ;@ r2 = 00CCBB00
    bic r0,r0,#0x00FF0000  ;@ r0 = AA00CCDD
    bic r0,r0,#0x0000FF00  ;@ r0 = AA0000DD
    orr r0,r0,r2           ;@ r0 = AACCBBDD
    bx lr

testfun:
    ldr r0,=0xAABBCCDD
    bl midswap
eor     r1,r0,r0,lsr #8
and     r1,r1,#0xFF00
orr     r1,r1,r1,lsl #8
eor     r0,r0,r1
t=x^(x>>8);
t=t&0xFF00;
t=t|(t<<8);
x^=t;
eor  XXXXEEXX
and  0000EE00
orr  00EEEE00
eor  AACCBBDD