programing

x86, win32의 빈 프로그램에 대한 GCC 어셈블리 출력

bestcode 2022. 8. 19. 20:50
반응형

x86, win32의 빈 프로그램에 대한 GCC 어셈블리 출력

stackoverflow 코더의 지옥을 짜증나게 하기 위해 빈 프로그램을 쓰고 있지 않다.나는 단지 gnu 툴체인을 탐색하고 있을 뿐이다.

다음 내용은 너무 복잡할 수 있지만, 빈 프로그램 이야기를 계속하기 위해 C 컴파일러의 출력, 즉 GNU가 소비하는 것을 조사하기 시작했습니다.

gcc version 4.4.0 (TDM-1 mingw32)

test.c:

int main()
{
    return 0;
}

gcc - S test.c

    .file   "test.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    call    ___main
    movl    $0, %eax
    leave
    ret 

여기서 무슨 일이 일어나는지 설명해 주시겠어요?여기 그것을 이해하기 위한 나의 노력이 있다.사용하였습니다.asx86 ASM:

  • .file "test.c"는 논리 파일명의 지시어입니다.
  • .def: 문서 "기호 이름에 대한 디버깅 정보 정의 시작"에 따르면기호(함수 이름/변수)는 무엇이며 어떤 종류의 디버깅 정보입니까?
  • .scl: docs는 "스토리지 클래스가 기호가 정적인지 외부인지 플래그를 표시할 수 있습니다."라고 말합니다.C에서 알 수 있는 정전기 및 외부기기와 같은 입니까?2는 뭐야?
  • .type: "심볼 테이블엔트리의 유형 속성"으로 파라미터를 저장합니다.모르겠습니다
  • .endef: 문제 없습니다.
  • .text이것은 문제가 되고 있습니다.섹션이라고 불리는 것 같고, 코드 위치라고 읽었는데, 의사 선생님께서 너무 많은 것을 알려주지 않았습니다.
  • .globl "기호를 ld에 표시하십시오." 설명서는 이에 대해 매우 명확합니다.
  • _main: 주소도 있습니다.
  • pushl_: EBP " (32비트)"
  • movl 이동 32살 C: 사c C:EBP = ESP;
  • andl AND : 논리 AND. C: 사c C:ESP = -16 & ESP이게 무슨 의미가 있는지 잘 모르겠어요
  • call를에 푸시 해), 다음의 장소에 합니다.IP 의 경우는, 「IP」를 참조해 주세요.__main(_main? /_main?
  • movl: 이 이 0은 코드 끝에 반환되는 상수여야 합니다.MOV 을 0 、 EAX 、 MOV 。
  • leave 후에 입력해 주세요.왜??
  • ret 「」로 .「 」 。

도와주셔서 감사합니다!

.file "test.c"

.로 시작하는 명령어는 어셈블러에 대한 지시어입니다.이것은 "file.c"라고만 표시되며, exe의 디버깅 정보로 정보를 내보낼 수 있습니다.

.def __main; .scl 2; .type 32; .endef

.def 디렉티브는 디버깅 기호를 정의합니다.scl 2는 스토리지 클래스 2(스토리지 클래스)를 의미합니다.type 32는 이 섬볼이 함수라고 합니다.이러한 번호는 pe-coff exe 형식으로 정의됩니다.

__main은 gcc가 필요로 하는 부트스트래핑을 처리하는 함수입니다(c++ static initializer 실행 및 기타 필요한 하우스키핑 등).

.text

텍스트 섹션을 시작합니다. 코드가 여기에 있습니다.

.global_메인

는 _main 기호를 global로 정의하며 링커 및 링크되어 있는 다른 모듈에 표시됩니다.

.def        _main;  .scl    2;      .type   32;     .endef

_main과 마찬가지로 _main이 함수임을 나타내는 디버깅 기호를 만듭니다.디버거가 사용할 수 있습니다.

메인:

새 라벨을 시작합니다(주소가 됩니다).위의 .globl 지시어는 이 주소를 다른 엔티티에 표시합니다.

pushl       %ebp

오래된 프레임 포인터(ebp 레지스터)를 스택에 저장합니다(이 기능이 종료되면 원래 위치로 되돌릴 수 있습니다).

movl        %esp, %ebp

스택 포인터를 ebp 레지스터로 이동합니다.ebp는 종종 프레임 포인터라고 불리며, 현재의 "프레임"(일반적으로 함수) 내에서 스택 값의 상단을 가리킵니다(ebp를 통해 스택 상의 변수를 디버거에 사용할 수 있습니다).

및 l $16, %190

스택에 fffff0을 붙여서 실질적으로 16바이트 경계에 맞춥니다.스택의 정렬된 값에 대한 접근은 정렬되지 않은 값보다 훨씬 빠릅니다.위의 모든 명령어는 거의 표준 기능 프롤로그입니다.

call        ___main

gcc에 필요한 초기화 작업을 수행하는 __메인 함수를 호출합니다.콜은 스택상의 현재 명령 포인터를 푸시하여 __main 주소로 점프합니다.

movl        $0, %eax

0을 eax 레지스터로 이동합니다(반환 0의 0). eax 레지스터는 stdcall 호출 규약의 함수 반환 값을 유지하는 데 사용됩니다.

떠나

휴가 지시는 거의 의 줄임말이다.

movl     ebp,esp
popl     ebp

즉, 기능을 시작할 때 수행된 작업을 "undos"하여 프레임 포인터와 스택을 이전 상태로 복원합니다.

리트

이 함수를 호출한 사용자로 돌아갑니다.스택에서 명령 포인터를 팝하고(해당 호출 명령이 거기에 배치됩니다) 점프를 합니다.

여기에서는, 매우 유사한 연습에 대해 설명합니다.http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax

대부분은 이해하셨을 겁니다.강조나 추가에 대해 메모하겠습니다.

__main는 GNU 표준 라이브러리의 서브루틴으로 다양한 스타트업 초기화를 처리합니다.C 프로그램에는 반드시 필요한 것은 아니지만 C 코드가 C++와 연동되는 경우에 필요합니다.

_main주요 서브루틴입니다.둘 다로서_main그리고.__main동일한 저장소 클래스 및 유형을 가진 코드 위치입니다.아직 정의를 못 내렸어요.scl그리고..type아직입니다. 몇 가지 글로벌 변수를 정의하면 어느 정도 빛을 얻을 수 있습니다.

첫 번째 세 가지 명령어는 스택프레임을 셋업하는 것입니다.이것은 서브루틴의 작업용 스토리지 기술 용어입니다.대부분 로컬 변수와 임시 변수입니다.밀어넣기ebp는 발신자 스택프레임의 베이스를 저장합니다.놓는 것espebp스택 프레임의 베이스를 설정합니다.andl얼라인먼트를 로 하는 SIMD 얼라인먼트는 의 얼라인먼트를 로 하지만 얼라인먼트는 16바이트의 통상 합니다).int §floats.

