일단 이거 부터 읽고 이해해야한다.
그리고 다음 소스를 보자.
.global navilnux_swiHandler
navilnux_swiHandler:
1; stmfd sp!,{r0-r12,r14}
2; mrs r1,spsr
3; stmfd sp!,{r1}
4; bl swiHandler
5; ldmfd sp!,{r1}
6; msr spsr_cxsf,r1
7; ldmfd sp!,{r0-r12,pc}^
============================
1; stmfd 는 아래와 같은 stack자료 구조가 있을때 , 예로 높은 주소 0x0c부터 낮은주소 0x00으로 와 같이 스택이 자라는 것이라고 한다. full descending이므로 stmdb와 같다. 감소하고 채우고. 이렇게 이해하면 쉽다. ㅋ
sp d(감소) 한다 b(전에) data input
난 여지껏 높은 주소가 아래이고 낮은 주소가 가장 위(limit)가 되어 높은 주소에서 낮은 주소로 , limit를 향해서 채워나가는 것이 스택이라고 생각했는데, 높은 주소로도 ,또는 낮은 주소로도 자랄 수 있다는 것을 알게 되었다.
하지만 보통 스택은 full descending으로 구현되며 위에서 보듯이 높은 주소에서 낮은 주소로 감소하고 채우고 방법을 많이 사용하게 된다.
여기서 중요 ascending 은 sp!,{r0-r12,r14}에서 r0부터 작업하지만, descending은 r14부터 작업한다. 즉,~!~!
stmfd sp!,{r0-r12,r14} 은 sp가 4byte씩 감소하면서 r14채우고 , 감소하고 r12채우고, 감소하고 r11채우고.... 이런 식이 되는것이다. 그림으로 보면 이런식이다.
2. arm에서는 상태레지스터를 메모리 접근 명령어의 인자로 사용불가 따라서 move to from stack status 명령어를 사용하여 r1에 복사후
3. 스택에 넣기
4. swi핸들러 가기
5. 밑의 글은 5번 라인의 ldmfd의 내용을 보기위해 한번쯤은 당연히 생각해 보았어야 할 문제다. 밑의 글은 질의 내용인데 여러 사이트에 올렸던 질문내용이다.
///////////////////////////////////
stmfd store multiple full descending
저장 한꺼번에쭉 꽉차게 주소감소하면서
ldmfd load multiple full descending
꺼냄 한꺼번에쭉 꽉차게 주소감소하면서
강의를보고 이해하기로 저렇게 이해했습니다. 그러면 stmfd에서 낮은 주소방향으로 스택이 쌓여가다가 ldmfd에서도 또 낮은 주소방향으로 주소 포인터가 이동하면서 꺼내야 되는데 왜 ldmfd에서는 높은 주소방향으로 주소 포인터가 이동하면서 쌓아놨던 스택을 꺼내는 걸까요? store와 load 명령어의 동작 방식 때문에 그렇다면 st와 ld로 인해 위에 d의 의미가 감소가 아니라 증가로 바뀌는 것인가요?
단순히 push pop개념으로 이해하면 그냥 넘어가겠는데, 명령어상 문자상의 의미로는 틀린거같아서요.
ldmfa라고 해야 맞는 명령어이지 않을까요?
왜 저렇게 쓰는지 밍모르겠어요.
다른 분은 full descending 의미는 store에서 라고 하셨는데 그 말은 st냐 ld에 따라 마지막 d의 의미가 달라진다는 말씀이신 것같은데요. 제가 생각하는게 맞나요?
또 한가지 더요.
ldmfd는 현재 주소에서 큰 주소 방향으로 이동하는데 , 주소가 증가하고 데이터 빼고 하는 pop 인가요? .......1
"" , 데이터 빼고 주소가 증가하는 pop 인가요? .......2
1번 이 맞는 것같은데... 확실한지 모르겠네요
/////////////////////////////////////
이 질문에 대한 대답은 이렇다. stmfd와 ldmfd를 명령어 적인 해석 보다는 push pop의 개념으로 이해하라!
그렇다. 명령어적으로 해석하면 분명 내가 질문했던 내용이 포인트가 될 수 도 있다.
하지만 이렇게 외우기로 했다. stmfd와 ldmfd를 쌍으로 push pop 으로 외우기로 했다.
마지막 질문인 1번인지 2번인지는 아직도 모르겠다. 주소이동이니까 이동하고 빼는지 빼고 이동하는지 순서가 있을텐데....
아직까지 미지의 부분이다. 혹시라도 이 글을 읽는 다른 사람이 있다면 알려주길...
6. msr spsr_cxsf,r1
2번에서의 설명과 같다.상태레지스터를 메모리 접근 명령어의 인자로 사용이 불가하기 때문에 spsr_cxsf에 r1의 내용을 넣는다 . 즉 spsr은 다시 복원되는 것이다. 근데 여기서 cxsf는 상태레지스터의 4가지 영역을 모두다 복원한다는 것이다. flag, status, extension, control.
7. ldmfd sp!,{r0-r12,pc}^
pop명령어로 스택의 포인터값을 4바이트씩 증가시키면서 낮은 주소로 쌓아올렸던 스택값을 빼내서 r0....r12, pc 순서로 까지 복구한다. 그리고 마지막 ^ 기호는 arm어셈블리 주소지정 방식으로 메모리에 있는 값을 레지스트리에 복구하고 pc의 주소로 자동으로 분기하며 동시에 spsr의 값을 cpsr의 값으로 복사한다.