Volver a la página principal.GUÍA DE ASM
Capítulo 2: Instrucciones Básicas
IntroducciónEn este capitulo se verán las instrucciones ASM principales y las que más se repiten en un Log (Tracer.log) que arroja el Snes9X trace.
Operaciones BinariasExisten 3 operaciones lógicas: AND, OR y NOT, pero existe un operador compuesto llamado XOR, todos se aplican sobre varios bit, pero en la SNES generalmente es sobre 2 bits.
AND (ambos bits deben ser 1 para que el resultado sea 1)
1 AND 1 = 1 => aquí los 2 bits son 1 y 1
1 AND 0 = 0
0 AND 1 = 0 => aquí los 2 bits son 0 y 1
0 AND 0 = 0
OR (basta un 1 para que el resultado sea 1)
1 OR 1 = 1
1 OR 0 = 1
0 OR 1 = 1
0 OR 0 = 0
NOT (es el negado de algo, el NOT de "algo" da como resultado lo contrario)
NOT 1 = 0
NOT 0 = 1
XOR (si todos son 1 o si todos son 0 entonces el resultado es 0)
1 OR 1 = 0
1 OR 0 = 1
0 OR 1 = 1
0 OR 0 = 0
Shifting (Rotaciones de Dígitos)Cualquier número decimal se puede componer de varias sumas de otros números que tienen una base. Tenemos varios base: 10 (decimal), 2(binario) o 8(octal). Por ejemplo el 12 en base 2 sería:
12 = 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0 = 8 + 4 + 0 + 0 = > en binario es 1100
Ahora si un dígito Binario lo invertimos o rotamos a la izquierda se multiplica por 2 ese número:
20 * 2 = 40
010100 => rotar a la izquierda => 101000 = 40 decimal
Y podemos rotar ese dígito a la derecha para dividir.
20 / 2 = 10
010100 => rotar a la derecha => 001010 = 10 decimal
Shifting se usa mucho para el dibujo de fuentes, ya que permite crear las sombras de las letras. Para más información mira este post que hice en Fortaleza Romhack cuando el foro estaba hospedado en Nekein.
Cargas y AlmacenamientosTodo se resume en meter datos a la memoria y sacar datos desde la memoria.
En la snes un valor es un dígito hexadecimal (hex abreviado) y se representa como #$Valor o 0xValor, por ejemplo #$AC, #$123, 0x12CA, 0xA, etc.
Otra forma sencilla de escribir un valor es usar hex o una h por ejemplo: BC hex o 0Ah. Esta forma sencilla solo es aplicable para enseñarles, no se usa en los LOG ni al programar en asm.
Una dirección en la snes igual es hexadecimal y se representa con $Dirección, por ejemplo la dirección de 16 bits $1238, o esta de 8 bits $FF.
LDACarga al acumulador un valor de 8/16 bits.
Ejemplos:
LDA $05 ; carga acumulador con el valor que está dentro de la dirección $05.
LDA #$AC ; carga acumulador con el valor AC hex.
LDA $CCE602, X ; carga el valor que esta en la dirección [CCE602 +X], X es un índice que se puede incrementar así podemos sacar valores desde $CCE602, $CCE603, $CCE604, etc.
LDX, LDYCarga al índice X/Y un valor de 8/16 bits.
Ejemplos:
LDX #$AC ; carga X con el valor AC hex.
LDX $AC ; carga X con el valor que esta dentro de la dirección AC.
STA, STX, STYAlmacena en una dirección de memoria un valor dado por A, X o Y.
Ejemplos:
STA $3AFF ; guarda lo que está en A en la dirección $3AFF.
STX $BB ; guarda lo que está en X en la dirección $00BB.
Modificaciones del ancho de bitSe puede cambiar el ancho de bits desde 8 a 16 bits y viceversa del Acumulador e Índices. Esto sirve para muchas cosas, que lo veremos luego, pero como ejemplo práctico, si queremos meter el valor 0xCA en el acumulador, conviene más tener un acumulador definido con un ancho de 8 bits (ya que 0xCA es de 8 bits), si A esta seteado con un ancho de 16 bits esta bien pero no es tan adecuado.
Otro ejemplo sería si queremos meter en A un 0x123D conviene tener un ancho de 16 bits.
Ejemplos:
REP #$20 ; Hacemos que el acumulador esté en modo de 16 bits (puede almacenar valores de 16 bits)
REP #$30 ; pone los índices X e Y en modo 16 bits.
SEP #$30 ; X,Y,A los dejamos en modo de 8 bit.
SEP #$20 ; Acumulador lo dejamos en modo de 8 bit.
Incrementos/DecrementosPara decrementar o aumentar en 1 el Acumulador o el Índice X/Y tenemos 2 instrucciones básicas: DEC que resta 1 y INC que suma 1.
Si conoces PHP, JAVA o C#, DEC es igual a i-- o el i=i-1 de C++ y INC es como el i++ o i=i+1.
Ejemplos:
INC ; incremento el valor del Acumulador en 1hex.
INC A ; incremento el valor del Acumulador en 1hex (da lo mismo que poner INC).
DEC X ; decremento el valor del registro X en 1hex.
DEX ; decrementa el registro X en 1hex.
DEY ; decrementa el registro X en 1hex.
INX ; incrementa el registro X en 1hex.
INY ; incrementa el registro Y en 1hex.
DEC $Dir ; decrementa lo que haya dentro de la dirección Dir en 1.
INC $Dir ; incrementa lo que haya dentro de la dirección Dir en 1.
Código comentado 1:
Si A=0x123C
INC ; A valdrá 0x123D
DEC
DEC ; aquí A valdría 0x123B
Código comentado 2:
$1234: 0xBC ; dentro de $1234 esta el valor 0xBC
INC $1234 ; $1234 contiene ahora un 0xBD
Saltos y CiclosCon algunas instrucciones podemos saltar a un cierto label o dirección. También puedo emular un típico IF-Then o incluso un ciclo for ya que puedo comparar y luego saltar.
En general tenemos 2 tipos de salto:
# 1. Instrucciones de Salto sin condición: JSR que salta a una subrutina, JSL que salta a una dirección o label.Ejemplo 1: uso del JSR
LDA #$00
hola ; esto es un Label
INC A
JSR hola
Este ciclo hace que se carge A=0x00, luego se incremente a A=01, luego vaya a "hola",
es decir que ejecute de nuevo INC (A=0x02), y así sucesivamente, A llegará a 0xFF si
esta en modo de 8 bits o a 0xFFFF si esta en modo de 16 bits.
Ejemplo 2: uso de RTS
STA $05
JSR Hola2 ; salta a Hola2 sin condición
LDA #$10
Hola2
LDA #$12 ; cargamos A=12h
RTS ; retorna de la subrutina (sale de ella) y llega a la instrucción que sigue a
; JSR que la llamo, es decir que al hacer RTS ejecuta LDA #$10.
# 2. Instrucciones de Salto con condición o con comparación: las que permiten simular un if-else o ciclos for/while.
Ejemplo 1: uso del CMP
CMP $CCE600 ; compara A con lo que hay en $CC:E600, esta instrucción siempre va seguida de
; un de salto, así si la comparación se cumple salta a otra dirección (nos
; salemos de esta rutina y vamos a otra), si no se cumple la comparación, sigue leyendo.
Ejemplo 2: CPX con BNE
LDX #$0800 ; cargamos X con 0800h
bucle:
LDA $7EC800,x ;cargamos a con lo que está en la dirección $7EC800 + $X=$7ED000
STA $7F0000,x ;ese valor se guarda en la dirección $7F0000+$800=$7F0800
DEX ;X=X-1, es decir, X = 0800-1 = 07FFh
CPX #$0000 ;se compara con X con 0000h ¿son iguales? No. ¿El operando es MENOR a X? Si. Entonces el Flag c=1 y Flag z=0.
BNE bucle ;como carry=0, BCC salta a "bucle". Entonces sube y hace el ciclo de nuevo.
... ;Pero ahora X=07FF y así sigue haciendo el ciclo hasta que X sea 0000. Luego se pregunta
;¿X es igual a 0000h? Si. El Flag Z cambia a 1. BNE salta si el Flag Z=0, por lo tanto no salta y sigue con ....
;En resumen se copiaron 800 datos desde la RAM (ya sabes según en al capitulo anterior,
;que si se habla de $7EXXXX o $7FXXXX es que accedimos a la RAM) y se dejan en
;posición RAM de $7F0000 en adelante.
TransferenciaEstas instrucciones sirven para copiar el contenido de un registro a otro.
Las transferencias mas conocidas son:
TAX ; se transfiere (es lo mismo que "copiar") el valor de A a X.
TAY ; se transfiere el valor de A a Y.
TCD ; se transfiere el valor de A al registro DP.
TXS ; Transfiere de X a la Pila.
TXY ; Transfiere de X a Y.
TYX ; Transfiere de Y a X.
TYA ; Transfiere de Y al acumulador.
TXA ; Transfiere de X al acumulador.
Referencia Rápida de InstruccionesAquí está la mayoría de las instrucciones en Ingles claro, no es necesario aprenderlas todas, pero es para que empiecen a acostumbrarse.
ADC - add with carry
AND - logical AND
BCC - branch if carry clear
BCS - branch if carry set
BEQ - branch if equal
BIT - bit test
BMI - branch if minus
BNE - branch if not equal
BPL - branch if plus
BRA - branch always
BRK - break point instruction
BVC - branch if overflow clear
BVS - branch if overflow set
CLC - clear the carry flag
CLD - clear the decimal flag
CLI - clear the interrupt flag
CLP - clear bits in P
CLR - store a zero into memory
CMP - compare accumulator
CPX - compare x register
CPY - compare y register
CSP - call system procedure
DEC - decrement acc or memory
DEX - decrement x register
DEY - decrement y register
EOR - exclusive-or accumulator
HLT - halt (stop) the clock
INC - increment acc or memory
INX - increment x register
INY - increment y register
JMP - jump to new location
JSR - jump to subroutine
LDA - load accumulator
LDX - load x register
LDY - load y register
MVN - block move (decrement)
MVP - block move (increment)
NOP - no operation
ORA - logical or accumulator
PHA - push accumulator
PHP - push p
PHX - push x register
PHY - push y register
PLA - pop accumulator
PLP - pop p
PLX - pop x register
PLY - pop y register
PSH - push operand
PUL - pop operand
RET - return from subroutine
ROL - rotate left acc/mem
ROR - rotate right acc/mem
RTI - return from interrupt
RTL - return from long subroutine
RTS - return from short subroutine
SBC - subtract with carry
SED - set decimal flag
SEI - set interrupt flag
SEP - set bits in P
SHL - shift left acc/mem
SHR - shift right acc/mem
STA - store accumulator
STX - store x register
STY - store y register
SWA - swap accumulator halves
TAD - transfer acc to D
TAS - transfer acc to S
TAX - transfer acc to x
TAY - transfer acc to y
TCB - test and clear bit
TDA - transfer D to acc
TSA - transfer S to acc
TSB - test and set bit
TSX - transfer S to X
TXA - transfer x to acc
TXS - transfer x to S
TXY - transfer x to y
TYA - transfer y to acc
TYX - transfer y to x
WAI - wait for interrupt
XCE - exchange carry with emulation bit
Preguntas y Respuestas1. Si tenemos
LDA #$0000
BEQ $1234
BNE $4321
BRA $0001
¿Salta a $1234, a $4321 o a $0001?
R: Salta a $1234 ya que LDA #$0000 pone Z=1 y BEQ salta si Z=1.
2. ¿Con cuanto queda Y?
Direc / Instrucción
------ ----------
$0998: LDY #$0000
$1000: LDA #$0002
$1002: INC
$1003: INY
$1004: CMP #$0A
$1006: BEQ $2000
$1008: BRA $1002
$1010: DEC
...
$2000: DEC
R: Es un ciclo que aumenta A e Y hasta que A sea igual a 0Ah. A parte con 0002h, y hasta 0Ah se le suman 8hex. El registro Y cuenta cada iteración por lo que Y=8.
Fuente:
darkn.romhackhispano.org
Volver a la página principal.