我试图清楚地了解谁(调用者或被调用者)负责堆栈对齐。 64 位汇编的情况很清楚,它是由caller 完成的。
引用 System V AMD64 ABI,第 3.2.2 节堆栈框架:
The end of the input argument area shall be aligned on a 16 (32, if __m256 is passed on stack) byte boundary.
换句话说,应该安全地假设,对于被调用函数的每个入口点:
16 | (%rsp + 8)
持有(额外八个是因为call 隐含地将返回地址压入堆栈)。
它在 32 位世界中看起来如何(假设 cdecl)?我注意到 gcc 使用以下构造将对齐放在被调用函数中:
and esp, -16
这似乎表明,这是被调用者的责任。
为了更清楚,请考虑以下 NASM 代码:
global main
extern printf
extern scanf
section .rodata
s_fmt db "%d %d", 0
s_res db `%d with remainder %d\n`, 0
section .text
main:
start 0, 0
sub esp, 8
mov DWORD [ebp-4], 0 ; dividend
mov DWORD [ebp-8], 0 ; divisor
lea eax, [ebp-8]
push eax
lea eax, [ebp-4]
push eax
push s_fmt
call scanf
add esp, 12
mov eax, [ebp-4]
cdq
idiv DWORD [ebp-8]
push edx
push eax
push s_res
call printf
xor eax, eax
leave
ret
调用scanf前是否需要对齐栈?如果是这样,那么这将需要在将这两个参数推送到 scanf 之前将 %esp 减少四个字节:
4 bytes (return address)
4 bytes (%ebp of previous stack frame)
8 bytes (for two variables)
12 bytes (three arguments for scanf)
= 28
最佳答案
GCC 仅 在 main 中执行此额外的堆栈对齐;该函数很特殊。如果您查看任何其他函数的代码生成,您将看不到它,除非您有一个带有 alignas(32) 或其他东西的本地文件。
GCC 只是对 -m32 采取防御性方法,不假设 main 是使用正确的 16B 对齐堆栈调用的。或者这种特殊处理是 -mpreferred-stack-boundary=4 只是一个好主意,而不是法律时遗留下来的。
i386 System V ABI 多年来一直保证/要求 ESP+4 在函数入口处是 16B 对齐的。 (即 ESP 在 CALL 指令之前必须是 16B 对齐的,因此堆栈上的参数从 16B 边界开始。这与 x86-64 System V 相同。)
ABI 还保证新的 32 位进程以在 16B 边界上对齐的 ESP 开始(例如,在 _start,ELF 入口点,其中 ESP 指向 argc,而不是返回地址), glibc CRT 代码保持这种对齐。
就调用约定而言,EBP 只是另一个调用保留寄存器。但是,是的,带有 -fno-omit-frame-pointer 的编译器输出确实会在其他调用保留寄存器(如 EBX)之前注意 push ebp,因此保存的 EBP 值形成一个链表。 (因为它还在推送之后设置帧指针的 mov ebp, esp 部分。)
也许 gcc 是防御性的,因为一个非常古老的 Linux 内核(从 i386 ABI 的修订版之前,当所需的对齐仅为 4B 时)可能违反该假设,并且它只是在生命中运行一次的额外指令 -进程时间(假设程序不递归调用 main)。
与 gcc 不同,clang 假定堆栈在进入 main 时正确对齐。 (clang 也是 assumes that narrow args have been sign or zero-extended to 32 bits ,即使当前的 ABI 修订版还没有指定该行为。gcc 和 clang 都发出在调用方执行的代码,但只有 clang 在被调用方依赖它。这发生在 64位代码,但我没有检查 32 位。)
查看 http://gcc.godbolt.org/ 上的编译器输出对于 main 和除 main 之外的函数,如果你好奇的话。
我刚刚更新了 x86 中的 ABI 链接前几天标记 wiki。 http://x86-64.org/仍然死了,似乎不会回来,所以我更新了 System V 链接以指向 HJ Lu 的 github 存储库中当前修订版的 PDF,和 his page with links .
请注意 last version on SCO's site 不是当前修订版,并且不包括 16B 堆栈对齐要求。
我认为某些 BSD 版本仍然不需要/保持 16 字节堆栈对齐。
关于linux - 32 位 x86 汇编中堆栈对齐的职责,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40307193/
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
在我的mac上安装几个东西时遇到这个问题,我认为这个问题来自将我的豹子升级到雪豹。我认为这个问题也与macports有关。/usr/local/lib/libz.1.dylib,filewasbuiltfori386whichisnotthearchitecturebeinglinked(x86_64)有什么想法吗?更新更具体地说,这发生在安装nokogirigem时日志看起来像:xslt_stylesheet.c:127:warning:passingargument1of‘Nokogiri_wrap_xml_document’withdifferentwidthduetoproto
我们在服务器端遇到libxml-rubygem的问题可能是因为它使用x86_64架构:$uname-aLinuxip-10-228-171-642.6.21.7-2.fc8xen-ec2-v1.0#1SMPTueSep110:25:30EDT2009x86_64GNU/Linuxrequire'libxml'LoadError:/usr/local/ruby-enterprise/lib/ruby/gems/1.8/gems/libxml-ruby-1.1.4/lib/libxml_ruby.so:invalidELFheader-/usr/local/ruby-enterprise/
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
Linux操作系统——网络配置与SSH远程安装完VMware与系统后,需要进行网络配置。第一个目标为进行SSH连接,可以从本机到VMware进行文件传送,首先需要进行网络配置。1.下载远程软件首先需要先下载安装一款远程软件:FinalShell或者xhell7FinalShellxhell7FinalShell下载:Windows下载http://www.hostbuf.com/downloads/finalshell_install.exemacOS下载http://www.hostbuf.com/downloads/finalshell_install.pkg2.配置CentOS网络安装好
文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分
如何在Ruby中获取linux系统(这必须适用于Fedora、Ubuntu等)的软件/硬件信息? 最佳答案 Chef背后的优秀人才,拥有一颗名为Ohai的优秀gemhttps://github.com/opscode/ohai以散列形式返回系统信息,例如操作系统、内核、规范、fqdn、磁盘、空间、内存、用户、接口(interface)、sshkey等。它非常完整,非常好。它还会安装命令行二进制文件(也称为ohai)。 关于ruby-如何在Ruby中获取linux系统信息,我们在Stack
我在LinuxMint17.2上。我最近使用apt-getpurgeruby删除了ruby。然后我安装了rbenv然后rbenvinstall2.3.0所以现在,~/.rbenv/versions/2.3.0/bin/ruby存在。但是现在,我无法执行geminstallrubocop。我明白了:$geminstallrubocoprbenv:gem:commandnotfoundThe`gem'commandexistsintheseRubyversions:2.3.0但是我可以~/.rbenv/versions/2.3.0/bin/geminstallrubocop。但是,
我是Ruby和RoR的新手。我有一个带有Ubuntu镜像的干净Linode实例,我想从源代码编译Ruby而不是使用apt-get。我已经在谷歌上搜索了执行此操作的说明,但经过一些尝试后,当我尝试运行一些教程示例时,我不断收到有关缺少zlib和其他一些包的错误。任何人都可以给我详细的说明(或链接),教我如何在从源代码编译Ruby之前安装必要的必备包吗?我的目的是编译Ruby的最新稳定版本,然后安装Rubygems和Rails。提前感谢您的帮助!!! 最佳答案 Thisblogpost涵盖从源代码编译ruby所需的包和安装过程;它引
我有Sinatra应用程序,需要测试我的应用程序。features/support/env.rb:require_relative"../../application"require"capybara"require"capybara/cucumber"require"rspec"WorlddoCapybara.app=ApplicationincludeCapybara::DSLincludeRSpec::Matchersendfeatures/one.feature:Feature:TesthomepageInordertomakesurepeoplecanopenmysiteIw