如何查找汇编中mov指令偏移量及代码修改的原始内存地址?
汇编指令偏移量与内存地址计算问题解答
一、如何查找汇编语言中MOV指令的偏移量?
偏移量得分两种场景来看,具体取决于你关注的是指令本身的偏移,还是内存操作数的偏移:
- 如果是指令自身的偏移(相对于代码段基址):
用调试器(比如x64dbg、OllyDbg)查看指令的实际地址(比如0x00401020),再获取代码段(CS寄存器)的基址——实模式下是CS值左移4位,保护模式下可以通过调试器的段信息窗口查看GDT/LDT里的基址。用指令地址减去代码段基址,得到的就是指令的偏移量。举个例子,指令地址是0x00401020,CS基址是0x00400000,那偏移就是0x1020。 - 如果是内存操作数的偏移(比如
[esi+10]里的10):
直接看汇编指令里的立即数就是偏移,比如[ebp+18]里的0x18就是相对于EBP的偏移。要是调试器里显示的是符号名(比如[ebp+var_8]),可以去栈窗口或者符号表查对应的数值——var_XX一般对应ebp-XX,所以偏移是-XX(也就是相对于EBP的负偏移)。
二、计算两条指令操作的原始内存地址
先把你的已知条件梳理清楚:
- 目标指令:
mov [esi+10],eax和movzx eax,byte ptr [ebp+18] - 寄存器值:EAX=0x003F6C39,ESI=0x20847BA0,EBP=0x010FF1B8
- 提到的新地址:0x20847BB0
我们逐条拆解分析:
1. 指令 mov [esi+10],eax 的目标内存地址
这条指令的作用是把EAX的值写入到ESI寄存器值 + 0x10对应的内存单元,计算过程很直接:
0x20847BA0(ESI的值) + 0x10(偏移量) = 0x20847BB0
这个结果正好是你说的“新地址”,说明这个地址就是这条指令要修改的内存单元。这里的地址本身是固定的,不存在“原始/新”的区别,你提到的“新地址”应该是指写入后存储了新值的地址,而它本身就是指令操作的原始目标地址,写入前是一个存储原有数据的内存单元,写入后就换成了EAX的值0x003F6C39。
2. 指令 movzx eax,byte ptr [ebp+18] 的源内存地址
这条指令是从EBP寄存器值 + 0x18对应的内存单元读取一个字节,再零扩展为32位存入EAX,计算过程如下:
0x010FF1B8(EBP的值) + 0x18(偏移量) = 0x010FF1D0
这个0x010FF1D0就是指令读取的原始内存地址,当前EAX的值0x003F6C39就是从这个地址读取的字节(低8位是0x39,零扩展后得到32位的0x003F6C39)。
内容的提问来源于stack exchange,提问作者NkaBall




