La misma rutina, miles de millones de veces
El servidor de una tienda en línea atiende pedidos todo el día. Su procesador da unos tres mil millones de pasos por segundo, y todos siguen la misma rutina corta.
Lee la instrucción siguiente, averigua qué pide, hazla y pasa a la otra. Si sabes seguir esa rutina con una instrucción, puedes seguirla con cualquier programa.
Al final de esta lección
Nota
Puedo seguir la búsqueda, la decodificación y la ejecución de una instrucción.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Contador de programa | el registro con la dirección de la siguiente instrucción | pc |
| Registro de instrucción | donde se guarda la instrucción recién leída | |
| Búsqueda | leer de la memoria la siguiente instrucción | |
| Decodificación | partir la instrucción en sus campos | |
| Ejecución | hacer el trabajo que pide la instrucción | |
| Código de operación | el campo que dice qué tipo de instrucción es | opcode |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Una rutina que se repite sin parar
El contador de programa, pc, guarda la dirección de la siguiente instrucción. En la búsqueda, el procesador lee la palabra de esa dirección, la deja en el registro de instrucción y suma 4 a pc.
En la decodificación parte la palabra en campos: qué tipo de instrucción es y qué registros usa. En la ejecución hace el trabajo y escribe el resultado. Después vuelve a buscar.
Entra en la carpeta de arquitectura
cd ~/archSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ensambla el add.s del laboratorio
riscv64-linux-gnu-as add.s -o add.oSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Enlázalo
riscv64-linux-gnu-ld add.o -o addSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Mira cómo el emulador busca y decodifica
qemu-riscv64 -d in_asm ./addSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lo que buscó el emulador
qemu buscó cinco palabras en la memoria y decodificó cada una. Cada línea enseña la dirección, la palabra en hexadecimal y la instrucción que salió al decodificarla.
Las direcciones suben de 4 en 4, de 0x000100b0 a 0x000100c0, porque aquí cada instrucción ocupa 4 bytes. Fíjate en que li ha desaparecido: el procesador solo ve addi a0,zero,2.
Decodificar es partir la palabra en campos
Un add son 32 bits cortados en seis campos. Los siete bits de abajo son el código de operación: 51, que significa cálculo con dos registros.
Después vienen cinco bits para rd, el registro de destino, tres bits de detalle y cinco bits para cada entrada, rs1 y rs2. El registro a0 es x10 y a1 es x11. Así que 00b50533 dice: x10 = x10 + x11.
Ejemplo resuelto: los campos de 00b50533
| Bits | Campo | Valor | Significado |
|---|---|---|---|
| 31 a 25 | funct7 | 0000000 | Suma normal, no resta |
| 24 a 20 | rs2 | 01011 (11) | Segunda entrada: x11, a1 |
| 19 a 15 | rs1 | 01010 (10) | Primera entrada: x10, a0 |
| 14 a 12 | funct3 | 000 | Suma o resta |
| 11 a 7 | rd | 01010 (10) | El resultado va a x10, a0 |
| 6 a 0 | opcode | 0110011 (51) | Cálculo con dos registros |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
La instrucción como 32 bits
python3 -c "print(format(0x00b50533, '032b'))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Saca opcode, rd, rs1 y rs2
python3 -c "print(0x00b50533 & 127, (0x00b50533 >> 7) & 31, (0x00b50533 >> 15) & 31, (0x00b50533 >> 20) & 31)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Se ejecuta y pc avanza
La ejecución hace el trabajo: una suma, una carga, una comparación. Casi todas las instrucciones dejan pc donde lo puso la búsqueda, 4 bytes más allá. Un salto que se toma escribe otra dirección en pc, y eso es todo lo que es un salto.
Con -d exec, qemu escribe una línea por cada instrucción que ejecuta. El segundo número entre corchetes es el pc de RISC-V.
Una línea por instrucción ejecutada
qemu-riscv64 -one-insn-per-tb -d exec,nochain ./addSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Guarda la traza en un archivo
qemu-riscv64 -one-insn-per-tb -d exec,nochain -D traza.txt ./addSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Cuenta las instrucciones ejecutadas
wc -l traza.txtSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error frecuente
Advertencia
Mucha gente cree que el contador de programa cuenta cuántas instrucciones se han ejecutado. No cuenta nada. Guarda una dirección: dónde está la siguiente instrucción. En un bucle vuelve una y otra vez a las mismas direcciones.
Avanzar en el procesador de esta máquina
gdb puede parar un programa nativo y ejecutarlo de instrucción en instrucción. Si lo usas a mano, espera tus órdenes. Con -batch y una lista de órdenes, las ejecuta y termina, así que un Run puede usarlo.
El Run de abajo para en main, muestra pc, ejecuta una instrucción con stepi y vuelve a mostrar pc. En un procesador Arm la dirección avanza 4. En uno x86 las instrucciones miden de 1 a 15 bytes, así que el paso varía.
Compila el programa loop del laboratorio
gcc -O2 -o loop loop.cSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Para en main y avanza una vez
gdb -batch -iex 'set debuginfod enabled off' -ex 'break main' -ex run -ex 'info registers pc' -ex stepi -ex 'info registers pc' ./loopSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Para ir más lejos: contar un bucle
Escribe y construye pares.s de la lección de instrucciones, o pide la línea de printf a alguien de tu grupo. Antes de ejecutar nada, calcula cuántas instrucciones ejecuta: tres antes del bucle, tres en cada vuelta, seis vueltas y dos al final.
Después guarda su traza con -D pares.txt, cuéntala con wc -l y compara. ¿Qué direcciones salen seis veces?