2010-01-20 19 views
10

estaba depurando poco de código C++ (WinCE 6 en la plataforma ARM), y me encuentro con un comportamiento extraño:comportamiento extraño del LDR [PC, #value]

4277220C mov   r3, #0x93, 30 
    42772210 str   r3, [sp] 
    42772214 ldr   r3, [pc, #0x69C] 
    42772218 ldr   r2, [pc, #0x694] 
    4277221C mov   r1, #0 
    42772220 ldr   r0, [pc, #0x688] 

Línea 42772214 ldr r3, [pc, #0x69C] se utiliza para obtener una constante de la sección .DATA, al menos eso creo.

Lo extraño es que según el código r2 debe llenarse con la memoria de la dirección pc = 0x42772214 + 0x69C = 0x427728B0, pero de acuerdo con los contenidos de la memoria se carga desde 0x427728B8 (8bytes +), también ocurre con otros ldr.

¿Es culpa del depurador o de mi comprensión de ldr/pc? Otro problema que no entiendo: ¿por qué el acceso a la sección .data es relativo al código ejecutado? Me parece un poco extraño.

Y una cuestión más: no puedo encontrar la sintaxis del comando primero mov (cualquiera podría señalarme una especificación de tipo de operación para el pulgar (1C2))

Lo siento por la descripción laico, pero sólo estoy familiarizando con las asambleas.

+0

que no se ve como 'thumb' código, pero como' código ARM'.Las direcciones de todas las instrucciones están separadas por 4 bytes; solo hay unas pocas instrucciones de 'pulgar' de 4 bytes. –

+0

En la mayoría de las arquitecturas que he visto, el contador del programa se incrementa * antes * de que se ejecute la instrucción. Durante la ejecución de una instrucción, el contador del programa contendrá la dirección del * fin * de la instrucción actual. –

Respuesta

17

Esto es correcto. Cuando se usa pc para leer, hay un desplazamiento de 8 bytes en el modo ARM y un desplazamiento de 4 bytes en el modo Thumb.

del brazo en ARM:

Cuando una instrucción lee el PC, el valor leído depende del conjunto de instrucciones se trata de:

  • Para una instrucción ARM, el valor leer es la dirección de la instrucción más 8 bytes. Los bits [1: 0] de este valor son siempre cero, porque las instrucciones ARM siempre están alineadas con la palabra.
  • Para una instrucción Thumb, la lectura del valor es la dirección de la instrucción más 4 bytes. El bit [0] de este valor es siempre cero, porque las instrucciones de pulgar siempre están alineadas a medias palabras.

Esta forma de leer la PC se usa principalmente para el direccionamiento rápido e independiente de la posición de las instrucciones y datos cercanos, incluida la bifurcación independiente de la posición dentro de un programa.

Existen 2 razones para el direccionamiento relativo de la PC.

  1. código de posición independiente, que es en su caso.
  2. conseguir un poco de constantes complicadas cercanos que no se puede escribir en 1 simple instrucción, por ejemplo, mov r3, #0x12345678 es imposible de completar en 1 instrucción, por lo que el compilador puede poner esto constante al final de la función y usar p. ldr r3, [pc, #0x50] para cargarlo en su lugar.

no sé qué mov r3, #0x93, 30 medios. Probablemente es mov r3, #0x93, rol 30 (que da 0xC0000024)?

+3

'mov r3, # 0x93, 30' en realidad significa' mov r3, # 0x93, ror 30', dando '0x24c'. –

+1

@Mike - buena explicación, y es bueno para citar el ARM ARM. En la tubería ARM de 3 etapas, la PC siempre apunta a la instrucción que se está buscando, y la PC-4 apunta a la instrucción que se está decodificando, y la PC-8 es la "instrucción actual", es decir, la instrucción que se está ejecutando. Esta es también la razón por la cual las excepciones deben ajustar el valor LR antes de regresar. Como ha señalado, esto se aplica a las instrucciones ARM (32 bits), de ahí el ajuste de 4 bytes por etapa de canalización. – Dan