Matrices : deux indices, une adresse
Une matrice est une grille de nombres disposés en lignes et en colonnes. Une ligne est une ligne horizontale de la grille, lue de gauche à droite. Une colonne est une ligne verticale de la grille, lue de haut en bas. La mémoire n'a aucune notion de lignes ni de colonnes. C'est une longue suite d'octets, le même genre de vecteur que celui abordé dans la leçon précédente. Pour stocker une matrice, ses lignes et ses colonnes doivent être placées l'une après l'autre dans cette unique suite. Le choix habituel est l'ordre row-major : stocker chaque nombre de la première ligne, puis chaque nombre de la deuxième ligne, et continuer jusqu'à ce que toutes les lignes aient été placées.
Deux indices, une adresse
La position d'un élément dans une matrice est donnée par deux indices : l'indice de ligne, à quelle ligne il appartient, et l'indice de colonne, à quelle colonne il appartient. Le comptage pour les deux commence à 0, de la même manière que les indices fonctionnaient dans la leçon sur les vecteurs. La mémoire contient une seule séquence plate de nombres, donc les deux indices doivent d'abord être combinés en un seul indice aplati : multiplier l'indice de ligne par le nombre de colonnes de la matrice, puis ajouter l'indice de colonne. À partir de là, l'indice aplati devient une adresse d'octet de la même manière que l'indice d'un vecteur : address = base + index * 4.
mul t4, t1, t3 # t4 = index de ligne * nombre de colonnesadd t4, t4, t2 # t4 = cela + indice de colonne (l'indice aplati)slli t4, t4, 2 # t4 = décalage en octets = index * 4add t5, t0, t4 # t5 = adresse de l'élément à cette ligne et colonnelw t5, 0(t5) # t5 = valeur à cette adresse
multiplie l'indice de ligne par le nombre de colonnes. Dans la leçon sur les vecteurs, la multiplication pouvait être effectuée avec un décalage car 4 est une puissance de deux, mais le nombre de colonnes d'une matrice ne l'est généralement pas, donc est utilisé ici au lieu de . L'indice de colonne est ajouté, et le résultat est mis à l'échelle par 4 avec un autre (4 est une puissance de deux, donc un décalage fonctionne encore pour cette partie). Cela produit le décalage en octets de l'élément à la ligne et à la colonne données.
Ligne 0, colonne 0 correspond à l'indice 0.
.data de votre programme et votre propre lecture de celle-ci imposent à cette unique ligne, en utilisant l'arithmétique , et montrée ci-dessus. Une fois que la grille et la ligne aplatie sont comprises comme une seule chose montrée deux fois, le même schéma couvre n'importe quelle grille de données : les rangées de pixels d'une image, un plateau de jeu ou un tableur. Chacun est un tableau, atteint avec une multiplication supplémentaire.Somme d'une matrice
.datam: .word 1, 2, 3, 4, 5, 6, 7, 8, 9 # matrice 3x3, stockée ligne par ligne.textla t0, m # adresse de baseli t1, 3 # nombre de lignesli t2, 3 # nombre de colonnesli t3, 0 # index de ligne courant, commence à 0li s0, 0 # total courantrow_loop:beq t3, t1, row_doneli t4, 0 # index de colonne courant, commence à 0col_loop:beq t4, t2, col_donemul t5, t3, t2 # index de ligne * nombre de colonnesadd t5, t5, t4 # + index de colonne = index aplatislli t5, t5, 2 # décalage en octets = index * 4add t6, t0, t5 # adresse de l'élément à cette ligne et colonnelw t6, 0(t6) # valeur à cette adresseadd s0, s0, t6 # total += élémentaddi t4, t4, 1 # passe à la colonne suivantej col_loopcol_done:addi t3, t3, 1 # passe à la ligne suivantej row_looprow_done:mv a0, s0 # affiche le total : 1+2+...+9 = 45li a7, 1ecallli a7, 10ecall
Deux boucles imbriquées indexent la matrice. La boucle externe sélectionne une ligne et la boucle interne sélectionne une colonne dans cette ligne. multiplie l'indice de ligne par le nombre de colonnes. Ajouter l'indice de colonne et mettre à l'échelle par 4 donne l'adresse de cet élément. La valeur stockée à cette adresse est chargée et ajoutée au total cumulé. Lorsque la boucle interne termine une ligne, la boucle externe passe à la ligne suivante, jusqu'à ce que les 3 lignes aient été traitées.
