Clase 3
La clase de hoy será una continuación de la clase anterior, en el sentido de que vamos a seguir con los comandos y unas csosas más. Por lo tanto, el temario del día será el siguiente.
- Comandos (lsl, lsr, cmp y condiciones...)
- Operaciones lógicas o binarias
- Funciones
Comandos
Antes de entrar en terreno desconocido empezaremos con un par de comandos bastante sencillos. Estos comandos son lsl y lsr. Por decirlo de alguna manera estos comandos cumplen una función opuesta.
lsl
Mueve el valor del registro un bit a la izquierda. Es un comando que trabaja a nivel de código de maquina, binario. Sirve para valores de un registro, y se especifica la cantidad de de posiciones que se cambian con un valor inmediato, de 0x0 hasta 0xFF. Cabe decir que un valor superior a 0x20 es inútil. Por ejemplo:
lsl r0, r0, #0x3 Mueve tres posiciones a la izquierda el valor de r0 en binario, y lo guarda en r0.
Empezaré con un ejemplo, imaginad que en mi registro tengo el valor 0xFF. Lo que en código de maquina se traduce como 00000000000000000000000011111111 . Aplicando el comando lsl r0, 0x1 conseguiremos lo siguiente:
00000000000000000000000111111110
Claramente aplicando un lsl de una posición haremos que el valor del registro se multiplique por dos. ¿ Qué no te fias? Dejame demostrártelo:
Antes de nada, todos los números del sistema decimal ( base diez) pueden ser expresados por dígitos multiplicado por potencias de diez sumándose. Un ejemplo:
4315 = 4 * 10^3 + 3 * 10^2 + 1 * 10^1 + 5 * 10^0
En otros sistemas como el hexadecimal, sexagesimal, octal pasa igual. Y como no podría ser de otra manera en el binario pasa lo mismo, por ejemplo:
1101 = 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0
Por lo tanto, si añadimos un cero a la derecha, como bien hace el comando lsl haremos lo siguiente, usando el número del ejemplo anterior:
11010 que se puede expresar como suma de los dígitos de una posición determinada multiplicada por la base del sistema elevado a la posición:
11010 = 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 0 * 2^0
Pero ese cero del final no está sumando nada, por lo tanto podemos olvidarlos de él:
11010 = 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1
Si ahora sacamos un dos como factor común:
11010 = ( 1 * 2^3 + 1 * 2^ + 0 * 2^1 + 1 * 2^0 ) * 2
Y recordemos que 1 * 2^3 + 1 * 2^ + 0 * 2^1 + 1 * 2^0 es 1101 Es decir,
11010 = 1101 * 2
Es decir, que al hacer lsl r0, r0, # 0x1 haremos que el valor de r0 se multiplique por dos, si hacemos lsl r0, r0, #0x2 haremos que se multiplique ( recordad que ahora sacamos un 2^2 como factor común) por cuatro (2^2), si hacemos con #0x3 lo multiplicaremos por 8, 2^3.
00000000000000000000000111111110
Claramente aplicando un lsl de una posición haremos que el valor del registro se multiplique por dos. ¿ Qué no te fias? Dejame demostrártelo:
Antes de nada, todos los números del sistema decimal ( base diez) pueden ser expresados por dígitos multiplicado por potencias de diez sumándose. Un ejemplo:
4315 = 4 * 10^3 + 3 * 10^2 + 1 * 10^1 + 5 * 10^0
En otros sistemas como el hexadecimal, sexagesimal, octal pasa igual. Y como no podría ser de otra manera en el binario pasa lo mismo, por ejemplo:
1101 = 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0
Por lo tanto, si añadimos un cero a la derecha, como bien hace el comando lsl haremos lo siguiente, usando el número del ejemplo anterior:
11010 que se puede expresar como suma de los dígitos de una posición determinada multiplicada por la base del sistema elevado a la posición:
11010 = 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 0 * 2^0
Pero ese cero del final no está sumando nada, por lo tanto podemos olvidarlos de él:
11010 = 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1
Si ahora sacamos un dos como factor común:
11010 = ( 1 * 2^3 + 1 * 2^ + 0 * 2^1 + 1 * 2^0 ) * 2
Y recordemos que 1 * 2^3 + 1 * 2^ + 0 * 2^1 + 1 * 2^0 es 1101 Es decir,
11010 = 1101 * 2
Es decir, que al hacer lsl r0, r0, # 0x1 haremos que el valor de r0 se multiplique por dos, si hacemos lsl r0, r0, #0x2 haremos que se multiplique ( recordad que ahora sacamos un 2^2 como factor común) por cuatro (2^2), si hacemos con #0x3 lo multiplicaremos por 8, 2^3.
lsr
Este comando funciona de la misma forma que el lsl pero en vez de mover el valor del registro un bit a la izquierda lo mueve a la derecha. La explicación matemática es la misma que la de lsl. Su uso es el siguiente:
lsl r0, r0, #0x3 Mueve tres bits a la derecha el valor del registro r0 y guarda el resultado en r0 (el primero de los dos).
Cmp y condiciones
Una vez que hayais aprendindo este apartado habreis ampliado vuestro conocimiento de ASM considerablemete. Pues gracias al comando cmp podremos comparar los valores de dos registros, o un registro con un valor inmediato entre si. Dependiendo de la situación podremos hacer que salte a un lugar de la rutina u otro. Pero antes de ver este comando hay que dar un par de comandos, el b, bl y bx.
Lo que en scripting viene a ser un pointer, si eso de #org @loquesea, dicho de forma rápida y simple. La rutina está repartida en label o etiquetas. Primero se ejecutará la primera etiqueta, y si no hay ningún salto este terminará y pasaremos a la siguiente etiqueta. Un ejemplo:
main:
mov r0, #0xA
loop:
ldr r1, =0xFFFFFF
En este caso primero se ejecutará el main y luego el loop. Bien, pero hay ciertos comandos para saltar de unos a otros. Y son b, bl, bx.
b:lo que en scripting viene siendo un goto. Es decir, si en mi rutina pongo un b (label), al ejecutar esa linea saltará automaticamente al label o etiqueta que hayamos especificado.
bl:Es lo que en scripting viene siendo un call, es decir, es como el b pero tiene una especie de return incorporado. Es decir, al usar bl (label), cuando se ejecute esa línea, pasara a la etiqueta especificada y una vez que termine volverá donde estaba.
bx:Sirve para saltar a otra rutina del juego, para usar funciones ya incorporadas en la ROM más que nada. Requieren de un parametro, ol offset donde está almacenada la rutina: bx r1 por ejemplo, saltará a la rutina del offset dado por r1.
Hay una forma de llamar a otra rutina y una vez que esa se ejecute del todo vuelva a la rutina que lo ha llamado, que es así:
Code:
...
bl linker
...
linker:
bx r1
De está forma llamaremos a otra rutina y una vez que termine volverá donde estaba.
Resumiendo, b sirve como si fuera un goto, bl como un call con return incorporado y bx para llamar a otras rutinas.
main:
mov r0, #0xA
loop:
ldr r1, =0xFFFFFF
En este caso primero se ejecutará el main y luego el loop. Bien, pero hay ciertos comandos para saltar de unos a otros. Y son b, bl, bx.
b:lo que en scripting viene siendo un goto. Es decir, si en mi rutina pongo un b (label), al ejecutar esa linea saltará automaticamente al label o etiqueta que hayamos especificado.
bl:Es lo que en scripting viene siendo un call, es decir, es como el b pero tiene una especie de return incorporado. Es decir, al usar bl (label), cuando se ejecute esa línea, pasara a la etiqueta especificada y una vez que termine volverá donde estaba.
bx:Sirve para saltar a otra rutina del juego, para usar funciones ya incorporadas en la ROM más que nada. Requieren de un parametro, ol offset donde está almacenada la rutina: bx r1 por ejemplo, saltará a la rutina del offset dado por r1.
Hay una forma de llamar a otra rutina y una vez que esa se ejecute del todo vuelva a la rutina que lo ha llamado, que es así:
Code:
...
bl linker
...
linker:
bx r1
De está forma llamaremos a otra rutina y una vez que termine volverá donde estaba.
Resumiendo, b sirve como si fuera un goto, bl como un call con return incorporado y bx para llamar a otras rutinas.
Una vez entendido estos conceptos pasaremos a explicar el cmp. Su sintaxis es muy sencilla.
Para comparar dos registros => cmp r0, r1
Para comparar un registro y un valor inmediato => cmp r2, #0x3
En la practica debemos usar una condición a continuación, las cuales son:
EQ => igual
NE => no igual
CS/HS => mayor o igual (>=)
CC/LO => menor (<)
MI => negativo
PL => positivo o cero
HI => mayor (>)
LS => menor o igual (<=)
AL => siempre
Para entenderlo mejor os pondré un ejemplo:
Dicho de forma general:cmp r0, r1 @compara el valor de ambos registros
beq label @si ambos valores son iguales salta a la etiqueta label
Operaciones lógicascmp (primero registro), (segundo registro)
b(condición) (etiqueta)
Son comando que trabajan a nivel binario. Los que hayas dado alguna vez electrónica digital conoceréis estas operaciones.
Antes de explicar cuales son quiero dejar claro como funcionan. Siempre comparan el valor de dos registros. Imaginad que en r0 tengo 8E4 y en r1 4FF. Entonces, en binario sería asi:
r0 => 0x8E4 => 0000 1000 1110 0100
r1 => 0x4FF => 0000 0100 1111 1111
Ahora lo que hacen todos estos comandos es comparar los bits de ambos registros que estén en la misma posición. Os pondré el ejemplo de and
Como veis compara digitos que compartan posición entre si y dependiendo de su tabla de la verdad os devolverá en esa posición 0 o 1.
and
Siendo A y B las señales entrantes y F el resultado.
or
Hay muchos más pero los más importantes son estos dos. También existe xor, not, nand, nor, eor, orr... podeis buscar en internet.
Pero quiero hablar un rato con vosotros. Mirad este ejemplo:
A and C => 8
¿Y a mi de que me sirve esa respuesta? Quiero decir, como saco yo provecho de una operación así. Pues bien, a veces para guardar información el la RAM no hace falta usar todo un byte, dicho de otra forma, podemos guardar más de un dato en un solo byte. Por ejemplo:
Imaginad que para guardar un dato necesito solo un bit. Por ejemplo, quiero guardar un dato en una variable 0 si no son shinys y 1 si lo son los datos de 16 de mis pokemon. Pues bien. Pongamos que solo el número 3, 8 y 14 lo son. El byte quedaría así:
0010 0000 1000 0100 => 20 84 en hex.
Y un vez más adelante quiero comprobar si el número ocho es shiny o no. Entonces haré lo siguiente, tened en cuenta que el r0 tenemos 2084.
Se que es un poco enrevesado, pero si hay dudas preguntad.mov r1, #80 @ en binario 80 => 1000 0000
and r0, r0, r1 @0010 0000 1000 0100 and 1000 0000 => 1000 000
lsr r0 , r0, #0x7 @ r0 => 1
cmp r0, #0x1
beq shiny
Funciones
Si recordáis el comando bx que hemos aprendido antes sabreis que este sirve para llamar a una función del juego. Pues uso es así:
¿Y cuales son las funciones? A continuación os deare una lista de algunas funciones. Bien, pues recordad añadir un +1 a cada dirección.bl linker
…
linker:
bx r3 (o el registro que sea)
>>Funciones<<
Solo leed bien lo que dice cada una y no tendréis problemas.
@Gosuto @Jaizu @White @KaiZ @Navy_ @Laquin @L!no the Maelstrom @speedgio @Hacko @Derlo @skhorus @Leviatan @BagBoy @Chema @Ancer @Edsteam8000 @Monika @Caco5400 @MasterNet @InmortalKaktus @Sharck @CompuMax @LilBuho19 @axel jose guerra @MichaKing @mikdark @5taDisminuida @★Urufu★ @~Jon. @Raul Company
@Venussaur best starter @Mod @esteban garcia @lucian @Edd el Penas @ElToby @Kurama @Subzero
@Venussaur best starter @Mod @esteban garcia @lucian @Edd el Penas @ElToby @Kurama @Subzero