2011-02-27 4 views
8

인라인 어셈블리를 사용하려고합니다 ... 이 페이지 http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx을 읽었지만 내 함수로 전달되는 매개 변수를 이해할 수 없습니다.C/C++에서 인라인 어셈블리 사용

가 나는 C 쓰기 예를 쓰고 있어요 ..이 내 기능 헤더입니다 :

write2(char *str, int len){ 
} 

그리고 이것은 내 어셈블리 코드입니다 : 내가 그 코드를 통과해야 할 일을

global write2 
write2: 
    push ebp 
    mov ebp, esp 
    mov eax, 4  ;sys_write 
    mov ebx, 1  ;stdout 
    mov ecx, [ebp+8] ;string pointer 
    mov edx, [ebp+12] ;string size 
    int 0x80  ;syscall 
    leave 
    ret 

C 함수에 ... 나는이 같은 일을 해요 :

write2(char *str, int len){ 
    asm ("movl 4, %%eax;" 
      "movl 1, %%ebx;" 
      "mov %1, %%ecx;" 
      //"mov %2, %%edx;" 
      "int 0x80;" 
      : 
      : "a" (str), "b" (len) 
    ); 
} 

내가 출력 변수가 없기 때문에, 그래서를 어떻게 할 그걸 처리해? 이 코드 또한 :

global main 
main: 
    mov ebx, 5866  ;PID 
    mov ecx, 9  ;SIGKILL 
    mov eax, 37  ;sys_kill 
    int 0x80  ;interruption 
    ret 

나는 그래서이 같은 .. 사용자에게 PID를 요청할 수 있습니다 .. 내 코드에서 해당 코드 인라인을 넣을 수있는 방법 ... 이 내 프리 코드

입니다
void killp(int pid){ 
    asm ("mov %1, %%ebx;" 
      "mov 9, %%ecx;" 
      "mov 37, %%eax;" 
      : 
      : "a" (pid)   /* optional */ 
    ); 
} 
+0

str, len?과 함께 하나의 매개 변수를 전달하려고하거나 str을 쓰고 자하는 파일 설명자를 보내려는 것을 의미합니까? – Zimbabao

+0

그냥 내 문자열 포인터와 문자열 길이를 전달하고 싶습니다 ... 정확히 어셈블리 코드를 보면 ... syscall 만 사용하면 문자열을 표준 출력으로 인쇄 할 수 있습니다. – RodrigoCR

답변

10

글쎄, 당신은 구체적으로 말하지 않지만, gcc와 제약 조건 구문을 가진 인라인 asm (다른 C 컴파일러는 매우 다른 인라인 구문을 가짐)을 사용하는 것처럼 나타납니다. 즉, gcc와 함께 사용되기 때문에 Intel보다는 AT & T 어셈블러 구문을 사용해야 할 것입니다.

위와 같이 write2 함수를 살펴 보겠습니다. 첫째, gcc가 스택 프레임을 생성하기 때문에 스택 프레임을 생성하고 싶지 않으므로 asm 코드에서 스택 프레임을 만들면 두 프레임이 생겨 결국 혼란스러워 질 것이다. 둘째, gcc가 스택 프레임을 배치하기 때문에 배치 방법을 모르는 "[ebp + offset]"광고로 바스에 액세스 할 수 없습니다. 이것이 제약 조건입니다. gcc가 값 (모든 레지스터, 메모리, 특정 레지스터)과 사용 "% X"을 asm 코드에 넣으려는 장소의 종류를 말합니다. 마지막으로, asm 코드에서 명시 적 레지스터를 사용하는 경우 gcc가 사용하고 있음을 알 수 있도록 입력 제한 조건 이후의 세 번째 섹션에 명시 적으로 나열해야합니다. 그렇지 않으면 레지스터 중 하나에 중요한 값을 넣을 수 있습니다. - 레지스터 이름 앞에 SRC, 이명 령보다는 이명 령, SRC 및 %

void write2(char *str, int len) { 
    __asm__ volatile (
     "movl $4, %%eax;" 
     "movl $1, %%ebx;" 
     "movl %0, %%ecx;" 
     "movl %1, %%edx;" 
     "int $0x80" 
     :: "g" (str), "g" (len) 
     : "eax", "ebx", "ecx", "edx"); 
} 

참고 AT & T 구문 :

그래서 모두와 함께, 귀하의 WRITE2 기능은 같다.

이제는 효과가 있지만 많은 추가 운동이 포함되어 비효율적입니다. 일반적으로 mov 인스트럭션이나 명시 적 레지스터를 asm 코드로 사용하면 안됩니다. 제약 조건을 사용하여 물건을 원하는 위치에서 말하고 컴파일러에서 그 위치를 확인하는 것이 훨씬 낫습니다. 그런 식으로, 옵티 마이저는 아마도 대부분의 mov를 제거 할 수 있습니다. 특히 함수를 인라인하는 경우 (-O3을 지정하면 수행 할 것입니다).편리의 i386 기계 모델은 특정 레지스터에 대한 제약이있다, 그래서 당신은 대신 수행 할 수 있습니다

void write2(char *str, int len) { 
    __asm__ volatile (
     "movl $4, %%eax;" 
     "movl $1, %%ebx;" 
     "int $0x80" 
     :: "c" (str), /* c constraint tells the compiler to put str in ecx */ 
      "d" (len) /* d constraint tells the compiler to put len in edx */ 
     : "eax", "ebx"); 
} 

또는 더 나은을

void write2(char *str, int len) { 
    __asm__ volatile ("int $0x80" 
     :: "a" (4), "b" (1), "c" (str), "d" (len)); 
} 

주의도 필요하다 volatile의 사용은 컴파일러에게 해당이 그것의 출력 (아무 것도없는)이 사용되지 않더라도 죽은 것으로 제거 될 수 없다.

편집

마지막으로 참고 - 기입 해지는 바이트 수 또는 오류 코드 중 하나 -이 기능은 EAX의 값을 반환 않는 write 시스템 호출을하고있다. 그래서 당신은 출력 제약 조건이를 얻을 수 있습니다 :

int write2(char *str, int len) { 
    __asm__ ("int $0x80" : "=a" (len) : "a" (4), "b" (1), "c" (str), "d" (len)); 
    return len; 
} 

실제 출력과 함께, 당신은 또는 휘발성을하지 않을 수 있습니다 - 그것은 죽은 코드를 컴파일러 수 있지 않는 쓰기를 제거 할 경우 반환 값 사용되지 않습니다. 하지만 항상 오류에 대한 반환 값을 확인합니다.

+1

AT & T로 변환하는 동안 한 가지를 놓쳤습니다. 상수 앞에 $가 있어야합니다. 그렇지 않으면 그들은 메모리 참조이며, 0x80에 어떤 인터럽트가 발생하더라도 수행을 원하지 않을 것이라고 확신합니다. – ughoavgfhw

+0

큰 도움이되는 답변에 감사드립니다. 나는 AT & T sintax에 대해 깨달았습니다. 그래서 코드를 수정했습니다 ...하지만 당신이보기에는 너무 늦었습니다 : P, 이제는 최적화에 대해 이해했습니다 ... 그래서 int $ 0x80을 넣어야합니까? – RodrigoCR

+0

void write2 (char * str, int len) { __asm__ volatile ("int $ 0x80" "a"(4), "b"(1), "c"(str), "d")); } 참고 : 정답입니다. 값을 교환하고 $를 사용하십시오. 둘 다 고마워! – RodrigoCR

관련 문제