├── GreenCardLEGv8.pdf ├── practico 1 ├── ej01.pdf ├── ej02.pdf ├── ej03.pdf ├── ej04.pdf ├── ej05.pdf ├── ej06.pdf ├── ej07.pdf ├── ej08.pdf ├── ej09.pdf ├── ej10.pdf └── notas.pdf ├── practico 2 ├── ej01.pdf ├── ej02.pdf ├── ej03.pdf ├── ej04.pdf ├── ej05.pdf └── notas.pdf ├── practico 3 ├── ej01.pdf ├── ej02.pdf ├── ej03.pdf ├── ej04.pdf ├── ej05.pdf ├── ej06.pdf ├── ej07.pdf ├── ej08.pdf ├── ej09.pdf ├── ej10.pdf ├── ej11.pdf ├── ej12.pdf └── ej13.pdf ├── practico 4 ├── ej01.pdf ├── ej02.pdf ├── ej03.pdf ├── ej04.pdf ├── ej05.pdf ├── ej06.pdf ├── ej07.pdf ├── ej08.pdf └── notas.pdf ├── practico 5 ├── ej01.pdf ├── ej02.pdf ├── ej03.pdf ├── ej04.pdf ├── ej05.pdf ├── ej06.pdf ├── ej07.pdf ├── ej08.pdf ├── ej09.pdf ├── ej10.pdf ├── ej11.pdf ├── ej12.pdf ├── ej13.pdf └── notas.pdf ├── lab ├── ejercicio1 │ ├── bin │ │ └── gpiom │ ├── descripcion.txt │ ├── memmap │ ├── Dockerfile │ ├── Makefile │ ├── app.s │ ├── README.md │ ├── start.s │ └── funciones.s ├── ejercicio2 │ ├── bin │ │ └── gpiom │ ├── memmap │ ├── Dockerfile │ ├── descripcion.txt │ ├── Makefile │ ├── README.md │ ├── start.s │ ├── app.s │ └── funciones.s └── README.md ├── practico 6 ├── assets │ └── ESR.png ├── ej10.md ├── ej09.md ├── ej02.md ├── ej03.md ├── ej04.md ├── ej05.md ├── ej11.md ├── ej01.md ├── ej06.md ├── ej07.md └── ej08.md ├── howToDebugAArch64GDB-dashboard.pdf ├── practico 9 ├── ej01.md ├── ej05.md ├── ej02.md ├── ej10.md ├── ej09.md ├── ej07.md ├── ej04.md ├── ej06.md ├── ej11.md ├── ej03.md ├── ej08.md └── assets │ └── ej08.1.svg ├── practico 7 ├── ej01.md ├── ej02.md ├── ej03.md ├── ej08.md ├── ej09.md ├── ej06.md ├── ej05.md ├── ej04.md └── ej07.md └── practico 8 ├── ej09.md ├── ej03.md ├── ej01.md ├── ej04.md ├── ej02.md ├── ej06.md ├── ej10.md ├── ej05.md ├── ej08.md └── ej07.md /GreenCardLEGv8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/GreenCardLEGv8.pdf -------------------------------------------------------------------------------- /practico 1/ej01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej01.pdf -------------------------------------------------------------------------------- /practico 1/ej02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej02.pdf -------------------------------------------------------------------------------- /practico 1/ej03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej03.pdf -------------------------------------------------------------------------------- /practico 1/ej04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej04.pdf -------------------------------------------------------------------------------- /practico 1/ej05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej05.pdf -------------------------------------------------------------------------------- /practico 1/ej06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej06.pdf -------------------------------------------------------------------------------- /practico 1/ej07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej07.pdf -------------------------------------------------------------------------------- /practico 1/ej08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej08.pdf -------------------------------------------------------------------------------- /practico 1/ej09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej09.pdf -------------------------------------------------------------------------------- /practico 1/ej10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/ej10.pdf -------------------------------------------------------------------------------- /practico 1/notas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 1/notas.pdf -------------------------------------------------------------------------------- /practico 2/ej01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 2/ej01.pdf -------------------------------------------------------------------------------- /practico 2/ej02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 2/ej02.pdf -------------------------------------------------------------------------------- /practico 2/ej03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 2/ej03.pdf -------------------------------------------------------------------------------- /practico 2/ej04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 2/ej04.pdf -------------------------------------------------------------------------------- /practico 2/ej05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 2/ej05.pdf -------------------------------------------------------------------------------- /practico 2/notas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 2/notas.pdf -------------------------------------------------------------------------------- /practico 3/ej01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej01.pdf -------------------------------------------------------------------------------- /practico 3/ej02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej02.pdf -------------------------------------------------------------------------------- /practico 3/ej03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej03.pdf -------------------------------------------------------------------------------- /practico 3/ej04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej04.pdf -------------------------------------------------------------------------------- /practico 3/ej05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej05.pdf -------------------------------------------------------------------------------- /practico 3/ej06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej06.pdf -------------------------------------------------------------------------------- /practico 3/ej07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej07.pdf -------------------------------------------------------------------------------- /practico 3/ej08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej08.pdf -------------------------------------------------------------------------------- /practico 3/ej09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej09.pdf -------------------------------------------------------------------------------- /practico 3/ej10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej10.pdf -------------------------------------------------------------------------------- /practico 3/ej11.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej11.pdf -------------------------------------------------------------------------------- /practico 3/ej12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej12.pdf -------------------------------------------------------------------------------- /practico 3/ej13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 3/ej13.pdf -------------------------------------------------------------------------------- /practico 4/ej01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej01.pdf -------------------------------------------------------------------------------- /practico 4/ej02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej02.pdf -------------------------------------------------------------------------------- /practico 4/ej03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej03.pdf -------------------------------------------------------------------------------- /practico 4/ej04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej04.pdf -------------------------------------------------------------------------------- /practico 4/ej05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej05.pdf -------------------------------------------------------------------------------- /practico 4/ej06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej06.pdf -------------------------------------------------------------------------------- /practico 4/ej07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej07.pdf -------------------------------------------------------------------------------- /practico 4/ej08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/ej08.pdf -------------------------------------------------------------------------------- /practico 4/notas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 4/notas.pdf -------------------------------------------------------------------------------- /practico 5/ej01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej01.pdf -------------------------------------------------------------------------------- /practico 5/ej02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej02.pdf -------------------------------------------------------------------------------- /practico 5/ej03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej03.pdf -------------------------------------------------------------------------------- /practico 5/ej04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej04.pdf -------------------------------------------------------------------------------- /practico 5/ej05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej05.pdf -------------------------------------------------------------------------------- /practico 5/ej06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej06.pdf -------------------------------------------------------------------------------- /practico 5/ej07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej07.pdf -------------------------------------------------------------------------------- /practico 5/ej08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej08.pdf -------------------------------------------------------------------------------- /practico 5/ej09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej09.pdf -------------------------------------------------------------------------------- /practico 5/ej10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej10.pdf -------------------------------------------------------------------------------- /practico 5/ej11.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej11.pdf -------------------------------------------------------------------------------- /practico 5/ej12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej12.pdf -------------------------------------------------------------------------------- /practico 5/ej13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/ej13.pdf -------------------------------------------------------------------------------- /practico 5/notas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 5/notas.pdf -------------------------------------------------------------------------------- /lab/ejercicio1/bin/gpiom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/lab/ejercicio1/bin/gpiom -------------------------------------------------------------------------------- /lab/ejercicio2/bin/gpiom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/lab/ejercicio2/bin/gpiom -------------------------------------------------------------------------------- /practico 6/assets/ESR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/practico 6/assets/ESR.png -------------------------------------------------------------------------------- /howToDebugAArch64GDB-dashboard.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nachogonzaliaunc/21-OrganizacionDelComputador/HEAD/howToDebugAArch64GDB-dashboard.pdf -------------------------------------------------------------------------------- /practico 9/ej01.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 1 2 | Marcar con una barra invertida e indicar el número de bits que representa cada una de las líneas del *data path*. 3 | 4 | ![Simple datapath with the control unit](./assets/ej01.svg) -------------------------------------------------------------------------------- /practico 6/ej10.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 10 2 | Suponga que el registro X9 contiene un número entero representado en complemento a dos. Dar una secuencia mínima de operaciones a realizar para devolver en X10 un 1 si y sólo si el contenido de X9 es negativo. 3 | 4 | ``` 5 | LSR X10, X9, #63 6 | ``` -------------------------------------------------------------------------------- /practico 9/ej05.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 5 2 | Agregando una compuerta en diagrama del data path & control, cambiar la implementación de la instrucción CBZ a CBNZ. 3 | ``` 4 | Me basta con negar la salida de la ALU "ALU result" 5 | ``` 6 | ![Simple datapath with the control unit](./assets/ej05.svg) -------------------------------------------------------------------------------- /practico 6/ej09.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 9 2 | Suponga que el registro X9 contiene el Exception Syndrome Register (ESR). Dé una secuencia mínima de instrucciones LEGv8 para poner en X10 el número que codifica la clase de excepción Exception Class (EC). 3 | 4 | ![Exception syndrome register](./assets/ESR.png) 5 | 6 | ``` 7 | LSR X10, X9, #26 8 | ``` -------------------------------------------------------------------------------- /lab/ejercicio1/descripcion.txt: -------------------------------------------------------------------------------- 1 | Integrantes Grupo: 2 | 3 | - Gonzalia Alvaro Tomas, 43150094 4 | - Gonzalia Ignacio Agustin, 41680508 5 | - Usaj Santiago, 41321444 6 | 7 | Descripcion del Ejercicio: 8 | 9 | El codigo realiza un dibujo de un cohete y la luna. Al presionar la tecla "W", la luna cambia de forma y tamaño. Cuando presionamos la tecla "A", el dibujo vuelve al original. -------------------------------------------------------------------------------- /lab/ejercicio1/memmap: -------------------------------------------------------------------------------- 1 | 2 | SECTIONS 3 | { 4 | . = 0x80000; 5 | .text : { KEEP(*(.text.boot)) *(.text*) } 6 | .bss : { *(.bss*) } 7 | .bss (NOLOAD) : { 8 | . = ALIGN(16); 9 | __bss_start = .; 10 | *(.bss .bss.*) 11 | *(COMMON) 12 | __bss_end = .; 13 | } 14 | _end = .; 15 | } 16 | __bss_size = (__bss_end - __bss_start)>>3; 17 | -------------------------------------------------------------------------------- /lab/ejercicio2/memmap: -------------------------------------------------------------------------------- 1 | 2 | SECTIONS 3 | { 4 | . = 0x80000; 5 | .text : { KEEP(*(.text.boot)) *(.text*) } 6 | .bss : { *(.bss*) } 7 | .bss (NOLOAD) : { 8 | . = ALIGN(16); 9 | __bss_start = .; 10 | *(.bss .bss.*) 11 | *(COMMON) 12 | __bss_end = .; 13 | } 14 | _end = .; 15 | } 16 | __bss_size = (__bss_end - __bss_start)>>3; 17 | -------------------------------------------------------------------------------- /lab/ejercicio1/Dockerfile: -------------------------------------------------------------------------------- 1 | # Este Dockerfile define un container con gcc y qemu para poder correr 2 | FROM debian:buster-slim as build-env 3 | WORKDIR /root/ 4 | 5 | RUN apt-get update && apt-get -y install \ 6 | git \ 7 | gcc-aarch64-linux-gnu \ 8 | build-essential \ 9 | python \ 10 | pkg-config \ 11 | zlib1g-dev \ 12 | libglib2.0-dev \ 13 | libpixman-1-dev \ 14 | qemu-system-arm 15 | 16 | WORKDIR /local 17 | ENTRYPOINT ["/bin/bash"] 18 | -------------------------------------------------------------------------------- /lab/ejercicio2/Dockerfile: -------------------------------------------------------------------------------- 1 | # Este Dockerfile define un container con gcc y qemu para poder correr 2 | FROM debian:buster-slim as build-env 3 | WORKDIR /root/ 4 | 5 | RUN apt-get update && apt-get -y install \ 6 | git \ 7 | gcc-aarch64-linux-gnu \ 8 | build-essential \ 9 | python \ 10 | pkg-config \ 11 | zlib1g-dev \ 12 | libglib2.0-dev \ 13 | libpixman-1-dev \ 14 | qemu-system-arm 15 | 16 | WORKDIR /local 17 | ENTRYPOINT ["/bin/bash"] 18 | -------------------------------------------------------------------------------- /lab/ejercicio2/descripcion.txt: -------------------------------------------------------------------------------- 1 | Integrantes Grupo: 2 | 3 | - Gonzalia Alvaro Tomas, 43150094 4 | - Gonzalia Ignacio Agustin, 41680508 5 | - Usaj Santiago, 41321444 6 | 7 | Descripcion del Ejercicio: 8 | 9 | Es un "juego" donde la nave debe alunisar. Esta se controla con las teclas "WASD". Al llegar a la luna comenzara una animacion, luego de una pequeña pantalla de carga, donde se mostrara a la nave alunisar y desplegar la bandera argentina. Una vez terminada la animacion, se puede reiniciar el juego apretando "SPACE". -------------------------------------------------------------------------------- /practico 7/ej01.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 1 2 | Para estos dos programas con entrada y salida en X0, decir que función realizan: 3 | ``` 4 | SUBIS X0, X0, #0 5 | B.LT else 6 | B done 7 | else: SUB X0, XZR, X0 8 | done: 9 | 10 | // El algorítmo calcula el valor absoluto de X0. 11 | ``` 12 | 13 | 14 | ``` 15 | MOV X9, X0 16 | MOV X0, XZR 17 | loop: ADD X0, X0, X9 18 | SUBI X9, X9, #1 19 | CBNZ X9, loop 20 | done: 21 | 22 | // El algorítmo calcula la sumatoria de X9 hasta 0. 23 | ``` -------------------------------------------------------------------------------- /practico 8/ej09.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 9 2 | Suponiendo que el PC está en la primera palabra de memoria 0x00000000 y se desea saltar a la última instrucción de los primeros 4 GiB o sea a 0xFFFFFFFC, cuántas instrucciones B son necesarias? (no se puede usar BR). 3 | ``` 4 | Recordemos, por lo visto en el ejercicio anterior, la maxima cantidad de lugares 5 | que puedo saltar con un branch es 0x07FFFFFC, entonces dividamos 0xFFFFFFFC/0x07FFFFFC 6 | 7 | 0xFFFFFFFC = 4294967292 8 | 0x07FFFFFC = 134217724 9 | 10 | 0xFFFFFFFC / 0x07FFFFFC = 32.00000092387202 (resuelto con calculadora) 11 | 12 | Entonces se necesitan 33 instrucciones B 13 | ``` -------------------------------------------------------------------------------- /practico 9/ej02.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 2 2 | Considerando la siguiente distribución de instrucciones en un programa: 3 | 4 | | R-type | I-type | LDUR | STUR | CBZ | B | 5 | |:------:|:------:|:----:|:----:|:---:|:--:| 6 | | 24% | 28% | 25% | 10% | 11% | 2% | 7 | 8 | 2.1) Qué porcentaje de todas las instrucciones utiliza data memory? 9 | ``` 10 | LDUR y STUR, el 35% 11 | ``` 12 | 13 | 2.2) Qué porcentaje de todas las instrucciones utiliza instruction memory? 14 | ``` 15 | Todos, 100% 16 | ``` 17 | 18 | 2.3) Qué porcentaje de todas las instrucciones utiliza el sign extend? 19 | ``` 20 | I-type, LDUR, STUR, CBZ y B ya que admiten inmediatos, en total el 76% 21 | ``` -------------------------------------------------------------------------------- /practico 6/ej02.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 2 2 | Dadas las siguientes sentencias en assembler LEGv8: 3 | ``` 4 | a) ADD X0, X1, X2 5 | b) ADDI X0, X0, #1 6 | ADD X0, X1, X2 7 | ``` 8 | #### 2.1) Escribir la secuencia mínima de código “C” asumiendo que los registros X0, X1 y X2 contienen las variables f, g y h respectivamente. 9 | 10 | #### 2.2) Dar el valor de cada variable en cada instrucción assembler si f, g y h se inicializan con valores de 1, 2, 3, en base 10, respectivamente. 11 | 12 | ```c 13 | // ADD X0, X1, X2 14 | 15 | f = g + h; // f = 2 + 3 = 5 16 | ``` 17 | ```c 18 | // ADDI X0, X0, #1 19 | // ADD X0, X1, X2 20 | 21 | f++; // f = f + 1 = 2 22 | f = g + h; // f = 2 + 3 = 5 23 | ``` -------------------------------------------------------------------------------- /practico 6/ej03.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 3 2 | Dadas las siguientes sentencias en “C”: 3 | ``` 4 | a) f = -g - f; 5 | b) f = g + (-f - 5); 6 | ``` 7 | 8 | #### 3.1) Escribir la secuencia mínima de código assembler LEGv8 asumiendo que f y g se asignan en los registros X0 y X1 respectivamente. 9 | 10 | #### 3.2) Dar el valor de cada variable en cada instrucción assembler si f y g se inicializan con valores de 4 y 5, en base 10, respectivamente. 11 | 12 | ``` 13 | a) f = -g - f; 14 | 15 | ADD X0, X1, X0 // f = 5 + 4 = 9 16 | SUB X0, XZR, X0 // f = -(5 + 4) = -5 - 4 = -9 17 | ``` 18 | ``` 19 | b) f = g + (-f - 5); 20 | 21 | ADDI X0, X0, #5 // f = 4 + 5 = 9 22 | SUB X0, X1, X0 // f = 5 - 9 = -4 23 | ``` -------------------------------------------------------------------------------- /practico 6/ej04.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 4 2 | Dadas las siguientes sentencias en assembler LEGv8: 3 | ``` 4 | a) SUB X1, XZR, X1 5 | ADD X0, X1, X2 6 | 7 | b) ADDI X2, X0, #1 8 | SUB X0, X1, X2 9 | ``` 10 | 11 | #### 4.1) Escribir la secuencia mínima de código “C” asumiendo que los registros X0, X1, y X2 contienen las variables f, g, y h respectivamente. 12 | 13 | #### 4.2) Dar el valor de cada variable en cada instrucción assembler si f, g, y h se inicializan con valores de 1, 2 y 3, en base 10 respectivamente. 14 | 15 | ```c 16 | // SUB X1, XZR, X1 17 | // ADD X0, X1, X2 18 | 19 | g = -g; // g = -2 20 | f = -g + h; // f = 1 21 | ``` 22 | ```c 23 | // ADDI X2, X0, #1 24 | // SUB X0, X1, X2 25 | 26 | h = f + 1; // h = 2 27 | f = g - h; // f = 0 28 | ``` -------------------------------------------------------------------------------- /practico 7/ej02.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 2 2 | Dado el siguiente programa LEGv8, dar el valor final de X10, dado que inicialmente 3 | { X10 = 0x0000000000000001 }. 4 | ``` 5 | SUBIS XZR, X9, #0 6 | B.GE else 7 | B done 8 | else: ORRI X10, XZR, #2 9 | done: 10 | ``` 11 | El algorítmo devuelve el resultado de la operación 0 or 2 (bit a bit) si y sólo si X9 es mayor a 0. 12 | 13 | #### 2.1) Dado que inicialmente { X9=0x0000000000101000 }. 14 | ``` 15 | En éste caso, X9 > 0, entonces X10 = #2 16 | ``` 17 | 18 | 19 | #### 2.2) Dado que inicialmente { X9=0x8000000000001000 }. 20 | ``` 21 | En éste caso, X9 < 0 (pues X9 = 1000....0000, 22 | donde el primer bit me marca el signo), 23 | luego, X10 no cambia su valor al terminar de ejecutarse 24 | el codigo. 25 | ``` -------------------------------------------------------------------------------- /practico 6/ej05.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 5 2 | Dadas las siguientes sentencias en “C”: 3 | ``` 4 | a) f = -g - A[4]; 5 | b) B[8] = A[i - j]; 6 | ``` 7 | 8 | Escribir la secuencia mínima de código assembler LEGv8 asumiendo que f, g, i y j se asignan en los registros X0, X1, X2 y X3 respectivamente, y que la dirección base de los arreglos A y B se almacenan en los registros X6 y X7 respectivamente. 9 | 10 | ``` 11 | // f = -g - A[4]; 12 | 13 | SUB X0, XZR, X1 // f = -g 14 | LDUR X3, [X6, #32] // j = a[4] 15 | SUB X0, X0, X3 // f = -g - a[4] 16 | ``` 17 | ``` 18 | // B[8] = A[i - j]; 19 | 20 | SUB X0, X2, X3 // f = i - j 21 | LSL X0, X0, #3 // f = (i - j) * 8 22 | ADD X0, X6, X0 // f = A + [(i - j) * 8] 23 | LDUR X0, [X0, #0] // f = A[i - j] 24 | STUR X0, [X7, #64] // B[8] = A[i - j] 25 | ``` -------------------------------------------------------------------------------- /practico 6/ej11.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 11 2 | Utilizar MOVZ, MOVK para cargar los registros: 3 | ``` 4 | X0 = 0x1234000000000000 5 | X1 = 0xBBB0000000000AAA 6 | X2 = 0xA0A0B1B10000C2C2 7 | X3 = 0x0123456789ABCDEF 8 | ``` 9 | 10 | ``` 11 | MOVZ X0, 0x1234, LSL 48 // X0 = 0x1234000000000000 12 | 13 | MOVZ X1, 0xBBB0, LSL 48 // X1 = 0xBBB0000000000000 14 | MOVK X1, 0x0AAA, LSL 00 // X1 = 0xBBB0000000000AAA 15 | 16 | MOVZ X2, 0xA0A0, LSL 48 // X2 = 0xA0A0000000000000 17 | MOVK X2, 0xB1B1, LSL 32 // X2 = 0xA0A0B1B100000000 18 | MOVK X2, 0xC2C2, LSL 00 // X2 = 0xA0A0B1B10000C2C2 19 | 20 | MOVZ X3, 0x0123, LSL 48 // X3 = 0x0123000000000000 21 | MOVZ X3, 0x4567, LSL 32 // X3 = 0x0123456700000000 22 | MOVZ X3, 0x89AB, LSL 16 // X3 = 0x0123456789AB0000 23 | MOVZ X3, 0xCDEF, LSL 00 // X3 = 0x0123456789ABCDEF 24 | ``` -------------------------------------------------------------------------------- /practico 7/ej03.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 3 2 | Dado el siguiente programa “C” y la asignación
3 | i <--> X0
4 | j <--> X1
5 | k <--> X2
6 | N <--> X9,
7 | escribir el programa LEGv8 que lo implementa. 8 | Notar que como se usa el operador || la evaluación es por cortocircuito. 9 | Opcional: hacerlo con el operador | que no está cortocircuitado. 10 | ```c 11 | long i,j,k; 12 | if (i==N || j==N) { 13 | ++k; 14 | } else { 15 | ++i; ++j; 16 | } 17 | ``` 18 | 19 | ``` 20 | subs xzr, x0, x9 // flags = i - N 21 | b.eq addk // si i = N salto a addk 22 | subs xzr, x1, x9 // flags = j - N 23 | b.eq addk // si j = N salto a addk 24 | addi x0, x0, #1 // i++ 25 | addi x1, x1, #1 // j++ 26 | done // salto a done 27 | addk: addi x2, x2, #1 // k++ 28 | done: 29 | ``` -------------------------------------------------------------------------------- /practico 9/ej10.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 10 2 | Supongamos que podemos construir una CPU con un ciclo de reloj variable, que se puede adaptar a la latencia de cada instrucción. Cuál sería la aceleración de esta nueva CPU sobre la anterior ([Ejercicio 8](./ej08.md)) si el mix de instrucciones de un programa es el siguiente: 3 | 4 | | R-type / I-type | LDUR | STUR | CBZ | B | 5 | |:---------------:|:----:|:----:|:---:|:--:| 6 | | 52% | 25% | 10% | 11% | 2% | 7 | 8 | * Como no tenemos implementado B, sumar el porcentaje a CBZ. 9 | 10 | ``` 11 | Tiempo promedio por instrucción = 0.52*775ps + 0.25*955ps + 0.1*955ps + (0.11+0.02)*780ps 12 | = 838.65ps 13 | 14 | Aceleración de la nueva CPU = periodo original / nuevo periodo 15 | = 955ps / 838.65ps 16 | ≈ 1.139 17 | ``` -------------------------------------------------------------------------------- /practico 8/ej03.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 3 2 | Dar el tipo de instrucción, la instrucción en assembler y la representación binaria de los siguientes campos de LEGv8: 3 | 4 | #### 3.1) op=0x658, Rm=13, Rn=15, Rd=17, shamt=0 5 | ``` 6 | op = 0x658 => sub 7 | 8 | La instrucción en assembler es: 9 | sub X17, X15, X13 10 | 11 | Y su representación binaria es: 11001011000011010000000111110001b 12 | opcode: 11001011000 13 | Rm: 01101 14 | shamt: 000000 15 | Rn: 01111 16 | Rd: 10001 17 | ``` 18 | 19 | #### 3.2) op=0x7c2, Rn=12, Rt=3, const=0x4 20 | ``` 21 | op = 0x7c2 => ldur 22 | 23 | La instrucción en assembler es: 24 | ldur x3, [x12, #4] 25 | 26 | Y su representación binaria es: 11111000010000000100000110000011b 27 | opcode: 11111000010 28 | dt_adress: 000000100 29 | op: 00 30 | Rn: 01100 31 | Rt: 00011 32 | ``` -------------------------------------------------------------------------------- /practico 8/ej01.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 1 2 | Extender los siguientes números de 26 bits en complemento a dos a 64 bits. Si el número es negativo verificar que la extensión a 64 bits codifica el mismo número original de 26 bits. 3 | 4 | #### 1.1) 00 0000 0000 0000 0000 0000 0001 5 | ``` 6 | Completo el numero: 7 | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 8 | 9 | Como es positivo, no debo calcular su complemento a 2. 10 | ``` 11 | 12 | #### 1.2) 10 0000 0000 0000 0000 0000 0000 13 | ``` 14 | Completo el numero: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 0000 0000 0000 0000 0000 0000 15 | Niego bit a bit: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1111 1111 1111 1111 1111 1111 16 | Sumo 1: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000 0000 0000 0000 0000 0000 17 | 18 | Este ultimo numero codifica el mismo numero original de 26 bits. 19 | ``` -------------------------------------------------------------------------------- /practico 6/ej01.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 1 2 | Dadas las siguientes sentencias en C: 3 | ``` 4 | a) f = g + h + i + j; 5 | b) f = g + (h + 5); 6 | c) f = (g + h) + (g + h) 7 | ``` 8 | 9 | #### 1.1) Escribir la secuencia **mínima** de código assembler LEGv8 asumiendo que f, g, h, i y j se asignan en los registros X0, X1, X2, X3 y X4 respectivamente. 10 | 11 | #### 1.2) Dar el valor de cada variable en cada instrucción assembler si f, g, h, i y j se inicializan con valores de 1, 2, 3, 4, 5, en base 10, respecticamente. 12 | 13 | ``` 14 | a) f = g + h + i + j; 15 | 16 | ADD X0, X1, X2 // f = 2 + 3 = 5 17 | ADD X0, X0, X3 // f = 5 + 4 = 9 18 | ADD X0, X0, X4 // f = 9 + 5 = 14 19 | ``` 20 | ``` 21 | b) f = g + (h + 5); 22 | 23 | ADDI X0, X2, #5 // f = 3 + 5 = 8 24 | ADD X0, X1, X0 // f = 2 + 8 = 10 25 | ``` 26 | ``` 27 | c) f = (g + h) + (g + h) 28 | 29 | ADD X0, X1, X2 // f = 2 + 3 = 5 30 | ADD X0, X0, X0 // f = 5 + 5 = 10 31 | ``` -------------------------------------------------------------------------------- /practico 9/ej09.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 9 2 | Para la tabla de latencias del [Ejercicio 8](./ej08.md), indicar el porcentaje de aumento de la velocidad de procesamiento si quitamos de las instrucciones de carga y almacenamiento la posibilidad de desplazamiento por el operando inmediato, es decir todas las instrucciones de carga son de la forma LDUR X0, [X1]. 3 | ``` 4 | Si modificamos LDUR y STUR para que no haya desplazamiento, ninguna de ellas 5 | usaría la ALU. Si quitamos la ALU del camino crítico de STUR tenemos: 6 | Camino Crítico = Reg.Read + I-Mem + Register File + D-Mem + Mux + Reg.Setup 7 | = 30 + 250 + 50 + 25 + 150 + 250 8 | = 755ps 9 | 10 | Con esta modificación, la instrucción con mayor latencia será CBZ, con 780ps. 11 | 12 | Calculamos el porcentaje de aumento de la velocidad como: 13 | (periodo original / nuevo periodo) * 100% = (955ps / 780ps)*100% 14 | = 122% 15 | ``` -------------------------------------------------------------------------------- /practico 9/ej07.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 7 2 | Agregar a la implementación de la ISA la instrucción de **salto incondicional** B, a partir de una nueva señal que sale de *Control*, *denominada UncondBranch*. 3 | 4 | ![Simple datapath with the control unit](./assets/ej07.svg) 5 | 6 | - Sign-extend: debe reconocer el opcode de la instrucción B, tomar el campo de inmediato (los 25 bits menos significativos) y extender el signo (replicar 36 veces el bit 25). 7 | - Control: debe decodificar el opcode de B y generar la señal de control “Uncondbranch”, que tomará valor ‘1’ en caso de ejecutar la instrucción B y ‘0’ en cualquier otro caso. 8 | 9 | | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | UncondBranch | 10 | |:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:|:------------:| 11 | | x | x | x | 0 | 0 | 0 | 0 | x | x | 1 | -------------------------------------------------------------------------------- /practico 9/ej04.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 4 2 | Cuando se fabrican los chips de silicio, defectos en los materiales y errores en la fabricación pueden generar circuitos defectuosos. Un defecto común es que un cable de señal se rompa y siempre registre un ‘0’ lógico. Esto se conoce comúnmente como *“stuck-at-0 fault”*. 3 | 4 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | 5 | |:-------|:-------:|:------:|:--------:| 6 | | **Tipo R** | 0 | 0 | 0 | 7 | | **LDUR** | x | `1` | `1` | 8 | | **STUR** | `1` | `1` | x | 9 | | **CBZ** | `1` | 0 | x | 10 | 11 | 4.1) ¿Qué instrucciones operarían de forma incorrecta si el cable MemToReg está atascado en ‘0’? 12 | ``` 13 | LDUR 14 | ``` 15 | 16 | 4.2) ¿Qué instrucciones operarían de forma incorrecta si el cable ALUSrc está atascado en ‘0’? 17 | ``` 18 | LDUR y STUR 19 | ``` 20 | 21 | 4.3) ¿Qué instrucciones operarían de forma incorrecta si el cable Reg2Loc está atascado en ‘0’? 22 | ``` 23 | STUR y CBZ 24 | ``` -------------------------------------------------------------------------------- /practico 8/ej04.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 4 2 | Transformar de binario a hexadecimal. Qué instrucciones LEGv8 representan en memoria? 3 | 4 | #### 4.1) 1000 1011 0000 0000 0000 0000 0000 0000 5 | ``` 6 | Los primeros 11 bits son: 10001011000b = 0x458 => add (tipo R) 7 | Entonces: 8 | opcode: 10001011000 9 | Rm: 00000 => x0 10 | shamt: 000000 11 | Rn: 00000 => x0 12 | Rd: 00000 => x0 13 | 14 | Finalmente, la instrucción es 15 | add x0, x0, x0 16 | ``` 17 | 18 | #### 4.2) 1101 0010 1011 1111 1111 1111 1110 0010 19 | ``` 20 | Los primeros 11 bits son: 11010010101b = 0x695 => movz (tipo IM) 21 | 22 | El opcode tiene solo 9 bits, descartamos los dos menos significativos, entonces: 23 | opcode: 110100101 24 | LSL: 01 => lsl 16 25 | MOV_immediate: 1111111111111111 => 0xffff 26 | Rd: 00010 => x2 27 | 28 | Finalmente, la instrucción es 29 | movz x2, 0xffff, lsl 16 30 | ``` -------------------------------------------------------------------------------- /practico 6/ej06.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 6 2 | Dadas las siguientes sentencias en assembler LEGv8: 3 | ``` 4 | a) LSL X2, X4, #1 5 | ADD X0, X2, X4 6 | ADD X0, X0, X4 7 | ``` 8 | ``` 9 | b) LSL X9, X3, #3 10 | ADD X9, X6, X9 11 | LSL X10, X4, #3 12 | ADD X10, X7, X10 13 | LDUR X12, [X9, #0] 14 | ADDI X11, X9, #8 15 | LDUR X9, [X11, #0] 16 | ADD X9, X9, X12 17 | STUR X9, [X10, #0] 18 | ``` 19 | Escribir la secuencia mínima de código “C” asumiendo que los registros X0, X1, X2, X3 y X4 contienen las variables f, g, h, i y j respectivamente, y los registros X6, X7 contienen las direcciones base de los arreglos A y B. 20 | 21 | ```c 22 | h = j * 2; 23 | f = h + j; // f = 2j + j = 3j 24 | f += j; // f = 3j + j = 4j 25 | 26 | Sería lo mismo hacer: 27 | LSL X0, X4, #2 28 | ``` 29 | ```c 30 | x9 = i * 8; 31 | x9 = &A + (i * 8); 32 | x10 = j * 8; 33 | x10 = &B + (j * 8); 34 | x12 = A[i]; 35 | x11 = &A + (i * 8) + 8; 36 | x9 = A[i + 1]; 37 | x9 = A[i + 1] + A[i]; 38 | B[j] = A[i + 1] + A[i]; 39 | ``` -------------------------------------------------------------------------------- /practico 8/ej02.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 2 2 | Tenemos las siguientes instrucciones en assembler LEGv8: 3 | ``` 4 | ADDI X9, X9, #0 5 | STUR X10, [X11,#32] 6 | ``` 7 | 8 | #### 2.1) Qué formato (R, I, D, B, CB, IM) de instrucciones son? 9 | ``` 10 | ADDI X9, X9, #0 es formato I 11 | STUR X10, [X11,#32] es fotmato D 12 | ``` 13 | 14 | #### 2.2) Ensamblar a código de máquina LEGv8, mostrando sus representaciones en binario y luego en hexadecimal. 15 | ``` 16 | addi x9, x9, #0: 17 | opcode: 1001000100 18 | ALU i: 000000000000 19 | Rn: 01001 20 | Rd: 01001 21 | 22 | luego, addi x9, x9, #0 se codifica como 23 | 10010001000000000000000100101001b o 24 | 0x91000129 25 | 26 | 27 | 28 | stur x10, [x11,#32] 29 | opcode: 11111000000 30 | DT_adress(#32): 000100000 31 | op: 00 32 | Rn(x11): 01011 33 | Rt(x10): 01010 34 | 35 | luego, stur x10, [x11,#32] se codifica como 36 | 11111000000000100000000101101010b o 37 | 0xF802016A 38 | ``` -------------------------------------------------------------------------------- /practico 7/ej08.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 8 2 | Mostrar cómo se implementarían las siguientes pseudoinstrucciones con la mínima cantidad de instrucciones LEGv8, pudiendo usar el registro X9 para almacenar valores temporales. 3 | 4 | |Nemónico| Operación | Semántica |Instrucción| Solución | 5 | |--------|-------------------------------------|--------------------|-----------|------------------------------| 6 | | CMP |comparación |FLAGS = R[Rn]-R[Rm] | cmp a, b | subs xzr, a, b | 7 | | CMPI |comparación con operando inmediato |FLAGS = R[Rn]-ALUImm| cmpi a, #n| subis xzr, a, #n | 8 | | MOV |copia de valores entre registros |R[Rd] = R[Rn] | mov a, b | add a, b, xzr | 9 | | NOP |no-operación, el skip de LEGv8 | | nop | add xzr, xzr, xzr | 10 | | NOT |operador lógico de negación bit a bit|R[Rd] = ~R[Rn] | not a |sub a, xzr, a
subi a, a, #1| -------------------------------------------------------------------------------- /lab/ejercicio1/Makefile: -------------------------------------------------------------------------------- 1 | ARMGNU ?= aarch64-linux-gnu 2 | 3 | AOPS = -g --warn --fatal-warnings 4 | ASM_SRCS = $(wildcard *.s) 5 | ASM_OBJS = $(ASM_SRCS:%.s=%.o) 6 | 7 | .PHONY: clean 8 | 9 | all: kernel8.img 10 | 11 | %.o: %.s 12 | $(ARMGNU)-as $(AOPS) $< -o $@ 13 | 14 | clean: 15 | rm -f *.o memory_map.txt kernel8.list kernel8.img kernel8.elf 16 | 17 | kernel8.img: memmap $(ASM_OBJS) 18 | $(ARMGNU)-ld $(ASM_OBJS) -T memmap -o kernel8.elf -M > memory_map.txt 19 | $(ARMGNU)-objdump -D kernel8.elf > kernel8.list 20 | $(ARMGNU)-objcopy kernel8.elf -O binary kernel8.img 21 | 22 | runQEMU: kernel8.img 23 | qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio -qtest unix:/tmp/qtest.sock,server,nowait 24 | 25 | runGPIOM: bin/gpiom 26 | ./bin/gpiom 27 | 28 | runGDB: 29 | gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" 30 | -------------------------------------------------------------------------------- /lab/ejercicio2/Makefile: -------------------------------------------------------------------------------- 1 | ARMGNU ?= aarch64-linux-gnu 2 | 3 | AOPS = -g --warn --fatal-warnings 4 | ASM_SRCS = $(wildcard *.s) 5 | ASM_OBJS = $(ASM_SRCS:%.s=%.o) 6 | 7 | .PHONY: clean 8 | 9 | all: kernel8.img 10 | 11 | %.o: %.s 12 | $(ARMGNU)-as $(AOPS) $< -o $@ 13 | 14 | clean: 15 | rm -f *.o memory_map.txt kernel8.list kernel8.img kernel8.elf 16 | 17 | kernel8.img: memmap $(ASM_OBJS) 18 | $(ARMGNU)-ld $(ASM_OBJS) -T memmap -o kernel8.elf -M > memory_map.txt 19 | $(ARMGNU)-objdump -D kernel8.elf > kernel8.list 20 | $(ARMGNU)-objcopy kernel8.elf -O binary kernel8.img 21 | 22 | runQEMU: kernel8.img 23 | qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio -qtest unix:/tmp/qtest.sock,server,nowait 24 | 25 | runGPIOM: bin/gpiom 26 | ./bin/gpiom 27 | 28 | runGDB: 29 | gdb-multiarch -ex "set architecture aarch64" -ex "target remote localhost:1234" --ex "dashboard registers -style list 'x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 sp pc cpsr'" 30 | -------------------------------------------------------------------------------- /practico 6/ej07.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 7 2 | Dadas las siguientes sentencias en assembler LEGv8: 3 | ``` 4 | ADDI X9, X6, #8 5 | ADD X10, X6, XZR 6 | STUR X10, [X9, #0] 7 | LDUR X9, [X9, #0] 8 | ADD X0, X9, X10 9 | ``` 10 | 11 | #### 7.1) Asumiendo que los registros X0, X6 contienen las variables f y A (dirección base del arreglo), escribir la secuencia mínima de código “C” que representa. 12 | ```c 13 | x9 = &A[1]; 14 | x10 = &A[0]; 15 | A[1] = &A[0]; 16 | x9 = A[1]; 17 | f = a[1] + &A[0]; 18 | 19 | // como A[1] = &A[0], la secuencia minima en C es lo último, 20 | // reemplazando queda: 21 | f = &A[0] + &A[0]; 22 | ``` 23 | 24 | #### 7.2) Asumiendo que los registros X0, X6 contienen los valores 0xA, 0x100, y que la memoria contiene los valores de la tabla, encuentre el valor del registro X0 al finalizar el código assembler. 25 | 26 | | Dirección | Valor | 27 | |-----------|-------| 28 | | 0x100 | 0x64 | 29 | | 0x108 | 0xC8 | 30 | | 0x110 | 0x12C | 31 | 32 | ``` 33 | f = 2 * &A[0] 34 | = 0x100 + 0x100 35 | = 0x200 36 | ``` -------------------------------------------------------------------------------- /practico 8/ej06.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 6 2 | Decidir cuáles de las siguientes instrucciones en assembler se pueden codificar en código de máquina LEGv8. Explique qué falla en las que no puedan ser ensambladas. 3 | ``` 4 | 1. LSL XZR, XZR, 0 // SI. aunque la instrucción no hace nada 5 | 2. ADDI X1, X2, -1 // NO. ALU_immediate debe ser un número no signado 6 | 3. ADDI X1, X2, 4096 // NO. ALU_immediate debe poder expresarse en 12 bits, #4096 necesita 13 7 | 4. EOR X32, X31, X30 // NO. no existe registro x32 8 | 5. ORRI X24, X24, 0x1FFF // NO. ALU_immediate debe poder expresarse en 12 bits, 0x1fff necesita 13 9 | 6. STUR X9, [XZR,#-129] // SI. stur permite direcciones de memoria signadas 10 | 7. LDURB XZR, [XZR,#-1] // SI. mismo caso, ldurb permite direcciones signadas 11 | 8. LSR X16, X17, #68 // NO. shamt debe poder representarse con 6 bits. #68 necesita 7 12 | 9. MOVZ X0, 0x1010, LSL #12 // NO. el inmediato de LSL debe ser 0, 16, 32 o 48 13 | 10. MOVZ XZR, 0xFFFF, LSL #48 // SI. 14 | ``` -------------------------------------------------------------------------------- /practico 7/ej09.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 9 2 | Suponiendo que el microprocesador LEGv8 está configurado en modo LE little-endian, decir que valores toman los registros X0 a X7 al terminar este programa. 3 | ``` 4 | MOVZ X9, 0xCDEF, LSL 0 // x9 = 0x0000 0000 0000 CDEF 5 | MOVK X9, 0x89AB, LSL 16 // x9 = 0x0000 0000 89AB CDEF 6 | MOVK X9, 0x4567, LSL 32 // x9 = 0x0000 4567 89AB CDEF 7 | MOVK X9, 0x0123, LSL 48 // x9 = 0x0123 4567 89AB CDEF 8 | STUR X9, [XZR, #0] 9 | LDURB X0, [XZR, #0] 10 | ⋮ 11 | LDURB X7, [XZR, #7] 12 | ``` 13 | ```c 14 | // Al finalizar el programa, los registros toman los siguientes valores: 15 | x0 = 0xEF 16 | x1 = 0xCD 17 | x2 = 0xAB 18 | x3 = 0x89 19 | x4 = 0x67 20 | x5 = 0x45 21 | x6 = 0x23 22 | x7 = 0x01 23 | ``` 24 | 25 | *Opcional: ¿Qué valores toman los registros X0 a X7 si el microprocesador LEGv8 está configurado en modo BE big-endian?* 26 | ```c 27 | // Si el micro está configurado en modo BE, 28 | // los registros toman los siguientes valores: 29 | x0 = 0x01 30 | x1 = 0x23 31 | x2 = 0x45 32 | x3 = 0x67 33 | x4 = 0x89 34 | x5 = 0xAB 35 | x6 = 0xCD 36 | x7 = 0xEF 37 | ``` -------------------------------------------------------------------------------- /practico 6/ej08.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 8 2 | Dado el contenido de los siguientes registros: 3 | 4 | a) X9 = 0x55555555, y X10 = 0x12345678 5 | 6 | b) X9 = 0x00000000AAAAAAAA, y X10 = 0x1234567812345678 7 | 8 | #### 8.1) ¿Cuál es el valor del registro X11 luego de la ejecución del siguiente código assembler en LEGv8? 9 | ``` 10 | LSL X11, X9, #4 11 | ORR X11, X11, X10 12 | ``` 13 | ``` 14 | a) 15 | X11 = 0x0000000055555550 16 | X11 = 0x557755778 17 | 18 | b) 19 | X11 = 0x0000000AAAAAAAA0 20 | X11 = 0x1234567ABABEFEF8 21 | ``` 22 | 23 | #### 8.2) ¿Cuál es el valor del registro X11 luego de la ejecución del siguiente código assembler en LEGv8? 24 | ``` 25 | LSL X11, X10, #4 26 | ANDI X11, X11, #0xFFF 27 | ``` 28 | ``` 29 | a) 30 | X11 = 0x0000000123456780 31 | X11 = 0x780 32 | 33 | b) 34 | X11 = 0x2345678123456780 35 | X11 = 0x780 36 | ``` 37 | 38 | #### 8.3) ¿Cuál es el valor del registro X11 luego de la ejecución del siguiente código assembler en LEGv8? 39 | ``` 40 | LSR X11, X9, #3 41 | ANDI X11, X11, #0x555 42 | ``` 43 | ``` 44 | a) 45 | X11 = 0x000000000AAAAAAA 46 | X11 = 0x0 47 | 48 | b) 49 | X11 = 0x15555555 50 | X11 = 0x555 51 | ``` -------------------------------------------------------------------------------- /practico 7/ej06.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 6 2 | Traducir el siguiente programa en “C” a ensamblador LEGv8 dada la asignación de variables a registros
3 | X0 <-> str
4 | X1 <-> found
5 | X2 <-> i
6 | X9 <-> N.
7 | El número 48 se corresponde con el carácter ‘0’ en ASCII, por lo tanto el programa cuenta la cantidad de ‘0’s que aparecen en una cadena de caracteres de longitud N. 8 | ```c 9 | #define N (1<<10) 10 | char *str; 11 | long found, i; 12 | for(found=0, i=0; i!=N; ++i) 13 | found += (str[i]==48); 14 | ``` 15 | 16 | ``` 17 | addi x0, xzr, #1024 // N = 1024 18 | addi x1, xzr, #0 // found = 0 19 | addi x2, xzr, #0 // i = 0 20 | add x0, x0, x2 // str = &str[i] 21 | loop: cmp x2, x9 // i = N ? 22 | B.EQ done // si i = N, salto a done 23 | add x3, x0, x2 // x3 = &str[i] + i 24 | ldur x4, [x3, #0] // x4 = str[i] 25 | cmpi x4, #48 // str[i] = 0 ? 26 | B.NE skip // si str[i] != 0, salto a skip 27 | addi x1, x1, #1 // found++ 28 | skip: addi x2, x2, #1 // i++ 29 | B loop // salto incondicional a loop 30 | done: 31 | ``` -------------------------------------------------------------------------------- /practico 8/ej10.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 10 2 | ¿Qué valor devuelve en X0 este programa? 3 | ``` 4 | .org 0x0000 5 | MOVZ X0, 0x0400, LSL #0 6 | MOVK X0, 0x9100, LSL #16 7 | STURW X0, [XZR,#12] 8 | STURW X0, [XZR,#12] 9 | ``` 10 | 11 | ``` 12 | 00:MOVZ X0, 0x0400, LSL #0 // x0 = 0x0000000000000400 13 | 04:MOVK X0, 0x9100, LSL #16 // x0 = 0x0000000091000400 14 | 08:STURW X0, [XZR,#12] // en la posición de memoria 12, guardo x0 15 | 12:STURW X0, [XZR,#12] se sobreescribe ésta instrucción por 0x91000400 16 | 17 | 0x91000400 = 10010001000000000000010000000000b 18 | Veamos de que instrucción se trata: 19 | opcode: 10010001000 = 0x488 => addi (tipo I) 20 | ALU_immediate: 00000000001 => (#1) 21 | Rn: 00000 => (x0) 22 | Rd: 00000 => (x0) 23 | 24 | La operación es: 25 | addi x0, x0, #1 26 | 27 | Entonces en la posición 12 reemplazamos STURW X0, [XZR,#12] por addi x0, x0, #1 28 | 29 | MOVZ X0, 0x0400, LSL #0 // x0 = 0x0000000000000400 30 | MOVK X0, 0x9100, LSL #16 // x0 = 0x0000000091000400 31 | STURW X0, [XZR,#12] 32 | addi x0, x0, #1 // x0 = x0 + 1 = 0x91000401 33 | 34 | Al finalizar el programa, x0 = 0x91000401 35 | ``` -------------------------------------------------------------------------------- /practico 8/ej05.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 5 2 | Ejecutar el siguiente código assembler que está en memoria para dar el valor final del registro X1. El contenido de la memoria se da como una lista de pares, *dirección de memoria: contenido*, suponiendo alineamiento de memoria del tipo *big endian*. Describir sintéticamente que hace el programa. 3 | ``` 4 | 0x10010000: 0x8B010029 5 | 0x10010004: 0x8B010121 6 | ``` 7 | 8 | ``` 9 | 0x10010000: 0x8B010029 10 | 11 | 0x8B010029 = 10001011000000010000000000101001b 12 | Los 11 primeros bits son 10001011000b = 0x458 => add (tipo R) 13 | Entonces: 14 | opcode: 10001011000 15 | Rm: 00001 => x1 16 | shamt: 000000 17 | Rn: 00001 => x1 18 | Rd: 01001 => x9 19 | 20 | La primera operación es add x9, x1, x1 21 | ``` 22 | ``` 23 | 0x10010004: 0x8B010121 24 | 25 | 0x8B010121 = 10001011000000010000000100100001 26 | Los 11 primeros bits son 10001011000b = 0x458 => add (tipo R) 27 | 28 | Entonces: 29 | opcode: 10001011000 30 | Rm: 00001 => x1 31 | shamt: 000000 32 | Rn: 01001 => x9 33 | Rd: 00001 => x1 34 | 35 | La segunda operación es add x1, x9, x1 36 | ``` 37 | ``` 38 | Entonces, el bloque de codigo 39 | 0x10010000: 0x8B010029 // add x9, x1, x1 40 | 0x10010004: 0x8B010121 // add x1, x9, x1 41 | realiza la operacion x1 = x1 * 3 42 | ``` -------------------------------------------------------------------------------- /practico 9/ej06.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 6 2 | En este ejercicio analizaremos en detalle cómo se ejecuta una instrucción en el single-cycle datapath, asumiendo que la palabra de instrucción que ejecuta el procesador es: 0xf8014062, dado que PC=0x100. 3 | 4 | 6.1) Cuáles son las salidas de los bloques *Sign-extend* y *Shift left 2* para esta palabra de instrucción? 5 | ``` 6 | Primero veamos cuál es la instrucción 0xf8014062 7 | 8 | 0xf8014062 = 11111000000000010100000001100010b 9 | 10 | opcode: 111 1100 0000 = 0x7C0 => stur 11 | DT_adress: 000010100 => 20 12 | op: 00 13 | Rn: 00011 => x3 14 | Rt: 00010 => x2 15 | 16 | La operación es stur x2, [x3, #20] 17 | ``` 18 | 19 | ![Simple datapath with the control unit](./assets/ej06.1.svg) 20 | 21 | ``` 22 | Por lo tanto, la salida de Sign-extend es 20, y la de Shift left 2 es 80 23 | ``` 24 | 25 |


