cursos:ensamblador:avanzadas1

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
cursos:ensamblador:avanzadas1 [21-01-2024 10:22] sromerocursos:ensamblador:avanzadas1 [21-01-2024 10:31] (actual) – [Obtener el valor de PC (Contador de Programa)] sromero
Línea 435: Línea 435:
  
 \\  \\ 
-==== Obtener el valor de PC (Contador de Programa) ====+\\  
 +===== Código Automodificable ===== 
 + 
 +Ya vimos en un capítulo anterior un ejemplo de **código automodificable**. Consiste en sobreescribir en memoria un opcode o un dato en función de una condición, para que cuando lleguemos a ese punto del programa, se ejecute el opcode modificado. 
 + 
 +En el ejemplo que ya vimos, utilizamos código automodificable para sobreescribir un instrucción de carga "futura" que nos permitirá recuperar el valor del registro BC más adelante, por ejemplo porque vamos a modificarlo con un bucle, y no tenemos la pila disponible: 
 + 
 +<code z80> 
 +    ld (save_bc+1), bc    ; Escribimos BC en la parte NN NN del 
 +                          ; opcode "ld bc, NN NN" en memoria 
 + 
 +    ... hacer cosas con BC, perdiendo su valor ... 
 + 
 +save_bc: 
 +    ld bc, $0000          ; En el LD anterior cambiamos $000 
 +                          ; por el valor de BC, así que cuando 
 +                          ; el z80 llegue aquí no es ya ld bc, 0 
 +                          ; sino ld bc, valor_que_tenia_BC 
 +                          ; así que recuperaremos BC aquí. 
 +</code> 
 + 
 +Cuando se ejecuta la instrucción ''ld (save_bc+1), bc'', estamos sobreescribiendo nuestro propio programa, cambiando el opcode que estaba ensamblado en memoria (''ld bc, $0000'', es decir "**$01 $00 $00**") por **$01 XX XX**, siendo **XX XX** el nuevo valor que queremos introducir en el opcode. 
 + 
 +Cuando se ejecuta el ''ld (save_bc+1), bc'', estamos escribiendo el valor de BC en ese momento encima de "XX XX" de forma que cuando la ejecución llegue a ese punto, el comando ''ld bc, XX'' se ejecutará y recuperará en BC el valor que tenía BC cuando se almacenó en esa posición de memoria. 
 + 
 +La escritura en memoria (''ld (nn), bc'' = 20 ciclos de reloj) y su posterior asignación (10 ciclos) cuesta un total de 30 ciclos de reloj, mientras que si hubiéramos usado PUSH/POP costaría sólo 21 ciclos en total (11 el ''PUSH'' y 10 el ''POP''). Sin embargo, si estamos en una rutina de impresión de Sprites donde usamos la pila para recuperar datos del Sprite, por ejemplo, es una forma de recuperar valores de registros en una situación donde no podemos hacer ''PUSH'' y ''POP'' para ello. 
 + 
 +Y no sólo podemos modificar datos, también podríamos modificar opcodes, cambiando ''JR Z''s por ''JR NZ''s, por ejemplo, para cambiar la condicionalidad de los saltos de alguna forma. 
 + 
 +\\  
 +===== Obtener el valor de PC (Contador de Programa) =====
  
 Utilizando ''CALL'' y la pila del Z80, podemos obtener en un registro el valor del Contador de Programa o ''PC'': Utilizando ''CALL'' y la pila del Z80, podemos obtener en un registro el valor del Contador de Programa o ''PC'':
  • cursos/ensamblador/avanzadas1.1705832520.txt.gz
  • Última modificación: 21-01-2024 10:22
  • por sromero