# # Autor(s) : Jordi Ferrer Plana # e-mail : jferrerp@eia.udg.es # Branch : - # # Working Group : Departament d'Electrònica, Informàtica i Automàtica # Project : Examen d'ETIS/ETIG d'Estructura i Tecnologia de Computadors, # 1era convocatòria, any 2004. # Homepage : http://eia.udg.es/etc/ # # Module : Problema 5. Dibuixar pixels i quadrats en una pantalla. # # File : so_2004_pjun_p5.s # Date : 20/06/2004 - 20/06/2004 # # Compiler : Spim 6.3 # Libraries : - # # Notes : - El quadrat que es dibuixa no és ple de dins. # - Es pot executar amb l'Spim si es comenten les linies "sb" # de "dibuixar_pixel" que generen excepció ja que adrecen # a posicions invàlides de memòria (per l'Spim). # - El codi de main és només un exemple de com cridar a # "dibuixar_quadrat". A "dibuixar_pixel" ja se la crida des # de "dibuixar_quadrat". # # ---------------------------------------------------------------------------- # # Copyright (C) 2002-2003, Jordi Ferrer Plana # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # See the GNU General Public License (http://www.gnu.org/copyleft/) # for more details. # # ---------------------------------------------------------------------------- # .text # # void dibuixar_pixel ( X : int, Y : int, R : char, G : char, B : char ); # # NOTES: # En conveni MIPS: # Es pot utilitzar $t0 - $t9 dins la funció sense guardar-los. # Els paràmetres estaran a: # a0: int X # a1: int Y # a2: char R # a3: char G # A partir del 4art estaran a la pila (tot i que és un byte, es # reserva tota una paraula per mantenir-la alineada a "word"): # 0($sp): char B # # No es guardarà res a la pila ja que no cal. # dibuixar_pixel: # Adreça del pixel = Base + ( Y * Amplada + X ) # Adreça del pixel = 0x00200000 + ( Y * 640 * 3 + X * 3 ) # Adreça del pixel = 0x00200000 + ( Y * 640 + X ) * 3 li $t0, 640 # $t0 = Constant 640 mul $t1, $a1, $t0 # $t1 = Y * 640 add $t1, $t1, $a0 # $t1 = Y * 640 + X sll $t0, $t1, 1 # $t0 = ( Y * 640 + X ) * 2 add $t1, $t1, $t0 # $t1 = ( Y * 640 + X ) * 3 li $t0, 0x00200000 # $t0 = Base 0x00200000 add $t1, $t1, $t0 # $t1 = 0x00200000 + ( Y * 640 + X ) * 3 lw $t0, 0($sp) # Paràmetre B de la Pila sb $a2, 0($t1) # Dibuixar R a l'offset +0 sb $a3, 1($t1) # Dibuixar G a l'offset +1 sb $t0, 2($t1) # Dibuixar B a l'offset +2 jr $ra # Retornar a l'invocador de dibuixar_pixel .end .text # # void void dibuixar_quadrat ( X1 : int, Y1 : int, X2 : int, Y2 : int, # R : char, G: char, B : char ); # # NOTES: # En conveni MIPS: # Es pot utilitzar $t0 - $t9 dins una funció sense guardar-los. # Com que s'utilitzen $s0 - $s3 es guarden a pila i es restauren. # Els paràmetres estaran a: # a0: X1 # a1: Y1 # a2: X2 # a3: Y2 # A partir del 4art estaran a la pila (tot i que són bytes, es # reserva tota una paraula per mantenir-la alineada a "word"): # 0($sp): char R # 4($sp): char G # 8($sp): char B # dibuixar_quadrat: subu $sp, $sp, 8 # Establir bloc d'activació de la funció sw $ra, 0($sp) # Guardar adreça de retorn sw $fp, 4($sp) # Guardar el Frame Pointer addi $fp, $sp, 8 # $fp ara apunta a la base dels paràmetres # de dibuixar_quadrat que hi ha a la pila subu $sp, $sp, 16 # Guardar a la pila $s0 - $s3 ja que sw $s0, 0($sp) # es modificaran sw $s1, 4($sp) sw $s2, 8($sp) sw $s3, 12($sp) # $a0 - $a3 cal modificar-los per dibuixar_pixel move $s0, $a0 # $s0 = X1 move $s1, $a1 # $s1 = Y1 move $s2, $a2 # $s2 = X2 move $s3, $a3 # $s3 = Y2 lw $a2, 8($fp) # Paràmetre R de dibuixar_pixel lw $a3, 4($fp) # Paràmetre G de dibuixar_pixel sw $t0, 0($fp) # Paràmetre B de dibuixar_pixel subu $sp, $sp, 4 # Empilar B per dibuixar_pixel sw $t0, 0($sp) # Iterar $a0 de X1 fins a X2 # $a0 ja val X1 HLoop: bgt $a0, $s2, ExitH # Si $a0 > X2 Sortir move $a1, $s1 # Linia horitzontal de sobre (i, Y1) jal dibuixar_pixel move $a1, $s3 jal dibuixar_pixel # Linia horitzontal de sota (i, Y2) addi $a0, $a0, 1 # $a0 = $a0 + 1 j HLoop # Iterar ExitH: # Iterar $a1 de Y1 fins a Y2 move $a1, $s1 # $a1 = Y1 VLoop: bgt $a1, $s3, ExitV # Si $a1 > Y2 Sortir move $a0, $s0 # Linia vertical de l'esquerre (X1, i) jal dibuixar_pixel move $a0, $s2 # Linia vertical de la dreta (X2, i) jal dibuixar_pixel addi $a1, $a1, 1 # $a1 = $1 + 1 j VLoop # Iterar ExitV: addi $sp, $sp, 4 # Desempilar B de la pila # Recuperar $a0 - $a3 amb els valors d'entrada move $a0, $s0 # $a0 = X1 move $a1, $s1 # $a1 = Y1 move $a2, $s2 # $a2 = X2 move $a3, $s3 # $a3 = Y2 lw $s0, 0($sp) # Restaurar $s0 - $s3 inicials lw $s1, 4($sp) lw $s2, 8($sp) lw $s3, 12($sp) addi $sp, $sp, 16 # Desempilar $s0 - $s3 lw $ra, 0($sp) # Restaurar l'adreça de retorn lw $fp, 4($sp) # Restaurar el Frame Pointer addi $sp, $sp, 8 # Eliminar bloc d'activació de la funció jr $ra # Retornar a l'invocador de dibuixar_quadrat .end .text # # Exemple de crida a dibuixar_quadrat: # # dibuixar_quadrat ( 100, 110, 160, 170, 255, 0, 127 ); # main: subu $sp, $sp, 4 # Establir bloc d'activació de la funció sw $ra, 0($sp) # Guardar l'adreça de retorn de main # Quadre primers paràmetres per registre li $a0, 100 # X1 li $a1, 110 # Y1 li $a2, 160 # X2 li $a3, 170 # Y2 subu $sp, $sp, 12 # Empilar els 3 altres paràmetres li $t0, 255 # R sw $t0, 8($sp) li $t0, 0 # G sw $t0, 4($sp) li $t0, 127 # B sw $t0, 0($sp) jal dibuixar_quadrat addi $sp, $sp, 12 # Desempilar els paràmetres lw $ra, 0($sp) # Restaurar l'adreça de retorn addi $sp, $sp, 4 # Eliminar bloc d'activació de la funció jr $ra # Retornar a l'invocador de main (Spim) .end