2008-12-07 4 views
7

tôi đã có một từ 32 bit (hệ thập lục phân) 0xaabbccdd và phải hoán đổi số 2. và byte 3.. cuối cùng, nó sẽ trông giống như 0xaaccbbddLàm thế nào để che dấu các byte trong hội đồng ARM?

làm cách nào tôi có thể "mặt nạ" byte thứ 2 và thứ 3 để tải chúng lên để đăng ký r1 và r2 và hoán đổi chúng. tôi cũng biết rằng tôi phải làm việc với lệnh lsl và lsr nhưng không biết cách bắt đầu.

xin lỗi vì tiếng anh xấu của tôi. Bất kỳ ai cũng có thể giúp tôi!

regards, sebastian

Trả lời

6

Đó không phải là một nhiệm vụ đơn giản trong lắp ráp ARM bởi vì bạn không thể dễ dàng sử dụng các hằng số 32 bit. Bạn phải chia nhỏ tất cả các hoạt động của bạn để che dấu các byte để sử dụng hằng số 8 bit (mỗi hằng số này cũng có thể được luân chuyển).

Bạn che dấu byte2 và 3 bằng lệnh AND và thực hiện ca sau. trong ARM-assembler, bạn có nhiều sự thay đổi chỉ dẫn một cách miễn phí, vì vậy sự dịch chuyển vào vị trí và hợp nhất với các bit khác thường kết thúc bằng một lệnh duy nhất.

Dưới đây là một số mã chưa được kiểm tra mà không được hoán đổi byte giữa (ARMv4, không ngón tay cái instruction set):

 .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 

Đó dịch từng dòng vào c-mã sau:

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; 
} 

Bạn sẽ thấy - rất nhiều dòng cho một nhiệm vụ đơn giản như vậy. Ngay cả kiến ​​trúc ARMv6 cũng không giúp ích nhiều cho lắm.


EDIT: phiên bản ARMv6 (cũng chưa được kiểm tra, nhưng hai hướng dẫn ngắn hơn)

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 
+0

Uh, không phải là sử dụng hằng số 32 bit, trong ví dụ đầu tiên? Gây nhầm lẫn. – unwind

+1

Có, đây là những hằng số 32 bit, nhưng nếu bạn nhìn kỹ hơn thì chúng chỉ có 8 bit liên tiếp được sử dụng trong các hằng số của chúng. ARM có thể làm 8 bit, nhưng vị trí của chúng có thể được tự do xoay vào vị trí bạn muốn. Bộ lắp ráp đủ thông minh để mã hóa các hằng số cho bạn. –

+2

mọi vị trí * ngay cả * bạn muốn; Ví dụ: 0x1fe không phải là biểu tượng có thể hiển thị, nhưng 0x3fc là. –

0

Bạn vould chỉ cần sử dụng con trỏ để trao đổi hai byte

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; 

Và bây giờ kết quả là

swap.DWbuf == 0xaaccbbdd; 
2

H mmm, không biết chuyện gì đã xảy ra, nó đã gửi câu trả lời của tôi trước khi tôi thực sự bắt đầu.

Lúc đầu, tôi không nghĩ rằng tôi có thể làm điều đó chỉ với hai thanh ghi nhưng sau đó tôi quyết định tôi có thể và đã làm. Các giải pháp này chỉ đăng ký, không có bộ nhớ (trừ ldr r0, = bạn có thể thay thế bằng bốn hướng dẫn). Nếu bạn sử dụng bộ nhớ và hmmm, hai thanh ghi bạn có thể cắt giảm số lượng các lệnh có thể, str, bic, bic, ldrb, lrr lr, ldrb, orr lsl. Được rồi tôi đã làm nó trong một hướng dẫn ít hơn nhưng sau đó bạn cần vị trí bộ nhớ và các cửa hàng và tải chu kỳ chi phí để cùng một số lượng bộ nhớ và chu kỳ hơn cho tôi để làm điều đó với bộ nhớ. Người khác có thể có một số thủ đoạn tốt. Tôi nghĩ rằng một số lõi mới hơn có một lệnh trao đổi cuối cùng mà sẽ làm cho nó dễ dàng hơn.

.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 
8

Quay lại ngày chúng tôi sử dụng để phụ thuộc rất nhiều vào EOR cho loại thủ thuật này.

Bạn có thể làm điều đó trong 4 chu kỳ.

Trước hết, chúng ta cần thực tế là: A^(A^B) = B

Chúng tôi bắt đầu với 0xAABBCCDD, và chúng tôi muốn 0xAACCBBDD. Để đến đó, chúng tôi cần 0x00EEEE00^0xAABBCCDD, trong đó EE = BB^CC.

Bây giờ, chúng ta cần một vài chu kỳ để xây dựng 00EEEE00:

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

Trong c:

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

Sau mỗi dòng, kết quả tính toán là: bắt đầu với: AABBCCDD

eor XXXXEEXX 
and 0000EE00 
orr 00EEEE00 
eor AACCBBDD 

Điều này sẽ hoạt động trên bất kỳ lõi ARM 32 bit nào.

0

Bạn có thể sử dụng BFI và UBFX chúng sẽ giúp công việc của bạn dễ dàng hơn