programing

함수 arg에 액세스하기 위해 x86 스택을 popping할 때의 세그먼트화 오류

powerit 2023. 7. 22. 10:30
반응형

함수 arg에 액세스하기 위해 x86 스택을 popping할 때의 세그먼트화 오류

x86 어셈블리와 C를 연결하려고 합니다.

내 C 프로그램:

extern int plus_10(int);

# include <stdio.h>

int main() {
    int x = plus_10(40);
    printf("%d\n", x);
    return 0;
}

내 어셈블리 프로그램:

[bits 32]

section .text

global plus_10
plus_10:
    pop edx
    mov eax, 10
    add eax, edx
    ret

저는 다음과 같이 두 가지를 컴파일하고 연결합니다.

gcc -c prog.c -o prog_c.o -m32
nasm -f elf32 prog.asm -o prog_asm.o
gcc prog_c.o prog_asm.o -m32

그러나 결과 파일을 실행하면 분할 오류가 발생합니다.

하지만 내가 대체할 때

소아마비

와 함께

movedx, [syslog+4]

그 프로그램은 잘 작동합니다.누가 왜 이런 일이 일어나는지 설명해 주시겠습니까?

다음의 가능한 어셈블리 코드입니다.int x = plus_10(40);

        push    40                      ; push argument
        call    plus_10                 ; call function
retadd: add     esp, 4                  ; clean up stack (dummy pop)
        ; result of the function call is in EAX, per the calling convention

        ; if compiled without optimization, the caller might just store it:
        mov     DWORD PTR [ebp-x], eax  ; store return value
                                        ; (in eax) in x

이제 당신이 전화할 때plus_10주소retadd스택에 의해 밀립니다.call설명.그것은 사실상.push+jmp,그리고.ret효과적으로pop eip.

스택은 다음과 같이 표시됩니다.plus_10함수:

|  ...   |
+--------+
|   40   |  <- ESP+4 points here (the function argument)
+--------+
| retadd |  <- ESP points here
+--------+

ESP반환 주소가 포함된 메모리 위치를 가리킵니다.

이제 당신이 사용할 수 있습니다.pop edx반송 주소가 에 들어갑니다.edx스택은 다음과 같습니다.

|  ...   |
+--------+
|   40   |  <- ESP points here
+--------+

이제 당신이 실행하면,ret이 시점에서 프로그램은 실제로 40 주소로 점프하여 segfault 또는 다른 예측 불가능한 방식으로 동작합니다.

컴파일러에 의해 생성된 실제 어셈블리 코드는 다를 수 있지만 이는 문제를 보여줍니다.


그나저나 함수를 작성하는 더 효율적인 방법은 다음과 같습니다. 대부분의 컴파일러는 이 작은 함수의 비선형 버전에 대해 최적화를 활성화하면 이 작업을 수행합니다.

global plus_10
plus_10:
    mov   eax,  [esp+4]    ; retval = first arg
    add   eax,  10         ; retval += 10
    ret

이것은 보다 작고 약간 더 효율적입니다.

    mov   eax,  10
    add   eax,  [esp+4]        ; decode to a load + add.
    ret

언급URL : https://stackoverflow.com/questions/56113827/segmentation-fault-when-popping-x86-stack-to-access-function-arg

반응형