26 | 27 | 6.2) Cuáles son los valores de entrada a la unidad ALU control para esta palabra de instrucción? 28 | ``` 29 | 00, que siempre es la misma para ldur y stur 30 | ``` 31 | 32 |


33 | 34 | 6.3) Cuál es la nueva dirección en el PC después de ejecutar esta instrucción? 35 | 36 | ![Simple datapath with the control unit](./assets/ej06.3.svg) 37 | 38 | ``` 39 | 0x104 40 | ``` 41 | 42 |


43 | 44 | 6.4) Mostrar los valores de las entradas y salidas de cada Mux durante la ejecución de esta instrucción. Para los valores que son salidas de Registers, utilizar “Reg[Xn]”. 45 | 46 | ![Simple datapath with the control unit](./assets/ej06.4.svg) 47 | 48 |


49 | 50 | 6.5) Cuáles son los valores de entrada de la ALU y las dos unidades Add? 51 | 52 | ![Simple datapath with the control unit](./assets/ej06.5.svg) 53 | 54 |


55 | 56 | 6.6) Cuáles son los valores de todas las entradas del bloque Registers? 57 | 58 | ![Simple datapath with the control unit](./assets/ej06.6.svg) -------------------------------------------------------------------------------- /practico 9/ej11.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 11 2 | Al implementar los circuitos Control, ALU control se utilizaron muchas condiciones no-importa para simplificar la lógica. Esto produce efectos laterales. Cuando Instruction[31:21] está en el rango 0x5B8-0x5BF, obtenemos del Control: 3 | 4 | | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | 5 | |:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:| 6 | | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 7 | 8 | Mientras que de ALU control tiene una implementación utilizando condiciones no importa que produce: 9 | 10 | | ALUop1 | ALUop0 | I[31:21] | Operation | 11 | |:------:|:------:|:--------:|:---------:| 12 | | 1 | 1 | 0x5B8 | 0110 | 13 | | ⋮ | ⋮ | ⋮ | ⋮ | 14 | | 1 | 1 | 0x5BF | 0110 | 15 | 16 | Este es un típico caso de [instrucción no documentada](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)) con un comportamiento no del todo claro. Si, además, en el módulo Sign-extend esta instrucción se interpreta como un formato CB, indicar que hace esta instrucción, asignarle un mnemónico y describir la operación, a fin de completar la fila correspondiente a la nueva instrucción en la *green card*. 17 | 18 | ![Simple datapath with the control unit](./assets/ej11.svg) 19 | 20 | - 0x5B8-0x5BF es un opcode no usado en LEGv8. 21 | - No se escriben registros ni la memoria de datos. 22 | - Se leen 2 registros, ambos entran a la ALU y se hace la resta entre ellos. 23 | - Si la resta da cero (si R1 = R2), como Branch = 1, salta a lo que haya en Sign-extend con Sl2 + PC. 24 | - Como Reg2Loc = 1, los bits 9-5 se utilizan para direccionar el segundo registro. Dado que en el módulo Sign-extend esta instrucción se interpreta como un formato CB, esos bits también se utilizan como parte del campo “COND_BR_address” para calcular el desplazamiento del branch. 25 | 26 | - Operación realizada: compara y salta si el registro 1 es igual al registro 2. 27 | - Mnemónico propuesto: CBEQ -------------------------------------------------------------------------------- /practico 8/ej08.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 8 2 | Dadas las siguientes direcciones de memoria: 3 | ``` 4 | 0x00014000 5 | 0x00114524 6 | 0x0F000200 7 | ``` 8 | 9 | #### 8.1) Si el valor del PC es 0x00000000, es posible llegar con una sola instrucción conditional branch a las direcciones de memoria arriba listadas? 10 | ``` 11 | El campo de inmediato de conditional branch es de 19 bits 12 | CB | opcode | COND_BR_address | Rt | 13 | ³¹ ²⁴ ²³ ⁵ ⁴ ⁰ 14 | 15 | La maxima cantidad de instrucciones que puedo saltar hacia adelante es 2¹⁸ - 1 16 | 2¹⁸ = 1000000000000000000b = 0x40000 17 | 2¹⁸ - 1 = 0111111111111111111b = 0x3FFFF 18 | 19 | La maxima cantidad de posiciones de memoria que puedo saltar hacia adelante es Instrucciones * 4 20 | 11111111111111111100b = 0xFFFFC 21 | 22 | Partiendo de PC = 0x00000000 se alcanza la dirección: 23 | 0x00000000 + 0x000FFFFC = 0x000FFFFC 24 | 25 | Entonces: 26 | - 0x00014000 es posible llegar con una sola instrucción 27 | - 0x00114524 no es posible llegar con una sola instrucción 28 | - 0x0F000200 no es posible llegar con una sola instrucción 29 | ``` 30 | 31 | #### 8.2) Si el valor del PC es 0x00000600, es posible llegar con una sola instrucción branch a las direcciones de memoria arriba listadas? 32 | ``` 33 | El campo de inmediato de branch es de 26 bits 34 | B | opcode | BR_address | 35 | ³¹ ²⁶ ²⁵ ⁰ 36 | 37 | La maxima cantidad de instrucciones que puedo saltar hacia adelante es 2²⁵ - 1 38 | 2²⁵ = 10000000000000000000000000b = 0x2000000 39 | 2²⁵ - 1 = 01111111111111111111111111b = 0x1FFFFFF 40 | 41 | La maxima cantidad de posiciones de memoria que puedo saltar hacia adelante es Instrucciones * 4 42 | 0111111111111111111111111100b = 0x07FFFFFC 43 | 44 | Partiendo de PC = 0x00000600 se alcanza la dirección: 45 | 0x00000600 + 0x07FFFFFC = 0x080005FC 46 | 47 | Entonces: 48 | - 0x00014000 es posible llegar con una sola instrucción 49 | - 0x00114524 es posible llegar con una sola instrucción 50 | - 0x0F000200 no es posible llegar con una sola instrucción 51 | ``` 52 | 53 | #### 8.3) Si el valor del PC es 0x00000000 y quiero saltar al primer GiB de memoria 0x40000000. Escribir exactamente 2 instrucciones contiguas que posibilitan el salto lejano (far jump). 54 | ``` 55 | MOVZ X0, 0x4000, LSL 16 // precacargo la direccion en el registro X0 56 | BR X0 // salto a la direccion que contiene el registro 57 | 58 | *si el PC es distinto de 0x0, la respuesta es la misma 59 | ``` -------------------------------------------------------------------------------- /practico 7/ej05.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 5 2 | 3 | Dados los siguientes programas en LEGv8: 4 | ```c 5 | // primer algorítmo: 6 | 7 | ADD X10, XZR, XZR // x10 = 0 8 | loop: LDUR X1, [X0,#0] // x1 = &x0[0] 9 | ADD X2, X2, X1 // x2 = x2 + &x0[0] 10 | ADDI X0, X0, #8 // &x0[0] += 8 = &x0[1] 11 | ADDI X10, X10, #1 // x10 += 1 12 | CMPI X10, #100 // flags = x10 - #100 13 | B.LT loop // si x10 < 100, loop 14 | ``` 15 | ```c 16 | segundo algorítmo: 17 | 18 | ADDI X10, XZR, #50 // x10 = 50 19 | loop: LDUR X1, [X0,#0] // x1 = &x0[0] 20 | ADD X2, X2, X1 // x2 += &x0[0] 21 | LDUR X1, [X0,#8] // x1 = &x0[1] 22 | ADD X2, X2, X1 // x2 += &x0[1] 23 | ADDI X0, X0, #16 // x0 += 16 24 | SUBI X10, X10, #1 // x10-- 25 | CBNZ X10, loop // si x10 != 0, loop 26 | ``` 27 | 28 | #### 5.1) ¿Cuántas instrucciones LEGv8 ejecuta cada uno? 29 | ``` 30 | En el primer algorítmo se ejecutan 501 instrucciones 31 | (100 veces un loop de 5 instrucciones + la innicialización de x10). 32 | 33 | En el segundo algorítmo se ejecutan 351 instrucciones 34 | (50 veces un loop de 7 instrucciones + la inicialización de x10). 35 | ``` 36 | 37 | #### 5.2) Reescribir en “C” dada la asignación
X10 <--> i
X1 <--> a
X2 <--> result
X0 <--> MemArray
38 | *Opcional: optimizar los códigos assembler para reducir el número de instrucciones LEGv8 ejecutadas.* 39 | ```c 40 | // primer algorítmo: 41 | 42 | i = 0; 43 | while(i < 100) { 44 | a = MemArray[0]; 45 | result += a; 46 | MemArray[0] = MemArray[1]; 47 | i++; 48 | } 49 | ``` 50 | ```c 51 | // segundo algorítmo: 52 | 53 | i = 50; 54 | while(i != 0) { 55 | a = MemArray[0]; 56 | result += a; 57 | a = MemArray[1]; 58 | result += a; 59 | MemArray += 16; 60 | } 61 | 62 | /* De igual manera: */ 63 | for(long i = 50; i != 0; i--) { 64 | a = MemArray[0]; 65 | result += a; 66 | a = MemArray[1]; 67 | result += a; 68 | MemArray += 16; 69 | } 70 | 71 | /* Reduciendo las líneas de código: */ 72 | for(long i = 50; i != 0; i--) { 73 | a = MemArray[0]; 74 | result += a 75 | MemArray += 8; 76 | } 77 | 78 | /* En assembler: */ 79 | addi x10, xzr, #50 // x10 = 50 80 | loop: ldur x1, [x0,#0] // x1 = &x0[0] 81 | add x2, x2, x1 // x2 += &x[0] 82 | addi x1, x1, #8 // x1 = &x0[1] 83 | subis x10, x10, 1 // flags = x10 - 1 84 | B.GE loop // si x10 >= 1, vuelvo a loop 85 | done: 86 | ``` -------------------------------------------------------------------------------- /practico 7/ej04.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 4 2 | 3 | Dados los siguientes programas LEGv8: 4 | ``` 5 | loop: ADDI X0, X0, #2 // x0 += 2 6 | SUBI X1, X1, #1 // x1-- 7 | CBNZ X1, loop // si x1 = 0, vuelvo a loop 8 | done: 9 | 10 | // éste algorítmo calcula x1 * 2 y lo guarda en x0 11 | ``` 12 | ``` 13 | loop: SUBIS X1, X1, #0 // flags = x1 - 0 14 | B.LE done // si x1 <= 0, salto a done 15 | SUBI X1, X1, #1 // x1-- 16 | ADDI X0, X0, #2 // x0 += 2 17 | B loop 18 | done: 19 | 20 | // es lo mismo que el primer algorítmo pero escrito de forma diferente 21 | ``` 22 | 23 | #### 4.1) Dar los valores finales de X0, teniendo en cuenta que inicialmente vale { X0=0, X1=10 }. 24 | ``` 25 | Al finalizar cualquiera de los dos algorítmos, x0 = 20. 26 | ``` 27 | 28 | #### 4.2) Dada la asignación a X0, X1 <-> acc, i, escribir el programa “C” equivalente donde todas las variables son de tipo long. 29 | ```c 30 | long acc, i; 31 | do { 32 | acc += 2; 33 | i--; 34 | } while(x1 != 0); 35 | ``` 36 | ```c 37 | long acc; 38 | for(long i = N; 0 < i; i--) { 39 | acc += 2; 40 | } 41 | ``` 42 | 43 | #### 4.3) Dado que inicialmente { X1=N } ¿Cuántas instrucciones LEGv8 se ejecutan? 44 | ``` 45 | Si x1 = N, se ejecutan 2N instrucciones en el primer algoritmo y 46 | 3N instrucciones en el segundo algorítmo. 47 | ``` 48 | 49 | #### 4.4) Para el segundo programa. Si reemplazamos B.LE done por B.MI(branch on minus) done ¿Cuál es el valor final de X0 suponiendo que inicialmente {X0=0; X1=10}? 50 | ``` 51 | loop: SUBIS X1, X1, #0 // flags = x1 - 0 52 | B.MI done // si x1 < 0, salto a done 53 | SUBI X1, X1, #1 // x1-- 54 | ADDI X0, X0, #2 // x0 += 2 55 | B loop 56 | done: 57 | 58 | Acá el loop termina cuando x1 es negativo, entonces se hace una vuelta más 59 | que en el algorítmo original, por lo tanto x0 = 22 al finalizar el algorítmo. 60 | ``` 61 | 62 | #### 4.5) Dada la asignación a X0, X1 <-> acc, i, escribir el programa “C” equivalente del punto “4.4”, donde todas las variables son de tipo long. 63 | ```c 64 | long acc; 65 | for(long i = N; 0 <= i; i--) { 66 | acc += 2; 67 | } 68 | ``` 69 | 70 | #### 4.6) Mostrar que se puede reducir el número de instrucciones ejecutadas en el segundo programa, combinando SUBIS y SUBI.
71 | *Ayuda: agregar una instrucción por fuera del lazo. Ayuda: es lo mejor de los dos mundos ;)* 72 | ``` 73 | loop: ADDI X0, X0, #2 // x0 += 2 74 | cmpi x1, #1 // flags = x1 - 1 75 | B.LE done // si x1 <= 0, salto a done 76 | B loop 77 | done: 78 | ``` -------------------------------------------------------------------------------- /practico 8/ej07.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 7 2 | Ensamblar estos delay loops. 3 | ``` 4 | MOVZ X0, 0x1, LSL #48 5 | L1: SUBI X0,X0,#1 6 | CBNZ X0, L1 7 | ``` 8 | ``` 9 | MOVZ X0, 0x1, LSL #48 = 0xD2E00020 10 | opcode: 110100101 11 | LSL: 11 12 | MOV_immediate: 0000000000000001 13 | Rd: 00000 14 | 15 | SUBI X0,X0,#1 = 0xD1000400 16 | opcode: 1101000100 17 | ALU_immediate: 000000000001 18 | Rn: 00000 19 | Rd: 00000 20 | 21 | CBNZ X0, L1 = 0xB5FFFFE0 22 | opcode: 10110101 23 | COND_BR_address: 1111111111111111111 = -1 (porque vuelvo una operacion para atras) 24 | Rt: 00000 25 | 26 | 27 | Entonces el bloque de codigo ensamblado seria: 28 | 0xD2E00020 29 | 0xD1000400 30 | 0xB5FFFFE0 31 | ``` 32 | 33 |