되면 기대하게 esp로컬 변수에 스택스페이스를 할당하기 위해 메모리 아래로 이동합니다.의 ★★★★★★★★★★★★★★★★★.main 때문에 gcc는 상관없습니다.gcc 없 、 has 、 has 、 has has has has has 。

의 콜__main는 메인 진입점에 특수하며 일반적으로 서브루틴에는 표시되지 않습니다.

나머지는 네가 추측한 대로다. ★★★★★eax는, spec에 입니다. leave하고, 「」를 실행해 주세요.ret발신자에게 돌아갑니다.는 추가 매직 등)을 C 입니다.atexit()프로세스의 종료 코드를 설정하고 운영체제에 프로세스 종료를 요청합니다.

그것에 대해 $16,%esp

  • 32비트: -16(십진수)은 0xffffff0(16진수)과 같습니다.
  • 64비트: -16(십진수)은 0xffffffffffffff0(16진수)과 같습니다.

따라서 ESP의 마지막 4비트(btw: 2**4는 16)를 마스크하고 다른 모든 비트를 유지합니다(타깃 시스템이 32비트인지 64비트인지에 관계없이).

★★★★★★★★에 대해서andl $-16,%esp은 낮은 0으로 조정되기 때문에 %esp x86에서는 스택의 가치가 낮아집니다.

내가 모든 답을 가진 것은 아니지만 내가 아는 것을 설명할 수 있다.

ebp하기 위해 합니다.esp흐름 중에 인수가 함수에 전달되는 위치와 자체 로컬 변수가 있는 위치를 참조합니다.입니다.ebppushl %ebp하며, 을 자신의 위치인 「스택의 위치」, 「스택의 위치」로하는 것보다 espmovl %esp, %ebp의를 0으로 .ebp이 시점에서는 GCC에 따라 다릅니다만, 이 컴파일러가 왜 그렇게 하는지 모르겠습니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★를 시작하겠습니다.call ___main , __main은 입니까? 많을 수 GCC와 함께0 으로 합니다.마지막으로 main()이 유일하게 하는 것은 반환값을 0으로 설정하는 것입니다.movl $0, %eax ★★★★★★★★★★★★★★★★★」leave 랑 똑같다movl %ebp, %esp; popl %ebp원상 ebp그 후 "displaces", "displaces"ret완성할 수 있습니다. reteip그 시점부터 스레드 플로우를 계속합니다(메인으로서 이 재시도에서는 프로그램의 끝을 처리하는 커널 프로시저가 발생할 가능성이 있습니다).

대부분은 스택 관리에 관한 것입니다.얼마 전에 스택의 사용법에 대한 자세한 튜토리얼을 썼는데, 그 이유를 설명하면 도움이 될 것 같습니다.근데 포르투갈어로...

언급URL : https://stackoverflow.com/questions/1317081/gccs-assembly-output-of-an-empty-program-on-x86-win32

반응형