2012-09-17 5 views
0

최근 Windows에서 GCC를 사용하여 x86 어셈블리를 연습 해 왔습니다. 나는 현재 테스트 목적으로 어셈블리와 C 코드를 혼합하고있다. 나는 내가 현재 가지고있는 지식으로는 설명 할 수없는 이상한 것을 보았고 그래서 나는 도움을 청한다.GCC 어셈블리 생성 - Segfault at C 함수 호출

최소한의 예를 봅시다. 우리는 test_func()을 C 코드로 가지고 있습니다.이 코드를 어셈블리로 변환 한 다음 나중에 C 코드에서 호출하려고합니다. 이 함수는 프로젝트에서 다른 함수를 호출하지만 거기에 문제가 있습니다. 어셈블리 내부에서 다른 C 코드 함수를 호출하면 세그먼트 오류가 발생합니다.

우리가 조립에 표시 할 기능이에 대한 어셈블리 코드를 뱉어 GCC를 요구

#include "rf_string.h" 
void test_func() 
{//nonsense function, just calling another C function of the project 
    RF_String s; 
    rfString_Init(&s,"anything"); 
} 

이 우리를 제공합니다

.file "to_asm.c" 
    .section .rdata,"dr" 
    .align 4 
LC0: 
    .ascii "anything\0" 
    .text 
    .globl _test_func 
    .def _test_func; .scl 2; .type 32; .endef 
_test_func: 
LFB6: 
    .cfi_startproc 
    pushl %ebp 
    .cfi_def_cfa_offset 8 
    .cfi_offset 5, -8 
    movl %esp, %ebp 
    .cfi_def_cfa_register 5 
    subl $40, %esp 
    movl $LC0, 4(%esp) 
    leal -16(%ebp), %eax 
    movl %eax, (%esp) 
    movl _rfString_Init, %eax 
    call *%eax 
    leave 
    .cfi_restore 5 
    .cfi_def_cfa 4, 4 
    ret 
    .cfi_endproc 
LFE6: 

그런 다음 "asm_test라는 파일에이를 저장하여. S "를 만들고 그것을 빌드하고 잘 링크 된 프로젝트의 빌드 프로세스에 포함시킵니다. 그래서 우리는 함수를 호출하는 간단한 프로그램을 만들려고 노력합니다.

int main() 
{ 
    test_func(); 
    return 0; 
} 

문제는 디버깅 할 때 발생합니다. 어셈블리 코드 내부에서 다른 C 함수를 호출하면 세그먼트 화 오류가 발생합니다. 이것은 어셈블리 코드에서 호출하려고하는 다른 모든 함수에 대해 발생합니다.이 함수는 내가 사용한 것과 특별히 관련이 없습니다.

은 나는 여기에 함수 호출과 관련이있다 생각 :

movl %eax, (%esp) 
movl _rfString_Init, %eax 
call *%eax 

왜이 일을하고 이것이 무엇을 의미합니까? 특히 단순히 함수를 호출하지 않는 이유는 무엇입니까? 또한 % eax 레지스터 앞에 * 무엇입니까? 나는 또한 아래의 함수에 대한 간단한 호출로 마지막 두 줄을 바꾸면 모든 것이 완벽하게 작동하는 것처럼 보이기 때문에 실제로 추가해야합니다.

call  _rfString_Init 

또 다른 사소한 질문은 모든 cfi_directives에 관한 것입니다. 내가 물어 본 질문에 대한 답변으로 판단한다면 예외 처리 목적으로 생성 된 것으로 보입니다. 문제는 코드의 기능에 관한 한 안전하게 무시할 수 있다는 것입니다. 여기

답변

1

: 없음 $_rfString_Init 전 (movl $LC0, 4(%esp) 달리)가 있다는

movl _rfString_Init, %eax 
call *%eax 

참고. _rfString_Init은 직접 상수가 아니며 (예 : 함수 또는 객체의 상수 주소 또는 상수), 메모리 변수가 아닙니다.

그래서 movl_rfString_Init 변수의 내용으로 eax을로드합니다.

calleax에 포함 된 주소로 전화를 겁니다. 별은 제어가 간접적으로 참조/포인터에 의해 전달된다는 것을 나타내는 구문적인 설탕이다.

따라서 rfString_Init은 실제로 함수에 대한 포인터입니다. C 코드에서 찾아보세요!

코드로 해석 될 것으로 예상되지 않는 데이터이기 때문에 포인터를 포함하는 바이트로 컨트롤을 전송하려고하면 아무 일도 일어나지 않습니다. 또한 기본 메모리는 실행 불가능한 것으로 구성 될 수 있습니다.

나는 이러한 지침에 대해 많이 모른다. 디버깅 용으로도 사용할 수 있습니다. 어쨌든, 그들은 당신이 그들을 볼 코드를 삽입하지 않습니다.

+0

내 이전 댓글을 긁어 라. 내 전화에서 왔어. 이 함수는 함수 포인터가 아니지만 제 질문은 세부 사항을 생략했습니다. 함수는 라이브러리의 일부입니다. 어느 dll로 수출했다. 테스트 케이스는 dll을 작성하지 않고 선언문에서 dllimport를 잘못 잊어 버렸습니다. 이로 인해 함수 심볼 이름 앞에 __imp_가 추가되었습니다. 나는 그것을 알아 차리고 그것을 올바르게 제거 할 것이라고 생각했다. 함수를 호출하는 방법은 dll로부터 어떻게 수행되는지입니다. func 포인터의 힌트가 대답으로 나를 인도하기 때문에 대답을 받아 들일 것입니다 – Lefteris

+0

여기에서 뭔가를 물어볼 때 새로운 것을 배우는 방법을 좋아합니다. 항상 직접적인 방법을 통해서는 안된다. – Lefteris

+0

DLL이든 아니든, 기계어 코드가 간접 호출을한다면 포인터를 사용한다. –