34 | 35 | ``` 36 | MOVZ X0, 0xFFFF, LSL #32 37 | L1: SUBIS X0,X0,#1 38 | B.NE L1 39 | ``` 40 | ``` 41 | MOVZ X0, 0xFFFF, LSL #32 = 0xD2DFFFE0 42 | opcode: 110100101 43 | LSL: 10 44 | MOV_immediate: 111111111111 45 | Rd: 00000 46 | 47 | SUBIS X0,X0,#1 = 0xF1000400 48 | opcode: 1111000100 49 | ALU_immediate: 000000000001 50 | Rn: 00000 51 | Rd: 00000 52 | 53 | B.NE L1 = 0x54FFFFE0 54 | opcode: 01010100 55 | COND_BR_address: 1111111111111111111 = -1 (porque vuelvo una operacion para atras) 56 | Rt: 00000 57 | 58 | 59 | Entonces el bloque de codigo ensamblado seria: 60 | 0xD2DFFFE0 61 | 0xF1000400 62 | 0x54FFFFE0 63 | ``` 64 | 65 |


66 | 67 | ``` 68 | MOVZ X0, 0x2, LSL #16 69 | L1: SUBIS XZR,X0,#0 70 | B.EQ EXIT 71 | SUBI X0,X0,#1 72 | B L1 73 | EXIT: 74 | ``` 75 | ``` 76 | MOVZ X0, 0x2, LSL #16 = 0xD2A00040 77 | opcode: 110100101 78 | LSL: 01 79 | MOV_immediate: 0000000000000010 80 | Rd: 00000 81 | 82 | SUBIS XZR,X0,#0 = 0xF100001F 83 | opcode: 1111000100 84 | ALU_immediate: 000000000000 85 | Rn: 00000 86 | Rd: 11111 87 | 88 | B.EQ EXIT = 0x54000060 89 | opcode: 01010100 90 | COND_BR_address: 0000000000000000011 = 3 (porque salto 3 operaciones) 91 | Rt: 00000 92 | 93 | SUBI X0,X0,#1 = 0xD1000400 94 | opcode: 1101000100 95 | ALU_immediate: 000000000001 96 | Rn: 00000 97 | Rd: 00000 98 | 99 | B L1 = 0x17FFFFFD 100 | opcode: 000101 101 | BR_address: 11111111111111111111111101 = -3 (porque vuelvo 3 operaciones para atras) 102 | 103 | 104 | Entonces el bloque de codigo ensamblado seria: 105 | 0xD2A00040 106 | 0xF100001F 107 | 0x54000060 108 | 0xD1000400 109 | 0x17FFFFFD 110 | ``` -------------------------------------------------------------------------------- /practico 9/ej03.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 3 2 | Completar la tabla con el estado de las señales.
3 | Indicar con X las condiciones no-importa. 4 | 5 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | ALUop | 6 | |:-------|:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:|:-----:| 7 | | **Tipo R** | | | | | | | | | | 10 | 8 | | **LDUR** | | | | | | | | | | 00 | 9 | | **STUR** | | | | | | | | | | 00 | 10 | | **CBZ** | | | | | | | | | | 01 | 11 | 12 |
13 |
14 |
15 | 16 | ![Simple datapath with the control unit](./assets/ej03-rtype.svg) 17 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | 18 | |:-------|:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:| 19 | | **Tipo R** | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 20 | 21 |
22 |
23 |
24 | 25 | ![Simple datapath with the control unit](./assets/ej03-ldur.svg) 26 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | 27 | |:-------|:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:| 28 | | **LDUR** | x | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 29 | 30 |
31 |
32 |
33 | 34 | ![Simple datapath with the control unit](./assets/ej03-stur.svg) 35 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | 36 | |:-------|:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:| 37 | | **STUR** | 1 | 1 | x | 0 | 0 | 1 | 0 | 0 | 0 | 38 | 39 |
40 |
41 |
42 | 43 | ![Simple datapath with the control unit](./assets/ej03-cbz.svg) 44 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | 45 | |:-------|:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:| 46 | | **CBZ**| 1 | 0 | x | 0 | 0 | 0 | 1 | 0 | 1 | 47 | 48 |
49 |
50 |
51 | 52 | 53 | Entonces, la tabla queda de la siguiente manera: 54 | | Instr. | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop1 | ALUop0 | 55 | |:-------|:-------:|:------:|:--------:|:--------:|:-------:|:--------:|:------:|:------:|:------:| 56 | | **Tipo R** | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 57 | | **LDUR** | x | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 58 | | **STUR** | 1 | 1 | x | 0 | 0 | 1 | 0 | 0 | 0 | 59 | | **CBZ**| 1 | 0 | x | 0 | 0 | 0 | 1 | 0 | 1 | 60 | -------------------------------------------------------------------------------- /lab/ejercicio1/app.s: -------------------------------------------------------------------------------- 1 | //---------------- Inicio Carga Parametros ------------------------------------ 2 | 3 | .equ SCREEN_WIDTH, 640 4 | .equ SCREEN_HEIGH, 480 5 | .equ BITS_PER_PIXEL, 32 6 | 7 | .equ GPIO_BASE, 0x3f200000 8 | .equ GPIO_GPFSEL0, 0x00 9 | .equ GPIO_GPLEV0, 0x34 10 | 11 | // Incluimos el archivo donde estan todas las funciones 12 | .include "funciones.s" 13 | 14 | // Los inputs para este programa son: 15 | // W,A 16 | 17 | .equ key_W, 0x2 18 | .equ key_A, 0x4 19 | 20 | .globl main 21 | 22 | main: 23 | // x0 contiene la direccion base del framebuffer 24 | mov x20, x0 // Guarda la dirección base del framebuffer en x20 25 | 26 | //---------------- Fin Carga Parametros ------------------------------------ 27 | 28 | reseteo: 29 | //---------------- Inicio Dibujo ------------------------------------ 30 | 31 | // Llamamos a todas las funciones encargadas de realizar el dibujo 32 | 33 | BL pintar_fondo 34 | 35 | BL cohete 36 | 37 | BL cabeza_cohete 38 | 39 | BL ventanillas 40 | 41 | BL luces 42 | 43 | BL propulsores 44 | 45 | BL estrellas 46 | 47 | BL luna 48 | 49 | //---------------- Fin Dibujo ------------------------------------ 50 | 51 | //---------------- Inicio Lectura Inputs ------------------------------------ 52 | 53 | // Debo realizar un loop que este todo el tiempo verificando si se pulsa una tecla 54 | 55 | loop_pulsador: 56 | 57 | // Seteamos el GPIO para poder realizar la lectura de los inputs 58 | mov x9, GPIO_BASE 59 | 60 | // Atención: se utilizan registros w porque la documentación de broadcom 61 | // indica que los registros que estamos leyendo y escribiendo son de 32 bits 62 | 63 | // Setea gpios 0 - 9 como lectura 64 | str wzr, [x9, GPIO_GPFSEL0] 65 | 66 | // Lee el estado de los GPIO 0 - 31 67 | ldr w10, [x9, GPIO_GPLEV0] 68 | 69 | // And bit a bit mantiene el resultado del bit 2 en w10 (notar 0b... es binario) 70 | // al inmediato se lo refiere como "máscara" en este caso: 71 | // - Al hacer AND revela el estado del bit 2 72 | // - Al hacer OR "setea" el bit 2 en 1 73 | // - Al hacer AND con el complemento "limpia" el bit 2 (setea el bit 2 en 0) 74 | 75 | and w11, w10, 0b00000010 76 | and w12, w10, 0b00000100 77 | 78 | // si w11 es 0 entonces el GPIO 1 estaba liberado 79 | // de lo contrario será distinto de 0, (en este caso particular 2) 80 | // significando que el GPIO 1 fue presionado 81 | 82 | cmp w11 , key_W // Al presionar la tecla "W" la luna cambia de tamaño 83 | beq cambiar_Luna 84 | 85 | cmp w12 , key_A // Al presionar la tecla "A" se resetea el dibujo 86 | beq reseteo 87 | 88 | b loop_pulsador 89 | 90 | //---------------- Fin Lectura Inputs ------------------------------------ 91 | 92 | //---------------- Inicio Modificacion ------------------------------------ 93 | 94 | cambiar_Luna: 95 | 96 | // LLamo a la funcion que cambia la luna y luego vuelvo al loop del pulsador 97 | 98 | BL bigLuna 99 | 100 | B loop_pulsador 101 | 102 | //---------------- Fin Modificacion ------------------------------------ 103 | 104 | //---------------- Infinite Loop ------------------------------------ 105 | InfLoop: 106 | b InfLoop 107 | -------------------------------------------------------------------------------- /practico 9/ej08.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 8 2 | Suponiendo que los diferentes bloques dentro del procesador tienen las siguientes **latencias**: 3 | 4 | | I-Mem / D-Mem | Register File | Mux | ALU | Adder | Single gate | Register Read | Register Setup | Sign extend | Control | Sl2 | 5 | |:-------------:|:-------------:|:-----:|:------:|:------:|:-----------:|:-------------:|:--------------:|:-----------:|:-------:|:-----:| 6 | | 250 ps | 150 ps | 25 ps | 200 ps | 150 ps | 5 ps | 30 ps | 20 ps | 50 ps | 50 ps | 25 ps | 7 | 8 | 8.1) Cuál es la latencia si lo único que tuviera que hacer el procesador es fetch de instrucciones consecutivas? 9 | 10 | **Latencia de fetch** = RegRead + Imem = 30 + 250 = **280ps** 11 | 12 | ![Simple datapath with the control unit](./assets/ej08.1.svg) 13 | 14 | - Register read: tiempo posterior al flanco ascendente de reloj, necesario para que el nuevo valor de registro aparezca en la salida. Este valor se aplica sólo al PC. 15 | - Register setup: tiempo que la entrada de datos de un registro debe permanecer estable antes del flanco ascendente de reloj. Este valor se aplica tanto al PC como al Register File. 16 | 17 |


