Registrarse

[RH - ASM] Clase 3

Estado
Cerrado para nuevas respuestas.

MetalKaktus

A la luz del quinto día, mira al este
Miembro insignia
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.

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.

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:

cmp r0, r1 @compara el valor de ambos registros
beq label @si ambos valores son iguales salta a la etiqueta label
Dicho de forma general:

cmp (primero registro), (segundo registro)
b(condición) (etiqueta)
Operaciones lógicas

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.

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
Se que es un poco enrevesado, pero si hay dudas preguntad.

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í:

bl linker



linker:
bx r3 (o el registro que sea)
¿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.

>>Funciones<<

Solo leed bien lo que dice cada una y no tendréis problemas.

 

Ancer

Usuario de oro
ok gracias al cmp pude hacer una mejora al de cambiar de genero
en el anterior tenia que definir si quería chico o chica con variable 8000 y ahora se hace detecta de que genero es y se cambia a su contratarte
Código:
.text
.align 2
.thumb

main:
	push {r0-r1, lr}
	ldr r0, datos
	ldr r0, [r0]
	ldrb r1, [r0,#0x8]
	cmp r1, #0x1
	beq hombre
	bne hembra
	
	hombre:
	mov  r1, #0x0
	strb r1, [r0,#0x8]
	b final
	
	hembra:
	mov  r1, #0x1
	strb r1, [r0,#0x8]
	b final
	
	final:
	pop {r0-r1, pc}

.align 2
	datos:	.word 0x0300500C
esta no tiene utilidad es solo algo que hice por probar
Código:
.text
.align 2
.thumb

main:
	push {r0-r2, lr}
	ldr r0,pokemonN
	ldrb r0, [r0]
	ldr r1,pokemonP
	strb r0,[r1]
	pop {r0-r2, pc}
	
.align 2
	pokemonP:	.word 0x020242D8
	pokemonN:	.word 0x02024080

pero si quería que alguien me ayudara con 2 cosa y son el lsl , lsr y el and ,or si entendí como funciona casi por completo pero lo que quisiera es que alguien de unos ejemplo de uso ya que me imagino que su uso es muy especifico por eso quisiera unos ejemplo para una mejora en la explicación
de ante mano gracias
 
Última edición:
Estado
Cerrado para nuevas respuestas.
Arriba