在 x86 汇编中,ESP 是否在调用后递减两次,然后在数据保存到堆栈之前压入?

2023-12-19

长话短说,我正在学习 Singh 和 Triebel 写的一本名为“8088 和 8086 微处理器”的书,以学习old那些特定CPU的汇编。现在,我练习的计算机是我最近组装的主计算机,因此寄存器更大。

也就是说,这本书(我发现这非常有帮助)说调用标签操作数导致调用后的指令地址被放置在堆栈上,然后SP减 2 (ESP,并在我的 CPU 上减 4)。在我正在研究的一些代码中,调用操作数后面紧跟着一个push。当CPU遇到一个push,书中指出SP减二(同样,ESP在我的 CPU 上减 4)。

; ESP=0xffffd840 right now
call iprint
mov eax, 0Ah

iprint:
push eax ; say eax contains 1

现在,说ESP=0xffffd840在通话之前。地址为EIP保存在堆栈上(紧随其后的指令的地址CALL操作数)。然后ESP减4。此时,ESP=0xffffd83c。然后遇到push操作数。按照书上的说法,首先将堆栈指针递减,然后将寄存器的内容压入堆栈。所以现在ESP=0xffffd838并且 1 被压入堆栈。

If it helps:
Stack addr  Contents
********** ********
0xffffd840  address of mov eax, 0Ah
0xffffd83c  ?
0xffffd838  1

现在,我的问题是0xffffd83c跳过?据书中所述,ESP保存后的下一条指令后递减call,然后在将数据放入堆栈之前push,再次减少。

我已经调试类似的场景有一段时间了,密切关注寄存器的值,但我无法判断调试器是否遵循书中所说的内容(在执行操作之前或之后递减)。

这是因为在某些情况下参数是在后面给出的RET在子程序中,导致堆栈指针递增?如果堆栈指针在放入数据之前确实递减两次,那么这是我能看到的唯一原因。

如果我有这个错误,有人可以确认或解释一下吗?

谢谢


