작성
·
411
1
인라인 어셈블러 포맷에서 ::: 마지막란에 Clobber list가 온다고 배웠습니다.
Clobber list에 "memory"를 쓰면 메모리 장벽이 생성된다는게 어떤 의미인지 구체적으로 알 수 있을까요?
강의 예시로 나온 코드의 내용입니다.
(strexb %0, %2 %1" : "=&r"(result), "=Q"(*addr): "r" ((uint32_t)value));
어셈블러 문법상 :::는 무조건 적어야한다고 강의를 통해 배웠는데요. 위 코드에서는 ' : ' 가 2개 뿐인걸로 확인했습니다. 특정 상황에서는 ' : '를 3개 다 적지 않아도 되는건가요?
감사합니다~
답변 1
1
안녕하세요, chltnckd7님!
Q1. 인라인 어셈블러 포맷에서 ::: 마지막란에 Clobber list가 온다고 배웠습니다.
Clobber list에 "memory"를 쓰면 메모리 장벽이 생성된다는게 어떤 의미인지 구체적으로 알 수 있을까요?
A1. 컴파일 과정에서 컴파일러는 최적화를 위해 필요한 경우 사용자 작성 코드를 재배치(Reordering)할 수 있습니다. 게다가 캐쉬, 레지스터를 사용하는 경우까지 가세하게 되니까 이는 시스템의 각 요소들 사이의 메모리 연산의 순서에 대한 보장이 굉장히 어렵고 중요한 문제가 될 수 있습니다. 이에 메모리 장벽이라는 기술을 사용할 수 있는데, DMB, DSB, ISB 와 같은 메모리 장벽을 위한 어셈블리 명령어를 사용할 경우 이를 통해 명령어의 사용전 코드 블럭과 사용 후의 코드 블럭사이에서의 메모리 연산의 실행 순서를 보장할 수 있습니다.
e.g. 클로버(memory)가 사용된 코드의 예
__STATIC_FORCEINLINE void __enable_irq(void){
__ASM volatile ("cpsie i" : : : "memory");
}
코드 블럭 A 영역
__enable_irq(); // 이 함수 호출을 기준으로 앞선 코드 블럭 A 영역에서의 메모리 관련 동작이 완전히 끝나야만, 코드 블럭 B의 실행이 진행된다.
코드 블럭 B 영역
메모리 장벽에 관련하여 자세한 것은 다음의 글을 참고하면 좋습니다.
Q2. 강의 예시로 나온 코드의 내용입니다.
(strexb %0, %2 %1" : "=&r"(result), "=Q"(*addr): "r" ((uint32_t)value));
어셈블러 문법상 :::는 무조건 적어야한다고 강의를 통해 배웠는데요. 위 코드에서는 ' : ' 가 2개 뿐인걸로 확인했습니다. 특정 상황에서는 ' : '를 3개 다 적지 않아도 되는건가요?
A2. 아래 시놉시스처럼 콜론은 입출력 오퍼랜드와 클로버가 작성된 상태에 따라 다릅니다.
asm asm-qualifiers ( AssemblerTemplate
: OutputOperands
[ : InputOperands
[ : Clobbers ] ] )
클로버가 인라인어셈블리에 표현되어 있다면 콜론 기호는 3개가 필요하지만, 표현된 문장에 클로버가 생략되어 있다면 콜론 기호는 2개 이하이겠지요. 자세한 내용은 아래 예시를 참조 바랍니다.
e.g. 클로버를 사용한 예( 콜론 3개 )
__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control){
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
}
e.g. 클로버를 사용하지 않은 예( 콜론 2개 )
__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control){
__ASM volatile ("MSR control, %0" : : "r" (control));
}
mov 명령의 오퍼랜드에는 메모리를 사용할 수 없습니다. 레지스터나 상수만이 가능하죠.
예를들어, mov r0,r1 혹은 mov r0,#4
그러므로 코드는 다음과 같이 작성되어야 합니다.
__STATIC_FORCEINLINE int MOV_TEST(volatile int* val1)
{
int result;
__ASM volatile( "ldr %0, %1" : "=r"(result) : "Q"(*val1) );
return result;
}
printf("ret=%#x\n", MOV_TEST(&a));
===
실행결과
ret=0x12345678
__STATIC_FORCEINLINE int MOV_TEST(volatile int *val1)
{
int result;
__ASM volatile( "MOV %0, %1" : "=r"(result) : "Q"(*val1) );
return result;
}
mov를 인라인 어셈블리로 위와 같이 작성 하였는데 해당 오류가 나옵니다.
오류 내용 :
Error: undefined symbol r3 used as an immediate value
일반 변수를 사용하면 잘 되는데 포인터로 작성하면 오류가 생기네요. 왜 이런 걸까요?
혹시나 __ASM volatile( "MOV %0, [%1]" : "=& r"(result) : "r"(val1) ); 이렇게 작성해도 오류가 나오네요.