Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 05-10-2003, 13:42
cAtA cAtA is offline
Friend
 
Join Date: Mar 2002
Posts: 98
Rept. Given: 0
Rept. Rcvd 4 Times in 3 Posts
Thanks Given: 0
Thanks Rcvd at 3 Times in 3 Posts
cAtA Reputation: 4
Dos executable

It's needed an algorithm to convert a logical address to physical address for dos executable.

Can someone help me? Thanks!
Reply With Quote
  #2  
Old 05-11-2003, 18:13
amitophia
 
Posts: n/a
You can use IDA to know physical offsets of segffset pair.
Or do you need only the algorithm in particular?
Reply With Quote
  #3  
Old 05-18-2003, 16:46
cAtA cAtA is offline
Friend
 
Join Date: Mar 2002
Posts: 98
Rept. Given: 0
Rept. Rcvd 4 Times in 3 Posts
Thanks Given: 0
Thanks Rcvd at 3 Times in 3 Posts
cAtA Reputation: 4
I need it to use in my programm.
Reply With Quote
  #4  
Old 05-20-2003, 08:49
amitophia
 
Posts: n/a
The algorithm is very simple.
It should be taken into consideration that DOS only addresses 1Mb of memory (20-bit addressing).
So the adress 041Ch in memory will have many SEG:OFFSET representations, for example:
0000:0041h, 0041,000Ch, 0020:021Ch adresses the same memory location

The addressed linear memory value is (SEG*10h)+OFF.

The EXE-module loads in memory just after PSP. So The EXE image (EXE without header) starts always at PSP:0100 or, as was said above, it's the same as (PSP+10h):0000 (this to variants points to the same physical memory location = (PSP*10h)+100h = (PSP+10h)*10h+0).
So let me name PSP+10h as BASE (e.g. BASE=PSP+10h).
MZ-header has two fields: InitCS and InitIP. When program loads CS is set to BASE+InitCS and IP is set to InitIP (but IP isn't meaningful for us).
This means that the phisycal address in EXE-file equals

The Algorithm

PhysOffset = (((SEG-BASE)*10h) + OFFSET) + Sizeof(MZheader)


Sizeof(MZheader) is calculated as appropriate field in the MZ-header (WORD at offset 8h) multiplied by 10h
BASE is the value that equals PSP+10h. PSP calculated when DOS loader loads the program into memory.

Additionally I'm postisng here some information about EXE-header. Mainly, you may need only the 9-th item. It shows how relocations are calculeted and how loader patches the program on load (that is why some offsets in memory cannot be found in EXE-file even it hasn't been packed - loader has patched it)

Code:
ExeHeaderRec
  Offset Size Contents
  ------ ---- -----------------------------------------------------
   +0      2  wSignature   5a4dH .EXE file signature ('MZ')
   +2      2  wPartPage    length of partial page at end (generally ignored)
   +4      2  wPageCnt     length of image in 512-byte pages, incl. header
   +6      2  wReloCnt     number of items in relocation table
   +8      2  wHdrSize     size of header in 16-byte paragraphs
  +0aH     2  wMinAlloc    minimum RAM needed above end of prog (paragraphs)
  +0cH     2  wMaxAlloc    maximum RAM needed above end of prog (paragraphs)
  +0eH     2  wInitSS      segment offset of stack segment (for setting SS)
  +10H     2  wInitSP      value for SP register when started
  +12H     2  wChkSum      file checksum (negative sum of all words in file)
  +14H     2  wInitIP      value for IP register when started
  +16H     2  wInitCS      segment offset of code segment (for setting CS)
  +18H     2  wTablOff     file-offset of first relo item (often 001cH)
  +1aH     2  wOverlayNo   overlay number (0 for base module)
          28               size of formatted portion of EXE header

  +?      4*? alReloTbl    variable-length relocation table
  +?       ?  abFiller     filler to paragraph boundary
  +?       ?  abImage      start of program image

 Since an EXE file may be loaded on any segment, all absolute segment
 references (such as FAR CALLs, long address pointers, and references such
 as MOV AX,data_seg) must be adjusted to work for the memory location in
 which they are loaded.  Here are the steps used by the DOS program loader
 (fn 4bH ) to load an EXE file:

       1. Create a PSP via DOS Fn 26H.

       2. Read 1cH bytes of the EXE file (the formatted portion of the EXE
          header) into a local memory area.

       3. Determine the load module size:
           size=((wPageCnt*512)-(wHdrSize*16))-wPartPage

       4. Determine file offset of load module = (wHdrSize * 16)

       5. Select a segment addr, START_SEG, for loading (usually PSP+10H)

       6. Allocate enough memory to hold the load module, honoring the
          settings in wMaxMem  and wMinMem.

       7. Read the load module into memory starting at START_SEG:0000

       8. LSEEK to the start of the relocation table (wTablOff)

       9. For each relocation item (wReloCnt):
          a. read the item as two 16-bit words (I_OFF,I_SEG)
          b. add RELO_SEG=START_SEG+I_SEG      (find the address of
             relocation ref)
          c. fetch the word at RELO_SEG:I_OFF  (read current value)
          d. add START_SEG to that word        (perform the segment fixup)
          e. store the sum back at its original address (RELO_SEG:I_OFF)

      10. Allocate memory for the program according to wMaxMem and wMinMem

      11. Initialize registers and execute the program:
          a. ES = DS = PSP
          b. Set AX to indicate the validity of drive IDs in command line
          c. SS = START_SEG+ReloSS, SP = ExeSP
          d. CS = START_SEG+ReloCS, IP = ExeIP
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



All times are GMT +8. The time now is 13:39.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )