我目前正在MacOS上学习x86汇编,并且每当进行两次C调用时都会遇到堆栈未对齐错误。
我已经尝试使用适当的堆栈填充,确保MacOS额外推动时确保堆栈大小为12字节,以满足16字节的堆栈对齐。
我已经在Mac x86汇编中谷歌进行了C调用,但是我似乎找不到除调用之外的示例,然后退出。我相信在进行一些导致堆栈未对齐的调用后,我无法正常进行堆栈清理,但是我似乎无法弄清楚。
_main:
# First open the file?
# int open(const char *path, int flags, ...)
subl $0x04, %esp # Pad the stack
pushl $0x0 # This is the flag for O_RDONLY
pushl $path # Then add the path
call _open # Make the call to open
movl %eax, fd # Put the file descriptor into the fd variable
# Let's just close the file
# int close(int fd);
subl $0x08, %esp # Stack padding
pushl $fd # Push the file descriptor onto the stack
call _close # Close that bitch
# Display a nice message and leave
subl $0x08, %esp # Buffer da stackaroo
pushl $end_message # Put our message on da stack
call _printf # Print the message
# Goodbye :)
call _exit
从理论上讲,这应该只是打开和关闭文件描述符,并且在我刚打开它时就可以使用,但是一旦我添加了关闭它的代码(或者只是printf代码,它就会失败)。
这是我从lldb
得到的完整错误:
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0xa7aa6bd0 libdyld.dylib`misaligned_stack_error_
有人在这里看到我到底在做什么错吗?
答案 0 :(得分:1)
问题是您假设在对C函数的调用返回后,堆栈再次按16字节对齐。不是。与您的call
指令之前相同,但减少了4个字节。
_main:
# on entry, %esp is 0x...0 (last digit is 0, 16-byte aligned)
subl $0x04, %esp # Pad the stack
# %esp is 0x...c
pushl $0x0 # This is the flag for O_RDONLY
# %esp is 0x...8
pushl $path # Then add the path
# %esp is 0x...4
# call will push 4-byte return address, making %esp on entry to open() 0x...0
call _open # Make the call to open
# open()'s ret will pop the 4-byte return address, putting %esp back to 0x...4
movl %eax, fd # Put the file descriptor into the fd variable
subl $0x08, %esp # Stack padding
# %esp is 0x...c
pushl $fd # Push the file descriptor onto the stack
# %esp is 0x...8
# call will push 4-byte return address, making %esp on entry to close() 0x...4
# that's mis-aligned
call _close # Close that bitch
...