x86分段,DOS,MZ文件格式和反汇编

时间:2014-08-07 16:40:19

标签: dos disassembly 16-bit memory-segmentation

我正在拆卸“试驾III”。这是1990年的DOS游戏。 * .EXE具有MZ格式。 我从来没有处理过细分或DOS,所以如果你回答了我的一些问题,我将不胜感激。

1)游戏的system requirements提到286 CPU,它有保护模式。据我所知,DOS是90%的实模式软件,但有些应用程序可以进入保护模式。我可以确定应用程序仅在实模式下使用CPU吗? IOW,是否保证段寄存器包含段的实际偏移量而不是段描述符的索引?

2)所述系统要求提到1 MB的RAM。如果地址空间的最高384 KB是为MMIO和ROM之类的东西保留的,那么这个RAM的数量是多少?我听说过UMB(在UMA中使用漏洞访问RAM)和HMA,但它仍然不允许访问整个1 MB的物理RAM。那么,宝贵的RAM只是浪费了,因为它的实际地址碰巧是为UMA保留的吗?或者游戏可能会使用一些拐杖,如LIM EMS或XMS?

3)当代码跨越段边界时,CS是否自动递增?比方说,IP达到0xFFFF,那么呢? CS是否在执行下一条指令之前切换到下一段? SS同样如此。当SP一直下降到0x0000时会发生什么?

4)可执行文件的MZ标题如下所示:

signature 23117 "0x5a4d" 
bytes_in_last_block 117 
blocks_in_file 270 
num_relocs 0 
header_paragraphs 32 
min_extra_paragraphs 3349 
max_extra_paragraphs 65535 
ss 11422 
sp 128 
checksum 0 
ip 16 
cs 8385 
reloc_table_offset 30 
overlay_number 0 

为什么没有重定位信息?如何在没有地址修正的情况下运行?或者它是否构建为完全独立于位置的代码,由程序计数器相对指令组成?游戏附带一个作弊工具,也是一个MZ可执行文件。尽管要小得多(8448字节 - 非常小以至于它适合单个段),它仍然具有重定位信息:

offset 1 
segment 0 

offset 222 
segment 0 

offset 272 
segment 0 

这允许IDA正确地反汇编作弊的代码。但是游戏EXE什么都没有,尽管它显然有很多远点。

5)在DOS中是否还有“部分”这样的东西?我的意思是,数据部分,代码(文本)部分等? MZ标头指向堆栈部分,但它没有关于数据部分的信息。数据和代码是否在DOS程序中完全混合?

6)为什么甚至在EXE文件中都有堆栈部分?它只有零。为什么要浪费磁盘空间而不只是说“从这里开始堆栈”?就像用BSS部分完成的那样?

7)MZ头包含有关SS和CS的初始值的信息。 DS怎么样?它的初始值是多少?

8)在exe数据之后,MZ可执行文件有什么作用?作弊实用程序在可执行文件的末尾有整个3507字节,看起来像

__exitclean.__exit.__restorezero._abort.DGROUP@.__MMODEL._main._access.
_atexit._close._exit._fclose._fflush._flushall._fopen._freopen._fdopen
._fseek._ftell._printf.__fputc._fputc._fputchar.__FPUTN.__setupio._setvbuf
._tell.__MKNAME._tmpnam._write.__xfclose.__xfflush.___brk.___sbrk._brk._sbrk
.__chmod.__close._ioctl.__IOERROR._isatty._lseek.__LONGTOA._itoa._ultoa.
_ltoa._memcpy._open.__open._strcat._unlink.__VPRINTER.__write._free._malloc
._realloc.__REALCVT.DATASEG@.__Int0Vector.__Int4Vector.__Int5Vector.
__Int6Vector.__C0argc.__C0argv.__C0environ.__envLng.__envseg.__envSize

这是某种调试符号信息吗?

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

重新。不,你不能确定,直到你证明不是你自己。一个giveaway将在代码中出现MOV CR0, ...

重新。 2.虽然不要将营销材料与工程规范相混淆,但这有一个技术原因。 286 CPU可以处理超过1M的物理地址空间。 RAM仅在实模式下“浪费”,并且仅在未使用EMM(或EMS)驱动程序时才被“浪费”。在286系统上,超过640kb的RAM通常被“推高”以开始于1088kb标记。 ISA和板载外设的内存地址空间以1:1的比例映射到640-1024kb窗口。要从实模式使用RAM,需要EMM或EMS驱动程序。从保护模式开始,只要您正确设置了段描述符,它就会“存在”。

如果游戏在真实模式下实际需要额外的384kb RAM而不是640kb,则表明它已切换到保护模式或需要服务或EMM或EMS驱动程序。

重新。我希望我记得那个。反思,我希望不是:)别人请编辑或单独回答。哈,我在某个时间点确实知道了:)

重新。你说“[代码]有许多指令,如调用far ptr 18DCh:78Ch”。这意味着三件事之一:

  • 使用保护模式,地址的细分部分为selector into the segment descriptor table

  • 那里有代码可以在没有DOS的情况下重新定位这些指令。

  • 那里有代码强制将游戏重新定位到地址空间中的恒定位置。如果游戏不使用DOS访问磁盘文件,它可以完全删除DOS并接管,在此过程中获得大量内存。我不记得你是否可以退出游戏返回命令提示符。有些游戏“直到你重启”。

重新。 5. .EXE标头没有“指向”任何堆栈,没有你暗示的堆栈部分,就.EXE文件而言,部分的概念不存在。 SS 寄存器值为obtained by,将可执行文件加载的段添加到标头中的SS值。

链接器确实可以在.EXE文件中连续排列节,但这些节的属性不包含在.EXE标头中。它们通常可以通过检查可执行文件进行反向工程。

重新。 6. .EXE头中的SS和SP值不是文件指针。 EXE文件可能有一个映射到堆栈的部分,但这完全是可选的。

重新。 7.这已经是asked and answered here

重新。 8.这看起来像一个调试符号列表。欺骗实用程序与剩下的调试信息相关联。你可以拥有完全任意的数据 - 通常它有各种资源(图形,音乐等)。

相关问题