8

私は 32 ビット (16 進数) ワード 0xaabbccdd を取得しており、2 バイトと 3 バイトを交換する必要があります。最終的には 0xaaccbbdd のようになります

2 番目と 3 番目のバイトを「マスク」して、最初に r1 と r2 を登録し、それらをスワップするようにするにはどうすればよいですか?

私の悪い英語で申し訳ありません.誰かが私を助けてくれることを願っています!

よろしく、セバスチャン

4

5 に答える 5

9

当時、私たちはこの種のトリックをEORに大きく依存していました。

あなたは4サイクルでそれを行うことができます。

まず、次の事実が必要です。A ^(A ^ B)= B

0xAABBCCDDから始め、0xAACCBBDDが必要です。そこに到達するには、0x00EEEE00 ^ 0xAABBCCDDが必要です。ここで、EE = BB^CCです。

ここで、00EEEE00をビルドするために数サイクルが必要です。

eor     r1,r0,r0,lsr #8
and     r1,r1,#0xFF00
orr     r1,r1,r1,lsl #8
eor     r0,r0,r1

cの場合:

t=x^(x>>8);
t=t&0xFF00;
t=t|(t<<8);
x^=t;

各行の後、計算された結果は次のとおりです。開始:AABBCCDD

eor  XXXXEEXX
and  0000EE00
orr  00EEEE00
eor  AACCBBDD

これは、32ビットARMコアで機能します。

于 2009-07-08T20:24:42.937 に答える
6

32 ビット定数は簡単に使用できないため、ARM アセンブリでは簡単な作業ではありません。それぞれ 8 ビットの定数を使用するためにバイトをマスクするすべての操作を分割する必要があります (これらの定数もローテーションできます)。

AND 命令を使用してバイト 2 と 3 をマスクし、後でシフトを実行します。ARM アセンブラーでは、ほとんどの命令で 1 つのシフトを無料で使用できるため、位置へのシフトと他のビットとのマージは、多くの場合、単一の命令になります。

以下は、ミドル バイト スワップを実行する未テストのコードです (サム命令セットではなく ARMv4)。

        .text

swap_v4:
        AND     R2, R0, #0x00ff0000     @ R2=0x00BB0000 get byte 2
        AND     R3, R0, #0x0000ff00     @ R3=0x0000CC00 get byte 1
        BIC     R0, R0, #0x00ff0000     @ R0=0xAA00CCDD clear byte 2
        BIC     R0, R0, #0x0000ff00     @ R0=0xAA0000DD clear byte 1
        ORR     R0, R2, LSR #8          @ R0=0xAA00BBDD merge and shift byte 2
        ORR     R0, R3, LSL #8          @ R0=0xAACCBBDD merge and shift byte 1
        B       LR

これは、1 行ずつ次の 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;
}

ご覧のとおり、このような単純なタスクには多くの行があります。ARMv6 アーキテクチャでさえ、ここではあまり役に立ちません。


EDIT:ARMv6バージョン(これもテストされていませんが、2命令短いです)

swap_v6:
        @ bits in R0: aabbccdd
        ROR     R0, R0, #8              @ r0 = ddaabbcc
        REV     R1, R0                  @ r1 = ccbbaadd
        PKHTB   R0, R0, R1              @ r0 = ddaaccbb
        ROR     R0, R0, #24             @ r0 = aaccbbdd
        BX      LR
于 2008-12-07T20:12:41.503 に答える
2

うーん、何が起こったのかわからない、それは私が実際に始める前に私の答えを提出した。

最初は2つのレジスタだけでできるとは思っていませんでしたが、それからできると思いました。これらのソリューションはレジスタのみであり、メモリはありません(ldr r0、= 4つの命令で置き換えることができます)。メモリとhmmm、2つのレジスタを使用する場合、おそらく命令の数を減らすことができます。str、bic、bic、ldrb、orr lsl、ldrb、orrlslです。さて、私は1つの命令でそれを行いましたが、メモリの場所が必要であり、保存とロードのコストサイクルが必要なので、同じ量のメモリとより多くのサイクルでメモリを使用できます。他の誰かがいくつかの良いトリックを持っているかもしれません。新しいコアの中には、エンディアンスワップ命令があり、それがさらに簡単になると思います。

.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
于 2009-04-29T04:26:11.673 に答える
1

BFI と UBFX を使用できますか?

于 2014-04-30T06:24:12.187 に答える
0

ポインタを使用して2バイトを交換するだけです

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;
于 2008-12-08T16:39:28.360 に答える