我有一個32位(十六進制)字0xaabbccdd並且必須交換2.和3.字節。最後它應該看起來像0xaaccbbdd如何屏蔽ARM程序集中的字節?
我怎麼能「掩蓋」第二個和第三個字節首先加載它們註冊r1和r2和交換它們.. 我也知道我必須與lsl和lsr命令但不知道如何啓動。
對不起,我的壞英語。任何人都可以幫助我!
問候, 塞巴斯蒂安
我有一個32位(十六進制)字0xaabbccdd並且必須交換2.和3.字節。最後它應該看起來像0xaaccbbdd如何屏蔽ARM程序集中的字節?
我怎麼能「掩蓋」第二個和第三個字節首先加載它們註冊r1和r2和交換它們.. 我也知道我必須與lsl和lsr命令但不知道如何啓動。
對不起,我的壞英語。任何人都可以幫助我!
問候, 塞巴斯蒂安
這不是ARM彙編一個簡單的任務,因爲你不能輕易使用32位的常數。你必須打破所有屏蔽字節的操作,每個操作使用8位常量(這些常量也可以旋轉)。
使用AND指令屏蔽掉字節2和3,稍後再進行轉換。在ARM彙編程序中,大多數指令都是免費的,所以移入位置和與其他位合併通常最終會成爲單個指令。
下面是一些未經測試的代碼,不會中間字節交換(的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
即由線轉換線劃分成以下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架構甚至都沒有幫助。
編輯:ARMv6的版本(也未經測試,但較短的兩個指令)
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
您vould只是使用指針交換兩個字節
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;
H嗯,不知道發生了什麼,它在我真正開始之前提交了我的答案。
起初我並不認爲我只用兩個寄存器就可以做到,但後來我決定我可以做到。這些解決方案只有寄存器,沒有內存(除了ldr r0,=可以用四條指令替換)。如果你使用內存和嗯,兩個寄存器,你可以減少指令的數量,可能是str,bic,bic,ldrb,orr lsl,ldrb,orr lsl。好吧,我只用一個指令來完成它,但是你需要內存位置和存儲器並加載成本週期,所以我需要相同數量的內存和更多的週期來處理內存。其他人可能會有一些好的技巧。我認爲一些較新的內核有一個endian swap指令,可以使它更容易。
.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來處理這種欺騙。
你可以在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內核。
你可以使用BFI和UBFX他們將讓您的工作更容易
呃,是不是使用32位的常數,在第一個例子嗎?混亂。 – unwind 2008-12-08 16:52:50