벡터: 위치별 인덱싱
벡터는 배열입니다. 메모리에서 서로 옆에 저장된 숫자의 연속입니다. 이전 레슨에서는 각 요소마다 포인터를 4바이트씩 앞으로 이동하면서 합계를 구했습니다. 같은 방법이 여기에서도 작동합니다. 요소에 도달하는 또 다른 일반적인 방법이 있습니다. 바로 인덱스로 접근하는 것입니다. 인덱스는 처음부터 센 요소의 위치이며, 첫 번째 요소의 인덱스는 0, 두 번째는 1, 이런 식으로 계속됩니다.
포인터를 이동하며 벡터의 합계 구하기
.dataa: .word 5, 10, 15, 20 # 4개 요소.textla t0, a # t0 = a의 주소li 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에서 시작합니다. 각 반복에서 은 카운트가 0에 도달하면 루프를 끝냅니다. 는 t0에 있는 주소의 요소를 로드합니다. 는 그 값을 누적 합계에 더합니다. 는 포인터를 다음 워드로 진행시킵니다. 은 카운트를 줄입니다. 네 번의 반복 후(5 + 10 + 15 + 20), done은 50을 출력합니다. 이것은 메모리 레슨에서 사용된 것과 같은 패턴이며, 이제 벡터에 적용됩니다.
인덱스에서 주소로
인덱싱은 베이스 포인터와 위치로부터 주소를 계산합니다. address = base + index * 4. 여기서 4는 워드의 크기(바이트)입니다. 컴파일러는 C와 같은 언어에서 a[i]에 대해 이와 동일한 계산을 생성합니다. 인덱스 자체는 메모리에 접근하지 않습니다. 그것으로부터 계산된 주소만이 접근합니다.
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]의 주소가 됩니다. 이 시프트는 산술 레슨에서 다룬 2의 거듭제곱 방법과 같으며, 인덱스를 워드 크기로 스케일링하는 표준 방법입니다.
a[0]: 인덱스 0, 오프셋 0.
i는 위치로서, 그리고 그 위치가 에 의해 4로 스케일링되고 베이스에 더해진 후 생성하는 주소입니다. 16진수 숫자는 시뮬레이터가 이 프로그램을 실행할 때 a가 차지하는 실제 주소입니다. 목표는 다음 주소가 나타나기 전에 그것을 예측하는 것입니다. 그러면 증가하는 루프 안의 이나 C 유사 언어의 a[i]를 읽고, 표기를 블랙박스로 취급하는 대신 그것이 건드리는 메모리 주소를 그려볼 수 있습니다.인덱스로 벡터 합산하기
.dataa: .word 5, 10, 15, 20 # 4개 요소.textla t0, a # t0 = a의 기본 주소li t1, 4 # t1 = 요소 개수li t2, 0 # t2 = 인덱스, 0부터 시작li 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 # 합계 출력: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
루프는 다음과 같이 실행됩니다. t2는 인덱스이며 0에서 시작합니다. 각 반복에서 은 인덱스가 t1에 담긴 요소 수인 4에 도달하면 루프를 끝냅니다. 는 인덱스를 바이트 오프셋으로 변환합니다. 는 그 오프셋을 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 # a의 기준 주소la t1, b # b의 기준 주소la t2, c # c의 기준 주소li t3, 0 # 인덱스, 0에서 시작li 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 # 합계 += c[index]addi t3, t3, 1 # 다음 인덱스로 이동j loopdone:mv a0, s0 # 합계 출력: 4+8+12+16 = 40li a7, 1ecallli a7, 10ecall
루프는 다음과 같이 실행됩니다. 는 인덱스 t3를 바이트 오프셋으로 변환합니다. 그것을 각 베이스 포인터(t0, t1, t2)에 더하면 a[i], b[i], c[i]의 주소가 됩니다. 각 반복에서 두 요소가 모두 로드되고, 더해지고, c에 저장되고, s0의 누적 합계에 더해집니다. 은 다음 인덱스로 진행하고, 네 요소가 모두 처리될 때까지 루프가 반복됩니다.
