Вектори: індексація за позицією
Вектор — це масив: послідовність чисел, що зберігаються поруч одне з одним у пам'яті. У попередньому уроці ви підсумовували його, переміщуючи вказівник уперед на 4 байти для кожного елемента. Той самий метод працює й тут. Є ще один поширений спосіб дістатися до елемента: за індексом. Індекс — це позиція елемента, що відраховується від початку, де перший елемент має індекс 0, другий має індекс 1, і так далі.
Підсумовування вектора просуванням вказівника
.dataa: .word 5, 10, 15, 20 # чотири елементи.textla t0, a # t0 = адреса ali t1, 4 # t1 = кількість елементів, що залишилисяli t2, 0 # t2 = поточна сумаloop:beq t1, zero, donelw t3, 0(t0) # завантажити поточний елементadd t2, t2, t3 # додати до сумиaddi t0, t0, 4 # перейти до наступного слова (4 байти)addi t1, t1, -1 # на один менше залишилосяj loopdone:mv a0, t2 # вивести суму: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
Цикл виконується так. t0 зберігає адресу a, а t1 зберігає кількість елементів, що залишилися, починаючи з 4. На кожному проході завершує цикл, коли лічильник досягає нуля. завантажує елемент за адресою в t0. додає це значення до поточної суми. просуває вказівник до наступного слова. зменшує лічильник. Після чотирьох проходів (5 + 10 + 15 + 20) done виводить 50. Це той самий шаблон, використаний в уроці про пам'ять, тепер застосований до вектора.
Від індексу до адреси
Індексація обчислює адресу з базового вказівника та позиції: address = base + index * 4. Число 4 — це розмір слова в байтах. Компілятор генерує таке саме обчислення для a[i] у такій мові, як C. Сам індекс ніколи не звертається до пам'яті. Це робить лише обчислена з нього адреса.
slli t5, t3, 2 # t5 = індекс * 4 (розмір слова)add t6, t0, t5 # t6 = адреса element[index]lw t6, 0(t6) # t6 = element[index]
зсуває індекс у t3 вліво на 2 біти, що множить його на 4 (два подвоєння: 2 x 2) — розмір одного слова. Додавання результату до базового вказівника дає адресу element[index]. Цей зсув — той самий метод степенів двійки з уроку арифметики, і це стандартний спосіб масштабування індексу на розмір слова.
a[0]: індекс 0, зсув 0.
i як позиція та адреса, яку ця позиція породжує після того, як масштабує її на 4 і додає до бази. Шістнадцяткові числа — це фактичні адреси, які займає a, коли симулятор запускає цю програму. Мета — передбачити наступну адресу до того, як вона з'явиться. Це дозволяє читати всередині інкрементувального циклу або a[i] у C-подібній мові та уявляти адресу пам'яті, до якої він звертається, замість того щоб сприймати запис як чорну скриньку.Підсумовування вектора за індексом
.dataa: .word 5, 10, 15, 20 # чотири елементи.textla t0, a # t0 = базова адреса ali t1, 4 # t1 = кількість елементівli t2, 0 # t2 = індекс, починається з 0li t3, 0 # t3 = накопичувальна сумаloop:beq t2, t1, doneslli t4, t2, 2 # t4 = індекс * 4 (зміщення в байтах)add t5, t0, t4 # t5 = адреса a[index]lw t5, 0(t5) # t5 = a[index]add t3, t3, t5 # total += a[index]addi t2, t2, 1 # перейти до наступного індексуj loopdone:mv a0, t3 # вивести total: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
Цикл виконується так. t2 — це індекс, починаючи з 0. На кожному проході завершує цикл, коли індекс досягає 4 — кількості елементів, що зберігається в t1. перетворює індекс на байтове зміщення. додає це зміщення до базової адреси в t0, щоб отримати адресу a[index]. завантажує значення, що там зберігається. Це значення додається до поточної суми в t3, а переходить до наступного індексу. Після чотирьох проходів (5 + 10 + 15 + 20) done виводить 50.
Додавання двох векторів, елемент за елементом
.dataa: .word 3, 6, 9, 12 # перший векторb: .word 1, 2, 3, 4 # другий векторc: .space 16 # місце для 4 слів результату.textla t0, a # базова адреса ala t1, b # базова адреса bla t2, c # базова адреса cli t3, 0 # індекс, починається з 0li t4, 4 # кількість елементівli s0, 0 # накопичувальна сумаloop:beq t3, t4, doneslli t5, t3, 2 # зміщення в байтах = індекс * 4add t6, t0, t5 # адреса a[index]lw t6, 0(t6) # значення a[index]add a0, t1, t5 # адреса b[index]lw a0, 0(a0) # значення b[index]add t6, t6, a0 # a[index] + b[index]add a0, t2, t5 # адреса c[index]sw t6, 0(a0) # c[index] = a[index] + b[index]add s0, s0, t6 # total += c[index]addi t3, t3, 1 # перейти до наступного індексуj loopdone:mv a0, s0 # вивести total: 4+8+12+16 = 40li a7, 1ecallli a7, 10ecall
Цикл виконується так. перетворює індекс t3 на байтове зміщення. Додавання його до кожного базового вказівника (t0, t1, t2) дає адреси a[i], b[i] і c[i]. На кожному проході обидва елементи завантажуються, додаються, зберігаються в c і додаються до поточної суми в s0. переходить до наступного індексу, і цикл повторюється, поки всі чотири елементи не буде оброблено.
