进行顺序 C 调用时,在 MacOS 上的 x86 程序集中出现堆栈对齐错误?
Getting stack alignment error in x86 Assembly on MacOS when making sequential C calls?
我目前正在学习 MacOS 上的 x86 汇编,每当进行两次 C 调用时,我都会收到堆栈未对齐错误。
我已经尝试过使用适当的堆栈填充,确保堆栈大小为 12 字节以满足 MacOS 进行额外推送时的 16 字节堆栈对齐。
我在 mac x86 汇编中用谷歌搜索了 C 调用,但我似乎无法找到不仅仅是调用的示例,然后退出。我相信在使堆栈未对齐的调用之后我没有正确执行一些堆栈清理,但我似乎无法弄清楚。
_main:
# First open the file?
# int open(const char *path, int flags, ...)
subl [=10=]x04, %esp # Pad the stack
pushl [=10=]x0 # 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 [=10=]x08, %esp # Stack padding
pushl $fd # Push the file descriptor onto the stack
call _close # Close that bitch
# Display a nice message and leave
subl [=10=]x08, %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_
有人知道我到底做错了什么吗?
问题是您假设堆栈在调用 C 函数后再次按 16 字节对齐 returns。不是。它与您的 call
指令之前相同,少了 4 个字节。
_main:
# on entry, %esp is 0x...0 (last digit is 0, 16-byte aligned)
subl [=10=]x04, %esp # Pad the stack
# %esp is 0x...c
pushl [=10=]x0 # 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 [=10=]x08, %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
...
我目前正在学习 MacOS 上的 x86 汇编,每当进行两次 C 调用时,我都会收到堆栈未对齐错误。
我已经尝试过使用适当的堆栈填充,确保堆栈大小为 12 字节以满足 MacOS 进行额外推送时的 16 字节堆栈对齐。
我在 mac x86 汇编中用谷歌搜索了 C 调用,但我似乎无法找到不仅仅是调用的示例,然后退出。我相信在使堆栈未对齐的调用之后我没有正确执行一些堆栈清理,但我似乎无法弄清楚。
_main:
# First open the file?
# int open(const char *path, int flags, ...)
subl [=10=]x04, %esp # Pad the stack
pushl [=10=]x0 # 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 [=10=]x08, %esp # Stack padding
pushl $fd # Push the file descriptor onto the stack
call _close # Close that bitch
# Display a nice message and leave
subl [=10=]x08, %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_
有人知道我到底做错了什么吗?
问题是您假设堆栈在调用 C 函数后再次按 16 字节对齐 returns。不是。它与您的 call
指令之前相同,少了 4 个字节。
_main:
# on entry, %esp is 0x...0 (last digit is 0, 16-byte aligned)
subl [=10=]x04, %esp # Pad the stack
# %esp is 0x...c
pushl [=10=]x0 # 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 [=10=]x08, %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
...