汇编学习之《指针寄存器&大小端学习》

什么是指针寄存器?

操作栈的寄存器

栈: 保存函数里面传递的参数,局部变量等。

EBP: 指向栈底的指针

ESP: 指向栈顶的指针。

计算入栈地址变化规则

通过OllDbg查看

有可能点击安装的时候栈区域第一次查看会没有显示上面的标题区域,可以通过右键点击栈区域

选择Appearanzhix选择show bar 就有了,其他几个区域一样的。

现在我们尝试通过F8执行一次push 命令来看栈顶指针寄存器的地址和数据变化。

首先我们需要通过F8执行让CPU执行到push 命令处停下来,并记录相关信息。 比如我这里。

(如果要和我一样,先修改EAX 累加寄存器的值为 00000022,修改指令为push EAX,栈顶寄存器值可能不一样。其实也没必要,大家可以看自己的数据,按照下面的规则算就可以了)

执行推送前信息:

当前CUP位置是待执行的push 指令 : push EAX; 推送累加寄存器的值到栈顶。

当前 EAX 的值是: 00000022

当前ESP栈顶的地址是: 0199F7D4

当前ESP栈顶地址的对应的值是: 15F58E65

执行推送后,我们期望的信息:

当前 EAX 的值是: 00000022 不变

当前ESP栈顶的地址是: 0199F7D0

当前ESP栈顶地址的对应的值是: 00000022

备注: 这里要说明下,为啥栈顶地址从0199F7D4变成了0199F7D0,这个是因为栈顶插入了4个字节,所以内存地址向高位偏移了4个字节。

我们尝试执行下,看看数据是否是我们预期的。

最终确认,以上数据符合预期

练习题

我们上章节学习了 16位寄存器, 高八位寄存器,低八位寄存器。假如我们的指令是

push ax指令,那么数据又会怎么变化呢? 这里我们尝试一次。

先修改下数据,EAX 寄存器的值修改位 00001100

按F8执行语句,查看EAX的值,可以看到已经改变。

修改当前CPU执行位置的命令是: push ax

现在我们开始记录执行后续命令前的数据:

当前CUP位置是待执行的push 指令 : push ax; 推送累加寄存器的值到栈顶。

当前 EAX 的值是:00001100

当前ESP栈顶的地址是: 0199FA78

当前ESP栈顶地址的对应的值是: 76987BA9

执行推送后,我们期望的信息:

当前 EAX 的值是: 00001100 不变

当前ESP栈顶的地址是: 0199FA76

当前ESP栈顶地址的对应的值是:7BA91100

F8执行语句后查看数据

执行后的结果:

当前 EAX 的值是: 00001100 不变

当前ESP栈顶的地址是: 0199FA76

当前ESP栈顶地址的对应的值是:7BA91100

以上为啥结果我会标记为红色?

其实在这结果运行之前,我的预期运行结果是

当前 EAX 的值是: 00001100 不变

当前ESP栈顶的地址是: 0199FA76

当前ESP栈顶地址的对应的值是:76981100

为啥会犯这样的错误?

先说结果我忽略了数据是小端数据存储的。x86 架构采用小端字节序所以,其实我们通过OllDbg看到的数据并不是真实的内存展示的数据,也不是想当然的直接替换后面两个字节的数据。

当然如果你对这以上没有疑问,完全可以跳过后面的章节。接下来我会详细描述下大小端的概念,以及为啥运行 push ax 后ESP栈顶的值是7BA91100,而不是76981100。

大端和小端?

比如有一个数据: 0x76 98 7B A9

在解释大端和小端之前,我先说几个概念。

低位字节,高位字节概念:

比如数据 0x76 98 7B A9

0x76 就是最高位字节, 0xA9就是最低位字节。

高位字节 ---------------------------低位字节

0x76 0x98 0x7B 0xA9

为了帮忙你记住,你就按照家里你的兄弟排位来,第一个生的就是老大,排位最高,后面依次老二,老三。

低地址,高地址概念:

就是内存地址序,比如运行指令之前ESP栈顶0x0199FA78

连续四个字节那么它们的地址就依次是

低地址---------------------------------------------------------高地址

0x0199FA78,0x0199FA79,0x0199FA7A,0x0199FA7B

以上概念清楚后,我们就来说说大端和小端的内存数据是如何存储的。

大端:高位字节数据存入低地址,低位字节数据存入高地址。

小端:低位字节数据存入低地址,高位字节数据存入高地址。

基于X86架构平台都是小端,无论是win,linux 还是其他系统。 有的设备平台可能是大端。另外就是网络通信中,基于TCP/IP标准,网络字节序就是大端的。

有了上面概念后,就可以接受为什么我们执行push ax后结果为啥是7BA91100。

执行命令前,我们看看当时数据在内存中是怎么样的。

执行命令 push ax; 将数据1100写入ESP栈顶, ax 是十六进制,所以需要在0x0199FA78进制向左移动两个字节。变成从0x0199FA76开始

以上就是内存存储情况,将上面内存中的数据 OllDbg展示的数据就是 0x7BA91100。

如果有问题欢迎大家指出来,有疑问也可以一起讨论。

上一篇:汇编学习之《数据寄存器》

下一篇:汇编学习之《变址寄存器》

相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
我在人间贩卖青春6 天前
汇编之伪指令
汇编·伪指令
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛6 天前
计算机系统概论——校验码
学习
babe小鑫6 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms6 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下6 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。6 天前
2026.2.25监控学习
学习
im_AMBER6 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode