티스토리 툴바


'OS개발 프로젝트/참고자료'에 해당되는 글 1건

  1. 2008/03/06 GNC AS 문법

http://blog.naver.com/cpls?Redirect=Log&logNo=40029210428

ldmfd   sp!,{r0-r12,pc}^

 ldm에서 ^는 pc가 register에 있다면 spsr을 cpsr로 복사해주는 역활을 합니다. 주로 특권 모드에서 user모드로
 복귀할 때 많이 사용합니다. 만약 pc가 없다면 {}안의 레지스터들이 user모드의 레지스터란 이야기입니다.

stmfd   sp!, {r0-r14}^

 stmfd 할때 뒤에 꺽쇠(^)를 붙이면 복사대상 레지스터는 USER모드의 레지스터가 된다.
 IRQ모드에서 USER모드의 레지스터를 백업,복구할려면 뒤에다가 ^를 붙여서 주소지정을 해주어야 한다.

ldr     r10,[lr,#-4]

 lr 에서 4를 빼서 r10 에 저장

bic     r10,r10,#0xff000000

 bic 는 NOT AND 연산을 한다, 즉 NOT(모든 비트를 반대로) 한 후, AND 연산을 하기때문에
 bit 를 clear 하는데 유용하다
 r10에서 하위 3바이트를 마스크하여 다시 r10 에 저장

msr     spsr_cxsf,r1
 
 r1의 내용을 spsr에 cxsf 마스크를 줘서 복사

mrs     r1,spsr

 spsr의 내용을 r1에 저장

stmfd   sp!,{r0-r12,r14}

 인덱스로 sp를 사용했기 때문에 14개의 해당 레지스터는 스택에 저장

ldmfd   sp!,{r0-r12,pc}^

 sp안의 14개의 word를 순서대로 r0~r12까지에 복구하고, 마지막에 lr 을 pc 로 복구한다
 =>Exception 이 발생하여 칩의 동작모드가 바뀌는 순간 pc 는 lr 로, cpsr 은 spsr 로 저장된다.

bl

 어셈블리어에서 c로 작성한 함수로 넘어갈 때 사용, c언어 함수로 점프할 때 c언어 함수에 매개변수가 있으면
 컴파일러는 해당 변수를 r0에서 부터 순서대로 선택하는 코드 생성

loop  ldrb r8 , [r5], #1

 [ ]는 메모리 간접억세스를 의미합니다. 즉, r5 값을 r8로 옮기는 명령이 아니고
 [r5]로 하면 r5의 값을 주소로 보고 그 주소의 내용을 읽어오라는 뜻입니다.
 즉, ldrb r8, [r5] 하면 r5의 현재값이 0x1000 이라면 어떻게 될까요?
 0x1000 번지에 있는 메모리의 내용을 바이트 단위로 읽어서 r8에 넣으라는 얘기가 됩니다.
 결국 r8에는 r5의 내용이 아니라 r5가 가진 값의 주소에 해당하는 메모리 내용이 들어오는 겁니다.
 근데 뒤에 , #1은 뭘까요? 이것은 개수를 의미하는 것이 아니라 post increment를 의미합니다.
 즉, ldrb r8, [r5], #1 하면 이렇게 동작 되는 겁니다. 현재 r5가 0x1000 이라면
 0x1000 번지의 1바이트 내용을 r8에 넣고 그 다음 r5(주소 인덱스)를 1을 더하라는 뜻입니다.
 그러므로 r5는 위의 명령이 수행되고 나면 0x1000에서 1이 증가하여 0x1001 이 되었겠지요...
 이렇게 r5를 주소로서 사용한 후 나중에 뒤의 # 숫자만큼 그 값을 증가시켜 놓는다는 의미로
 사용되고 그래서 post increment라고 합니다. 이렇게 해두면 밑에서 r5를 하나 증가시키지
 않아도 자동으로 증가하니까 다음 반복수행때는 알아서 0x10001 번지 내용을 읽게 되겠지요

subs r6, r6 , #1

 subs 명령어가 sub랑 뭐가 틀린가요? 그냥 루프카운터를 1씩 빼주면 되는데 subs명령어를
 쓴 이유는 뭔가요?

 결론 부터 말씀드리지요... 만약 subs를 쓰지 않았다면 어떻게 프로그램이 작성되어야 하는가를 보죠
 코드를 그대로 활용합니다.

 sub r6, r6, #1
 cmp r6, #0
 bne  loop

 이렇게 세줄로 짜야합니다. 즉, r6을 감소시키고 0과 비교하여 같지않으면(즉, 0이 아니면) loop로 가라
 그런데 두 값을 비교하는 것은 뺄셈을 수행하는 것이므로 r6 - #0 = 0 이면 bne 조건이 참이 되는 거지요
 그래서 이는 곧 연산결과가 0이 되면 세트되는 zero flag가 세트되었는가를 확인하는것이 됩니다.
 어차피 뺄셈할 때 결과가 0이면 이것도 zero flag가 세트되니까 그냥 sub 한 결과를 가지고 조건판단으로
 쓰고자 했습니다.

 조건의 참, 거짓 판단은 앞의 문장이 어떻게 되었느냐가 아니라 하드웨어적으로
 상태레지스터(ARM의 CPSR)의 어느 비트가 어떻게 되었느냐를 가지고 판답합니다.
 그러면 위의 아이디어에 근거하여 다음과 같이 작성하면 어떻게 될까요?

 sub r6, r6 , #1  
 bne loop

 이렇게 쓰면 원하는대로 동작하지 않습니다. 왜일까요?
 ARM은 기본적으로 비교를 위한 명령어들 CMP, CMN, TST등의 명령들 이외의 산술연산 명령들은
 명령의 수행이 완료되어도 상태 레지스터에 변화를 주지 않습니다. 고로 아무리 sub를 하더라도
 그 결과가 0이 되어도 zero flag는 변화되지 않습니다. 그러니 밑에 bne에서 조건 판단을 위하여
 zero flag를 보면 이것은 0일수도 1일수도 있지만 이는 위의 sub 명령 결과를 의미하는 것이 아니죠
 그래서 ARM에서는 산술연산 명령어를 수행하면 상태레지스터를 변경할 수 있도록 하기 위하여
 S Suffix를 두고 있습니다. 즉, sub뒤에 s를 두어 subs로 하면 sub 명령이 수행된 뒤에
 상태레지스터를 갱신하게 됩니다. 그러니 위의 명령에서는 반드시 subs로 해야만 합니다.
 결국 이렇게 됩니다.

 subs r6, r6 , #1  
 bne loop

Posted by 베리머치 트랙백 0 : 댓글 0