IT_Programming/C · C++

[C] C언어에서 inline assembly 사용하기

JJun ™ 2009. 10. 7. 15:13

출처 : http://www.kernel.kr/mips/02/mips0201.htm

 

C언어에서 inline assembly 사용하기

 

inline은 함수 호출을 통하여 코드 흐름을 제어하지 않고, 함수 내부에 코드을 삽입하므로

함수 호출로 인한 부하를 줄일 수 있으며, "inline function"이라고도 한다.

 

inline assembly라 함은 어셈블리 명령들을 inline 함수로 작성하는 것이다.

인라인 어셈블리는 실행속도 향상을 위해서 사용하며, 시스템 프로그래밍에서 자주 사용된다.

 

C언어에서 asm 키워드를 사용하여 어셈블리 명령어를 코딩한다. 

C언어와 어셈블리 명령어를 혼합할 수 있으므로, 빠른 실행처리는 어셈블리로 수행하고,

결과 데이터는 C언어의 변수들로 확인 가능한 장점이 있다.

 

 

 

GCC 인라인 어셈블리 문법

어셈블리 언어는 2가지 유형이 있는데, 인텔 형식과 AT&T 형식이다.

GNU C 컴파일러 즉, GCC는 AT&T 문법이며 우리는 이것을 사용하기로 한다.

인라인 어셈블리 코드는 아래와 같이 2가지 형식이다.

1) asm ("assembly code");

2) __asm__ ("assembly code");

 

 

 

인라인 어셈블리 매개변수

asm ( "assembly code"

           : output operands                   /* 출력변수 */

           : input operands                     /* 입력변수 */

           : list of clobbered registers      /* 변경되는 레지스터 */

);

 

 

레지스터 제약조건

+---+--------------------+

| r |    Register(s)     |

+---+--------------------+

| a |   %eax, %ax, %al   |

| b |   %ebx, %bx, %bl   |

| c |   %ecx, %cx, %cl   |

| d |   %edx, %dx, %dl   |

| S |   %esi, %si        |

| D |   %edi, %di        |

+---+--------------------+

 

 

asm ("movl %eax, %0;" : "=r" ( val )); 

"=r"는 val이 출력 변수라는 의미이고, eax 레지스터의 값이 변수 val에 할당된다.

 

 

    int no = 100, val ;

 

        asm ("movl %1, %%ebx;"

             "movl %%ebx, %0;"

             : "=r" ( val )        /* output */

             : "r" ( no )          /* input */

             : "%ebx"            /* clobbered register */

         );

 

 

(예제1)

 

#include <stdio.h>

 

int main() {

 

    int arg1, arg2, add, sub, mul, quo, rem ;

 

    printf( "Enter two integer numbers : " );

    scanf( "%d%d", &arg1, &arg2 );

 

    /* Perform Addition, Subtraction, Multiplication & Division */

    __asm__ ( "addl %%ebx, %%eax;" : "=a" (add) : "a" (arg1) , "b" (arg2) );

    __asm__ ( "subl %%ebx, %%eax;" : "=a" (sub) : "a" (arg1) , "b" (arg2) );

    __asm__ ( "imull %%ebx, %%eax;" : "=a" (mul) : "a" (arg1) , "b" (arg2) );

 

    __asm__ ( "movl $0x0, %%edx;"

              "movl %2, %%eax;"

              "movl %3, %%ebx;"

               "idivl %%ebx;" : "=a" (quo), "=d" (rem) : "g" (arg1), "g" (arg2) );

 

    printf( "%d + %d = %d\n", arg1, arg2, add );

    printf( "%d - %d = %d\n", arg1, arg2, sub );

    printf( "%d * %d = %d\n", arg1, arg2, mul );

    printf( "%d / %d = %d\n", arg1, arg2, quo );

    printf( "%d %% %d = %d\n", arg1, arg2, rem );

 

    return 0 ;

}

 

 

(예제2)

asm volatile () 메인함수가 아닌 서브함수에서 사용

 

#include <stdio.h>

 

float sinx( float degree ) {

    float result, two_right_angles = 180.0f ;

    /* Convert angle from degrees to radians and then calculate sin value */

    __asm__ __volatile__ ( "fld %1;"

                            "fld %2;"

                            "fldpi;"

                            "fmul;"

                            "fdiv;"

                            "fsin;"

                            "fstp %0;" : "=g" (result) : "g"(two_right_angles), "g" (degree)

    ) ;

    return result ;

}

 

float cosx( float degree ) {

    float result, two_right_angles = 180.0f, radians ;

    /* Convert angle from degrees to radians and then calculate cos value */

    __asm__ __volatile__ ( "fld %1;"

                            "fld %2;"

                            "fldpi;"

                            "fmul;"

                            "fdiv;"

                            "fstp %0;" : "=g" (radians) : "g"(two_right_angles), "g" (degree)

    ) ;

    __asm__ __volatile__ ( "fld %1;"

                            "fcos;"

                            "fstp %0;" : "=g" (result) : "g" (radians)

    ) ;

    return result ;

}

 

float square_root( float val ) {

    float result ;

    __asm__ __volatile__ ( "fld %1;"

                            "fsqrt;"

                            "fstp %0;" : "=g" (result) : "g" (val)

    ) ;

    return result ;

}

 

int main() {

    float theta ;

    printf( "Enter theta in degrees : " ) ;

    scanf( "%f", &theta ) ;

 

    printf( "sinx(%f) = %f\n", theta, sinx( theta ) );

    printf( "cosx(%f) = %f\n", theta, cosx( theta ) );

    printf( "square_root(%f) = %f\n", theta, square_root( theta ) ) ;

 

    return 0 ;

}

 

'IT_Programming > C · C++' 카테고리의 다른 글

[C++] Casting (형변환)  (0) 2010.05.15
[C++] assert  (0) 2009.11.12
[펌] MySQL 최적화 c api 소스  (0) 2009.09.16
[C++] 스마트 포인터(Smart Pointer) 맛보기  (0) 2009.09.15
[펌_C++] SAFE_DELETE 를 template으로 구현!  (0) 2009.08.12