errores_dia_1 #2

Merged
sejo merged 7 commits from maleza/compudanzas:errores_dia_1 into main 6 months ago
  1. 121
      src/tutorial_de_uxn_día_1.gmo

121
src/tutorial_de_uxn_día_1.gmo

@ -6,13 +6,13 @@ también saltaremos directo a nuestros primeros programas simples para demostrar
# ¿por qué uxn?
o primero que nada... qué es uxn?
o primero que nada... ¿qué es uxn?
> Uxn es una computadora portable de 8 bit capaz de correr herramientas y juegos simples programable en su propio pequeño lenguaje ensamblador. Es también un ámbito de juego donde aprender habilidades básicas de computación.
=> https://wiki.xxiivv.com/site/uxn.html XXIIVV - uxn
i invite you to read "why create a smol virtual computer" from the 100R site, as well:
te invito a leer "why create a smol virtual computer" del sitio de 100R, también:
=> https://100r.co/site/uxn.html 100R - uxn
@ -22,17 +22,17 @@ personalmente, veo en ella las siguientes virtudes:
* hecha para el largo plazo
* hecha para aplicaciones audiovisuales interactivas
* arquitectura y set de instrucciones simple (sólo 32 instrucciones!)
* arquitectura y set de instrucciones simple (¡sólo 32 instrucciones!)
* primero-offline: funciona localmente y sólo necesitas unos pocos archivos de documentación para avanzar
* ámbito de práctica y experimentación de computación dentro de límites
* ya ortada a plataformas de computación actuales y de varios años de antigüedad
* ya portada a plataformas de computación actuales y de varios años de antigüedad
¡todos estos conceotos suenan genial para mí, y espero que para tí también! sin embargo, noto algunos aspectos que pueden hacerla parecer no tan asequible:
* es programada en un lenguaje ensamblador, uxntal
* utiliza notación {postfix} (alias notación polaca inversa) / está inspirada en máquinas forth
la idea de este tutorial es explorar estos dos aspectos y revelar cómo trabajan juntos para dar a uxn su poder con una complegidad relativamente baja.
la idea de este tutorial es explorar estos dos aspectos y revelar cómo trabajan juntos para dar a uxn su poder con una complejidad relativamente baja.
# notación postfija (y la pila)
@ -42,7 +42,7 @@ esto implica que está principalmente basada en interacciones con una pila "push
> Notación Polaca Reversa (NPR), también conocida como notación postfija polaca o simplemente notación postfija, es una notación matemática en la que los operadores siguen a sus operandos [...]
=> https://en.wikipedia.org/wiki/Reverse_Polish_notation Reverse Polish notation - Wikipedia
=> https://es.wikipedia.org/wiki/Notaci%C3%B3n_polaca_inversa Notación Polaca Inversa - Wikipedia
## suma postfija
@ -58,20 +58,21 @@ dónde, leyendo de izquierda a derecha:
* el número 48 es empujado en la pila
* + toma dos elementos de la parte superior de la pila, los suma, y empuja el resultado en la pila
the book Starting Forth has some great illustrations of this process of addition:
el libro Starting Forth tiene algunas ilustraciones grandiosas sobre este proceso de suma:
=> https://www.forth.com/starting-forth/1-forth-stacks-dictionary/#The_Stack_Forth8217s_Workspace_for_Arithmetic The Stack: Forth’s Workspace for Arithmetic
## de infija a postfija
expresiones más complejas en notación infija, que requieren paréntesis o reglas de precedencia de operadores (y un sistema más complejo para codificarlas), pueden ser simplificadas mediante notación postfija.
por ejemplo, la siguiente expresión infija:
``` (2 + 16)/8 + 48
(3 + 5)/2 + 48
```
pueden ser escritas en notación postfija como:
puede ser escrita en notación postfija como:
``` 3 5 + 2 / 48 +
3 5 + 2 / 48 +
@ -96,7 +97,6 @@ nota: en el caso de la división, los operandos siguen el mismo orden de izquier
irás descubriendo cómo el uso de la pila puede ser muy poderoso ya que ahorra operandos y/o resultados intermedios sin necesidad de que asignemos explicitamente un espacio en memoria para ellos (por ejemplo, mediante el uso de "variables" en otros lenguajes de programación)
we'll come back to postfija notation and the stack very soon!
¡vamos a volver a la notación postfija y la pila muy pronto!
# arquitectura de la computadora uxn
@ -121,7 +121,6 @@ cada instrucción junto con sus banderas de modo puede ser codificada en una sol
todas estas instrucciones operan sobre elementos en la pila, ya sea tomando de ella sus operandos y/o empujando en ella sus resultados.
we'll be covering these instructions slowly over this tutorial.
vamos a ir cubriendo lentamente estas instrucciones durante este tutorial.
## memoria uxn
@ -155,13 +154,13 @@ la instrucción va a implicar normalmente un cambio en la(s) pila(s), y algunas
# instalación y toolchain
liste? obtengamos el ensamblador uxn (uxnasm) y emulador (uxnemu) de su repositorio git:
¿liste? obtengamos el ensamblador uxn (uxnasm) y emulador (uxnemu) de su repositorio git:
=> https://git.sr.ht/~rabbits/uxn ~rabbits/uxn - sourcehut git
estas instrucciones son para sistemas basados en linux.
si necesitas una mano, encuèntranos en #uxn en irc.esper.net :)
si necesitas una mano, encuéntranos en #uxn en irc.esper.net :)
## instalar SDL2
@ -237,7 +236,7 @@ en sistemas de tipo forth podemos ver el siguiente tipo de notación para expres
ADD ( a b -- a+b )
```
esto significa que ADD tome el primer elemento desde arriba 'b', luego toma el siguiente primer elemento 'a', y empuja devuelta el resultado de sumar a+b.
esto significa que ADD toma el primer elemento desde arriba 'b', luego toma el siguiente primer elemento 'a', y empuja devuelta el resultado de sumar a+b.
ahora que estamos en eso, hay una instrucción complementaria, SUB (resta) (opcode 19), que toma los dos elementos superiores de la pila, los resta, y empuja a la pila el resultado:
@ -249,24 +248,24 @@ nota que el orden de los operandos es similar al de la división que discutimos
## un primer programa
escribamos el siguiente programa en nuestro editor de texto favorito, y guardémoslo como hello.tal:
escribamos el siguiente programa en nuestro editor de texto favorito, y guardémoslo como hola.tal:
```
( hello.tal )
( hola.tal )
|0100 LIT 68 LIT 18 DEO
```
ensamblémoslo y corrámoslo:
```
$ ./bin/uxnasm hello.tal bin/hello.rom && ./bin/uxnemu bin/hello.rom
$ ./bin/uxnasm hola.tal bin/hola.rom && ./bin/uxnemu bin/hola.rom
```
veremos una salida con el siguiente aspecto:
```
Assembled bin/hello.rom(5 bytes), 0 labels, 0 macros.
Uxn loaded[bin/hello.rom].
Assembled bin/hola.rom(5 bytes), 0 labels, 0 macros.
Uxn loaded[bin/hola.rom].
Device added #00: system, at 0x0000
Device added #01: console, at 0x0010
Device added #02: screen, at 0x0020
@ -295,7 +294,7 @@ la última 'h' que vemos es la salida de nuestro programa. cambia el 68 a, por e
acabamos de correr el siguiente programa en uxntal:
```
( hello.tal )
( hola.tal )
|0100 LIT 68 LIT 18 DEO
```
@ -314,7 +313,7 @@ leyendo el programa de izquierda a derecha, podemos ver el siguiente comportamie
* la instrucción LIT empuja el número 68 a la pila
* la instrucción LIT empuja el número 18 a la pila
* la instrucción DEO toma el elemento superior de la pila (18) y lo usa como dirección de dispositivo
* la instrucción DEO toma el elemento superiir de la pila (68) y lo usa como byte a escribir
* la instrucción DEO toma el elemento superior de la pila (68) y lo usa como byte a escribir
* la instrucción DEO escribe el byte a la dirección de dispositivo, dejando la pila vacía
¿y qué es el dispositivo de entrada/salida con la dirección 18?
@ -342,7 +341,7 @@ Assembled bin/hello.rom(5 bytes), 0 labels, 0 macros.
para el curioso (¡como tu!), podemos usar una herramienta como hexdump para ver sus contenidos:
```
$ hexdump -C bin/hello.rom
$ hexdump -C bin/hola.rom
00000000 01 68 01 18 17 |.h...|
00000005
```
@ -355,7 +354,7 @@ $ hexdump -C bin/hello.rom
de hecho, podríamos haber escrito nuestro programa con estos números hexadecimales (el código máquina), y hubiera funcionado igual:
```
( hello.tal )
( hola.tal )
|0100 01 68 01 18 17 ( LIT 68 LIT 18 DEO )
```
@ -370,16 +369,15 @@ puedes encontrar los opcodes de todas las 32 instrucciones en la referencia uxnt
podemos expandir nuestro programa para imprimir más caracteres:
```
( hello.tal )
( hola.tal )
|0100 LIT 68 LIT 18 DEO ( h )
LIT 65 LIT 18 DEO ( e )
LIT 6c LIT 18 DEO ( l )
LIT 6c LIT 18 DEO ( l )
LIT 6f LIT 18 DEO ( o )
LIT 6c LIT 18 DEO ( l )
LIT 61 LIT 18 DEO ( a )
LIT 0a LIT 18 DEO ( newline )
```
si lo ensamblamos y corremos, tendremos un 'hello' en nuestra terminal, usando 30 bytes de programa :)
si lo ensamblamos y corremos, tendremos un 'hola' en nuestra terminal, usando 25 bytes de programa :)
¿ok, y... te gusta?
@ -395,9 +393,9 @@ las runas son caracteres especiales que indican a uxnasm algún pre procesamient
ya vimos la primera de ellas: | define un pad absoluto: la dirección donde el siguiente elemento escrito será ubicado en memoria.
si la dirección es de 1 byte de longitud, es asumido que es una dirección de el espacio de entrada/salidao de la página cero.
si la dirección es de 1 byte de longitud, es asumido que es una dirección de el espacio de entrada/salida o de la página cero.
si la dirección es de 2 bytes de longitud, es asumido que es una dirección de la memoria principal.
si la dirección es de 2 bytes de longitud, es asumido que es una dirección de la memoria principal.
## runa hex literal
@ -408,7 +406,7 @@ hablemos de otra: #.
usando esta runa, podemos reescribir nuestro primer programa como:
```
( hello.tal )
( hola.tal )
|0100 #68 #18 DEO
```
@ -417,7 +415,7 @@ nota que sólo puedes usar esta runa para escribir los contenidos de uno o dos b
el siguiente tendría el mismo comportamiento que el programa de arriba, pero usando un byte menos (en la siguiente sección/día veremos por qué)
```
( hello.tal )
( hola.tal )
|0100 #6818 DEO
```
@ -429,15 +427,14 @@ importante: recuerda que esta runa (y las otras con la palabra "literal" en su n
nos permite que uxnasm decodifique el valor numérico de un caracter ascii.
nuestro "programa hello" luciría de la siguiente manera, usando las nuevas runas que acabamos de aprender:
nuestro "programa hola" luciría de la siguiente manera, usando las nuevas runas que acabamos de aprender:
```
( hello.tal )
( hola.tal )
|0100 LIT 'h #18 DEO
LIT 'e #18 DEO
LIT 'l #18 DEO
LIT 'l #18 DEO
LIT 'o #18 DEO
LIT 'l #18 DEO
LIT 'a #18 DEO
#0a #18 DEO ( newline )
```
@ -455,7 +452,7 @@ por ejemplo, para el dispositivo de consola, la manera en que verías esto escri
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
```
podemos ver un pad absokuto a la dirección 10, que asigna lo siguiente a esa dirección. dado que la dirección consiste en un sólo byte, uxnasm asume que es para el espacio de memoria de entrada/salida o la página cero.
podemos ver un pad absoluto a la dirección 10, que asigna lo siguiente a esa dirección. dado que la dirección consiste en un sólo byte, uxnasm asume que es para el espacio de memoria de entrada/salida o la página cero.
luego vemos la etiqueta @Console: ésta etiqueta va a corresponder a la dirección 10.
@ -479,20 +476,19 @@ la runa para referirse a una dirección literal en la página cero o el espacio
recuerda: al ser una runa de "dirección literal" va a agregar una instrucción LIT antes de la correspondiente dirección :)
podemos reescribir nuestro "programa hello world" como sigue:
podemos reescribir nuestro "programa hola mundo" como sigue:
```
( hello.tal )
( hola.tal )
( devices )
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
( main program )
( programa principal )
|0100 LIT 'h .Console/write DEO
LIT 'e .Console/write DEO
LIT 'l .Console/write DEO
LIT 'l .Console/write DEO
LIT 'o .Console/write DEO
LIT 'l .Console/write DEO
LIT 'a .Console/write DEO
#0a .Console/write DEO ( newline )
```
@ -515,49 +511,48 @@ podemos definir un macro llamado EMIT que tomará de la pila un byte correspondi
¡no olvides los espacios!
```
( print a character to standard output )
%EMIT { .Console/write DEO } ( character -- )
( escribe un caracter a la salida estandard )
%EMIT { .Console/write DEO } ( caracter -- )
```
para llamar a un macro, sólo escribimos su nombre:
```
( print character h )
( imprime caracter h )
LIT 'h EMIT
```
podemos llamar macros dentro de macros, por ejemplo:
```
( print a newline )
( imprime una nueva línea )
%NL { #0a EMIT } ( -- )
```
# un hello world más idiomático
# un hola mundo más idiomático
usando todos estos macros y runas, nuestro programa puede terminar luciendo como lo siguiente:
```
( hello.tal )
( devices )
( hola.tal )
( dispositivos )
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
( macros )
( print a character to standard output )
%EMIT { .Console/write DEO } ( character -- )
( print a newline )
( imprime un caracter en la salida estandard )
%EMIT { .Console/write DEO } ( caracter -- )
( imprime una nueva línea )
%NL { #0a EMIT } ( -- )
( main program )
( programa principal )
|0100 LIT 'h EMIT
LIT 'e EMIT
LIT 'l EMIT
LIT 'o EMIT
LIT 'l EMIT
LIT 'o EMIT
LIT 'a EMIT
NL
```
termina siendo ensamblado en los mismos 30 bytes que los ejemplos de arriba, pero con suerte más legible y mantenible.
termina siendo ensamblado en los mismos 25 bytes que los ejemplos de arriba, pero con suerte más legible y mantenible.
podemos "mejorar" este programa haciendo que un loop imprima los caracteres, pero estudiaremos eso más tarde :
@ -575,12 +570,12 @@ EMIT EMIT EMIT EMIT EMIT
## imprimir un dígito
si miras en la tabla ascii, verás que esl código hexadecimal 30 corresponde al dígito 0, 31 al dígito 1, siguiendo hasta el 39 que corresponde al dígito 9.
si miras en la tabla ascii, verás que el código hexadecimal 30 corresponde al dígito 0, 31 al dígito 1, siguiendo hasta el 39 que corresponde al dígito 9.
define un macro PRINT-DIGIT que toma un número (del 0 al 9) de la pila, e imprime el correspondiente dígito en la salida estandard.
define un macro IMPRIMIR-DIGITO que toma un número (del 0 al 9) de la pila, e imprime el correspondiente dígito en la salida estandard.
```
%PRINT-DIGIT { } ( number -- )
%IMPRIMIR-DIGITO { } ( número -- )
```
# instrucciones del día 1
@ -590,9 +585,9 @@ define un macro PRINT-DIGIT que toma un número (del 0 al 9) de la pila, e impri
* ADD: toma los dos elementos superiores de la pila, los suma, y empuja el resultado ( a b -- a+b )
* SUB: toma los dos elementos superiores de la pila, los resta, y empuja el resultado ( a b -- a-b )
* LIT: empuja el siguiente byte en memoria a la pila
* DEO: escribe el byte dado en la dirección de dispositivo dada, tomando ambos de la pila ( byte address -- )
* DEO: escribe el byte dado en la dirección de dispositivo dada, tomando ambos de la pila ( byte dirección -- )
# day 2
# día 2
¡mantente al tanto por las siguientes secciones del {tutorial de uxn}!

Loading…
Cancel
Save