assembly - presidenciales - presidente de zimbabue
¿Por qué la PC ARM registra el punto de la instrucción después de la siguiente para ser ejecutado? (2)
es verdad...
un ejemplo es a continuación: programa C:
int f,g,y;//global variables
int sum(int a, int b){
return (a+b);
}
int main(void){
f = 2;
g = 3;
y = sum(f, g);
return y;
}
compilar para ensamblar:
00008390 <sum>:
int sum(int a, int b) {
return (a + b);
}
8390: e0800001 add r0, r0, r1
8394: e12fff1e bx lr
00008398 <main>:
int f, g, y; // global variables
int sum(int a, int b);
int main(void) {
8398: e92d4008 push {r3, lr}
f = 2;
839c: e3a00002 mov r0, #2
83a0: e59f301c ldr r3, [pc, #28] ; 83c4 <main+0x2c>
83a4: e5830000 str r0, [r3]
g = 3;
83a8: e3a01003 mov r1, #3
83ac: e59f3014 ldr r3, [pc, #20] ; 83c8 <main+0x30>
83b0: e5831000 str r1, [r3]
y = sum(f,g);
83b4: ebfffff5 bl 8390 <sum>
83b8: e59f300c ldr r3, [pc, #12] ; 83cc <main+0x34>
83bc: e5830000 str r0, [r3]
return y;
}
83c0: e8bd8008 pop {r3, pc}
83c4: 00010570 .word 0x00010570
83c8: 00010574 .word 0x00010574
83cc: 00010578 .word 0x00010578
vea el valor de PC de la LDR anterior; aquí se usa para cargar la dirección de variable f, g, y a r3.
83a0: e59f301c ldr r3, [pc, #28];83c4 main+0x2c
PC=0x83c4-28=0x83a8-0x1C = 0x83a8
El valor de la PC es solo la instrucción siguiente de la próxima instrucción de ejecución. como ARM usa instrucción de 32 bits, pero está usando una dirección de byte, entonces + 8 significa 8 bytes, dos instrucciones de longitud.
tan unida la búsqueda de línea de 5 etapas de ARM archi archi, decodificación, ejecución, memoria, reescritura
el registro de la PC se agrega por 4 cada reloj, por lo tanto, cuando las instrucciones salieron a borbotones para ejecutarse, la instrucción actual, ¡el registro de PC ya pasó 2 horas! ahora es +8 lo que en realidad significa: PC señala la instrucción "fetch", la instrucción actual significa instrucción "execute", por lo que PC significa la próxima siguiente para ser ejecutada.
Por cierto: la foto es del libro de Harris de Diseño Digital y Arquitectura de Computadora ARM Edition
De acuerdo con el ARM IC.
En el estado ARM, el valor de la PC es la dirección de la instrucción actual más 8 bytes.
En estado de pulgar:
- Para las instrucciones B, BL, CBNZ y CBZ, el valor de la PC es la dirección de la instrucción actual más 4 bytes.
- Para todas las demás instrucciones que usan etiquetas, el valor de la PC es la dirección de la instrucción actual más 4 bytes, con el bit [1] del resultado borrado a 0 para alinear la palabra.
Simplemente diciendo, el valor del registro de PC apunta a la instrucción después de la siguiente instrucción. Esto es lo que no entiendo. Usualmente (particularmente en el x86) el registro del contador del programa se usa para apuntar a la dirección de la siguiente instrucción que se ejecutará.
Entonces, ¿cuáles son las premisas que subyacen a eso? Ejecución condicional, tal vez?
Es un poco desagradable fuga de abstracción heredada.
El diseño original de ARM tenía una tubería de 3 etapas (fetch-decode-execute). Para simplificar el diseño, eligen que la PC lea como el valor actualmente en las líneas de dirección de búsqueda de instrucciones, en lugar de la instrucción que se está ejecutando actualmente desde hace 2 ciclos. Dado que la mayoría de las direcciones relativas a PC se calculan en tiempo de enlace, es más fácil que el ensamblador / enlazador compense ese desplazamiento de 2 instrucciones en lugar de diseñar toda la lógica para "corregir" el registro de PC.
Por supuesto, todo eso está firmemente en el montón de "cosas que tuvieron sentido hace 30 años". Ahora imagine lo que se necesita para mantener un valor significativo en ese registro en las etapas actuales de más de 15 etapas, problemas múltiples, y puede apreciar por qué es difícil encontrar un diseñador de CPU en estos días que piense exponer la PC como un registro es una buena idea.
Aún así, al alza, al menos no es tan horrible como las máquinas tragamonedas de retraso . En cambio, al contrario de lo que supones, hacer que cada instrucción se ejecute de forma condicional era en realidad otra optimización más en torno a esa compensación de captación previa. En lugar de tener que tomar retrasos de enrutamiento cuando se ramifica alrededor del código condicional (o aún ejecutar lo que queda en la tubería como una persona loca), puede evitar ramas muy cortas por completo; la tubería permanece ocupada, y las instrucciones descodificadas pueden simplemente ejecutarse como NOP cuando las banderas no coinciden * . Una vez más, en estos días tenemos predictores de ramificaciones efectivas y termina siendo más un obstáculo que una ayuda, pero para 1985 fue genial.
* "... la instrucción establecida con la mayoría de los NOP del planeta".