In a DOS EXE file, if I have sub1, sub2, and sub3, split between two code segments, how do I know which sub is in which segment? There seem to be no physical markers in the exe code.

I know the EXE header gives a couple of these items, but looking at the relocation table for a random large EXE, all the segment addresses there were 0, yet there are actually 20 different segments in the program when I look at it in IDA.

Do programs like IDA just guess at segment sizes and offsets based on code analysis? Or have I missed something important in the DOS EXE file structure?

1 Answer 1


In a DOS EXE file, if I have sub1, sub2, and sub3, split between two code segments, how do I know which sub is in which segment?

Theoretically, you can't, since most addresses can belong to at least 16 different segments, but in practice there are some heuristics. For example, for targets of far calls and jumps you know their selector (segment value) and offset in that segment, so if you gather that info over the whole executable, you can figure out (at least roughly) what part belongs to which segment. See here for a specific example

As for loading EXE files, you can check how IDA does it in the source of the DOS EXE loader in the SDK (ldr/dos). Here's the relevant part (function doRelocs):

uint16 curval = get_word(xEA);
uint16 base = curval + delta;
put_word(xEA, base);
fd.sel = base;
set_fixup(xEA, &fd);
if ( dosegs )
  add_segm_by_selector(base, NULL);

So basically, a segment is added for each unique relocated selector value. Of course, this may be not enough for some complicated executables, so manual tuning of segment boundaries may be necessary.

  • I was already starting to come to this conclusion on further study, but your answer is much more detailed and informative than what I'd figured out so far. Thanks! May 14, 2017 at 17:53
  • "any address can belong to 16 different segments" Not accurate. Addresses between 64 KiB and 1024 KiB can belong to 4096 different segments each. Addresses below 64 KiB have less possible aliases if the A20 line is enabled (addresses beyond 1024 KiB point into the HMA).
    – ecm
    May 17, 2021 at 12:07
  • @ecm thanks, updated
    – Igor Skochinsky
    May 17, 2021 at 12:09
  • Your update is still incorrect. With A20 enabled the addresses 0 to 0Fh can only belong to segment 0. Each 16 bytes until the 64 KiB boundary, one possible alias adds up, up to 4096 possible aliases.
    – ecm
    May 17, 2021 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.