The call <address>就好像:push eip jmp <address>,所以在你的情况下如果esp is 0xffffd840领先于call,下一条指令的返回地址被压入0xffffd83c(因为伪“push eip" 将首先递减esp创建新的栈顶,然后它将存储当前值eip那里(之间,eip已经指向下一条指令,作为获取+解码指令阶段call已完成,因此它实际上是所需的值ret).

您还可以在调试器中查看内存。而“栈”只是普通的内存。所以如果你有esp等于0xffffd840,您可以打开例如内存视图0xffffd824,您将看到 32 字节的堆栈内存,其中 28 字节尚未使用,最后 4 字节是当前的“堆栈顶部”。

我到处都使用 4 个字节组,因为这是 CPU“字”的本机大小(dword在 x86 术语中,word仅 16 位)在 32b 保护模式下。 IIRC你仍然可以强制CPU做push ax or use sub/add esp,immediate甚至可以将其移动单个字节,但通常会涉及性能损失,并且在 64b 模式下,多个调用约定甚至需要 16 字节对齐,因此我建议坚持使用 +-4esp32b 模式下的操作。

但如果你的书是关于8086的,你可能想使用dosbox模拟旧的 DOS 16 位环境,以避免一开始出现一些特定于平台的问题。虽然也许你应该为你的操作系统找到一些最近的 32/64 位书籍,因为 x86 上的 32b 保护模式更容易学习(只是图形输出不像 DOS 时代那么简单,但如果你愿意的话)将你的asm文件与C++“加载器”混合,例如将一些窗口表面初始化为ARGB内存数组,你可以将该指针向下传递给asm例程并玩弄像素,以同样简单的方式,旧的320x200“ DOS 中的模式 13h" 有效。甚至更简单(没有调色板,也没有 64k 段限制)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 x86 汇编中,ESP 是否在调用后递减两次,然后在数据保存到堆栈之前压入? 的相关文章

  • 如何从 obj-c / ios 中的堆栈跟踪获取源代码行

    I use NSSetUncaughtExceptionHandler将堆栈跟踪打印到 iPhone 中的本地文件 该文件将在下次应用程序启动时发送到我们的服务器 然后我可以检查异常数据并修复错误 在某些崩溃中 我有模块名称和引发异常的函数
  • 如何避免将相同的片段添加到堆栈中

    我需要一些帮助 他们以这种方式将片段添加到活动中 问题是每次调用 openFragment 时都会创建片段并添加 这是显而易见的 问题 我做了什么修改 这样它只能添加一次片段 在下次使用相同片段标签的调用时 它将什么也不做 案例 第一次按下
  • 在java中获取调用层次结构

    我在追踪错误时遇到了很大的困难 了解哪个方法调用了某个方法会很有帮助 有没有一种简单的方法可以从java获取调用层次结构 Java 是应用程序的一小部分 因此我无法在 eclipse net beans 中编译和运行整个应用程序 因此我无法
  • 使用 Easy 68K (68000) 组装范围内的随机数

    我正在使用 Easy 68K 模拟器创建一个简单的黑杰克游戏 需要使用随机数来分配牌 我的牌必须在 2 到 11 的范围内 我似乎每次都得到相同的数字 但它不在我预期的范围内 我的卡值需要以 D3 结束 因此我有以下随机数代码 CLR L
  • Intel 64 和 IA-32 上的 MESI 有何意义

    MESI 的要点是保留共享内存系统的概念 然而 对于存储缓冲区 事情就变得复杂了 一旦数据到达 MESI 实现的缓存 下游内存就会保持一致 然而 在此之前 每个核心可能对内存位置 X 中的内容存在分歧 具体取决于每个核心的本地存储缓冲区中的
  • 寄存器寻址模式与直接寻址模式

    我在试卷中遇到过这个问题 它指出 哪种给定的寻址模式更快 为什么 寄存器寻址方式 直接寻址方式 现在根据我的说法 寄存器寻址模式应该更快 因为寄存器是计算机中最快的存储位置 这是正确答案吗 请帮忙 谢谢 两种寻址模式之间的区别是 地址的来源
  • 在 android studio 上单击推送通知后重定向到特定活动

    我正在努力开发一个 Android 应用程序 以便在单击所有传入的推送通知时将应用程序重定向到特定的活动页面 我是 Android 开发新手 对我的编程感到抱歉 下面是推送通知部分的 android manifest xml 如果对此主题有
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 为什么我的空循环在 Intel Skylake CPU 上作为函数调用时运行速度是原来的两倍?

    我正在运行一些测试来比较 C 和 Java 并遇到了一些有趣的事情 在 main 调用的函数中 而不是在 main 本身中 运行具有优化级别 1 O1 的完全相同的基准代码 导致性能大约翻倍 我正在打印 test t 的大小 以毫无疑问地验
  • ARMv8 A64 汇编中立即值的范围

    我的理解是 ARMv8 A64 汇编中的立即参数可以是 12 位长 如果是这样的话 为什么这行汇编代码是 AND X12 X10 0xFEF 产生此错误 使用 gcc 编译时 Error immediate out of range at
  • 从 exe 文件中获取汇编级代码?

    我当时正在做linux汇编编程 在过去的几天里我已经转而学习windows汇编编程 我在用ml作为我的汇编器和golink作为我的链接器 我有我的汇编代码并已获得我的exe从中 现在我需要取回它的十六进制 xff xab x55等等 在li
  • 程序集比较标志理解

    我正在努力理解汇编程序中的以下代码片段 if EAX gt 5 EBX 1 else EBX 2 在汇编程序中 可以写如下 根据我的书 模拟jge操作说明 https www felixcloutier com x86 jcc您通常会使用
  • Android 堆栈大小

    我如何获取和更改 Android 应用程序的堆栈大小 即使是主线程 主线程堆栈大小是在固件中设置的 无法修改 除非修改您自己手机的固件 正如斯特朗先生指出的那样 对于您分叉的线程 您可以设置自己的堆栈大小
  • Git - 推送到远程存储库中的远程跟踪分支

    当简单地做git push到远程存储库 其master分支得到更新 对于非裸存储库来说 这是不希望出现的情况 最近的 Git 版本显示的警告消息清楚地表明了这一点 我希望能够推送到远程存储库 并拥有其之一远程追踪分支进行更新 稍后 当我登录
  • 保存和恢复陷阱状态?管理多个陷阱处理程序的简单方法?

    有什么好的方法可以覆盖bash陷阱处理程序不会永久破坏可能已设置或尚未设置的现有处理程序 动态管理任意陷阱例程链怎么样 有没有办法保存陷阱处理程序的当前状态 以便以后可以恢复 在 Bash 中保存和恢复陷阱处理程序状态 我将提交以下堆栈实现
  • AVX-512 指令编码 - {er} 含义

    在 Intel x86 指令集参考中 有许多 AVX 512 指令在指令中具有可选的 er 例如 VADDPD 的一种形式定义为 EVEX NDS 512 66 0F W1 58 r VADDPD zmm1 k1 z zmm2 zmm3 m
  • 长多字节 NOP:通常理解的宏或其他符号

    x86 和 x86 64 处理器不仅具有单字节 这不是什么大秘密NOP指令 还包括各种类型的多字节类 NOP 指令 这些是我设法找到的 AMD 推荐 参考 AMD 系列 15h 处理器的 AMD 软件优化指南 文档 47414 http s
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐

  • JMeter JSON Extractor 按条件获取值

    I get a JSON像这样的字符串 id 123 name XX default false type other id 789 name ZZ default false type first 我想得到id 其中名称是ZZ 所以提取的
  • 将 svelte 应用程序构建为一组静态文件

    我想在我的下一个项目中使用 Svelte 因为它的语法简洁并且使用起来非常愉快 不幸的是 要在我的公司部署该应用程序 我无法使用node或服务器上类似的东西 我只能从以下位置提供应用程序nginx作为静态文件 苗条有可能吗 我找不到任何可以
  • 即使套接字是非阻塞的,Perl 上的 recv 也会阻塞

    我在守护进程中用 perl 创建了一个像这样的套接字 IO Socket INET gt new LocalPort gt port Proto gt udp Blocking gt 0 or die socket 在 Linux 机器上
  • 如何在启动时检查麦克风访问情况?

    在我的应用程序中 我将使用麦克风进行一些录音 从iOS7 0开始 用户在开始音频之前会被要求检查访问麦克风的权限 我的应用程序中有一个 开始录制 按钮 这里它首先检查用户的录音权限 这是执行此操作的代码 if AVAudioSession
  • 获取文档后从 Firestore 获取文档 ID

    成功获取文档后如何获取 firestore 文档的文档 id 我正在从这样的 firestore 集合中获取用户数据 const ref await db collection users where phone phone where p
  • 从 Android 模拟器中删除密码?

    如何摆脱 摆脱Android模拟器中的 输入密码解锁 提示 希望我能解释一下这是如何打开的 但这可能是我的错 我一直在尝试使用 android maven 插件为自定义内核构建应用程序 以构建自定义设备管理应用程序 我记得在模拟器中找到了一
  • 解压文件跳过文件夹

    我正在创建一个 php 文件 该文件将从 BitBucket Git 存储库 中拉出后更新我的网站 它下载整个主文件或提交的 zip 文件 然后将其解压缩到网站的文件夹中 我遇到的问题是有一个随机命名的文件夹 其中包含 zip 文件中的所有
  • 解决方案的 NuGet 包还原失败(仅在命令行上)

    我最近切换到 NuGet 最新推荐的方法 该方法为项目使用 packages json 文件 dependencies Newtonsoft Json 9 0 1 RestSharpSigned 105 2 3 frameworks net
  • IE 中的 SVG 动画笔划-dashoffset - 笔划宽度为 0

    我正在尝试使用 SVG 制作圆形填充动画 它在 Chrome FF Safari 中工作得很好 但在 IE 中动画不会发生 我正在使用 jQuery animate 不是 css 动画 IE 11 及以下版本不支持 SVG 简化的动画代码
  • 当应用程序进入后台时如何继续运行 NSTimer

    我正在创建益智游戏应用程序 并使用 NSTimer 显示时间 即 01 20 当应用程序进入后台时 NSTimer 会暂停 但即使应用程序处于后台状态 我也想继续它 例如当应用程序进入后台时 计时器计数为 15 秒 and I 放置5秒现在
  • 如何在Python中格式化浮点数? [复制]

    这个问题在这里已经有答案了 我想将浮点数格式化为小数点后两位 gt gt gt x 5 0 gt gt gt y float 0 2f format x gt gt gt y 5 0 我希望我的输出采用这种格式 5 00 对于较新版本的 p
  • 什么时候*不*使用准备好的语句?

    我正在重新设计一个使用最小数据库的 PHP 驱动的网站 原始版本使用 伪准备语句 进行引用和参数替换的 PHP 函数 来防止注入攻击并将数据库逻辑与页面逻辑分开 用使用 PDO 和真正准备好的语句的对象替换这些临时函数似乎很自然 但在阅读它
  • Android Beep 或 Light 没有通知对象?

    有没有办法在没有通知实例的情况下启动蜂鸣声 是的 蜂鸣声 或打开设备的灯 有了通知就很简单 如下所示 http developer android com guide topics ui notifiers notifications ht
  • Ruby 1.9 与 Rails 2.3 兼容吗?

    ruby 1 9 可以与rails 2 3 一起使用吗 我知道 Rails 2 3 5 可以与 ruby 1 9 1 一起运行 但是 您需要仔细检查要与 ruby 1 9 一起使用的任何 gem 或插件 看看它们是否有效
  • keras 中一维卷积网络的输入维度

    确实很难理解卷积 1d 的输入维度layer http keras io layers convolutional convolution1d在喀拉斯 输入形状 具有形状的 3D 张量 样本 步长 input dim 输出形状 形状为 sa
  • Woocommerce 更新结帐 ajax

    由于我对 1 个产品使用 onepager 因此当我将产品添加到购物车时 我想利用 wordpress ajax 来更新现场结账 产品添加到购物车按钮已经是ajax了 我已经尝试过 body trigger update checkout
  • 在 R 中使用 ggplot 绘制谷歌地图

    我正在尝试绘制使用 RgoogleMaps 包查询并将其与 ggplot 结合起来 最后 我想显示使用的总人口geom point 有点类似于下图 但由于过度绘制 我试图将注意力集中在蒙哥马利地区 我很沮丧 因为我无法在 R 中绘制查询的地
  • 如何在SQL Server 2008中部署CLR功能

    我在 VS2008 中创建了一个名为 RegularExpression 的 SQL Server 项目 在该项目中 我创建了一个 Regex cs 类 并编写了一个有关正则表达式的函数 然后我构建解决方案 现在我的问题是通过脚本在SQL
  • 为什么 expat 拒绝短划线字符作为无效字符?

    在我的 XML 输入文件中 有以下行
  • 在 x86 汇编中,ESP 是否在调用后递减两次,然后在数据保存到堆栈之前压入?

    长话短说 我正在学习 Singh 和 Triebel 写的一本名为 8088 和 8086 微处理器 的书 以学习old那些特定CPU的汇编 现在 我练习的计算机是我最近组装的主计算机 因此寄存器更大 也就是说 这本书 我发现这非常有帮助