8. Arrays and structures


이번 장에서는 Indexing mode for load and store 에 대해 알아본다.
괄호 [r#] 는 r# 이 저장된 주소값을 의미한다.

Array, structure

  • 배열의 asm 코드
int a[100];

in C

.data

.balign 4
a: .skip 400

in assembly 100 x 4 의 공간을 만든다. .skip 지시자: 어셈블러에게 미리 메모리 공간을 할당한다고 지시

  • 구조체의 asm코드
struct my_struct
{
    char f0;
    int f1;
} b;

in C

.balign 4
b: .skip 8

in assembly 왜 char 멤버가 있는데도 8바이트를 할당? C코드에서 Padding 기법 으로 alignment를 하지 않았기 때문이다.

배열 초기화: Indexing modes 사용 안함

for (i = 0; i < 100; i++)
    a[i] = i;
/********** data **********/
.data

.balign 4
a: .skip 400

.balign 4
b: .skip 8

/********** text **********/
.text

.global main
main:
    ldr r1, addr_of_a       /* r1 <- &a , r1은 a의 base 주소 */
    mov r2, #0              /* r2 <- 0 */
loop:
    cmp r2, #100            /* Have we reached 100 yet<- */
    beq end                 /* If so, leave the loop, otherwise continue */
    add r3, r1, r2, LSL #2  /* r3 <- r1 + (r2*4): 배열의 주소 계산, index계산 */
    str r2, [r3]            /* *r3 <- r2 , Addressing modes */
    add r2, r2, #1          /* r2 <- r2 + 1, r2: count 변수 i */
    b loop                  /* Go to the beginning of the loop */
end:
    bx lr
addr_of_a: .word a

addr_of_a: .data영역의 심볼을 .text영역으로 가져온것임. (#3장 참고)

    add r3, r1, r2, LSL #2  /* r3 <- r1 + (r2*4) */

r3는 배열 a의 base주소인 r1에서부터 4byte씩 증가

배열 초기화: Indexing mode를 사용한

ARM instruction set은 위의 asm코드 보다 compact한 방법을 제공한다!
진정한 의미의 indexing mode임

ARM이 제공하는 9개의 인덱싱 모드 형태

1) [Rsource1, #+immediate]
2) [Rsource1, +Rsource2]
3) [Rsource1, +Rsource2, shift_operation #immediate]

4) [Rsource1], #+immediate 
5) [Rsource1], +Rsource2
6) [Rsource1], +Rsource2, shift_operation #immediate

7) [Rsource1, #+immediate]!
8) [Rsource1, +Rsource2]!
9) [Rsource1, +Rsource2, shift_operation #immediate]!

1. Non updating indexing modes

(1) [Rsource1, #+immediate] or [Rsource1, #-immediate]

mov r2, #3          /* r2 ← 3 */
str r2, [r1, #+12]  /* *(r1 + 12) ← r2 */

배열 a의 base 주소 r1으로부터 인덱스[3]에 12byte 직접 접근
immediate 크기는 12비트를 초과할 수 없다.

(2) [Rsource1, +Rsource2] or [Rsource1, -Rsource2]

mov r2, #3          /* r2 ← 3 */  
mov r3, #12         /* r3 ← 12 */  
str r2, [r1, +r3]   /* *(r1 + r3) ← r2 */

offset을 값대신 reg에 있는 값 사용.
offset 값이 큰 경우 유용

(3) [Rsource1, +Rsource2, shift_operation #immediate]

        또는 [Rsource1, -Rsource2, shift_operation #immediate]  
add r3, r1, r2, LSL #2  /* r3 ← r1 + r2*4 */  
str r2, [r3]            /* *r3 ← r2 */

이 방법이 아래와 같은 indexing mode로 compact 해짐

str r2, [r1, +r2, LSL #2]  /* *(r1 + r2*4) ← r2 */

r1 base주소에 r2 x 4 에 해당하는 index에 r2 값 store
주소값을 고정된 상수로 곱할 때 유용

2. Updating indexing modes

순차적으로 접근한다면 매번 base주소에 offset을 계산할 필요가 없다.
no need to compute everytime from the beginning the address of the next item

a) Post-indexing modes

(4) [Rsource1], #+immediate 또는 [Rsource1], #-immediate

loop:  
    cmp r2, #100            /* Have we reached 100 yet? */  
    beq end                 /* If so, leave the loop, otherwise continue */  
    str r2, [r1], #4        /* *r1 ← r2 then r1 ← r1 + 4 */  
    add r2, r2, #1          /* r2 ← r2 + 1 */  
    b loop                  /* Go to the beginning of the loop */  
end:

base 주소 r1자체가 4씩 증가되고 값이 저장됨
먼저 r2를 a[r1]에 저장한 뒤, r1+=4 함.
#뒤에 +는 생략가능?

(5) [Rsource1], +Rsource2 또는 [Rsource1], -Rsource2

(4) 와 동일 #imediate 대신 reg사용

(6) [Rsource1], +Rsource2, shift_operation #immediate

        또는 [Rsource1], -Rsource2, shift_operation #immediate   

(4) 와 동일 #imediate 대신 reg에 shift 연산 사용

b) Pre-indexing modes

! 사용

(7) [Rsource1, #+immediate]! 또는 [Rsource1, #-immediate]!

ldr r2, [r1, #+12]!  /* r1 ← r1 + 12 then r2 ← *r1 */  
add r2, r2, r2       /* r2 ← r2 + r2 */  
str r2, [r1]         /* *r1 ← r2 *

a[3] = a[3] + a[3]
(1) 과 유사해 보임. r1이 저장된다는점이 다름.
(4) 와 다른점은 미리 인덱싱을 한뒤 값을 저장한다는 점.
[]! 를 붙이면 Rsrc1이 저장됨 Updated됨.

(8) [Rsource1, +Rsource2]! 또는 [Rsource1, +Rsource2]!

(7) 과 동일 #imediate 대신 reg사용

(9) [Rsource1, +Rsource2, shift_operation #immediate]!

        또는 [Rsource1, -Rsource2, shift_operation #immediate]!  

(7) 과 동일 #imediate 대신 reg에 shift 연산 사용

pre-indexing 과 post-indexing 차이 확인 (feat. 'sp' operation)

str lr, [sp, #-8]!  /* Pre-index: sp ←  sp - 8; *sp ←  lr */  
... // Code of the function  
ldr lr, [sp], #+8   /* Post-index; lr ←  *sp; sp ←  sp + 8 */  
bx lr

sp를 8바이트 확장 시켜놓고 -> splr값을 저장한다. (pre-index; 미리 인덱싱)
lr*sp 로부터 복구 시켜놓은 뒤 -> sp를 다시 8byte 줄인다. (post-index)

구조체 초기화 with 인덱싱 모드

b.f1 = b.f1 + 7;

in C code

ldr r2, [r1, #+4]!  /* r1 ← r1 + 4 then r2 ← *r1 */  
add r2, r2, #7     /* r2 ← r2 + 7 */  
str r2, [r1]       /* *r1 ← r2 */

in asm code
r1 은 +4byte만큼 증가되어 저장됨.
따라서 r2를 r1에 str 할때 index를 다시 계산 할 필요없음.

results matching ""

    No results matching ""