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를 이해할 때 편리
ST ~ , LD~ : Destination Register가 가리키는 곳 > Parameter Register들을 한꺼번에 Multiple Store할 수 있는 명령어
R9 > R13(SP)으로 대치 : Stack으로 사용 가능하게 해줌
( 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}
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 |