我注意到我正在编写的某些代码中存在潜在的错误。
但是,如果使用mov ax, seg segment_name
,该程序可能是不可移植的,并且只能在特定配置的一台计算机上运行,因为加载位置可能因计算机而异。
因此,我决定在运行DOS的两台不同机器上反汇编一个仅包含一条指令的程序,然后发现该问题已经神奇地解决了。
在一台机器上的调试输出: 0C7A:014C B8BB0C MOV AX,0CBB
在第二台机器上的调试输出: 06CA:014C B80B07 MOV AX,070B
十六进制转储程序后,我发现未更改的字节实际上是B84200
。
手动将这些字节重新插入程序会导致 mov ax, 0042
PE格式是否存储对这些指令的引用并在运行时进行更新?
正如Peter Cordes指出的那样,MS-DOS不使用Windows使用的PECOFF可执行格式。它具有自己的“ MZ”可执行文件格式,以可执行文件的前两个字节(以该格式标识)命名。
MZ格式通过包含重定位的重定位表支持使用多个段。这些重定位只是简单的segment:offset值,这些值指示需要根据可执行文件在内存中的加载位置来调整16位段值的位置。MS-DOS通过简单地将程序的实际负载段添加到可执行文件中包含的值来执行这些调整。这意味着如果不应用重定位,则可执行文件仅在加载到段0时才起作用,而这恰巧是不可能的。
请注意,这不仅是一个程序在多台计算机上工作所必需的,而且同一程序在同一台计算机上可靠地工作也有必要。可以根据各种配置详细信息以及已经在内存中加载的其他程序和驱动程序来更改加载地址,因此,MS-DOS可执行文件的加载地址本质上是不可预测的。
从您的示例开始,我们可以告诉您示例程序在两台计算机上的加载位置。由于将0042h重定位到第一台计算机上的0CBBh和第二台计算机上的070Bh,我们知道MS-DOS分别将您的程序加载到两台计算机上的0C79h和06C9h段:
0CBB - 0042 = 0C79
070B - 0042 = 06C9
由此可以确定您的示例可执行文件在其重定位表中具有条目0001:014D或等效的segment:offset值:
0C7A:014D - 0C79:0000 = 0001:014D
06CA:014D - 06C9:0000 = 0001:014D
该条目指示mov ax, seg segname
需要调整的指令的16位立即数操作数的未重定位位置。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句