代码段错误,除非增加esp [英] Code segfaults unless esp incremented

查看:99
本文介绍了代码段错误,除非增加esp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下所有代码要做的就是使用CoreFoundation函数打印Hello World.但是,每当我似乎有正确对齐的堆栈时,它就无法正常工作,例如段错误.但是,当我终于知道它工作时,堆栈并没有对齐?!?!?!

I have the following code all it is suppose to do is print Hello World using CoreFoundation functions. However whenever I seemingly have a proper aligned stack it doesn't work, seg faulting. But then when I finally got it working the stack isn't aligned?!?!?!

global  _main

align 4, db 0x90

extern _CFStringCreateWithCString
extern _CFShow

section .data
    hw:  db 'Hello World!' ,0xA,0

section .text
    _main: ; entering a new function stack must be balanced right?

    push ebp ; saving ebp  (esp + 4)
    mov  ebp, esp ; moving registers around 
    ; align stack as calling pushed a 4 byte address on to the stack
    sub  esp, 12 ; balancing the stack back to mod 16 (4 + 12 = 16)


    push 8   ; 4 bytes
    push hw  ; 4 bytes
    push 0   ; 4 bytes
    call _CFStringCreateWithCString ; 4 bytes

    ; stack still balanced

    sub  esp, 12 ; 12 bytes
    push eax     ; 4 bytes
    call _CFShow ; 4 bytes

    ; that is 20 bytes?!?!? yet when I change the 12 to an 8 it doesn't run and instead segfaults! When I have the stack balanced!


    mov eax, 99 ; return value

    mov esp, ebp ; restore stack for function that called us
    pop ebp
    ret          ; return

运行时它可以工作,但是我找不到原因.对于一个参数函数,我必须从esp中减去12.它不应该是8,不是已经推入了处理递增自变量的堆栈了吗?

When run it works, however I can find no reason why it does. I have to subtract 12 from esp for a one argument function. Shouldn't it be 8, doesn't push already handle incrementing the stack for the argument?

推荐答案

我不确定为什么原始函数会在不使用在堆栈上分配的空间的情况下,从堆栈中进行额外的减法.堆栈在x86上逐渐变小.在这种情况下,如果您这样做:

I'm not sure why the original function is doing additional subtractions from the stack without using the space which is so allocated on the stack. The stack grows down on the x86. In this context, if you do:

sub esp, NUMBER

您正在堆栈中分配(可用)NUMBER个字节以用于某些目的.

you are allocating (making available) NUMBER bytes on the stack to be used for some purpose.

我假设库遵循C调用约定:

I'm making an assumption that the library follows a C calling convention:

1) Push the parameters (in reverse order) onto the stack
2) Call the function
3) Restore the stack based upon the amount of space used by the prior pushes.

记住这些事情,这就是我编写您的函数的方式:

With these things in mind, here's how I'd write your function:

global  _main

align   4, db 0x90

extern _CFStringCreateWithCString
extern _CFShow

section .data
hw: db 'Hello World!' ,0xA,0

section .text
_main: ; entering a new function stack must be balanced right?

    push   ebp         ; saving ebp  (esp + 4)
    mov    ebp, esp    ; set stack frame pointer 

    push   8           ; String encoding - 4 bytes
    push   hw          ; String pointer - 4 bytes
    push   0           ; Allocator [0 for default] - 4 bytes
    call   _CFStringCreateWithCString
    add    esp, 12     ; restore the stack [pop the 12 bytes back off]

    push   eax         ; Address of string to show (returned by prior call) - 4 bytes
    call   _CFShow
    add    esp, 4      ; restore the stack [pop the 4 bytes back off] NOT NEEDED with 

    mov    eax, 99     ; return value

    mov    esp, ebp    ; restore stack for function that called us
    pop    ebp
    ret

请注意,由于最后一条mov指令将恢复堆栈,因此可以省略最后一条add esp,4,但这是为了完整性.

Note that since the last mov instruction restores the stack, then the last add esp,4 could be omitted, but it's here for completeness.

MacOS要求/保证用于函数调用的堆栈指针的16字节对齐.为此:

MacOS requires / guarantees 16-byte alignment of the stack pointer for function calls. To do this:

global  _main

align   4, db 0x90

extern _CFStringCreateWithCString
extern _CFShow

section .data
hw: db 'Hello World!' ,0xA,0

section .text
_main:
 ; ESP was aligned before the call instruction pushed a return address
 ; now the nearest alignment boundaries are ESP+4 and ESP-12

    push   ebp         ; saving ebp  (esp + 4)
    mov    ebp, esp    ; set stack frame pointer 

 ; ESP-8 is 16-byte aligned; not enough room for 12 bytes of args
    sub    esp,12      ; So we have to go past that to aim for the *next* alignment boundary
    push   8           ; String encoding - 4 bytes
    push   hw          ; String pointer - 4 bytes
    push   0           ; Allocator [0 for default] - 4 bytes
    call   _CFStringCreateWithCString

    ;add    esp, 12+12 - 4    ; pop the padding and args, then sub 4 for 16-byte alignment on next call (after push)
    ;push   eax         ; Address of string to show (returned by prior call) - 4 bytes

    mov    [esp], eax   ; reuse the stack reservation; ESP is still aligned
    call   _CFShow
    add    esp, 12+12   ; restore the stack [pop the args + padding back off]

    mov    eax, 99     ; return value

    mov    esp, ebp    ; restore stack for function that called us
    pop    ebp
    ret

与第一种情况一样,最后一个add esp,24可以省略.

Likewise as in the first case, the last add esp,24 could be omitted.

这篇关于代码段错误,除非增加esp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