18 | 19 | 8.2) Hay un modo alternativo de generar la señal Reg2Loc fácilmente de la instrucción sin tener que esperar la latencia de Control. Explicar cómo sería. 20 | ``` 21 | El bit 28 de las instrucciones contiene el valor correcto para la línea de control Reg2Loc 22 | ``` 23 | 24 |


25 | 26 | 8.3) Cuál es la latencia si solo hubiera instrucciones de tipo R? 27 | ``` 28 | Latencia de una instrucción tipo R = RegRead + I-Mem + Control + Mux + RegFile + Mux + ALU + Mux + RegSetup
29 | = 30 + 250 + 50 + 25 + 150 + 25 + 200 + 25 + 20 30 | = 775ps 31 | ``` 32 | 33 |


34 | 35 | 8.4) Cuál es la latencia para LDUR? 36 | ``` 37 | Latencia de la instrucción LDUR = Register Read + I-Mem + Register File + ALU + D-Mem + Mux + Register Setup 38 | = 30 + 250 + 150 + 200 + 250 + 25 + 20 39 | = 925ps 40 | ``` 41 | 42 |


43 | 44 | 8.5) Cuál es la latencia para STUR? 45 | ``` 46 | Latencia de la instrucción STUR = Register Read + I-Mem + Control + Mux + Adder + ALU + D-Mem 47 | = 30 + 250 + 50 + 25 + 150 + 200 + 250 48 | = 955ps 49 | ``` 50 | 51 |


52 | 53 | 8.6) Cuál es la latencia para CBZ? 54 | ``` 55 | Latencia de la instrucción CBZ = Register Read + I-Mem + Control + Mux + Register File + Mux + ALU + Gate + Mux + Register Setup 56 | = 30 + 250 + 50 + 25 + 150 + 25 + 200 + 5 + 25 + 20 57 | = 780ps 58 | ``` 59 | 60 |


