최근 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에 관한 것입니다. 내가 물어 본 질문에 대한 답변으로 판단한다면 예외 처리 목적으로 생성 된 것으로 보입니다. 문제는 코드의 기능에 관한 한 안전하게 무시할 수 있다는 것입니다. 여기
내 이전 댓글을 긁어 라. 내 전화에서 왔어. 이 함수는 함수 포인터가 아니지만 제 질문은 세부 사항을 생략했습니다. 함수는 라이브러리의 일부입니다. 어느 dll로 수출했다. 테스트 케이스는 dll을 작성하지 않고 선언문에서 dllimport를 잘못 잊어 버렸습니다. 이로 인해 함수 심볼 이름 앞에 __imp_가 추가되었습니다. 나는 그것을 알아 차리고 그것을 올바르게 제거 할 것이라고 생각했다. 함수를 호출하는 방법은 dll로부터 어떻게 수행되는지입니다. func 포인터의 힌트가 대답으로 나를 인도하기 때문에 대답을 받아 들일 것입니다 – Lefteris
여기에서 뭔가를 물어볼 때 새로운 것을 배우는 방법을 좋아합니다. 항상 직접적인 방법을 통해서는 안된다. – Lefteris
DLL이든 아니든, 기계어 코드가 간접 호출을한다면 포인터를 사용한다. –