임베디드/임베디드 레시피

stack initialization

twoweeks-within 2024. 12. 5. 21:41

Embedded system : Heap, Stack > 전역변수의 Array로 선언되어 있음.

ex) recipe_task에서 사용할 Stack : dword recipe_stack[20000] 
                       공용사용 heap : static uint32 commonMemoryPool[20000]; 

Memory 상에 일단 영역확보 > 어떻게 Handling을 할 것인가 > stack, Heap구분

 Stack, Heap > Bootup 할떄 : 내가 원하는 대로 여러 가지 종류로 선언해서 사용할 수 있음
 
 Linker  > 초기화 되지 않은 (Uninitialized) 전역변수 배열 이라고 알아봄
        : .bss section, 즉 ZI중 하나

값 넣기
Stack : 높은 주소에서 낮은 주소
Heap은: 낮은 주소에서 높은 주소로 쌓임

어떻게 쌓아나가냐
 stack이나 heap이 어떻게 data를 쌓는지 확인하시는 것이 상당히 중요
 >  Stack Back Tracing //. 고급 디버깅의 초석

stack : recipe_stack[200000] 
  > stack limit (가장 늦게쌓임) : recipe_stack[0]
  > stack base (제일 먼저 쌓임) : recipe_stack[199999]

 > debugger랑 연결해서 stack overflow를 이해할 때 편리

 

 

Embedded system : stack, heap

 

 

 

ST ~ , LD~ : Destination Register가 가리키는 곳 > Parameter Register들을 한꺼번에 Multiple Store할 수 있는 명령어
 
 R9 > R13(SP)으로 대치 :  Stack으로 사용 가능하게 해줌

 

 

ARM specification



( Stack )
Ascending stack: 낮은 >높은 주소로 자라는 것 // 일부분
Descending stack: 높은 >낮은 주소로 자라는 것 // 주로 사용
Full :  현재 Stack pointer가 방금 push나 pop을 한 Data를 포함
empty : Full 이 아님

// 빈공간이라는 의미는 아님

// 말그대로 방금 push ,pop 한 값이 있냐없냐
After와 Before :  Stack pointer가 Data를 넣은 후 변하느냐 or 먼저 변하고 SP가 변하느냐

Stack back tracing의 핵심 : Stack Pointer가 특정시점에서 어떻게 update되어 있느냐

 Stack : Multiple register transfer addressing 명령어 > push, pop

ST ( store ) / LD ( load ) : 각각 push냐, pop이냐를 나눌 수 있음.
M : Multiple > 모든 명령어에 들어감

IB : ( Increase Before ) SP를 Data를 넣기 전에 증가 시킨다는 의미
IA : ( Increase After ) SP를 Data를 넣고 난 후에 증가 시킨다는 뜻.
DB : ( Decrease Before ) SP를 Data를 넣기 전에 감소 시킨다는 의미
DA : ( Decrease After ) SP를 Data를 넣고 난 후에 감소 시킨다는 의미

FA : ( Full Ascending ) SP는 유효한 Data를 가르키고 큰 주소 방향으로 늘어난다는 뜻
FD : ( Full Descending ) SP는 유효한 Data를 가르키고 작은 주소 방향으로 늘어난다는 뜻
EA : ( Empty Ascending ) SP는 유효한 Data를 가르키지 않고, 큰 주소 방향으로 늘어난다는 뜻
ED : ( Empty Descending ) SP는 유효한 Data를 가르키지 않고, 작은 주소 방향으로 늘어난다는 뜻이


명령어 r9!, {r0, r1, r5}
  :  R9가 가리키는 곳 > R0, R1, R5를 넣음 > 개수 3개 만큼 R9을 update

 

STMIA r9! {r0, r1, r5} 
R9가 가리키는 곳에 R0, R1, R5를 집어 넣음 >IA :  R9 (SP)을 데이터 먼저 넣고, R9을 나중에 늘려라

 

 

 

STMIA r9! {r0, r1, r5}
Store, R9을 Data를 넣고 Increase
 : R9가 가리키는 곳부터 R0 넣고 R9++, R1넣고 R9++, R5넣고 R9++   
 > IA : R9 > R5가 들어있는 주소보다 하나 더 큰 곳을 가리킴

 >> R9 : Empty >실제 유효한 Data를 품고 있지 않음 , Ascending 큰주소로 쌓임

@ STMEA r9! {r0, r1, r5}와 같은 의미 
// empty 까지 큰주소 방향으로 증가하라

 

 

STMIB r9! {r0, r1, r5}
 : Store, R9를 Increase 후에 Data를 넣고 가라 
( IB ) R9++
하고 R0넣고, R9++하고 R1넣고, R9++하고 R5넣고 넣음
 > 주소가 더 큰 방향,  R9 : 마지막 R5가 들어 있는 곳을 가리키게됨
  >> Full : R9에 실제 유효한 Data를 품고 있음 , Ascending

STMFA r9! {r0, r1, r5}와 같은 의미

 

 

STMDA r9! {r0, r1, r5}
Store ,데이터를 넣고 R9을 Decrease
 원래 R9이 가리키는 주소에 R0 넣고 R9--하고, R1넣고 R9--하고, R5넣고 R-- 하라는 의미
  >  주소가 더 작은 방향으로 Data를 쌓음 > R9 : 마지막 R5가 들어간 곳 보다 하나 더 적은 주소를 가리킴.
 Empty, decreasing

STMED r9! {r0, r1, r5}와 같은 의미

 

STMDB r9! {r0, r1, r5} = STMFD r9!, {r0, r1, r5}

 

 

Store 총정리


Load도 마찬가지

주로 우리가 사용 Stack : Full Descending으로 구현,
 더 낮은 주소로 Stack이 자람 + SP가 가리키는 주소 : Valid한 Data를 품고 있음

 Stack에 Full Descending으로 넣고 빼는 일
ex)
stmfd sp!, {r4-r12,lr} // FD 형식으로 store
ldmfd sp!, {r4-r12,lr}    // FD 형식으로 Load
 sp : R13 stack pointer
 lr : ( Linked Register ) : R14를 의미해요!

Stack Initialize : R13을 엮는 일만 잘하면됨
ex)  Abort mode의 Stack 주소를 R13에 엮어 주기만 하면됨

// R13 : stack pointer의 시작점 이기에

Abort mode로 CPU mode를 바꾸고, Abort stack을 r13에 엮어주는 과정

msr  CPSR_c, #PSR_Abort  

// CPSR : 현재 레지스터 > PSR_Abort // abort 로 전환 > 예외처리 모드
ldr  r13, =abort_stack+Abort_Stack_Size

              // 시작주소 + 크기 == 끝주소 

 > r13에 엮인 주소부터 push, pop

 Stack관련한 명령어 : ARM sate <차이> Thumb state
ARM state : Stack에 관련된 명령어를 위의 Multiple Register Transfer 명령 사용,
Thumb state : Push/ Pop이라는 명령으로 대신.
 > Thumb state : Stack을 사용하는 자리에 stmfd나 ldmfd 같은 명령어 없음

'임베디드 > 임베디드 레시피' 카테고리의 다른 글

stack 메모리 dump  (0) 2024.12.07
stack : 함수를 불렀을때  (1) 2024.12.06
Stack , Heap  (0) 2024.12.05
struct , packed  (0) 2024.12.05
Pointer  (0) 2024.12.04