61 | 62 | 8.7) Cuál es el mínimo periodo de reloj para esta implementación de la ISA? Indicar también la frecuencia de reloj correspondiente (f = 1/t). 63 | ``` 64 | Para que todas las instrucciones puedan ejecutarse completamente el periodo de reloj 65 | debe ser mayor o iguala la latencia de instrucción más grande. En este caso, 66 | corresponde a la latencia de STUR. 67 | Mínimo periodo de reloj para esta implementación de la ISA (t) = 955ps = 955e-12s 68 | 69 | Se calcula la frecuencia como la inversa del periodo. 70 | Máxima frecuencia de reloj (f) = 1/t ≈ 1.047 GHz 71 | ``` -------------------------------------------------------------------------------- /practico 7/ej07.md: -------------------------------------------------------------------------------- 1 | ## Ejercicio 7 2 | Traducir el siguiente programa “C” a LEGv8. La asignación de variables a registros 3 | X0 <-> A 4 | X1 <-> s 5 | X2 <-> i 6 | X3 <-> j 7 | X9 <-> N. 8 | Notar que en “C” los arreglos bidimensionales se representan en 9 | memoria usando un orden por filas, es decir &A[i][j] = A + 8*(i*N+j). 10 | ``` 11 | #define N (1<<10) 12 | long A[N][N], s, i, j; 13 | s=0; 14 | for (i=0; i | 1 | 7 | 2 | 44| 3 | 21| 1 | 2 | 3 | 31 | 32 | ``` 33 | addi x9, xzr, #3 // N = 3 34 | add x1, x1, xzr // s = 0 35 | add x2, x2, xzr // i = 0 36 | loopi: cmp x2, x9 // i = N ? 37 | B.EQ done // si i = n, salto a done 38 | add x3, xzr, xzr // j = 0 39 | loopj: cmp x3, x9 // j = N ? 40 | B.EQ skip // si j = N, salto a n_row 41 | mul x4, x2, x9 // x4 = i*N 42 | add x4, x4, x3 // x4 = i*N + j 43 | lsl x4, x4, #3 // x4 = (i*N + j) * 8 44 | add x4, x4, x0 // x4 = &A[i][j] 45 | ldur x5, [x4, #0] // x5 = A[i][j] 46 | add x1, x1, x5 // s += A[i][j] 47 | addi x3, x3, #1 // j++ 48 | B loopj // salto incondicional a loopj 49 | n_row: addi x2, x2, #1 // i++ 50 | B loopi // salto incondicional a loopi 51 | done: 52 | ``` 53 | 54 | 55 | 56 | #### 7.1) Hacer lineal el acceso al arreglo y recorrerlo con un solo lazo. 57 | ``` 58 | puedo pensar al arreglo como unidimensional y en ese caso el código en c es: 59 | for(i = 0; i <= n²-1; i++) { 60 | s += A[i] 61 | } 62 | 63 | addi x9, xzr, #3 // N = 3 64 | add x1, xzr, xzr // s = 0 65 | add x2, xzr, xzr // i = 0 66 | mul x9, x9, x9 // N = 9 (tamaño del arreglo unidimensional) 67 | loop: cmp x2, x9 // i = N ? 68 | B.EQ done // si i = N salto a done 69 | add x3, xzr, x2 // x3 = i 70 | lsl x3, x3, #3 // x3 = i*8 71 | add x3, x0, x3 // x3 = &A + i*8 = &A[i] 72 | ldur x4, [x3, #0] // x4 = A[i] 73 | add x1, x1, x4 // s += A[i] 74 | addi x2, x2, #1 // i++ 75 | B loop // salto incondicional a loop 76 | done: 77 | ``` 78 | 79 | 80 | 81 | #### 7.2) Se puede hacer lo mismo sin usar ninguna variable índice i, j. 82 | ``` 83 | Puedo lograrlo tomando la posición de memoria del primer elemento e iterar 84 | hasta la posición del último elemento del arreglo, ésto se puede lograr ya 85 | que aunque sea un arreglo multidimensional, los elementos están alojados en 86 | memoria uno al lado del otro, en c el algoritmo sería: 87 | 88 | final_pos = &A[0][0] + (N * N) 89 | for (i=0; i != final_pos; ++i) 90 | s += A[i]; 91 | 92 | mul x9, x9, x9 // N = N*N 93 | lsl x9, x9, #3 // N = N*N*8 94 | add x1, xzr, xzr // s = 0 95 | add x9, x0, x9 // final_pos = &A[0][0] + N*N*8 96 | loop: cmp x0, x9 // &A[i] = final_pos ? 97 | b.eq done // si &A[i] = final_pos salto a done 98 | ldur x10, [x0, #0] // x10 = A[i] 99 | add x1, x1, x10 // s += A[i] 100 | addi x0, x0, #8 // i++ 101 | b loop // salto incondicional a loop 102 | done: 103 | ``` -------------------------------------------------------------------------------- /lab/ejercicio1/README.md: -------------------------------------------------------------------------------- 1 | # Lab Org. y Arq. de Computadoras 2 | 3 | * Configuración de pantalla: `640x480` pixels, formato `ARGB` 32 bits. 4 | * El registro `X0` contiene la dirección base del FrameBuffer (Pixel 1). 5 | * El código de cada consigna debe ser escrito en el archivo _app.s_. 6 | * El archivo _start.s_ contiene la inicialización del FrameBuffer **(NO EDITAR)**, al finalizar llama a _app.s_. 7 | * El código de ejemplo pinta toda la pantalla un solo color. 8 | 9 | ## Estructura 10 | 11 | * **[app.s](app.s)** Este archivo contiene a apliación. Todo el hardware ya está inicializado anteriormente. 12 | * **[start.s](start.s)** Este archivo realiza la inicialización del hardware. 13 | * **[Makefile](Makefile)** Archivo que describe como construir el software _(que ensamblador utilizar, que salida generar, etc)_. 14 | * **[memmap](memmap)** Este archivo contiene la descripción de la distribución de la memoria del programa y donde colocar cada sección. 15 | 16 | * **README.md** este archivo. 17 | 18 | ## Uso 19 | 20 | El archivo _Makefile_ contiene lo necesario para construir el proyecto. 21 | Se pueden utilizar otros archivos **.s** si les resulta práctico para emprolijar el código y el Makefile los ensamblará. 22 | 23 | **Para correr el proyecto ejecutar** 24 | 25 | ```bash 26 | $ make runQEMU 27 | ``` 28 | Esto construirá el código y ejecutará qemu para su emulación. 29 | 30 | Si qemu se queja con un error parecido a `qemu-system-aarch64: unsupported machine type`, prueben cambiar `raspi3` por `raspi3b` en la receta `runQEMU` del **Makefile** (línea 23 si no lo cambiaron). 31 | 32 | **Para correr el gpio manager** 33 | 34 | ```bash 35 | $ make runGPIOM 36 | ``` 37 | 38 | Ejecutar *luego* de haber corrido qemu. 39 | 40 | ## Como correr qemu y gcc usando Docker containers 41 | 42 | Los containers son maquinas virtuales livianas que permiten correr procesos individuales como el qemu y gcc. 43 | 44 | Para seguir esta guia primero tienen que instala docker y asegurarse que el usuario que vayan a usar tenga permiso para correr docker (ie dockergrp) o ser root 45 | 46 | ### Linux 47 | * Para construir el container hacer 48 | ```bash 49 | docker build -t famaf/rpi-qemu . 50 | ``` 51 | * Para arrancarlo 52 | ```bash 53 | xhost + 54 | cd rpi-asm-framebuffer 55 | docker run -dt --name rpi-qemu --rm -v $(pwd):/local --privileged -e "DISPLAY=${DISPLAY:-:0.0}" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 56 | ``` 57 | * Para correr el emulador y el simulador de I/O 58 | ```bash 59 | docker exec -d rpi-qemu make runQEMU 60 | docker exec -it rpi-qemu make runGPIOM 61 | ``` 62 | * Para terminar el container 63 | ```bash 64 | docker kill rpi-qemu 65 | ``` 66 | 67 | ### MacOS 68 | En MacOS primero tienen que [instalar un X server](https://medium.com/@mreichelt/how-to-show-x11-windows-within-docker-on-mac-50759f4b65cb) (i.e. XQuartz) 69 | * Para construir el container hacer 70 | ```bash 71 | docker build -t famaf/rpi-qemu . 72 | ``` 73 | * Para arrancarlo 74 | ```bash 75 | xhost + 76 | cd rpi-asm-framebuffer 77 | docker run -dt --name rpi-qemu --rm -v $(pwd):/local --privileged -e "DISPLAY=host.docker.internal:0" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 78 | ``` 79 | * Para correr el emulador y el simulador de I/O 80 | ```bash 81 | docker exec -d rpi-qemu make runQEMU 82 | docker exec -it rpi-qemu make runGPIOM 83 | ``` 84 | * Para terminar el container 85 | ```bash 86 | docker kill rpi-qemu 87 | ``` 88 | ---------------------------------- 89 | ### Otros comandos utiles 90 | ```bash 91 | # Correr el container en modo interactivo 92 | docker run -it --rm -v $(pwd):/local --privileged -e "DISPLAY=${DISPLAY:-:0.0}" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 93 | # Correr un shell en el container 94 | docker exec -it rpi-qemu /bin/bash 95 | ``` -------------------------------------------------------------------------------- /lab/ejercicio2/README.md: -------------------------------------------------------------------------------- 1 | # Lab Org. y Arq. de Computadoras 2 | 3 | * Configuración de pantalla: `640x480` pixels, formato `ARGB` 32 bits. 4 | * El registro `X0` contiene la dirección base del FrameBuffer (Pixel 1). 5 | * El código de cada consigna debe ser escrito en el archivo _app.s_. 6 | * El archivo _start.s_ contiene la inicialización del FrameBuffer **(NO EDITAR)**, al finalizar llama a _app.s_. 7 | * El código de ejemplo pinta toda la pantalla un solo color. 8 | 9 | ## Estructura 10 | 11 | * **[app.s](app.s)** Este archivo contiene a apliación. Todo el hardware ya está inicializado anteriormente. 12 | * **[start.s](start.s)** Este archivo realiza la inicialización del hardware. 13 | * **[Makefile](Makefile)** Archivo que describe como construir el software _(que ensamblador utilizar, que salida generar, etc)_. 14 | * **[memmap](memmap)** Este archivo contiene la descripción de la distribución de la memoria del programa y donde colocar cada sección. 15 | 16 | * **README.md** este archivo. 17 | 18 | ## Uso 19 | 20 | El archivo _Makefile_ contiene lo necesario para construir el proyecto. 21 | Se pueden utilizar otros archivos **.s** si les resulta práctico para emprolijar el código y el Makefile los ensamblará. 22 | 23 | **Para correr el proyecto ejecutar** 24 | 25 | ```bash 26 | $ make runQEMU 27 | ``` 28 | Esto construirá el código y ejecutará qemu para su emulación. 29 | 30 | Si qemu se queja con un error parecido a `qemu-system-aarch64: unsupported machine type`, prueben cambiar `raspi3` por `raspi3b` en la receta `runQEMU` del **Makefile** (línea 23 si no lo cambiaron). 31 | 32 | **Para correr el gpio manager** 33 | 34 | ```bash 35 | $ make runGPIOM 36 | ``` 37 | 38 | Ejecutar *luego* de haber corrido qemu. 39 | 40 | ## Como correr qemu y gcc usando Docker containers 41 | 42 | Los containers son maquinas virtuales livianas que permiten correr procesos individuales como el qemu y gcc. 43 | 44 | Para seguir esta guia primero tienen que instala docker y asegurarse que el usuario que vayan a usar tenga permiso para correr docker (ie dockergrp) o ser root 45 | 46 | ### Linux 47 | * Para construir el container hacer 48 | ```bash 49 | docker build -t famaf/rpi-qemu . 50 | ``` 51 | * Para arrancarlo 52 | ```bash 53 | xhost + 54 | cd rpi-asm-framebuffer 55 | docker run -dt --name rpi-qemu --rm -v $(pwd):/local --privileged -e "DISPLAY=${DISPLAY:-:0.0}" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 56 | ``` 57 | * Para correr el emulador y el simulador de I/O 58 | ```bash 59 | docker exec -d rpi-qemu make runQEMU 60 | docker exec -it rpi-qemu make runGPIOM 61 | ``` 62 | * Para terminar el container 63 | ```bash 64 | docker kill rpi-qemu 65 | ``` 66 | 67 | ### MacOS 68 | En MacOS primero tienen que [instalar un X server](https://medium.com/@mreichelt/how-to-show-x11-windows-within-docker-on-mac-50759f4b65cb) (i.e. XQuartz) 69 | * Para construir el container hacer 70 | ```bash 71 | docker build -t famaf/rpi-qemu . 72 | ``` 73 | * Para arrancarlo 74 | ```bash 75 | xhost + 76 | cd rpi-asm-framebuffer 77 | docker run -dt --name rpi-qemu --rm -v $(pwd):/local --privileged -e "DISPLAY=host.docker.internal:0" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 78 | ``` 79 | * Para correr el emulador y el simulador de I/O 80 | ```bash 81 | docker exec -d rpi-qemu make runQEMU 82 | docker exec -it rpi-qemu make runGPIOM 83 | ``` 84 | * Para terminar el container 85 | ```bash 86 | docker kill rpi-qemu 87 | ``` 88 | ---------------------------------- 89 | ### Otros comandos utiles 90 | ```bash 91 | # Correr el container en modo interactivo 92 | docker run -it --rm -v $(pwd):/local --privileged -e "DISPLAY=${DISPLAY:-:0.0}" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 93 | # Correr un shell en el container 94 | docker exec -it rpi-qemu /bin/bash 95 | ``` -------------------------------------------------------------------------------- /lab/README.md: -------------------------------------------------------------------------------- 1 | # Lab Organización del computador 2 | 3 | * Configuración de pantalla: `640x480` pixels, formato `ARGB` 32 bits. 4 | * El registro `X0` contiene la dirección base del FrameBuffer (Pixel 1). 5 | * El código de cada consigna debe ser escrito en el archivo _app.s_. 6 | * El archivo _start.s_ contiene la inicialización del FrameBuffer **(NO EDITAR)**, al finalizar llama a _app.s_. 7 | * El código de ejemplo pinta toda la pantalla un solo color. 8 | 9 | ## Estructura 10 | 11 | * **[app.s](app.s)** Este archivo contiene a apliación. Todo el hardware ya está inicializado anteriormente. 12 | * **[start.s](start.s)** Este archivo realiza la inicialización del hardware. 13 | * **[Makefile](Makefile)** Archivo que describe como construir el software _(que ensamblador utilizar, que salida generar, etc)_. 14 | * **[memmap](memmap)** Este archivo contiene la descripción de la distribución de la memoria del programa y donde colocar cada sección. 15 | 16 | * **README.md** este archivo. 17 | 18 | ## Uso 19 | 20 | El archivo _Makefile_ contiene lo necesario para construir el proyecto. 21 | Se pueden utilizar otros archivos **.s** si les resulta práctico para emprolijar el código y el Makefile los ensamblará. 22 | 23 | **Para correr el proyecto ejecutar** 24 | 25 | ```bash 26 | $ make runQEMU 27 | ``` 28 | Esto construirá el código y ejecutará qemu para su emulación. 29 | 30 | Si qemu se queja con un error parecido a `qemu-system-aarch64: unsupported machine type`, prueben cambiar `raspi3` por `raspi3b` en la receta `runQEMU` del **Makefile** (línea 23 si no lo cambiaron). 31 | 32 | **Para correr el gpio manager** 33 | 34 | ```bash 35 | $ make runGPIOM 36 | ``` 37 | Ejecutar *luego* de haber corrido qemu. 38 | 39 | 40 | ## Como correr qemu y gcc usando Docker containers 41 | 42 | Los containers son maquinas virtuales livianas que permiten correr procesos individuales como el qemu y gcc. 43 | 44 | Para seguir esta guia primero tienen que instala docker y asegurarse que el usuario que vayan a usar tenga permiso para correr docker (ie dockergrp) o ser root 45 | 46 | ### Linux 47 | * Para construir el container hacer 48 | ```bash 49 | docker build -t famaf/rpi-qemu . 50 | ``` 51 | * Para arrancarlo 52 | ```bash 53 | xhost + 54 | cd rpi-asm-framebuffer 55 | docker run -dt --name rpi-qemu --rm -v $(pwd):/local --privileged -e "DISPLAY=${DISPLAY:-:0.0}" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 56 | ``` 57 | * Para correr el emulador y el simulador de I/O 58 | ```bash 59 | docker exec -d rpi-qemu make runQEMU 60 | docker exec -it rpi-qemu make runGPIOM 61 | ``` 62 | * Para terminar el container 63 | ```bash 64 | docker kill rpi-qemu 65 | ``` 66 | 67 | ### MacOS 68 | En MacOS primero tienen que [instalar un X server](https://medium.com/@mreichelt/how-to-show-x11-windows-within-docker-on-mac-50759f4b65cb) (i.e. XQuartz) 69 | * Para construir el container hacer 70 | ```bash 71 | docker build -t famaf/rpi-qemu . 72 | ``` 73 | * Para arrancarlo 74 | ```bash 75 | xhost + 76 | cd rpi-asm-framebuffer 77 | docker run -dt --name rpi-qemu --rm -v $(pwd):/local --privileged -e "DISPLAY=host.docker.internal:0" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 78 | ``` 79 | * Para correr el emulador y el simulador de I/O 80 | ```bash 81 | docker exec -d rpi-qemu make runQEMU 82 | docker exec -it rpi-qemu make runGPIOM 83 | ``` 84 | * Para terminar el container 85 | ```bash 86 | docker kill rpi-qemu 87 | ``` 88 | ---------------------------------- 89 | ### Otros comandos utiles 90 | ```bash 91 | # Correr el container en modo interactivo 92 | docker run -it --rm -v $(pwd):/local --privileged -e "DISPLAY=${DISPLAY:-:0.0}" -v /tmp/.X11-unix:/tmp/.X11-unix -v "$HOME/.Xauthority:/root/.Xauthority:rw" famaf/rpi-qemu 93 | # Correr un shell en el container 94 | docker exec -it rpi-qemu /bin/bash 95 | ``` 96 | 97 | --- 98 | -------------------------------------------------------------------------------- /lab/ejercicio2/start.s: -------------------------------------------------------------------------------- 1 | .text 2 | .org 0x80000 3 | 4 | // Setup Frame Buffer 5 | .equ SCREEN_WIDTH, 640 6 | .equ SCREEN_HEIGH, 480 7 | .equ BITS_PER_PIXEL, 32 8 | 9 | .equ MAIL_BASE, 0xB880 // Mailbox Base Address 10 | .equ MAIL_WRITE, 0x20 // Mailbox Write Register 11 | .equ MAIL_TAGS, 0x8 // Mailbox Channel 8: Tags (ARM to VC) 12 | .equ PERIPHERAL_BASE, 0x3F000000 // Peripheral Base Address 13 | 14 | .equ Get_Allocate_Buffer, 0x00040001 // Frame Buffer: Allocate Buffer (Response: Frame Buffer Base Address In Bytes, Frame Buffer Size In Bytes) 15 | 16 | .equ Set_Physical_Display, 0x00048003 // Frame Buffer: Set Physical (Display) Width/Height (Response: Width In Pixels, Height In Pixels) 17 | .equ Set_Virtual_Buffer, 0x00048004 // Frame Buffer: Set Virtual (Buffer) Width/Height (Response: Width In Pixels, Height In Pixels) 18 | .equ Set_Depth, 0x00048005 // Frame Buffer: Set Depth (Response: Bits Per Pixel) 19 | .equ Set_Virtual_Offset, 0x00048009 // Frame Buffer: Set Virtual Offset (Response: X In Pixels, Y In Pixels) 20 | .equ Set_Palette, 0x0004800B // Frame Buffer: Set Palette (Response: RGBA Palette Values (Index 0 To 255)) 21 | .equ Set_Pixel_Order, 0x00048006 // Frame Buffer: Set Pixel Order 22 | .equ Get_Pixel_pitch, 0x00048006 // Frame Buffer: Set Pixel Order 23 | 24 | // UART data 25 | .equ Set_Power, 0x00028001 // UART: Set Power 26 | .equ Set_ClkRate, 0x00038002 // UART: Set Clock Rate 27 | 28 | .equ MMIO_BASE_ALTA, 0x3f20 29 | 30 | .equ GPFSEL0, 0x0000 31 | .equ GPFSEL1, 0x0004 32 | .equ GPPUD, 0x0094 33 | .equ GPPUDCLK0, 0x0098 34 | 35 | .equ UART0_DR, 0x1000 36 | .equ UART0_FR, 0x1018 37 | .equ UART0_IBRD, 0x1024 38 | .equ UART0_FBRD, 0x1028 39 | .equ UART0_LCRH, 0x102C 40 | .equ UART0_CR, 0x1030 41 | .equ UART0_IMSC, 0x1038 42 | .equ UART0_ICR, 0x1044 43 | // Return CPU ID (0..3) Of The CPU Executed On 44 | 45 | .section ".text.boot" 46 | .globl _start 47 | 48 | _start: 49 | mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) 50 | and x1, x1, #3 // X0 = CPU ID (Bits 0..1) 51 | cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop 52 | // Infinite Loop For Core 1, 2 and 3 53 | CoreLoop: 54 | b CoreLoop 55 | 56 | StackInit: 57 | // set stack before our code 58 | ldr x1, =_start 59 | mov sp, x1 60 | 61 | // clear bss 62 | ldr x1, =__bss_start 63 | ldr w2, =__bss_size 64 | _StackInit_loop: 65 | cbz w2, FB_Init 66 | str xzr, [x1], #8 67 | sub w2, w2, #1 68 | cbnz w2, _StackInit_loop 69 | 70 | // Core 0 Init the framebuffer 71 | FB_Init: 72 | ldr x0, =(FB_STRUCT + MAIL_TAGS) 73 | ldr x1, =MAIL_BASE 74 | ldr x2, =FB_POINTER 75 | orr x1,x1,PERIPHERAL_BASE 76 | str w0,[x1,MAIL_WRITE + MAIL_TAGS] // Mail Box Write 77 | ldr w0,[x2] // W0 = Frame Buffer Pointer 78 | cbz w0,FB_Init // IF (Frame Buffer Pointer == Zero) Re-Initialize Frame Buffer 79 | and w0,w0,0x3FFFFFFF // Convert Mail Box Frame Buffer Pointer From BUS Address To Physical Address ($CXXXXXXX -> $3XXXXXXX) 80 | str w0,[x2] // Store Frame Buffer Pointer Physical Address 81 | add w10,w0,wzr 82 | b main 83 | 84 | .align 16 85 | FB_STRUCT: // Mailbox Property Interface Buffer Structure 86 | .word FB_STRUCT_END - FB_STRUCT // Buffer Size In Bytes (Including The Header Values, The End Tag And Padding) 87 | .word 0x00000000 // Buffer Request/Response Code 88 | // Request Codes: $00000000 Process Request Response Codes: $80000000 Request Successful, $80000001 Partial Response 89 | // Sequence Of Concatenated Tags 90 | .word Set_Physical_Display // Tag Identifier 91 | .word 0x00000008 // Value Buffer Size In Bytes 92 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 93 | .word SCREEN_WIDTH // Value Buffer 94 | .word SCREEN_HEIGH // Value Buffer 95 | 96 | .word Set_Virtual_Buffer // Tag Identifier 97 | .word 0x00000008 // Value Buffer Size In Bytes 98 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 99 | .word SCREEN_WIDTH // Value Buffer 100 | .word SCREEN_HEIGH // Value Buffer 101 | 102 | .word Set_Virtual_Offset // Tag Identifier 103 | .word 0x00000008 // Value Buffer Size In Bytes 104 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 105 | FB_OFFSET_X: 106 | .word 0 // Value Buffer 107 | FB_OFFSET_Y: 108 | .word 0 // Value Buffer 109 | 110 | .word Set_Depth // Tag Identifier 111 | .word 0x00000004 // Value Buffer Size In Bytes 112 | .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 113 | .word BITS_PER_PIXEL // Value Buffer 114 | 115 | .word 0x48006 // Tag Identifier 116 | .word 0x00000004 // Value Buffer Size In Bytes 117 | .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 118 | .word 0 // RGB, not BGR preferably 119 | 120 | .word Set_Palette // Tag Identifier 121 | .word 0x00000010 // Value Buffer Size In Bytes 122 | .word 0x00000010 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 123 | .word 0 // Value Buffer (Offset: First Palette Index To Set (0-255)) 124 | .word 2 // Value Buffer (Length: Number Of Palette Entries To Set (1-256)) 125 | FB_PAL: 126 | .word 0x00000000,0xFFFFFFFF // RGBA Palette Values (Offset To Offset+Length-1) 127 | 128 | .word Get_Allocate_Buffer // Tag Identifier 129 | .word 0x00000008 // Value Buffer Size In Bytes 130 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 131 | FB_POINTER: 132 | .word 0 // FrameBuffer Pointer 133 | FB_SIZE: 134 | .word 0 // FrameBuffer Size 135 | 136 | .word 0x00000000 // $0 (End Tag) 137 | FB_STRUCT_END: 138 | 139 | -------------------------------------------------------------------------------- /lab/ejercicio1/start.s: -------------------------------------------------------------------------------- 1 | .text 2 | .org 0x80000 3 | 4 | // Setup Frame Buffer 5 | .equ SCREEN_WIDTH, 640 6 | .equ SCREEN_HEIGH, 480 7 | .equ BITS_PER_PIXEL, 32 8 | 9 | .equ MAIL_BASE, 0xB880 // Mailbox Base Address 10 | .equ MAIL_WRITE, 0x20 // Mailbox Write Register 11 | .equ MAIL_TAGS, 0x8 // Mailbox Channel 8: Tags (ARM to VC) 12 | .equ PERIPHERAL_BASE, 0x3F000000 // Peripheral Base Address 13 | 14 | .equ Get_Allocate_Buffer, 0x00040001 // Frame Buffer: Allocate Buffer (Response: Frame Buffer Base Address In Bytes, Frame Buffer Size In Bytes) 15 | 16 | .equ Set_Physical_Display, 0x00048003 // Frame Buffer: Set Physical (Display) Width/Height (Response: Width In Pixels, Height In Pixels) 17 | .equ Set_Virtual_Buffer, 0x00048004 // Frame Buffer: Set Virtual (Buffer) Width/Height (Response: Width In Pixels, Height In Pixels) 18 | .equ Set_Depth, 0x00048005 // Frame Buffer: Set Depth (Response: Bits Per Pixel) 19 | .equ Set_Virtual_Offset, 0x00048009 // Frame Buffer: Set Virtual Offset (Response: X In Pixels, Y In Pixels) 20 | .equ Set_Palette, 0x0004800B // Frame Buffer: Set Palette (Response: RGBA Palette Values (Index 0 To 255)) 21 | .equ Set_Pixel_Order, 0x00048006 // Frame Buffer: Set Pixel Order 22 | .equ Get_Pixel_pitch, 0x00048006 // Frame Buffer: Set Pixel Order 23 | 24 | // UART data 25 | .equ Set_Power, 0x00028001 // UART: Set Power 26 | .equ Set_ClkRate, 0x00038002 // UART: Set Clock Rate 27 | 28 | .equ MMIO_BASE_ALTA, 0x3f20 29 | 30 | .equ GPFSEL0, 0x0000 31 | .equ GPFSEL1, 0x0004 32 | .equ GPPUD, 0x0094 33 | .equ GPPUDCLK0, 0x0098 34 | 35 | .equ UART0_DR, 0x1000 36 | .equ UART0_FR, 0x1018 37 | .equ UART0_IBRD, 0x1024 38 | .equ UART0_FBRD, 0x1028 39 | .equ UART0_LCRH, 0x102C 40 | .equ UART0_CR, 0x1030 41 | .equ UART0_IMSC, 0x1038 42 | .equ UART0_ICR, 0x1044 43 | // Return CPU ID (0..3) Of The CPU Executed On 44 | 45 | .section ".text.boot" 46 | .globl _start 47 | 48 | _start: 49 | mrs x1, mpidr_el1 // X0 = Multiprocessor Affinity Register (MPIDR) 50 | and x1, x1, #3 // X0 = CPU ID (Bits 0..1) 51 | cbz x1, StackInit // IF (CPU ID == 0) Branch To Finit else (Core ID 1..3) CoreLoop 52 | // Infinite Loop For Core 1, 2 and 3 53 | CoreLoop: 54 | b CoreLoop 55 | 56 | StackInit: 57 | // set stack before our code 58 | ldr x1, =_start 59 | mov sp, x1 60 | 61 | // clear bss 62 | ldr x1, =__bss_start 63 | ldr w2, =__bss_size 64 | _StackInit_loop: 65 | cbz w2, FB_Init 66 | str xzr, [x1], #8 67 | sub w2, w2, #1 68 | cbnz w2, _StackInit_loop 69 | 70 | // Core 0 Init the framebuffer 71 | FB_Init: 72 | ldr x0, =(FB_STRUCT + MAIL_TAGS) 73 | ldr x1, =MAIL_BASE 74 | ldr x2, =FB_POINTER 75 | orr x1,x1,PERIPHERAL_BASE 76 | str w0,[x1,MAIL_WRITE + MAIL_TAGS] // Mail Box Write 77 | ldr w0,[x2] // W0 = Frame Buffer Pointer 78 | cbz w0,FB_Init // IF (Frame Buffer Pointer == Zero) Re-Initialize Frame Buffer 79 | and w0,w0,0x3FFFFFFF // Convert Mail Box Frame Buffer Pointer From BUS Address To Physical Address ($CXXXXXXX -> $3XXXXXXX) 80 | str w0,[x2] // Store Frame Buffer Pointer Physical Address 81 | add w10,w0,wzr 82 | b main 83 | 84 | .align 16 85 | FB_STRUCT: // Mailbox Property Interface Buffer Structure 86 | .word FB_STRUCT_END - FB_STRUCT // Buffer Size In Bytes (Including The Header Values, The End Tag And Padding) 87 | .word 0x00000000 // Buffer Request/Response Code 88 | // Request Codes: $00000000 Process Request Response Codes: $80000000 Request Successful, $80000001 Partial Response 89 | // Sequence Of Concatenated Tags 90 | .word Set_Physical_Display // Tag Identifier 91 | .word 0x00000008 // Value Buffer Size In Bytes 92 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 93 | .word SCREEN_WIDTH // Value Buffer 94 | .word SCREEN_HEIGH // Value Buffer 95 | 96 | .word Set_Virtual_Buffer // Tag Identifier 97 | .word 0x00000008 // Value Buffer Size In Bytes 98 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 99 | .word SCREEN_WIDTH // Value Buffer 100 | .word SCREEN_HEIGH // Value Buffer 101 | 102 | .word Set_Virtual_Offset // Tag Identifier 103 | .word 0x00000008 // Value Buffer Size In Bytes 104 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 105 | FB_OFFSET_X: 106 | .word 0 // Value Buffer 107 | FB_OFFSET_Y: 108 | .word 0 // Value Buffer 109 | 110 | .word Set_Depth // Tag Identifier 111 | .word 0x00000004 // Value Buffer Size In Bytes 112 | .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 113 | .word BITS_PER_PIXEL // Value Buffer 114 | 115 | .word 0x48006 // Tag Identifier 116 | .word 0x00000004 // Value Buffer Size In Bytes 117 | .word 0x00000004 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 118 | .word 0 // RGB, not BGR preferably 119 | 120 | .word Set_Palette // Tag Identifier 121 | .word 0x00000010 // Value Buffer Size In Bytes 122 | .word 0x00000010 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 123 | .word 0 // Value Buffer (Offset: First Palette Index To Set (0-255)) 124 | .word 2 // Value Buffer (Length: Number Of Palette Entries To Set (1-256)) 125 | FB_PAL: 126 | .word 0x00000000,0xFFFFFFFF // RGBA Palette Values (Offset To Offset+Length-1) 127 | 128 | .word Get_Allocate_Buffer // Tag Identifier 129 | .word 0x00000008 // Value Buffer Size In Bytes 130 | .word 0x00000008 // 1 bit (MSB) Request/Response Indicator (0=Request, 1=Response), 31 bits (LSB) Value Length In Bytes 131 | FB_POINTER: 132 | .word 0 // FrameBuffer Pointer 133 | FB_SIZE: 134 | .word 0 // FrameBuffer Size 135 | 136 | .word 0x00000000 // $0 (End Tag) 137 | FB_STRUCT_END: 138 | 139 | -------------------------------------------------------------------------------- /practico 9/assets/ej08.1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | 21 | PCReadaddressInstructionmemoryInstruction4ADD -------------------------------------------------------------------------------- /lab/ejercicio2/app.s: -------------------------------------------------------------------------------- 1 | //---------------- Inicio Carga Parametros ------------------------------------ 2 | 3 | .equ SCREEN_WIDTH, 640 4 | .equ SCREEN_HEIGH, 480 5 | .equ BITS_PER_PIXEL, 32 6 | 7 | .equ GPIO_BASE, 0x3f200000 8 | .equ GPIO_GPFSEL0, 0x00 9 | .equ GPIO_GPLEV0, 0x34 10 | 11 | // Incluimos el archivo donde estan todas las funciones 12 | .include "funciones.s" 13 | 14 | // Los inputs para este programa son: 15 | // W,A,S,D,SPACE 16 | 17 | .equ key_W, 0x2 18 | .equ key_A, 0x4 19 | .equ key_S, 0x8 20 | .equ key_D, 0x10 21 | .equ key_SPACE, 0x20 22 | 23 | .globl main 24 | 25 | main: 26 | // x0 contiene la direccion base del framebuffer 27 | mov x20, x0 // Guarda la dirección base del framebuffer en x20 28 | 29 | //---------------- Fin Carga Parametros ------------------------------------ 30 | 31 | reseteo: 32 | //---------------- Inicio Dibujo ------------------------------------ 33 | 34 | BL pintar_fondo 35 | 36 | BL pintar_bordes 37 | 38 | BL pintar_luna 39 | 40 | BL pintar_nave 41 | 42 | //---------------- Fin Dibujo ------------------------------------ 43 | 44 | //---------------- Variables Globales ------------------------------------ 45 | 46 | // Valores Hitbox: (este hitbox debe encerrar la nave) 47 | // x1 -> Ancho. 48 | // x2 -> Alto. 49 | // x3 -> Pixel X. 50 | // x4 -> Pixel Y. 51 | mov x1, 20 52 | mov x2, 11 53 | mov x3, 50 54 | mov x4, 44 55 | 56 | BL calcular_pixel // Encuentro la esquina superior izq del Hitbox con x3 y x4 57 | 58 | mov x25 , x0 // Guardo la direccion del Hitbox en x25 59 | 60 | movz w7, 0x16, lsl 16 // x7 debe de ser del mismo color que los bordes que me detienen 61 | movk w7, 0x15, lsl 00 // En caso de modificar el color de los bordes, tambien se debe modificar x7 62 | 63 | movz w9, 0xE0, lsl 16 // x9 debe de ser del mismo color de la Luna (salta animacion final) 64 | movk w9, 0xE0E0, lsl 00 // En caso de modificar el color de la luna, tambien se debe modificar x9 65 | 66 | movz x8, 0x3F, lsl 16 // x8 -> Tiempo de delay = Velocidad del Meteoro. 67 | movk x8, 0xFFFF, lsl 00 // Este valor se puede modificar a gusto de cada jugador 68 | 69 | //---------------------------------------------------- 70 | 71 | //---------------- Loop Inicial ------------------------------------ 72 | 73 | // Realizo un loop inicial hasta que el jugador decide moverse 74 | quieto: 75 | 76 | BL loop_pulsador 77 | 78 | B quieto 79 | 80 | //---------------------------------------------------- 81 | 82 | //---------------- Inicio Movimiento ------------------------------------ 83 | 84 | mov_hitbox_izq: 85 | 86 | loop_mov_hitbox_izq: 87 | 88 | // Primero debo detectar si puedo moverme 89 | 90 | mov x21, x25 // x21 -> Direccion Esquina Superior Izq 91 | sub x21, x21 , 8 // Reviso 2 pixeles a la izq si debo detenerme 92 | ldr w6, [x21] 93 | 94 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 95 | b.eq quieto 96 | 97 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 98 | b.eq final 99 | 100 | movz x23, 0xA00, lsl 00 // x23 = 2560 101 | mul x22, x2, x23 // x22 -> alto * 2560 102 | add x21, x21, x22 // x21 -> Direccion Esquina Inferior Izq 2 pixeles a la izq 103 | ldr w6, [x21] 104 | 105 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 106 | b.eq quieto 107 | 108 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 109 | b.eq final 110 | 111 | // Si llegue hasta aca entonces no debo detenerme 112 | 113 | BL funcion_delay 114 | 115 | // x1 -> Ancho del hitbox 116 | // x2 -> Alto del hitbox 117 | // x25 -> Ubicacion del hitbox 118 | BL funcion_mover_elem_izq 119 | 120 | sub x25 , x25 , 4 // Mi nueva esquina superior izq ahora esta un pixel a la izq que antes 121 | 122 | BL loop_pulsador // Reviso si ingreso un nuevo input 123 | 124 | B loop_mov_hitbox_izq 125 | 126 | mov_hitbox_der: 127 | 128 | loop_mov_hitbox_der: 129 | 130 | // Primero debo detectar si puedo moverme 131 | 132 | mov x21, x25 // x21 -> Direccion Esquina Superior Izq 133 | 134 | add x22, x1, x1 // x22 -> ancho + ancho 135 | add x22, x22, x22 // x22 -> ancho + ancho + ancho + ancho = ancho * 4 136 | add x22, x22, 4 137 | add x21, x21 , x22 // Me muevo a la esquina superior derecha y 2 pixeles mas 138 | ldr w6, [x21] 139 | 140 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 141 | b.eq quieto 142 | 143 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 144 | b.eq final 145 | 146 | movz x23, 0xA00, lsl 00 // x23 = 2560 147 | mul x22, x2, x23 // x22 -> alto * 2560 148 | add x21, x21, x22 // x21 -> Direccion Esquina Inferior Der 2 pixeles a la der 149 | ldr w6, [x21] 150 | 151 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 152 | b.eq quieto 153 | 154 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 155 | b.eq final 156 | 157 | // Si llegue hasta aca entonces no debo detenerme 158 | 159 | BL funcion_delay 160 | 161 | // x1 -> Ancho del hitbox 162 | // x2 -> Alto del hitbox 163 | // x25 -> Ubicacion del hitbox 164 | BL funcion_mover_elem_der 165 | 166 | add x25, x25, 4 // Mi nueva esquina superior izq ahora esta un pixel a la der que antes 167 | 168 | BL loop_pulsador // Reviso si ingreso un nuevo input 169 | 170 | B loop_mov_hitbox_der 171 | 172 | mov_hitbox_arr: 173 | 174 | loop_mov_hitbox_arr: 175 | 176 | // Primero debo detectar si puedo moverme 177 | 178 | mov x21, x25 // x21 -> Direccion Esquina Superior Izq 179 | movz x22 , 0x1400 , lsl 00 // x22 -> 2560 * 2 180 | sub x21, x21 , x22 // Me muevo 2 pixeles arriba 181 | ldr w6, [x21] 182 | 183 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 184 | b.eq quieto 185 | 186 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 187 | b.eq final 188 | 189 | add x22, x1, x1 // x22 -> ancho + ancho 190 | add x22, x22, x22 // x22 -> ancho + ancho + ancho + ancho = ancho * 4 191 | add x21, x21 , x22 // x21 -> Direccion Esquina Superior Der 2 pixeles arriba 192 | ldr w6, [x21] 193 | 194 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 195 | b.eq quieto 196 | 197 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 198 | b.eq final 199 | 200 | // Si llegue hasta aca entonces no debo detenerme 201 | 202 | BL funcion_delay 203 | 204 | // x1 -> Ancho del hitbox 205 | // x2 -> Alto del hitbox 206 | // x25 -> Ubicacion del hitbox 207 | BL funcion_mover_elem_arr 208 | 209 | sub x25, x25, 2560 // Mi nueva esquina superior izq ahora esta un pixel arriba que antes 210 | 211 | BL loop_pulsador // Reviso si ingreso un nuevo input 212 | 213 | B loop_mov_hitbox_arr 214 | 215 | mov_hitbox_aba: 216 | 217 | loop_mov_hitbox_aba: 218 | 219 | // Primero debo detectar si puedo moverme 220 | 221 | mov x21, x25 // x21 -> Direccion Esquina Superior Izq 222 | 223 | movz x23, 0xA00, lsl 00 // x23 = 2560 224 | mul x22, x2, x23 // x22 -> alto * 2560 225 | add x22, x22, 2560 226 | add x21, x21, x22 // x21 -> Direccion Esquina Inferior Izq 227 | ldr w6, [x21] 228 | 229 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 230 | b.eq quieto 231 | 232 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 233 | b.eq final 234 | 235 | add x22, x1, x1 // x22 -> ancho + ancho 236 | add x22, x22, x22 // x22 -> ancho + ancho + ancho + ancho = ancho * 4 237 | add x21, x21 , x22 // x21 -> Direccion Esquina Inferior Der 2 pixeles arriba 238 | ldr w6, [x21] 239 | 240 | cmp w6, w7 // Si el color es el que me detiene, entonces freno 241 | b.eq quieto 242 | 243 | cmp w6, w9 // Si el color es el de la luna, entonces animacion final 244 | b.eq final 245 | 246 | // Si llegue hasta aca entonces no estoy en el borde y me muevo 247 | 248 | BL funcion_delay 249 | 250 | // x1 -> Ancho del hitbox 251 | // x2 -> Alto del hitbox 252 | // x25 -> Ubicacion del hitbox 253 | BL funcion_mover_elem_aba 254 | 255 | add x25, x25, 2560 // Mi nueva esquina superior izq ahora esta un pixel abajo que antes 256 | 257 | BL loop_pulsador // Reviso si ingreso un nuevo input 258 | 259 | B loop_mov_hitbox_aba 260 | 261 | animacion_der: 262 | 263 | mov x3, 300 // x3 -> Pixel X limite 264 | mov x4, 44 // x4 -> Pixel Y limite 265 | 266 | BL calcular_pixel // Encuentro la direccion donde quiero que se detenga 267 | 268 | mov x6, x0 // x6 -> Guardo la direccion del limite 269 | 270 | // Valores Hitbox: (este cuadrado debe encerrar la nave) 271 | mov x1, 20 // x1 -> Ancho 272 | mov x2, 11 // x2 -> Alto 273 | mov x3, 50 // x3 -> Pixel X 274 | mov x4, 44 // x4 -> Pixel Y 275 | 276 | BL calcular_pixel // Encuentro la esquina superior izq del Hitbox con x3 y x4 277 | 278 | mov x25, x0 // x25 -> Direccion del hitbox 279 | 280 | loop_animacion_der: 281 | 282 | BL funcion_delay 283 | 284 | // x1 -> Ancho del hitbox 285 | // x2 -> Alto del hitbox 286 | // x25 -> Ubicacion del hitbox 287 | BL funcion_mover_elem_der 288 | 289 | add x25, x25, 4 // Mi nueva esquina superior izq ahora esta un pixel a la der que antes 290 | 291 | cmp x25, x6 // Si llego al limite entonces freno 292 | b.eq fin_animacion_der 293 | 294 | B loop_animacion_der 295 | 296 | animacion_aba: 297 | 298 | mov x3, 300 // x3 -> Pixel X limite 299 | mov x4, 140 // x4 -> Pixel Y limite 300 | 301 | BL calcular_pixel // Encuentro la direccion donde quiero que se detenga 302 | 303 | mov x6, x0 // x6 -> Guardo la direccion del limite 304 | 305 | mov x3, 300 // x3 -> Pixel X apago propulsor 306 | mov x4, 110 // x4 -> Pixel Y apago propulsor 307 | 308 | BL calcular_pixel // Encuentro la direccion donde quiero que se apague el propulsor 309 | 310 | mov x7, x0 // x7 -> Guardo la direccion de apagado del propulsor 311 | 312 | // Valores Hitbox: (este cuadrado debe encerrar la nave) 313 | mov x1, 20 // x1 -> Ancho 314 | mov x2, 31 // x2 -> Alto 315 | mov x3, 300 // x3 -> Pixel X 316 | mov x4, 44 // x4 -> Pixel Y 317 | 318 | BL calcular_pixel // Encuentro la esquina superior izq del Hitbox con x3 y x4 319 | 320 | mov x25, x0 // x25 -> Direccion del hitbox 321 | 322 | loop_animacion_aba: 323 | 324 | BL funcion_delay 325 | 326 | // x1 -> Ancho del hitbox 327 | // x2 -> Alto del hitbox 328 | // x25 -> Ubicacion del hitbox 329 | BL funcion_mover_elem_aba 330 | 331 | add x25, x25, 2560 // Mi nueva esquina superior izq ahora esta un pixel abajo que antes 332 | 333 | cmp x25, x7 // Si todavia no llegue a donde tengo que apagar, no apago 334 | b.ne no_apago 335 | // Para apagarlo devuelvo el valor original del alto del hitbox 336 | mov x2, 11 // x2 -> Alto hitbox 337 | 338 | no_apago: 339 | cmp x25, x6 // Si llego al limite entonces freno 340 | b.eq fin_animacion_aba 341 | 342 | B loop_animacion_aba 343 | 344 | //---------------- Fin Movimiento ------------------------------------ 345 | 346 | //---------------- Inicio Lectura Inputs ------------------------------------ 347 | 348 | loop_pulsador: 349 | 350 | // Guardo el valor de x9 debido a guarda el color de la luna 351 | SUB SP, SP, 8 352 | STUR x9, [SP, 0] 353 | 354 | // Seteamos el GPIO para poder realizar la lectura de los inputs 355 | mov x9, GPIO_BASE 356 | 357 | // Atención: se utilizan registros w porque la documentación de broadcom 358 | // indica que los registros que estamos leyendo y escribiendo son de 32 bits 359 | 360 | // Setea gpios 0 - 9 como lectura 361 | str wzr, [x9, GPIO_GPFSEL0] 362 | 363 | // Lee el estado de los GPIO 0 - 31 364 | ldr w10, [x9, GPIO_GPLEV0] 365 | 366 | // Devolvemos el valor de x9 367 | LDR x9, [SP, 0] 368 | ADD SP, SP, 8 369 | 370 | // And bit a bit mantiene el resultado del bit 2 en w10 (notar 0b... es binario) 371 | // al inmediato se lo refiere como "máscara" en este caso: 372 | // - Al hacer AND revela el estado del bit 2 373 | // - Al hacer OR "setea" el bit 2 en 1 374 | // - Al hacer AND con el complemento "limpia" el bit 2 (setea el bit 2 en 0) 375 | 376 | and w11, w10, 0b00000010 377 | and w12, w10, 0b00000100 378 | and w13, w10, 0b00001000 379 | and w14, w10, 0b00010000 380 | and w15, w10, 0b00100000 381 | 382 | // si w11 es 0 entonces el GPIO 1 estaba liberado 383 | // de lo contrario será distinto de 0, (en este caso particular 2) 384 | // significando que el GPIO 1 fue presionado 385 | 386 | cmp w11 , key_W // Al presionar la W el hitbox se mueve para arriba 387 | beq mov_hitbox_arr 388 | 389 | cmp w12 , key_A // Al presionar la A el hitbox se mueve para la izquierda 390 | beq mov_hitbox_izq 391 | 392 | cmp w13 , key_S // Al presionar la S el hitbox se mueve para abajo 393 | beq mov_hitbox_aba 394 | 395 | cmp w14 , key_D // Al presionar la D el hitbox se mueve para la derecha 396 | beq mov_hitbox_der 397 | 398 | cmp w15 , key_SPACE // Al presionar SPACE el juego se reinicia 399 | beq reseteo 400 | 401 | ret 402 | 403 | //---------------- Fin Lectura Inputs ------------------------------------ 404 | 405 | //---------------- Inicio Animacion Final ------------------------------------ 406 | final: 407 | 408 | BL pintar_pantalla_carga 409 | 410 | movz x8, 0x1FFF, lsl 16 // Damos un tiempo de delay para cambiar de escena. 411 | movk x8, 0xFFFF, lsl 00 // Modificable a gusto del jugador 412 | 413 | BL funcion_delay 414 | 415 | BL pintar_fondo 416 | 417 | BL pintar_luna_centrada 418 | 419 | BL pintar_nave 420 | 421 | movz x8, 0x3F, lsl 16 // x8 -> Tiempo de delay = Velocidad de la animacion 422 | movk x8, 0xFFFF, lsl 00 // Modificable a gusto del jugador 423 | 424 | B animacion_der 425 | 426 | fin_animacion_der: 427 | 428 | movz x8, 0xFFF, lsl 16 // Damos un tiempo de delay para que active los propulsores 429 | movk x8, 0xFFFF, lsl 00 // Modificable a gusto del jugador 430 | 431 | BL funcion_delay 432 | 433 | BL pintar_propulsor 434 | 435 | movz x8, 0xAF, lsl 16 // Volvemos a setear x8 -> Tiempo de delay = Velocidad descenso nave 436 | movk x8, 0xFFFF, lsl 00 // Modificable a gusto del jugador 437 | 438 | B animacion_aba 439 | 440 | fin_animacion_aba: 441 | 442 | BL pintar_tren_aterrizaje 443 | 444 | movz x8, 0xFFF, lsl 16 // Damos un tiempo de delay para poner la bandera 445 | movk x8, 0xFFFF, lsl 00 // Modificable a gusto del jugador 446 | 447 | BL funcion_delay 448 | 449 | BL pintar_bandera 450 | 451 | B quieto 452 | 453 | //---------------- Fin Animacion Final ------------------------------------ 454 | 455 | //---------------- Infinite Loop ------------------------------------ 456 | InfLoop: 457 | b InfLoop 458 | -------------------------------------------------------------------------------- /lab/ejercicio1/funciones.s: -------------------------------------------------------------------------------- 1 | .equ SCREEN_WIDTH, 640 2 | .equ SCREEN_HEIGH, 480 3 | 4 | //------------------ Inicio Funciones Basicas ------------------ 5 | 6 | calcular_pixel: 7 | // Parametros: 8 | // x3 -> Pixel X 9 | // x4 -> Pixel Y 10 | // Return x0 -> Posición (x,y) en la imagen 11 | 12 | mov x0, SCREEN_WIDTH // x0 = 640 13 | mul x0, x0, x4 // x0 = 640 * y 14 | add x0, x0, x3 // x0 = (640 * y) + x 15 | lsl x0, x0, 2 // x0 = ((640 * y) + x) * 4 16 | add x0, x0, x20 // x0 = ((640 * y) + x) * 4 + A[0] 17 | ret 18 | 19 | pintar_pixel: 20 | // Parametros: 21 | // x1 -> Pixel X 22 | // x2 -> Pixel Y 23 | // x10 -> Color 24 | 25 | // Guardamos los valores previos en el stack 26 | SUB SP, SP, 24 27 | STUR x30, [SP, 16] 28 | STUR x3, [SP, 8] 29 | STUR x4, [SP, 0] 30 | 31 | // Chequeamos que las coordenadas esten dentro de la pantalla, si no lo estan, no pintamos 32 | cmp x1, SCREEN_WIDTH 33 | b.ge no_paint // x1 >= 640 34 | 35 | cmp x2, SCREEN_HEIGH 36 | b.ge no_paint // x2 >= 480 37 | 38 | mov x3, x1 // x3 -> Pixel X 39 | mov x4, x2 // x4 -> Pixel Y 40 | 41 | BL calcular_pixel // Calculamos la direccion del pixel a pintar 42 | 43 | stur w10, [x0] // Pintamos el Pixel 44 | 45 | no_paint: 46 | // Devolvemos los valores previos del stack 47 | LDR x4, [SP, 0] 48 | LDR x3, [SP, 8] 49 | LDR x30, [SP, 16] 50 | ADD SP, SP, 24 51 | 52 | ret 53 | 54 | si_pixel_en_circulo_pintar: 55 | // Verificamos si el pixel en la coordenada (x1 , x2) pertenece al circulo. Si pertenece, lo pintamos 56 | // Parametros: 57 | // (x1 , x2) -> Pixel que estamos analizando 58 | // (x4 , x5) -> Pixel centro del circulo 59 | // x3 -> Radio del Circulo 60 | // x10 -> Color 61 | 62 | // Si (x1 - x4)² + (x2 - x5)² ≤ x3² => (x1 , x2) esta dentro del circulo 63 | 64 | // Guardamos los valores previos en el stack 65 | SUB SP, SP, 32 66 | STUR x30, [SP, 24] 67 | STUR x15, [SP, 16] 68 | STUR x14, [SP, 8] 69 | STUR x13, [SP, 0] 70 | 71 | mul x15,x3,x3 // x15 -> r * r 72 | 73 | sub x13, x1, x4 // x13 -> (x1 - x4) 74 | mul x13, x13, x13 // x13 -> (x1 - x4) * (x1 - x4) 75 | 76 | sub x14, x2, x5 // x14 -> (x2 - x5) 77 | mul x14, x14, x14 // x14 -> (x2 - x5) * (x2 - x5) 78 | 79 | add x13, x13, x14 // x13 -> (x1 - x4)² + (x2 - x5)² 80 | 81 | cmp x13, x15 82 | b.gt outside // Si no esta dentro, no pinto 83 | 84 | bl pintar_pixel // Si estoy dentro, pinto el pixel (x1 , x2) 85 | 86 | outside: 87 | // Devolvemos los valores previos del stack 88 | LDR x13, [SP, 0] 89 | LDR x14, [SP, 8] 90 | LDR x15, [SP, 16] 91 | LDR x30, [SP, 24] 92 | ADD SP, SP, 32 93 | ret 94 | 95 | dibujar_circulo: 96 | // Circulo de radio r centrado en (x0 , y0) 97 | // Parametros: 98 | // x3 -> r 99 | // (x4 , x5) -> (x0 , y0) 100 | // x10 -> Color 101 | 102 | // Guardamos los valores previos en el stack 103 | SUB SP, SP, 56 104 | STUR x30, [SP, 48] 105 | STUR x9, [SP, 40] 106 | STUR x8, [SP, 32] 107 | STUR x7, [SP, 24] 108 | STUR x6, [SP, 16] 109 | STUR x2, [SP, 8] 110 | STUR x1, [SP, 0] 111 | 112 | // Calculamos el tamaño del lado del minimo cuadrado que contiene el circulo 113 | add x6, x3, x3 // x6 -> r + r 114 | 115 | subs x1, x4, x3 // x1 -> x0 - r 116 | b.lt set_x1_to_0 // Si da negativo entonces x1 tiene que ser 0 117 | b skip_x1 118 | 119 | set_x1_to_0: 120 | add x1, xzr, xzr // x1 -> 0 121 | skip_x1: 122 | subs x2, x5, x3 // x2 -> y0 - r 123 | b.lt set_x2_to_0 // Si da negativo entonces x2 tiene que ser 0 124 | b skip_x2 125 | set_x2_to_0: 126 | add x2, xzr, xzr // x2 -> 0 127 | skip_x2: 128 | 129 | mov x7, x1 // x7 -> x1 130 | mov x9, x6 // x9 -> x6 131 | 132 | // Ahora recorro todo el cuadrado que contiene el circulo y solo pinto los pixeles que pertenecen a el. 133 | loop_1: 134 | cbz x9, endloop_1 135 | cmp x2, SCREEN_HEIGH 136 | b.ge endloop_1 137 | mov x1, x7 138 | mov x8, x6 139 | loop_0: 140 | cbz x8, endloop_0 141 | cmp x1, SCREEN_WIDTH 142 | b.ge endloop_0 143 | bl si_pixel_en_circulo_pintar 144 | add x1, x1, 1 145 | sub x8, x8, 1 146 | b loop_0 147 | 148 | endloop_0: 149 | add x2, x2, 1 150 | sub x9, x9, 1 151 | b loop_1 152 | 153 | endloop_1: 154 | // Devolvemos los valores previos del stack 155 | LDR x1, [SP, 0] 156 | LDR x2, [SP, 8] 157 | LDR x6, [SP, 16] 158 | LDR x7, [SP, 24] 159 | LDR x8, [SP, 32] 160 | LDR x9, [SP, 40] 161 | LDR x30, [SP, 48] 162 | ADD SP, SP, 56 163 | ret 164 | 165 | dibujar_cuadrado: 166 | // Parametros: 167 | // w10 -> Color 168 | // x1 -> Ancho 169 | // x2 -> Alto 170 | // x3 -> Pixel X 171 | // x4 -> Pixel Y 172 | 173 | // Guardamos los valores previos en el stack 174 | SUB SP, SP, 40 175 | STUR x30, [SP, 32] 176 | STUR x13, [SP, 24] 177 | STUR x12, [SP, 16] 178 | STUR x11, [SP, 8] 179 | STUR x9, [SP, 0] 180 | 181 | BL calcular_pixel // Calculamos la direccion del pixel a dibujar 182 | 183 | mov x9, x2 // x9 = x2 --> A x9 le guardamos el alto del cuadrado 184 | mov x13, x0 // x13 = x0 --> A x13 le guardamos la direccion calculada 185 | pintar_cuadrado: 186 | mov x11, x1 // x11 = x1 --> A x11 le asignamos el ancho del cuadrado 187 | mov x12, x13 // x12 = x13 --> A x12 le guardamos x13, el pixel inicial de la fila 188 | color_cuadrado: 189 | stur w10, [x13] // Memory[x13] = w10 -> A x13 le asignamos en memoria el color que respresenta w10 190 | add x13, x13, 4 // w13 = w13 + 4 -> x13 se mueve un pixel hacia la derecha 191 | sub x11, x11, 1 // w11 = w11 - 1 -> x11 le restamos un pixel de ancho 192 | cbnz x11, color_cuadrado // Si x11 no es 0, entonces la fila no se termino de pintar. Seguimos pintandola 193 | mov x13, x12 // Terminamos de pintar la fila. x13 = x12. Volvemos al pixel de origen de la fila (el mas a la izq) 194 | add x13, x13, 2560 // x13 = x13 + 2560. Al sumarle 2560 damos un salto de linea (640 * 4) 195 | sub x9, x9, 1 // x9 = x9 - 1 -> Le restamos 1 al alto de la fila 196 | cbnz x9, pintar_cuadrado // Si el alto no es 0, es porque aún no se termino de pintar 197 | 198 | // Devolvemos los valores previos del stack 199 | LDR x9, [SP, 0] 200 | LDR x11, [SP, 8] 201 | LDR x12, [SP, 16] 202 | LDR x13, [SP, 24] 203 | LDR x30, [SP, 32] 204 | ADD SP, SP, 40 205 | ret 206 | 207 | 208 | dibujar_triangulo: 209 | // Parametros: 210 | // w10 -> Color 211 | // x1 -> Ancho 212 | // x2 -> Cantidad de filas a pintar antes de disminuir en 1 su valor (Altura = x1 * x2) 213 | // x3 -> Pixel X 214 | // x4 -> Pixel Y 215 | 216 | // Guardamos los valores previos en el stack 217 | SUB SP, SP, 48 218 | STUR x30, [SP, 40] 219 | STUR x15, [SP, 32] 220 | STUR x14, [SP, 24] 221 | STUR x13, [SP, 16] 222 | STUR x12, [SP, 8] 223 | STUR x11, [SP, 0] 224 | 225 | BL calcular_pixel // Calculamos la direccion del pixel a dibujar 226 | 227 | mov x13, x0 // x13 = x0 -> A x13 le guardamos la direccion calculada 228 | mov x14, x1 // x14 = x1 -> A x14 le asignamos el ancho de la fila 229 | 230 | pintar_triangulo: 231 | mov x15, x2 // x15 = x2 -> A x15 le asignamos la cantidad de filas a pintar antes de disminuir el ancho de la fila actual 232 | pintar_fila: 233 | mov x11, x14 // x11 = x14 -> A x11 le asignamos el ancho de la fila 234 | mov x12, x13 // x12 = x13 -> A x12 le guardamos x13 (En esta parte de la ejecucción a x12 se le guarda el pixel inicial de la fila) 235 | 236 | color_triangulo: 237 | stur w10, [x13] // Memory[x13] = w10 -> A x13 le asignamos en memoria el color que respresenta w10 238 | add x13, x13, 4 // w13 = w13 + 4 -> x13 se mueve un pixel hacia la derecha 239 | sub x11, x11, 1 // w11 = w11 - 1 -> x11 le restamos un pixel de ancho 240 | cbnz x11, color_triangulo // Si x11 <= 0 (la fila no se termino de pintar), seguimos pintandola 241 | 242 | mov x13, x12 // En esta parte, ya se termino de pintar la fila. x13 = x12. Volvemos al pixel de origen de la fila 243 | add x13, x13, 2560 // Pasamos a la siguiente fila 244 | sub x15, x15, 1 // x15 = x15 - 1. Le restamos 1 a x15 para pintar al siguiente fila del mismo ancho que la anterior 245 | cbnz x15, pintar_fila 246 | 247 | mov x13, x12 // En esta parte, ya se termino de pintar la fila. x13 = x12. Volvemos al pixel de origen de la fila 248 | add x13, x13, 2564 // x13 = x13 + 2562. La constante 2560 es el total de pixeles de una fila, el numero 4 que se suma a 2560 sirve para movernos 249 | // 1 pixel (4 posiciones) hacia la derecha. entonces si lo sumamos es como dar un salto de linea movido 1 pixeles a la derecha 250 | sub x14, x14, 2 // x14 = x14 - 2. A x14 le restamos 2 para disminuir el ancho de la siguiente fila en 1 pixel 251 | cbnz x14, pintar_triangulo 252 | 253 | // Devolvemos los valores previos del stack 254 | LDR x11, [SP, 0] 255 | LDR x12, [SP, 8] 256 | LDR x13, [SP, 16] 257 | LDR x14, [SP, 24] 258 | LDR x15, [SP, 32] 259 | LDR x30, [SP, 40] 260 | ADD SP, SP, 48 261 | ret 262 | 263 | funcion_delay: 264 | // Parametros: 265 | // x8 -> Duración DELAY. 266 | 267 | // Guardamos los valores previos en el stack 268 | SUB SP, SP, 8 269 | STUR x9, [SP, 0] 270 | 271 | mov x9, x8 // Inicializo x9 con x8. 272 | delay: 273 | sub x9, x9, 1 274 | cbnz x9, delay 275 | 276 | // Devolvemos los valores previos del stack 277 | LDR x9, [SP, 0] 278 | ADD SP, SP, 8 279 | ret 280 | 281 | 282 | //------------------ Fin Funciones Basicas ------------------ 283 | 284 | //------------------ Inicio Funciones Dibujo ------------------ 285 | 286 | cohete: 287 | // Guardamos los valores previos en el stack 288 | SUB SP, SP, 8 289 | STUR X30, [SP, 0] 290 | 291 | // Dibujo cohete 292 | movz w10, 0x5B, lsl 16 // Color cohete 293 | movk w10, 0x5B5B, lsl 0 294 | mov x1, 130 // x1 -> Ancho 295 | mov x2, 250 // x2 -> Alto 296 | mov x3, 140 // x3 -> Pixel X 297 | mov x4, 100 // x4 -> Pixel Y 298 | BL dibujar_cuadrado 299 | 300 | // Devolvemos los valores previos del stack 301 | LDR X30, [SP, 0] 302 | ADD SP, SP, 8 303 | ret 304 | 305 | 306 | cabeza_cohete: 307 | // Guardamos los valores previos en el stack 308 | SUB SP, SP, 8 309 | STUR X30, [SP, 0] 310 | 311 | movz w10, 0xFE, lsl 16 // Color Cabeza cohete 312 | movk w10, 0x0000, lsl 0 313 | 314 | // Cabeza cohete 315 | mov x1, 113 // x1 -> Ancho 316 | mov x2, 20 // x2 -> Alto 317 | mov x3, 150 // x3 -> Pixel X 318 | mov x4, 80 // x4 -> Pixel Y 319 | BL dibujar_cuadrado 320 | 321 | mov x1, 90 // x1 -> Ancho 322 | mov x2, 20 // x2 -> Alto 323 | mov x3, 162 // x3 -> Pixel X 324 | mov x4, 60 // x4 -> Pixel Y 325 | BL dibujar_cuadrado 326 | 327 | mov x1, 60 // x1 -> Ancho 328 | mov x2, 20 // x2 -> Alto 329 | mov x3, 177 // x3 -> Pixel X 330 | mov x4, 40 // x4 -> Pixel Y 331 | BL dibujar_cuadrado 332 | 333 | // Devolvemos los valores previos del stack 334 | LDR X30, [SP, 0] 335 | ADD SP, SP, 8 336 | ret 337 | 338 | 339 | luces: 340 | // Guardamos los valores previos en el stack 341 | SUB SP, SP, 8 342 | STUR X30, [SP, 0] 343 | 344 | 345 | // Luz arriba derecha 346 | movz w10, 0xEA, lsl 16 347 | movk w10, 0xEA00, lsl 0 348 | mov x1, 10 349 | mov x2, 10 350 | mov x3, 250 351 | mov x4, 175 352 | BL dibujar_cuadrado 353 | 354 | movz w10, 0xEA, lsl 16 355 | movk w10, 0x0000, lsl 0 356 | mov x1, 5 357 | mov x2, 5 358 | mov x3, 255 359 | mov x4, 175 360 | BL dibujar_cuadrado 361 | 362 | 363 | // Luz abajo derecha 364 | movz w10, 0xEA, lsl 16 365 | movk w10, 0xEA00, lsl 0 366 | mov x1, 10 367 | mov x2, 10 368 | mov x3, 250 369 | mov x4, 250 370 | BL dibujar_cuadrado 371 | 372 | movz w10, 0xEA, lsl 16 373 | movk w10, 0x0000, lsl 0 374 | mov x1, 5 375 | mov x2, 5 376 | mov x3, 255 377 | mov x4, 250 378 | BL dibujar_cuadrado 379 | 380 | // Luz abajo izquierda 381 | movz w10, 0xEA, lsl 16 382 | movk w10, 0xEA00, lsl 0 383 | mov x1, 10 384 | mov x2, 10 385 | mov x3, 150 386 | mov x4, 250 387 | BL dibujar_cuadrado 388 | 389 | movz w10, 0xEA, lsl 16 390 | movk w10, 0x0000, lsl 0 391 | mov x1, 5 392 | mov x2, 5 393 | mov x3, 150 394 | mov x4, 250 395 | BL dibujar_cuadrado 396 | 397 | // Luz arriba izquierda 398 | movz w10, 0xEA, lsl 16 399 | movk w10, 0xEA00, lsl 0 400 | mov x1, 10 401 | mov x2, 10 402 | mov x3, 150 403 | mov x4, 175 404 | BL dibujar_cuadrado 405 | 406 | movz w10, 0xEA, lsl 16 407 | movk w10, 0x0000, lsl 0 408 | mov x1, 5 409 | mov x2, 5 410 | mov x3, 150 411 | mov x4, 175 412 | BL dibujar_cuadrado 413 | 414 | // Devolvemos los valores previos del stack 415 | LDR X30, [SP, 0] 416 | ADD SP, SP, 8 417 | ret 418 | 419 | 420 | ventanillas: 421 | // Guardamos los valores previos en el stack 422 | SUB SP, SP, 8 423 | STUR X30, [SP, 0] 424 | 425 | // Ventanilla 1 426 | movz w10, 0x00, lsl 16 427 | movk w10, 0xEAE0, lsl 0 428 | mov x1, 30 429 | mov x2, 40 430 | mov x3, 190 431 | mov x4, 120 432 | BL dibujar_cuadrado 433 | 434 | movz w10, 0x00, lsl 16 435 | movk w10, 0x32EA, lsl 0 436 | mov x1, 20 437 | mov x2, 20 438 | mov x3, 190 439 | mov x4, 120 440 | BL dibujar_cuadrado 441 | 442 | // Ventanilla 2 443 | movz w10, 0x00, lsl 16 444 | movk w10, 0xEAE0, lsl 0 445 | mov x1, 30 446 | mov x2, 40 447 | mov x3, 190 448 | mov x4, 200 449 | BL dibujar_cuadrado 450 | 451 | movz w10, 0x00, lsl 16 452 | movk w10, 0x32EA, lsl 0 453 | mov x1, 20 454 | mov x2, 20 455 | mov x3, 200 456 | mov x4, 200 457 | BL dibujar_cuadrado 458 | 459 | // Ventanilla 3 460 | movz w10, 0x00, lsl 16 461 | movk w10, 0xEAE0, lsl 0 462 | mov x1, 30 463 | mov x2, 40 464 | mov x3, 190 465 | mov x4, 280 466 | BL dibujar_cuadrado 467 | 468 | movz w10, 0x00, lsl 16 469 | movk w10, 0x32EA, lsl 0 470 | mov x1, 20 471 | mov x2, 20 472 | mov x3, 190 473 | mov x4, 300 474 | BL dibujar_cuadrado 475 | 476 | // Devolvemos los valores previos del stack 477 | LDR X30, [SP, 0] 478 | ADD SP, SP, 8 479 | ret 480 | 481 | 482 | propulsores: 483 | // Guardamos los valores previos en el stack 484 | SUB SP, SP, 8 485 | STUR X30, [SP, 0] 486 | 487 | // Propulsor 1 488 | movz w10, 0xEA, lsl 16 489 | movk w10, 0xE000, lsl 00 490 | mov x1, 30 491 | mov x2, 3 492 | mov x3, 150 493 | mov x4, 350 494 | BL dibujar_triangulo 495 | 496 | movz w10, 0xFC, lsl 16 497 | movk w10, 0x0000, lsl 00 498 | mov x1, 30 499 | mov x2, 2 500 | mov x3, 150 501 | mov x4, 350 502 | BL dibujar_triangulo 503 | 504 | 505 | // Propulsor 2 506 | movz w10, 0xEA, lsl 16 507 | movk w10, 0xE000, lsl 00 508 | mov x1, 30 509 | mov x2, 3 510 | mov x3, 190 511 | mov x4, 350 512 | BL dibujar_triangulo 513 | 514 | movz w10, 0xFC, lsl 16 515 | movk w10, 0x0000, lsl 00 516 | mov x1, 30 517 | mov x2, 2 518 | mov x3, 190 519 | mov x4, 350 520 | BL dibujar_triangulo 521 | 522 | // Propulsor 3 523 | movz w10, 0xEA, lsl 16 524 | movk w10, 0xE000, lsl 00 525 | mov x1, 30 526 | mov x2, 3 527 | mov x3, 230 528 | mov x4, 350 529 | BL dibujar_triangulo 530 | 531 | movz w10, 0xFC, lsl 16 532 | movk w10, 0x0000, lsl 00 533 | mov x1, 30 534 | mov x2, 2 535 | mov x3, 230 536 | mov x4, 350 537 | BL dibujar_triangulo 538 | 539 | // Devolvemos los valores previos del stack 540 | LDR X30, [SP, 0] 541 | ADD SP, SP, 8 542 | ret 543 | 544 | 545 | estrellas: 546 | // Guardamos los valores previos en el stack 547 | SUB SP, SP, 8 548 | STUR X30, [SP, 0] 549 | 550 | movz w10, 0xFF, lsl 16 // Color Estrellas 551 | movk w10, 0xFFFF, lsl 0 552 | 553 | mov x1, 10 554 | mov x2, 10 555 | mov x3, 340 556 | mov x4, 400 557 | BL dibujar_cuadrado 558 | 559 | mov x1, 10 560 | mov x2, 10 561 | mov x3, 370 562 | mov x4, 370 563 | BL dibujar_cuadrado 564 | 565 | mov x1, 10 566 | mov x2, 10 567 | mov x3, 400 568 | mov x4, 320 569 | BL dibujar_cuadrado 570 | 571 | mov x1, 10 572 | mov x2, 10 573 | mov x3, 10 574 | mov x4, 400 575 | BL dibujar_cuadrado 576 | 577 | mov x1, 10 578 | mov x2, 10 579 | mov x3, 10 580 | mov x4, 90 581 | BL dibujar_cuadrado 582 | 583 | mov x1, 10 584 | mov x2, 10 585 | mov x3, 75 586 | mov x4, 120 587 | BL dibujar_cuadrado 588 | 589 | mov x1, 10 590 | mov x2, 10 591 | mov x3, 550 592 | mov x4, 120 593 | BL dibujar_cuadrado 594 | 595 | mov x1, 10 596 | mov x2, 10 597 | mov x3, 600 598 | mov x4, 470 599 | BL dibujar_cuadrado 600 | 601 | mov x1, 10 602 | mov x2, 10 603 | mov x3, 500 604 | mov x4, 50 605 | BL dibujar_cuadrado 606 | 607 | mov x1, 10 608 | mov x2, 10 609 | mov x3, 560 610 | mov x4, 230 611 | BL dibujar_cuadrado 612 | 613 | mov x1, 10 614 | mov x2, 10 615 | mov x3, 430 616 | mov x4, 60 617 | BL dibujar_cuadrado 618 | 619 | mov x1, 10 620 | mov x2, 10 621 | mov x3, 450 622 | mov x4, 100 623 | BL dibujar_cuadrado 624 | 625 | 626 | mov x1, 10 627 | mov x2, 10 628 | mov x3, 380 629 | mov x4, 210 630 | BL dibujar_cuadrado 631 | 632 | // Devolvemos los valores previos del stack 633 | LDR X30, [SP, 0] 634 | ADD SP, SP, 8 635 | ret 636 | 637 | 638 | luna: 639 | // Guardamos los valores previos en el stack 640 | SUB SP, SP, 8 641 | STUR X30, [SP, 0] 642 | 643 | movz w10, 0xFF, lsl 16 // Color Luna 644 | movk w10, 0xFFFF, lsl 0 645 | 646 | mov x1, 70 647 | mov x2, 70 648 | mov x3, 500 649 | mov x4, 120 650 | BL dibujar_cuadrado 651 | 652 | 653 | movz w10, 0x95, lsl 16 // Color Craters 654 | movk w10, 0x9595, lsl 0 655 | 656 | mov x1, 15 657 | mov x2, 15 658 | mov x3, 510 659 | mov x4, 155 660 | BL dibujar_cuadrado 661 | 662 | mov x1, 20 663 | mov x2, 20 664 | mov x3, 540 665 | mov x4, 125 666 | BL dibujar_cuadrado 667 | 668 | // Devolvemos los valores previos del stack 669 | LDR X30, [SP, 0] 670 | ADD SP, SP, 8 671 | ret 672 | 673 | bigLuna: 674 | // Guardamos los valores previos en el stack 675 | SUB SP, SP, 8 676 | STUR X30, [SP, 0] 677 | 678 | // Luna 679 | movz w10, 0xFF, lsl 16 // w10 -> Color Luna 680 | movk w10, 0xFFFF, lsl 00 681 | mov x3, 80 // x3 -> Radio 682 | mov x4, 535 // x4 -> x0 683 | mov x5, 175 // x4 -> y0 684 | BL dibujar_circulo 685 | 686 | // Craters 687 | movz w10, 0x95, lsl 16 // w10 -> Color Craters 688 | movk w10, 0x9595, lsl 0 689 | 690 | mov x3, 8 // x3 -> Radio 691 | mov x4, 518 // x4 -> x0 692 | mov x5, 163 // x5 -> y0 693 | BL dibujar_circulo 694 | 695 | mov x3, 10 // x3 -> Radio 696 | mov x4, 550 // x4 -> x0 697 | mov x5, 135 // x5 -> y0 698 | BL dibujar_circulo 699 | 700 | // Devolvemos los valores previos del stack 701 | LDR X30, [SP, 0] 702 | ADD SP, SP, 8 703 | ret 704 | 705 | 706 | pintar_fondo: 707 | // Guardamos los valores previos en el stack 708 | SUB SP, SP, 8 709 | STUR X30, [SP, 0] 710 | 711 | movz w10, 0x16, lsl 16 // w10 -> Color Fondo 712 | movk w10, 0x16, lsl 00 713 | 714 | mov x1, SCREEN_WIDTH 715 | mov x2, SCREEN_HEIGH 716 | mov x3, 0 717 | mov x4, 0 718 | BL dibujar_cuadrado 719 | 720 | // Devolvemos los valores previos del stack 721 | LDR X30, [SP, 0] 722 | ADD SP, SP, 8 723 | ret 724 | 725 | //------------------ Fin Funciones Dibujo ------------------ 726 | -------------------------------------------------------------------------------- /lab/ejercicio2/funciones.s: -------------------------------------------------------------------------------- 1 | .equ SCREEN_WIDTH, 640 2 | .equ SCREEN_HEIGH, 480 3 | 4 | //------------------ Inicio Funciones Basicas ------------------ 5 | 6 | calcular_pixel: 7 | // Parametros: 8 | // x3 -> Pixel X 9 | // x4 -> Pixel Y 10 | // Return x0 -> Posición (x,y) en la imagen 11 | 12 | mov x0, SCREEN_WIDTH // x0 = 640 13 | mul x0, x0, x4 // x0 = 640 * y 14 | add x0, x0, x3 // x0 = (640 * y) + x 15 | lsl x0, x0, 2 // x0 = ((640 * y) + x) * 4 16 | add x0, x0, x20 // x0 = ((640 * y) + x) * 4 + A[0] 17 | ret 18 | 19 | pintar_pixel: 20 | // Parametros: 21 | // x1 -> Pixel X 22 | // x2 -> Pixel Y 23 | // x10 -> Color 24 | 25 | // Guardamos los valores previos en el stack 26 | SUB SP, SP, 24 27 | STUR x30, [SP, 16] 28 | STUR x3, [SP, 8] 29 | STUR x4, [SP, 0] 30 | 31 | // Chequeamos que las coordenadas esten dentro de la pantalla, si no lo estan, no pintamos 32 | cmp x1, SCREEN_WIDTH 33 | b.ge no_paint // x1 >= 640 34 | 35 | cmp x2, SCREEN_HEIGH 36 | b.ge no_paint // x2 >= 480 37 | 38 | mov x3, x1 // x3 -> Pixel X 39 | mov x4, x2 // x4 -> Pixel Y 40 | 41 | BL calcular_pixel // Calculamos la direccion del pixel a pintar 42 | 43 | stur w10, [x0] // Pintamos el Pixel 44 | 45 | no_paint: 46 | // Devolvemos los valores previos del stack 47 | LDR x4, [SP, 0] 48 | LDR x3, [SP, 8] 49 | LDR x30, [SP, 16] 50 | ADD SP, SP, 24 51 | 52 | ret 53 | 54 | si_pixel_en_circulo_pintar: 55 | // Verificamos si el pixel en la coordenada (x1 , x2) pertenece al circulo. Si pertenece, lo pintamos 56 | // Parametros: 57 | // (x1 , x2) -> Pixel que estamos analizando 58 | // (x4 , x5) -> Pixel centro del circulo 59 | // x3 -> Radio del Circulo 60 | // x10 -> Color 61 | 62 | // Si (x1 - x4)² + (x2 - x5)² ≤ x3² => (x1 , x2) esta dentro del circulo 63 | 64 | // Guardamos los valores previos en el stack 65 | SUB SP, SP, 32 66 | STUR x30, [SP, 24] 67 | STUR x15, [SP, 16] 68 | STUR x14, [SP, 8] 69 | STUR x13, [SP, 0] 70 | 71 | mul x15,x3,x3 // x15 -> r * r 72 | 73 | sub x13, x1, x4 // x13 -> (x1 - x4) 74 | mul x13, x13, x13 // x13 -> (x1 - x4) * (x1 - x4) 75 | 76 | sub x14, x2, x5 // x14 -> (x2 - x5) 77 | mul x14, x14, x14 // x14 -> (x2 - x5) * (x2 - x5) 78 | 79 | add x13, x13, x14 // x13 -> (x1 - x4)² + (x2 - x5)² 80 | 81 | cmp x13, x15 82 | b.gt outside // Si no esta dentro, no pinto 83 | 84 | bl pintar_pixel // Si estoy dentro, pinto el pixel (x1 , x2) 85 | 86 | outside: 87 | // Devolvemos los valores previos del stack 88 | LDR x13, [SP, 0] 89 | LDR x14, [SP, 8] 90 | LDR x15, [SP, 16] 91 | LDR x30, [SP, 24] 92 | ADD SP, SP, 32 93 | ret 94 | 95 | dibujar_circulo: 96 | // Circulo de radio r centrado en (x0 , y0) 97 | // Parametros: 98 | // x3 -> r 99 | // (x4 , x5) -> (x0 , y0) 100 | // x10 -> Color 101 | 102 | // Guardamos los valores previos en el stack 103 | SUB SP, SP, 56 104 | STUR x30, [SP, 48] 105 | STUR x9, [SP, 40] 106 | STUR x8, [SP, 32] 107 | STUR x7, [SP, 24] 108 | STUR x6, [SP, 16] 109 | STUR x2, [SP, 8] 110 | STUR x1, [SP, 0] 111 | 112 | // Calculamos el tamaño del lado del minimo cuadrado que contiene el circulo 113 | add x6, x3, x3 // x6 -> r + r 114 | 115 | subs x1, x4, x3 // x1 -> x0 - r 116 | b.lt set_x1_to_0 // Si da negativo entonces x1 tiene que ser 0 117 | b skip_x1 118 | 119 | set_x1_to_0: 120 | add x1, xzr, xzr // x1 -> 0 121 | skip_x1: 122 | subs x2, x5, x3 // x2 -> y0 - r 123 | b.lt set_x2_to_0 // Si da negativo entonces x2 tiene que ser 0 124 | b skip_x2 125 | set_x2_to_0: 126 | add x2, xzr, xzr // x2 -> 0 127 | skip_x2: 128 | 129 | mov x7, x1 // x7 -> x1 130 | mov x9, x6 // x9 -> x6 131 | 132 | // Ahora recorro todo el cuadrado que contiene el circulo y solo pinto los pixeles que pertenecen a el. 133 | loop_1: 134 | cbz x9, endloop_1 135 | cmp x2, SCREEN_HEIGH 136 | b.ge endloop_1 137 | mov x1, x7 138 | mov x8, x6 139 | loop_0: 140 | cbz x8, endloop_0 141 | cmp x1, SCREEN_WIDTH 142 | b.ge endloop_0 143 | bl si_pixel_en_circulo_pintar 144 | add x1, x1, 1 145 | sub x8, x8, 1 146 | b loop_0 147 | 148 | endloop_0: 149 | add x2, x2, 1 150 | sub x9, x9, 1 151 | b loop_1 152 | 153 | endloop_1: 154 | // Devolvemos los valores previos del stack 155 | LDR x1, [SP, 0] 156 | LDR x2, [SP, 8] 157 | LDR x6, [SP, 16] 158 | LDR x7, [SP, 24] 159 | LDR x8, [SP, 32] 160 | LDR x9, [SP, 40] 161 | LDR x30, [SP, 48] 162 | ADD SP, SP, 56 163 | ret 164 | 165 | dibujar_cuadrado: 166 | // Parametros: 167 | // w10 -> Color 168 | // x1 -> Ancho 169 | // x2 -> Alto 170 | // x3 -> Pixel X 171 | // x4 -> Pixel Y 172 | 173 | // Guardamos los valores previos en el stack 174 | SUB SP, SP, 40 175 | STUR x30, [SP, 32] 176 | STUR x13, [SP, 24] 177 | STUR x12, [SP, 16] 178 | STUR x11, [SP, 8] 179 | STUR x9, [SP, 0] 180 | 181 | BL calcular_pixel // Calculamos la direccion del pixel a dibujar 182 | 183 | mov x9, x2 // x9 = x2 --> A x9 le guardamos el alto del cuadrado 184 | mov x13, x0 // x13 = x0 --> A x13 le guardamos la direccion calculada 185 | pintar_cuadrado: 186 | mov x11, x1 // x11 = x1 --> A x11 le asignamos el ancho del cuadrado 187 | mov x12, x13 // x12 = x13 --> A x12 le guardamos x13, el pixel inicial de la fila 188 | color_cuadrado: 189 | stur w10, [x13] // Memory[x13] = w10 -> A x13 le asignamos en memoria el color que respresenta w10 190 | add x13, x13, 4 // w13 = w13 + 4 -> x13 se mueve un pixel hacia la derecha 191 | sub x11, x11, 1 // w11 = w11 - 1 -> x11 le restamos un pixel de ancho 192 | cbnz x11, color_cuadrado // Si x11 no es 0, entonces la fila no se termino de pintar. Seguimos pintandola 193 | mov x13, x12 // Terminamos de pintar la fila. x13 = x12. Volvemos al pixel de origen de la fila (el mas a la izq) 194 | add x13, x13, 2560 // x13 = x13 + 2560. Al sumarle 2560 damos un salto de linea (640 * 4) 195 | sub x9, x9, 1 // x9 = x9 - 1 -> Le restamos 1 al alto de la fila 196 | cbnz x9, pintar_cuadrado // Si el alto no es 0, es porque aún no se termino de pintar 197 | 198 | // Devolvemos los valores previos del stack 199 | LDR x9, [SP, 0] 200 | LDR x11, [SP, 8] 201 | LDR x12, [SP, 16] 202 | LDR x13, [SP, 24] 203 | LDR x30, [SP, 32] 204 | ADD SP, SP, 40 205 | ret 206 | 207 | 208 | dibujar_triangulo: 209 | // Parametros: 210 | // w10 -> Color 211 | // x1 -> Ancho 212 | // x2 -> Cantidad de filas a pintar antes de disminuir en 1 su valor (Altura = x1 * x2) 213 | // x3 -> Pixel X 214 | // x4 -> Pixel Y 215 | 216 | // Guardamos los valores previos en el stack 217 | SUB SP, SP, 48 218 | STUR x30, [SP, 40] 219 | STUR x15, [SP, 32] 220 | STUR x14, [SP, 24] 221 | STUR x13, [SP, 16] 222 | STUR x12, [SP, 8] 223 | STUR x11, [SP, 0] 224 | 225 | BL calcular_pixel // Calculamos la direccion del pixel a dibujar 226 | 227 | mov x13, x0 // x13 = x0 -> A x13 le guardamos la direccion calculada 228 | mov x14, x1 // x14 = x1 -> A x14 le asignamos el ancho de la fila 229 | 230 | pintar_triangulo: 231 | mov x15, x2 // x15 = x2 -> A x15 le asignamos la cantidad de filas a pintar antes de disminuir el ancho de la fila actual 232 | pintar_fila: 233 | mov x11, x14 // x11 = x14 -> A x11 le asignamos el ancho de la fila 234 | mov x12, x13 // x12 = x13 -> A x12 le guardamos x13 (En esta parte de la ejecucción a x12 se le guarda el pixel inicial de la fila) 235 | 236 | color_triangulo: 237 | stur w10, [x13] // Memory[x13] = w10 -> A x13 le asignamos en memoria el color que respresenta w10 238 | add x13, x13, 4 // w13 = w13 + 4 -> x13 se mueve un pixel hacia la derecha 239 | sub x11, x11, 1 // w11 = w11 - 1 -> x11 le restamos un pixel de ancho 240 | cbnz x11, color_triangulo // Si x11 <= 0 (la fila no se termino de pintar), seguimos pintandola 241 | 242 | mov x13, x12 // En esta parte, ya se termino de pintar la fila. x13 = x12. Volvemos al pixel de origen de la fila 243 | add x13, x13, 2560 // Pasamos a la siguiente fila 244 | sub x15, x15, 1 // x15 = x15 - 1. Le restamos 1 a x15 para pintar al siguiente fila del mismo ancho que la anterior 245 | cbnz x15, pintar_fila 246 | 247 | mov x13, x12 // En esta parte, ya se termino de pintar la fila. x13 = x12. Volvemos al pixel de origen de la fila 248 | add x13, x13, 2564 // x13 = x13 + 2562. La constante 2560 es el total de pixeles de una fila, el numero 4 que se suma a 2560 sirve para movernos 249 | // 1 pixel (4 posiciones) hacia la derecha. entonces si lo sumamos es como dar un salto de linea movido 1 pixeles a la derecha 250 | sub x14, x14, 2 // x14 = x14 - 2. A x14 le restamos 2 para disminuir el ancho de la siguiente fila en 1 pixel 251 | cbnz x14, pintar_triangulo 252 | 253 | // Devolvemos los valores previos del stack 254 | LDR x11, [SP, 0] 255 | LDR x12, [SP, 8] 256 | LDR x13, [SP, 16] 257 | LDR x14, [SP, 24] 258 | LDR x15, [SP, 32] 259 | LDR x30, [SP, 40] 260 | ADD SP, SP, 48 261 | ret 262 | 263 | funcion_delay: 264 | // Parametros: 265 | // x8 -> Duración DELAY. 266 | 267 | // Guardamos los valores previos en el stack 268 | SUB SP, SP, 8 269 | STUR x9, [SP, 0] 270 | 271 | mov x9, x8 // Inicializo x9 con x8. 272 | delay: 273 | sub x9, x9, 1 274 | cbnz x9, delay 275 | 276 | // Devolvemos los valores previos del stack 277 | LDR x9, [SP, 0] 278 | ADD SP, SP, 8 279 | ret 280 | 281 | 282 | //------------------ Fin Funciones Basicas ------------------ 283 | 284 | //------------------ Inicio Funciones Dibujo ------------------ 285 | 286 | pintar_luna: 287 | 288 | // Guardamos los valores previos en el stack 289 | SUB SP, SP, 8 290 | STUR X30, [SP, 0] 291 | 292 | // Luna 293 | movz w10, 0xE0, lsl 16 // w10 -> Color Luna 294 | movk w10, 0xE0E0, lsl 00 295 | mov x3, 90 // x3 -> Radio 296 | mov x4, 535 // x4 -> x0 297 | mov x5, 355 // x5 -> y0 298 | BL dibujar_circulo 299 | 300 | // Craters 301 | movz w10, 0x95, lsl 16 // w10 -> Color Craters 302 | movk w10, 0x9595, lsl 0 303 | mov x3, 15 // x3 -> Radio 304 | mov x4, 560 // x4 -> x0 305 | mov x5, 320 // x5 -> y0 306 | BL dibujar_circulo 307 | 308 | mov x3, 25 // x3 -> Radio 309 | mov x4, 500 // x4 -> x0 310 | mov x5, 340 // x5 -> y0 311 | BL dibujar_circulo 312 | 313 | mov x3, 22 // x3 -> Radio 314 | mov x4, 550 // x4 -> x0 315 | mov x5, 380 // x5 -> y0 316 | BL dibujar_circulo 317 | 318 | // Devolvemos los valores previos del stack 319 | LDR X30, [SP, 0] 320 | ADD SP, SP, 8 321 | ret 322 | 323 | pintar_luna_centrada: 324 | 325 | // Guardamos los valores previos en el stack 326 | SUB SP, SP, 8 327 | STUR X30, [SP, 0] 328 | 329 | // Luna 330 | movz w10, 0xE0, lsl 16 // w10 -> Color Luna 331 | movk w10, 0xE0E0, lsl 00 332 | mov x3, 90 // x3 -> Radio 333 | mov x4, 320 // x4 -> x0 334 | mov x5, 240 // x4 -> y0 335 | BL dibujar_circulo 336 | 337 | // Craters 338 | movz w10, 0x95, lsl 16 // w10 -> Color Craters 339 | movk w10, 0x9595, lsl 0 340 | mov x3, 15 // x3 -> Radio 341 | mov x4, 355 // x4 -> x0 342 | mov x5, 205 // x5 -> y0 343 | BL dibujar_circulo 344 | 345 | mov x3, 25 // x3 -> Radio 346 | mov x4, 285 // x4 -> x0 347 | mov x5, 225 // x5 -> y0 348 | BL dibujar_circulo 349 | 350 | mov x3, 22 // x3 -> Radio 351 | mov x4, 335 // x4 -> x0 352 | mov x5, 265 // x5 -> y0 353 | BL dibujar_circulo 354 | 355 | // Devolvemos los valores previos del stack 356 | LDR X30, [SP, 0] 357 | ADD SP, SP, 8 358 | ret 359 | 360 | pintar_fondo: 361 | 362 | // Guardamos los valores previos en el stack 363 | SUB SP, SP, 8 364 | STUR X30, [SP, 0] 365 | 366 | movz w10, 0x16, lsl 16 // w10 -> Color Fondo 367 | movk w10, 0x16, lsl 00 368 | mov x1, SCREEN_WIDTH // x1 -> Ancho 369 | mov x2, SCREEN_HEIGH // x2 -> Alto 370 | mov x3, 0 // x3 -> Pixel X 371 | mov x4, 0 // x4 -> Pixel Y 372 | BL dibujar_cuadrado 373 | 374 | // Devolvemos los valores previos del stack 375 | LDR X30, [SP, 0] 376 | ADD SP, SP, 8 377 | ret 378 | 379 | pintar_pantalla_carga: 380 | 381 | // Guardamos los valores previos en el stack 382 | SUB SP, SP, 8 383 | STUR X30, [SP, 0] 384 | 385 | movz w10, 0x00, lsl 16 // w10 -> Color Fondo 386 | movk w10, 0x0000, lsl 00 387 | mov x1, SCREEN_WIDTH // x1 -> Ancho 388 | mov x2, SCREEN_HEIGH // x2 -> Alto 389 | mov x3, 0 // x3 -> Pixel X 390 | mov x4, 0 // x4 -> Pixel Y 391 | BL dibujar_cuadrado 392 | 393 | // Devolvemos los valores previos del stack 394 | LDR X30, [SP, 0] 395 | ADD SP, SP, 8 396 | ret 397 | 398 | pintar_bordes: 399 | 400 | // Guardamos los valores previos en el stack 401 | SUB SP, SP, 8 402 | STUR X30, [SP, 0] 403 | 404 | movz w10, 0x16, lsl 16 // w10 -> Color Bordes 405 | movk w10, 0x15, lsl 00 406 | mov x1, SCREEN_WIDTH 407 | mov x2, 1 408 | mov x3, 0 409 | mov x4, 0 410 | BL dibujar_cuadrado 411 | 412 | mov x1, 1 413 | mov x2, SCREEN_HEIGH 414 | mov x3, 0 415 | mov x4, 0 416 | BL dibujar_cuadrado 417 | 418 | mov x1, 1 419 | mov x2, SCREEN_HEIGH 420 | mov x3, 639 421 | mov x4, 0 422 | BL dibujar_cuadrado 423 | 424 | mov x1, SCREEN_WIDTH 425 | mov x2, 1 426 | mov x3, 0 427 | mov x4, 479 428 | BL dibujar_cuadrado 429 | 430 | // Devolvemos los valores previos del stack 431 | LDR X30, [SP, 0] 432 | ADD SP, SP, 8 433 | ret 434 | 435 | pintar_nave: 436 | 437 | // Guardamos los valores previos en el stack 438 | SUB SP, SP, 8 439 | STUR X30, [SP, 0] 440 | 441 | // Base 442 | movz w10, 0xFF, lsl 16 // w10 -> Color Base 443 | movk w10, 0x9933, lsl 00 444 | mov x1, 20 // x1 -> Ancho 445 | mov x2, 5 // x2 -> Alto 446 | mov x3, 50 // x3 -> Pixel X 447 | mov x4, 50 // x4 -> Pixel Y 448 | BL dibujar_cuadrado 449 | 450 | // Capsula 451 | movz w10, 0x00, lsl 16 // w10 -> Color Capsula 452 | movk w10, 0xCCCC, lsl 00 453 | mov x1, 6 // x1 -> Ancho 454 | mov x2, 6 // x2 -> Alto 455 | mov x3, 57 // x3 -> Pixel X 456 | mov x4, 44 // x4 -> Pixel Y 457 | BL dibujar_cuadrado 458 | 459 | // Devolvemos los valores previos del stack 460 | LDR X30, [SP, 0] 461 | ADD SP, SP, 8 462 | ret 463 | 464 | pintar_propulsor: 465 | 466 | // Guardamos los valores previos en el stack 467 | SUB SP, SP, 8 468 | STUR X30, [SP, 0] 469 | 470 | // Propulsor 471 | movz w10, 0xEA, lsl 16 // w10 -> Color Fuego externo 472 | movk w10, 0xE000, lsl 00 473 | mov x1, 10 // x1 -> Ancho 474 | mov x2, 2 // x2 -> Altura = x1 * x2 475 | mov x3, 305 // x3 -> Pixel X 476 | mov x4, 55 // x4 -> Pixel Y 477 | BL dibujar_triangulo 478 | 479 | movz w10, 0xFC, lsl 16 // w10 -> Color Fuego interno 480 | movk w10, 0x0000, lsl 00 481 | mov x1, 6 // x1 -> Ancho 482 | mov x2, 2 // x2 -> Altura = x1 * x2 483 | mov x3, 307 // x3 -> Pixel X 484 | mov x4, 55 // x4 -> Pixel Y 485 | BL dibujar_triangulo 486 | 487 | // Devolvemos los valores previos del stack 488 | LDR X30, [SP, 0] 489 | ADD SP, SP, 8 490 | ret 491 | 492 | pintar_tren_aterrizaje: 493 | 494 | // Guardamos los valores previos en el stack 495 | SUB SP, SP, 8 496 | STUR X30, [SP, 0] 497 | 498 | movz w10, 0x00, lsl 16 // w10 -> Color Patitas 499 | movk w10, 0x0000, lsl 00 500 | 501 | // Pata Izq 502 | mov x1, 2 // x1 -> Ancho 503 | mov x2, 5 // x2 -> Alto 504 | mov x3, 305 // x3 -> Pixel X 505 | mov x4, 151 // x4 -> Pixel Y 506 | BL dibujar_cuadrado 507 | 508 | mov x1, 3 509 | mov x2, 2 510 | mov x3, 303 511 | mov x4, 156 512 | BL dibujar_cuadrado 513 | 514 | // Pata der 515 | mov x1, 2 // x1 -> Ancho 516 | mov x2, 5 // x2 -> Alto 517 | mov x3, 313 // x3 -> Pixel X 518 | mov x4, 151 // x4 -> Pixel Y 519 | BL dibujar_cuadrado 520 | 521 | mov x1, 3 522 | mov x2, 2 523 | mov x3, 314 524 | mov x4, 156 525 | BL dibujar_cuadrado 526 | 527 | // Devolvemos los valores previos del stack 528 | LDR X30, [SP, 0] 529 | ADD SP, SP, 8 530 | ret 531 | 532 | pintar_bandera: 533 | 534 | // Guardamos los valores previos en el stack 535 | SUB SP, SP, 8 536 | STUR X30, [SP, 0] 537 | 538 | // Mastil 539 | movz w10, 0x66, lsl 16 // w10 -> Color Mastil 540 | movk w10, 0x3300, lsl 00 541 | mov x1, 2 // x1 -> Ancho 542 | mov x2, 50 // x2 -> Alto 543 | mov x3, 350 // x3 -> Pixel X 544 | mov x4, 120 // x4 -> Pixel Y 545 | BL dibujar_cuadrado 546 | 547 | // Franjas Azules 548 | movz w10, 0x6C, lsl 16 // w10 -> Color Azul 549 | movk w10, 0xACE4, lsl 00 550 | mov x1, 50 // x1 -> Ancho 551 | mov x2, 30 // x2 -> Alto 552 | mov x3, 350 // x3 -> Pixel X 553 | mov x4, 120 // x4 -> Pixel Y 554 | BL dibujar_cuadrado 555 | 556 | // Franja Blanca 557 | movz w10, 0xFF, lsl 16 // w10 -> Color Blanco 558 | movk w10, 0xFFFF, lsl 00 559 | mov x1, 50 // x1 -> Ancho 560 | mov x2, 10 // x2 -> Alto 561 | mov x3, 350 // x3 -> Pixel X 562 | mov x4, 130 // x4 -> Pixel Y 563 | BL dibujar_cuadrado 564 | 565 | // Sol 566 | movz w10, 0xFF, lsl 16 // w10 -> Color Sol 567 | movk w10, 0xFF00, lsl 00 568 | mov x3, 5 // x3 -> Radio 569 | mov x4, 375 // x4 -> x0 570 | mov x5, 135 // x5 -> y0 571 | BL dibujar_circulo 572 | 573 | // Devolvemos los valores previos del stack 574 | LDR X30, [SP, 0] 575 | ADD SP, SP, 8 576 | ret 577 | 578 | //------------------ Fin Funciones Dibujo ------------------ 579 | 580 | //------------------ Iinicio Funciones Animacion ------------------ 581 | 582 | funcion_mover_elem_der: 583 | // Parametros 584 | // x1 -> Ancho del elemento. 585 | // x2 -> Alto del elemento. 586 | // x25 -> Esquina Superior Izquierda del elemento. 587 | 588 | // Guardamos los valores previos en el stack 589 | SUB SP, SP, 24 590 | STUR x30, [SP, 16] 591 | STUR x25, [SP, 8] 592 | STUR x1, [SP, 0] 593 | 594 | 595 | // Hacemos cuentas nesesarias. 596 | add x22, x1, x1 // x22 -> ancho + ancho 597 | add x22, x22, x22 // x22 -> ancho + ancho + ancho + ancho = ancho * 4 598 | add x25, x25, x22 // x25 = x25 + x1 * 4 599 | sub x25, x25, 4 // x25 = x25 - 4 600 | add x1, x1, 1 // x1 = x1 + 1 601 | BL calcular_pixel 602 | 603 | mov x16, x25 // x16 = x0 -> Inicializo x16 con x0 (Pixel Derecho Superior). 604 | mov x17, x2 // x17 = x2 -> x17 alto del elemento 605 | mover_elemento_der: 606 | mov x18, x1 // x18 = x1 -> Contador de Ancho 607 | mov x19, x16 // x19 = x16 -> Actual Pixel 608 | mover_pixel_der: 609 | mov x21, x19 // x21 = x19 -> guardo en x21 el pixel actual 610 | add x21, x21, 4 // x21 = x21 + 4 -> Me situo en el pixel de la derecha de x21 611 | ldr w5, [x19] // w5 = [x19] -> cargo en w5 el color de x19 612 | str w5, [x21] // pinto el pixel de x21, con el color guardado en w5 613 | sub x18, x18, 1 // Resto 1 al contador de ancho 614 | sub x19, x19, 4 // voy al pixel de la izq de x19 615 | cbnz x18, mover_pixel_der 616 | sub x17, x17, 1 617 | add x16, x16, 2560 618 | cbnz x17, mover_elemento_der 619 | 620 | // Devolvemos los valores previos del stack 621 | LDR x1, [SP, 0] 622 | LDR x25, [SP, 8] 623 | LDR x30, [SP, 16] 624 | ADD SP, SP, 24 625 | ret 626 | 627 | 628 | funcion_mover_elem_izq: 629 | // Parametros 630 | // x1 -> Ancho del elemento. 631 | // x2 -> Alto del elemento. 632 | // x25 -> Esquina Superior Izquierda del elemento. 633 | 634 | // Guardamos los valores previos en el stack 635 | SUB SP, SP, 24 636 | STUR x30, [SP, 16] 637 | STUR x25, [SP, 8] 638 | STUR x1, [SP, 0] 639 | 640 | // Hacemos cuentas nesesarias. 641 | add x1, x1, 1 // x1 = x1 + 1 642 | 643 | mov x16, x25 // x16 = x0 -> Inicializo x16 con x0 (Pixel Superior Izquierdo). 644 | mov x17, x2 // x17 = x2 -> x17 alto del elemento 645 | mover_elemento_izq: 646 | mov x18, x1 // x18 = x1 -> Contador de Ancho 647 | mov x19, x16 // x19 = x16 -> Actual Pixel 648 | mover_pixel_izq: 649 | mov x21, x19 // x21 = x19 -> guardo en x21 el pixel actual 650 | sub x21, x21, 4 // x21 = x21 - 4 -> Me situo en el pixel de la izquierda de x21 651 | ldr w5, [x19] // w5 = [x19] -> cargo en w5 el color de x19 652 | str w5, [x21] // pinto el pixel de x21, con el color guardado en w5 653 | sub x18, x18, 1 // Resto 1 al contador de ancho 654 | add x19, x19, 4 // voy al pixel de la der de x19 655 | cbnz x18, mover_pixel_izq 656 | sub x17, x17, 1 657 | add x16, x16, 2560 658 | cbnz x17, mover_elemento_izq 659 | 660 | // Devolvemos los valores previos del stack 661 | LDR x1, [SP, 0] 662 | LDR x25, [SP, 8] 663 | LDR x30, [SP, 16] 664 | ADD SP, SP, 24 665 | ret 666 | 667 | 668 | funcion_mover_elem_arr: 669 | // Parametros 670 | // x1 -> Ancho del elemento. 671 | // x2 -> Alto del elemento. 672 | // x25 -> Esquina Superior Izquierda del elemento. 673 | 674 | // Guardamos los valores previos en el stack 675 | SUB SP, SP, 24 676 | STUR x30, [SP, 16] 677 | STUR x25, [SP, 8] 678 | STUR x2, [SP, 0] 679 | 680 | // Hacemos cuentas nesesarias. 681 | add x2, x2, 1 // x2 = x2 + 1 682 | 683 | mov x16, x25 // x16 = x0 -> Inicializo x16 con x0 (Pixel Superior Izquierdo). 684 | mov x17, x2 // x17 = x2 -> x17 alto del elemento 685 | mover_elemento_arr: 686 | mov x18, x1 // x18 = x1 -> Contador de Ancho 687 | mov x19, x16 // x19 = x16 -> Actual Pixel 688 | mover_pixel_arr: 689 | mov x21, x19 // x21 = x19 -> guardo en x21 el pixel actual 690 | sub x21, x21, 2560 // x21 = x21 - 2560 -> Me situo en el pixel de arriba de x21 691 | ldr w5, [x19] // w5 = [x19] -> cargo en w5 el color de x19 692 | str w5, [x21] // pinto el pixel de x21, con el color guardado en w5 693 | sub x18, x18, 1 // Resto 1 al contador de ancho 694 | add x19, x19, 4 // voy al pixel de la der de x19 695 | cbnz x18, mover_pixel_arr 696 | sub x17, x17, 1 697 | add x16, x16, 2560 698 | cbnz x17, mover_elemento_arr 699 | 700 | // Devolvemos los valores previos del stack 701 | LDR x2, [SP, 0] 702 | LDR x25, [SP, 8] 703 | LDR x30, [SP, 16] 704 | ADD SP, SP, 24 705 | ret 706 | 707 | funcion_mover_elem_aba: 708 | // Parametros 709 | // x1 -> Ancho del elemento. 710 | // x2 -> Alto del elemento. 711 | // x25 -> Esquina Superior Izquierda del elemento. 712 | 713 | // Guardamos los valores previos en el stack 714 | SUB SP, SP, 24 715 | STUR x30, [SP, 16] 716 | STUR x25, [SP, 8] 717 | STUR x2, [SP, 0] 718 | 719 | // Hacemos cuentas nesesarias. 720 | add x22, x1, x1 // x22 -> ancho + ancho 721 | add x22, x22, x22 // x22 -> ancho + ancho + ancho + ancho = ancho * 4 722 | add x25, x25, x22 // x25 = x25 + x1 * 4 723 | sub x25, x25, 4 // x25 = x25 - 4 724 | 725 | movz x23, 0xA00, lsl 00 // x23 = 2560 726 | mul x24, x2, x23 // x22 -> alto * 2560 727 | add x25, x25, x24 // x25 = x25 + x24 728 | sub x25, x25, 2560 // x25 = x25 - 2560 729 | 730 | add x2, x2, 1 // x2 = x2 + 1 731 | 732 | mov x16, x25 // x16 = x0 -> Inicializo x16 con x0 (Pixel Derecho Inferior). 733 | mov x17, x2 // x17 = x2 -> x17 alto del elemento 734 | mover_elemento_aba: 735 | mov x18, x1 // x18 = x1 -> Contador de Ancho 736 | mov x19, x16 // x3 = x0 -> Actual Pixel 737 | mover_pixel_aba: 738 | mov x21, x19 // x21 = x19 -> guardo en x21 el pixel actual 739 | add x21, x21, 2560 // x21 = x21 + 2560 -> Me situo en el pixel de abajo de x21 740 | ldr w5, [x19] // w5 = [x19] -> cargo en w5 el color de x19 741 | str w5, [x21] // pinto el pixel de x21, con el color guardado en w5 742 | sub x18, x18, 1 // Resto 1 al contador de ancho 743 | sub x19, x19, 4 // voy al pixel de la izq de x19 744 | cbnz x18, mover_pixel_aba 745 | sub x17, x17, 1 746 | sub x16, x16, 2560 747 | cbnz x17, mover_elemento_aba 748 | 749 | // Devolvemos los valores previos del stack 750 | LDR x2, [SP, 0] 751 | LDR x25, [SP, 8] 752 | LDR x30, [SP, 16] 753 | ADD SP, SP, 24 754 | ret 755 | 756 | 757 | //------------------ Fin Funciones Animacion ------------------ 758 | --------------------------------------------------------------------------------