linux 프로그램을 하다보면 가끔 어셈블러 코드가 필요하다.

주로 하는게 ARM 코아 이다 보니 ARM 코아 위주로 간략히 설명하기로 하겠다.


<특정주소의 값을 변수로 읽어오는 코드>


C 코드


val = *addr;


GCC 인라인 어셈코드


asm  ( " ldr  %0, [%1]" : "=r" (val) : "r" (addr) );



GCC 인라이 어셈블러 규칙을 보면 다음과 같다.


asm ( code : output operand list : input operand list : clobber list );


    여기서  code 란 "ldr  %0, [%1]"  이라고 쓴 영역을 말하며

    ':' 콜론으로 분리된 다음영역이 output  또 다음영역이 input  그리고 마지막이 클로버영역이다.

    마지막 클로버 영역은 생략이 가능하다.


    중요한 것은  output, input operand 의 의미이다.


    output operand 란 레지스터(ARM 코아에서는 R0, R1, R2 .... ) 의 값을 빼내서 메모리 변수(여시서는 val 변수)

    에 넣는 것을 말한다.


    input operand 란 메모리 변수(여기서는 addr 변수)의 값을 레지스터에  넣는  것을 말한다.


    clobber 영역은 인라인어셈 영역에서 프로그래머가 직접 레지스터를 제어한다면 이곳에 넣어 컴파일러가

    사용하지 못하도록 할때 사용한다.


    실제 어셈블러코드는 아래와 같을 것이다.

    

    ldr    r0, =val         <-- val 변수의 주소를 임의로 문자열로 표시하였다.

    ldr    r1, =addr       <-- addr 변수의 주소를 임의로 문자열로 표시하였다.

    ldr   r2, [r1]      <-- addr 가 가리키는 주소의 값을 읽어온다.

    str    r2, [r0]         <-- r0 레지스터가 가리키는 주소 즉 val 변수에 값을 넣는다.


    위의 내용중 붉은색 코드만을 인라이어셈으로 지정하면 나머지는 컴파일러가 알라서 채워준다

    우리가 선언하는  val, addr 값은 변수는 메모리상의 주소이기 때문에 메모리에서 로드(load)하고 스토아(store)

    하는 코드는 항상 이루어지는 것이니 컴파일러가 자동화 하는 것이다.


    code 영역에서  "ldr  %0, [%1]"   %0, %1 이라고 표시되는 것은 뒤쪽에 따라오는 변수의 순서번호이다

    output, input 등의 필드구분없이 앞쪽부터 0 번으로 표시된다.


    각 operand  에서  'r'  이라고 표시되는 것은 레지스터로 대치하라는 것이며

    '=r'  이 표시는 output 전용이라는 말이다.  output operand 쪽에는 반드시 이와 같이 써준다.



특정 프로그램을 C 로 작성하는데 컴파일러가 의도하지 않는 형태로 버스를 엑세스하는 것을 발견하고 이를 잡기위해

인라이 어셈블러를 사용하게 되었다. 모르는 상태에서 공부해서 작성하려니 4줄 작성하는데

2시간이나 걸렸다.  문서를 검색해 보니 영문이라..  이해하느라 힘들었다.


아래는 영문으로 잘 설명된 링크이다


http://www.ethernut.de/en/documents/arm-inline-asm.html