You need to enable JavaScript to run this app. MS-DOS Executable入口mov指令的dynamic relocation疑问
优惠活动
大模型
产品
解决方案
定价
更多

MS-DOS Executable入口mov指令的dynamic relocation疑问

结论

是,程序加载过程中确实发生了动态地址修正,本质是16位MS-DOS MZ可执行文件的加载时重定位,由DOS系统的程序加载器在入口指令执行前完成。差异来自两份内容的状态区别:IDA默认模拟了加载后的内存状态,而raw转储读取的是磁盘上未修正的原始文件。

两边结果不一致的原因
  • 对磁盘文件做raw hex转储时,读取的是链接生成后未经过任何处理的静态文件内容,保留了指令操作数的链接初始值。
  • IDA原生支持MZ格式,加载时会自动解析文件头中的重定位表,默认应用全部重定位修正,还原程序加载到内存后的实际指令,因此和raw转储结果不同。
这条mov指令的重定位逻辑

MZ格式的重定位以16位段地址为修正单位,完整处理流程按顺序如下:

  • 链接阶段登记重定位项:链接生成EXE时,链接器默认假设程序加载到段地址0x0000的位置。这条指令需要获取程序自身某段的地址(本例中就是可执行映像的起始段),因此立即数初始值设为0x0000,对应机器码B8 00 00。同时链接器会将这个立即数的位置(相对于映像基址的段偏移地址)添加到MZ文件头的重定位表中。
  • 加载时确定实际基址:DOS运行EXE时,会根据当前内存空闲情况动态分配内存,将可执行映像加载到任意可用段地址。本例中映像的加载段基址为0x1000(对应线性地址0x10000),这个地址会随系统内存环境变化,每次运行都可能不同。
  • 修正指令立即数:加载器遍历重定位表,对每个需要修正的16位字执行加法操作:
    内存中修正后的值 = 文件原始值 + 映像加载段基址
    
    对这条指令而言,原始值为0x0000,加上基址0x1000后得到0x1000,写回内存后机器码变为B8 00 10,也就是IDA中显示的mov ax, 0x1000。
  • 初始化完成后跳转入口:所有重定位修正、段寄存器和栈初始化工作完成后,加载器才会跳转到入口点执行,因此第一条指令运行时已经是修正后的状态。
补充说明
  • 这类重定位属于加载时静态重定位:所有修正仅在加载阶段执行一次,程序运行过程中不会再修改对应地址。由于DOS没有虚拟内存机制,程序加载地址不固定,必须通过该方式修正地址,广义上也属于加载期动态重定位的范畴,但和现代操作系统的动态链接重定位不是同一机制。
  • 如果在IDA中以原始二进制(Binary)方式加载文件、不解析MZ头,就会看到和raw转储一致的B8 00 00。

内容的提问来源于stack exchange,提问作者3usi9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 07:06:01