2012-04-21 12 views
18

Por alguna razón, cuando intento compilar este trozo de código, el compilador dice syscall.s:72:invalid constant (0x172) after fixup:¿Constante inválida después de la corrección?

.globl _mach_msg_trap$MACH 
_mach_msg_trap$MACH: 
    stmfd sp!, {r4,r7} 
    mov r7, #370 /* this is line 72 */ 
    svc 0 
    ldmfd sp!, {r4, r7} 
    bx lr 

No sé por qué lo está haciendo. Cuando pongo una constante más pequeña en r7, funciona bien. Pero con números más altos, escupe este error. Lo he arreglado temporalmente haciendo mov r7, #300 y add r7, #70, que logra el efecto deseado. Aún no estoy seguro de qué causó el error.

Respuesta

35

La instrucción ARM solo puede cargar un rango limitado de valores inmediatos con mov. El problema es que el valor debe codificarse en la instrucción mov en sí. Como todas las instrucciones ARM tienen 32 bits de ancho, la configuración original de la instrucción hasta ARMv5 solo tenía un total de 8 + 4 bits para codificar las inmediatas. Con los primeros 8 bits pueden cargar cualquier valor de 8 bits int en el rango de 0-255 y los 4 bits girando a la derecha en pasos de 2 entre 0 y 30.

Para cargar valores como :

#0 
#122 
#121 ror #24 = 30976 
#230 ror #12 = 241172480 

Pero, # 370 no se puede cargar con este esquema, se requeriría algo así como #185 ror #31 que no es posible.

Hay dos maneras de cargar su valor inmediato.

  1. Cómo lo ha resuelto construyendo el valor en varios pasos.
  2. Al cargar el valor de la memoria con ldr: ldr r7,=#370 El ensamblador creará un conjunto constante y cargará el valor desde allí mediante el direccionamiento relativo de la PC.

Por lo general, debería preferir construir constantes con hasta 2 instrucciones, si eso no es posible (o el valor tiene que ser reubicable) use ldr.

Comenzando con ARMv7 también puede usar movw para cargar cualquier valor de 16 bits en la mitad inferior de un registro mientras pone a cero la mitad superior y movt para cargar otro valor de 16 bits en la mitad superior sin tocar la mitad inferior.

+0

Tengo el mismo problema, pero usando armv4. Quiero cargar 0x0000ffff en un registro. movw y movt no son compatibles en este modo de brazo. Y tampoco puedo usar ldr r3, = # 0000ffff –

+1

Tienes que cargar ldr r3, = # 0x0000ffff not = # 0000ffff. La reparación está desactivada por el ensamblador. También puede simplemente mov r3, # 255 - orr r3, r3, # 65280 –

+0

No puedo poner ese valor en el registro. No es una dirección, es una constante que quiero almacenar en la memoria, en una posición dada por la variable v1 (en C la instrucción es: iowrite32 (v1, 0x0000FFFF). El mensaje es: No se puede manejar la solicitud de paginación del núcleo en la dirección virtual 0000ffff –

Cuestiones relacionadas