tutorial raspberry instruction ensamblador data assembly arm

assembly - raspberry - ¿Cómo enmascarar bytes en el ensamblaje de ARM?



ensamblador en raspberry pi (5)

Tengo una palabra de 32 bits (hexadecimal) 0xaabbccdd y tengo que cambiar el 2. y el 3. byte. al final debería parecerse a 0xaaccbbdd

¿Cómo puedo "enmascarar" el 2do y el 3er byte para cargarlos primero para registrar r1 yr2 y cambiarlos? También sé que tengo que trabajar con los comandos lsl e lsr pero no sé cómo comenzar.

perdón por mi mal inglés. ¡Espero que alguien pueda ayudarme!

saludos, sebastian


Debería usar punteros para intercambiar dos bytes

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;

Y ahora el resultado es

swap.DWbuf == 0xaaccbbdd;


Hmmm, no sé lo que pasó, presentó mi respuesta antes de que realmente comenzara.

Al principio no pensé que podría hacerlo con solo dos registros, pero luego decidí que podía hacerlo y lo hice. Estas soluciones son solo de registro, no tiene memoria (excepto la ldr r0, = que puede reemplazar con cuatro instrucciones). Si usa memoria y hmmm, dos registros, puede reducir el número de instrucciones, quizás, str, bic, bic, ldrb, orr lsl, ldrb, orr lsl. De acuerdo, lo hice en una instrucción menos, pero luego necesitas la ubicación de la memoria y las tiendas y los ciclos de costos de carga para la misma cantidad de memoria y más ciclos para que lo haga con la memoria. Alguien más puede tener algunos buenos trucos. Creo que algunos de los núcleos más nuevos tienen una instrucción de intercambio endian que lo haría aún más fácil.

.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


En el pasado, solíamos confiar mucho en EOR para este tipo de engaños.

Puedes hacerlo en 4 ciclos.

Primero, necesitamos el hecho de que: A ^ (A ^ B) = B

Comenzamos con 0xAABBCCDD, y queremos 0xAACCBBDD. Para llegar allí, necesitamos 0x00EEEE00 ^ 0xAABBCCDD, donde EE = BB ^ CC.

Ahora, necesitamos unos ciclos para construir 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;

Después de cada línea, el resultado calculado es: comenzando con: AABBCCDD

eor XXXXEEXX and 0000EE00 orr 00EEEE00 eor AACCBBDD

Esto funcionará en cualquier núcleo ARM de 32 bits.


¿Puedes usar BFI y UBFX para facilitar tu trabajo?


Esa no es una tarea sencilla en el ensamblaje de ARM porque no puede usar fácilmente las constantes de 32 bits. Debe dividir todas las operaciones que enmascaran los bytes para usar constantes de 8 bits cada una (también estas constantes se pueden rotar).

Enmascara los bytes 2 y 3 usando la instrucción AND y realiza el cambio más tarde. en ARM-assembler tiene la mayoría de las instrucciones de un turno de forma gratuita, por lo que el cambio de posición y la combinación con los otros bits a menudo terminan siendo una sola instrucción.

Aquí hay un código no probado que realiza el intercambio de bytes del medio (ARMv4, no el conjunto de instrucción de pulgar):

.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

Que traducir línea por línea en el siguiente código 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; }

Verá - muchas líneas para una tarea tan simple. Ni siquiera la arquitectura ARMv6 ayuda mucho aquí.

EDITAR: Versión ARMv6 (también no probados, pero dos instrucciones más cortas)

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