'inline assembly'에 해당되는 글 1건

  1. 2012.09.25 인라인 어셈블리
프로그래밍/C2012. 9. 25. 09:15

    인라인 어셈블리



    1. #if __LINUX_ARM_ARCH__ >= 6

    2. static inline unsigned long arch_local_irq_save(void)

    3. {

    4. unsigned long flags;

    5. asm volatile(" mrs %0, cpsr    @ arch_local_irq_save\n"

    6. "            cpsid i"

    7. : "=r" (flags) : : "memory", "cc");

    8. return flags;

    9. }


 인라인 어셈블리에 대해서 간단히 짚고 넘어가자. 나중에 보면 이해가 안될거 같으니까.

보통 다음과 같은 문법이다.

__asm__ __volatile__ (asms : output: input: clobber);

ANSI에서는 __asm__만 쓰니까, asm 보단 __asm__을 쓰는게 낫다.  volatile(__volatile__)은 최적화를 진행하지 않는다.  컴파일러가 괜히 머리 쓴다고 사용되지 않는다고 판단되는 변수를 없애는 불상사를 방지한다.

asm은 따옴표로 둘러싸인 어셈블리 코드(여기서는 "mrs ... cpsid i"가 되겠다)이며, %와 같은 형태로 input, output parameter를 사용할 수 있다.  컴파일 후, 파라미터가 치환된 대로 어셈블리 코드로 나타난다.

output은 결과값을 출력하는 변수이다. 

"=r"(flags)이다. =는 쓰기전용이란 뜻이다.

input은 output과 같은 방식으로 사용하고, 인라인 어셈블리 코드에 넘겨주는 parameter를 적는다.

clobber는 asm를 실행 시, 값이 변하는 것을 적어준다.  각 변수는 쉼표로 구분되며 각각을 따옴표로 감싸준다. "memory", "cc"가 되겠다.

이제 실제 코드를 분석해 보면,

mrs %0, cpsr 에서는 "=r" (flags)에서, 레지스터 넘버를 flags로 받은 뒤 나오는 레지스터로 cpsr를 저장시킨다. 그 후 cpsid i를 통해 인터럽트를 disable 시킨다. cpsid i는 arm cortex에서 인터럽트를 disable 시킨다. armv7 전용 명령어로 알고 있었는데, ifdef에서 version 6부터 체크하는 걸 보니, armv6에서도 가능한가 보다.

clobber 영역의 "memory"는 컴파일러에게 어셈브릴 코드가 메모리의 어딘가를 변경한다고 가르쳐 주는 것이다. 만약 이렇게 안해주면 컴파일러는 어셈블리코드에서 메모리의 내뇽을 변경하는 것을 컴파일러는 전혀 알 수 없다. "memory"를 명시해 주면, 컴파일러는 어셈블리 코드를 실행하기 전/후에 레지스터에 저장되어 있는 모든 변수의 값을 갱신하도록 한다. "cc"는 컴파일러에게 어셈블리 명령어가 컨디션 코드 플래그를 읽고 쓴다고 알려준다.  설명이 길어졌다. 결국, cpsr를 저장하고 인터럽트를 disable 시킨다.

'프로그래밍 > C' 카테고리의 다른 글

symbol visibility  (0) 2013.08.07
typedef 와 static 을 동시에 사용 못하는 이유  (0) 2012.11.24
include guard에 대해서  (0) 2012.09.24
구조체 초기화 방법  (0) 2012.08.21
error: expected identifier before numeric constant  (0) 2012.07.03
Posted by code cat