home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 14 Text / 14-Text.zip / EN0709.ZIP / ENV.709
Text File  |  1988-04-23  |  45KB  |  657 lines

  1. Exploring the OS/2 .EXE File
  2.  
  3. Understanding the "New Executable" file format, which is required for OS/2, will allow you to appreciate how OS/2 operates.
  4.  
  5.     DOS supports two binary file formats for executable files: .COM and .EXE.  The .COM format was inherited from CP/M. The format is adequate for programs up to 64K in length that do not require relocation information for adjusting explicit references to segment addresses within the program.  DOS loads a .COM file into memory at offset 100h in a segment and sets all four segment registers to the same segment address.  Many small assembly language programs (such as those that appear regularly in the Productivity section of PC Magazine) use the .COM file format because it is compact and simple.
  6.     The .EXE format was designed specifically for DOS.  It supports programs over 64K in length and those that make references to explicit segment addresses.  A relocation table in the header section of the .EXE file allows DOS to adjust these references based on where the program is loaded into memory.
  7.  
  8. NOT ADEQUATE FOR OS/2  Neither the .COM format nor the .EXE format is suitable  for a protected mode operating system such as OS/2.  The .COM format is clearly inadequate because code and data share the same segment.  Under OS/2, code and data must be located in separate segments.
  9.     The .EXE format is also inadequate because there is no information in the file that defines how the binary image of the executable breaks down into code and data segments.  Although .EXE format programs often use separate segments for code and data, the operating system cannot determine where these segments begin and end in the file.
  10.     For this reason, a new format for executable files was required for OS/2.  It's called (appropriately enough) the "New Executable" format, or sometimes the "Segmented Executable" format.  The latter name indicates that the various code and data segments that make up the program are identified in the file.
  11.     Actually, the New Executable file format isn't all that new.  It was first used with Microsoft Windows, which was introduced in November, 1985.  The format is documented in the Windows 2.0 re Development Kit, in Appendix K of the all-new MS-DOS Encyclopedia (Microsoft Press, 1988), and in Microsoft's mammoth $3000 OS/2 Software Development Kit.
  12.     New Executable files have an .EXE extension because they incorporate the old MS-DOS executable format within the new format.  Under OS/2, the New Executable format is used for all programs that run under protected-mode (these files can have a .EXE or a .COM extension), all dynamic link libraries (which have the extension .DLL), and all protected-mode device drivers (which have a .SYS extension).
  13.     Although you don't need to understand its format to program in OS/2, examining a typical New Executable file provides some valuable insights into the workings of OS/2.  So, let's use a hex dump program on an OS/2 .EXE file and take a look.  Since you probably don't yet have an OS/2 hex dump program, let's solve that problem right away.
  14.  
  15. AN OS/2 HEX DUMP  Figure 1 shows an OS/2 assembly language program called DUMP.ASM, which is a simple hex dump program.  You can assemble this program using Microsoft's MASM 5.0 under the OS/2 DOS compatibility mode simply by entering
  16.  
  17. MASM DUMP;
  18.  
  19. (You could also assemble it with an OS/2 version of MASM, of course.) Then, using the LINK.EXE program included with IBM's OS/2 1.0, run
  20.  
  21. LINK DUMP, /ALIGN:16,, DOSCALLS;
  22.  
  23. The DOSCALLS.LIB file is also included with OS/2 1.0.  Before you run LINK, use the SET command to set the LIB environment variable to the directory where you store DOSCALLS.LIB.
  24.  
  25. SET LIB=directory
  26.  
  27. If you don't have the Microsoft Macro Assembler 5.0, you can create DUMP.EXE by typing the BASIC program shown in Figure 2 into BASICA and running it.  This will create DUMP.EXE for you.
  28.  
  29. DUMPING DUMP.EXE  You can use DUMP to dump itself by typing
  30.  
  31. DUMP DUMP.EXE
  32.  
  33. Figure 3 shows what you'll see, and it identifies the five major sections of the file.  (If you created DUMP.EXE from the BASIC program, you'll see two more bytes at the end of the file.)
  34.     DUMP is a "small model" program--that is, it has one code segment and one data segment.  Medium model programs (which have multiple code segments), compact model programs (multiple data segments), and large model programs (multiple code and data segments) have additional code and data segments.   Windows programs and OS/2 Presentation Manager programs have additional segments following the code and data segments.  These additional segments are for "resources," which include icons, cursors, and bitmaps, and templates for menus and dialog boxes.
  35.     You'll notice that the code and data segments begin on a nice even 16-byte boundary.  That's the result of using the /ALIGN:16 switch when running LINK.
  36.  
  37. A TALE OF TWO HEADERS  An OS/2 .EXE file has two header sections.  The first is the familiar DOS .EXE header; the second is the New Executable header.  Each header begins with a two-byte "signature" word.  The DOS signature word is "MZ," the initials of Mark Zbikowski, one of the key designers of DOS at Microsoft.  The more anonymous "NE" signature that begins the New Executable header stands for "New Executable."
  38.     When you run DUMP.EXE under DOS or under the OS/2 DOS Compatibility Mode, the operating system recognizes the DOS .EXE header and assumes the file is a normal DOS executable.  It therefore runs the DOS program that is imbedded in the file.  This program simply displays the message, "This program cannot be run in DOS mode," and terminates.
  39.     This tiny DOS program is automatically inserted into the .EXE file by LINK.  (Earlier versions of LINK distributed with the Microsoft OS/2 Software Development Kit did not do this.) It is also possible to specify a different program to be inserted into the OS/2 .EXE file by indicating its name in a "module definition file" and specifying the module definition file as the fifth parameter to LINK.
  40.     When you create a "dual-mode" (or Family API) program that runs under both OS/2 and DOS, this tiny DOS program is replaced with a much larger DOS loader program.  This loader program patches the OS/2 program so that the calls it makes to OS/2 functions are replaced with calls to DOS functions that approximate the OS/2 functions.
  41.     When you execute a dual-mode .EXE file under OS/2, OS/2 looks at the double word stored at offset 3Ch in the DOS header section (see Figure 4).  This double word is the offset in the .EXE file where the new header section begins.  In the discussion below, I'll refer to this offset as NEWHDR ("new header").
  42.  
  43. IDENTIFYING THE SEGMENTS  When OS/2 loads a program into memory to be executed, it must be able to identify the code and data segments in that program.  OS/2 can then allocate segments for the program and set up the program's "local descriptor table," which is required in protected-mode.
  44.     The header section contains a "segment table" that identifies all the code and data segments in the program.  Figure 5 shows the new executable header and the information that OS/2 uses to locate and use this segment table.
  45.     The word at (NEWHDR + 1Ch)--which is the word at offset 9Ch in DUMP.EXE--is the number of code and data segments in the file.  This is simply 2.
  46.     The word stored at offset (NEWHDR + 22h)--which is offset A2h in the DUMP.EXE file--is 0040h.  This indicates that the segment table begins at offset (NEWHDR + 40h) or C0h.
  47.     The word at (NEWHDR + 32h)--offset B2h in DUMP.EXE--is the "alignment shift count," which is set to 4.  (Recall that when linking we specified an ALIGN value of 16, which is 1 shifted left by 4 bits.)
  48.     Each segment requires 4 words (8 bytes) in the segment table.  These four words are shown in the table, "DUMP.EXE's Segment Table".
  49.     The word in the segment table that indicates the location of the segment in the file must be adjusted.  You take the number in the table (0010h or 0028h) and shift it left by the alignment shift count.  Thus, segment 1 begins at offset 0100h from the beginning of the .EXE file and segment 2 begins at offset 0280h from the beginning of the file, which agress with what I showed in Figure 3.
  50.     The flags word in the segment table describes the segment.  The least significant bit (bit 0) is 0 for a code segment and 1 for a data segment.  So, segment 1 is a code segment and segment 2 is a data segment.  Bits 10 and 11 indicate the I/O privilege level of the segment.  Both these segments run under ring 3, which under protected mode is the least privileged level.  This is normal for a simple program like DUMP.
  51.     Bit 8 is set to 1 when the segment includes relocation information.  This bit is set for segment 1 but not for segment 2.  I'll describe this relocation information towards the end of this column.
  52.  
  53. EXPANDING THE SEGMENTS  Notice that the segment table contains two sizes--the first is the size of the segment in the file; the second is the size of the segment in memory.  For the code segment, these two values are the same, but for the data segment they are not.
  54.     When OS/2 loads DUMP.EXE's data segment into memory, it must first allocate a segment that is 310h bytes long.  The data segment in the DUMP.EXE file is loaded into the first 96h bytes of this memory segment.  The rest of the segment is initialized to 0.
  55.     In DUMP.ASM (Figure 1), the segments identified with the .STACK, .DATA, and .DATA? keywords are consolidated into one segment group, often called DGROUP.  If you compare the .DATA and .DATA? segments in DUMP.ASM (Figure 1) with the data segment in DUMP.EXE (Figure 3), you'll notice that the data segment in the file encompasses only the data initialized to something other than 0.  Everything in .DATA? (plus the last few bytes in .DATA) does not require space in the .EXE file because OS/2 initializes the variables to zero when the program is loaded into memory.
  56.     When programming for OS/2 in assembly language, keep this in mind.  Any variable you want initialized to zero can go in the .DATA? segment or at the end of the .DATA segment.  This prevents these variables from taking up space in the .EXE file.  Do not do something like this:
  57.  
  58.        .DATA
  59.   
  60. Data1  db  "Some data"
  61. Data2  db  256 dup (0)
  62. Data3  db  "More data"
  63.  
  64. Because the assembler will not reorder variables, this code will require 256 bytes of zeros in the .EXE file's data segment.
  65.  
  66. ENTRY CONDITIONS  Other information in the header section of the file indicates how OS/2 is to set registers on entry to the program.  This is shown in Figure 6.
  67.     The word at offset (NEWHDR + 0Eh) is the segment number of the "automatic data segment." In DUMP.EXE this word is set to 2, which indicates segment 2, or the data segment.  The automatic data segment is often called DGROUP and contains the program's stack.  On entry to the program, DS is set to the address of this segment and CX is set to the segment's size (310h).
  68.     The double word at offset (NEWHDR + 14h) is the initial value of the instruction pointer on entry to the program.  The first word is the offset (10h in DUMP.EXE) and the second word is the segment number--segment 1, or the code segment.
  69.     The double word at offset (NEWHDR + 18h) is the initial value of the stack pointer.  In DUMP.EXE this indicates segment 2 (the data segment) and offset 310h, which is the very top of segment 2 after it has been expanded in memory.  In DUMP.ASM, a stack size of 200h was specified.  The size of the data segment (310h) is enough to accomodate the total size of the initialized data, the uninitialized data, and the 200h byte stack.
  70.  
  71. DYNAMIC LINKING  The New Executable format must also support dynamic linking.  Code segments that contain calls to OS/2 functions are followed by a "relocation table" in the .EXE file.  This table is used with information in the header to resolve calls to OS/2 functions when the program is loaded into memory.
  72.     I've described how dynamic linking works in previous Environments columns.  Basically, OS/2 inserts the addresses of OS/2 functions into a program's code segment when the program is executed.  However, it is instructive to see how this information is encoded into the .EXE file.
  73.     Figure 7 shows DUMP.EXE's code segment.  The calls to OS/2 functions in DUMP.EXE are coded as far calls (whose op-code is 9Ah), followed by an offset and segment address.  Figure 7 shows these addresses for each of the seven OS/2 functions that DUMP.EXE calls.  You'll notice that most of these addresses are coded as 0000:FFFF, which is an impossible address for a far call.  It's a dummy address because the addresses of these functions are not known until the program is run.
  74.     The segment table indicates that the code segment is 14Eh bytes long.  This means that the information that starts at offset 24Eh in the DUMP.EXE file is not part of the code segment.  In fact, it's the relocation table.   
  75.     In medium or large model programs, this relocation table could also contain information necessary to adjust far calls between code segment.  However, in DUMP.EXE, the relocation table contains only dynamic link information.
  76.     The table begins with a word that indicates the number of entries in the relocation table.  In DUMP.EXE this is 5.  Not coincidentally, this is the number of unique OS/2 functions called by the program (DosWrite, DosExit, DosOpen, DosRead, and DosClose).
  77.     Each entry in the relocation table is 8 bytes long.  Let's take a look at the first entry.  The first byte is a 3.  This indicates that the adjustment to be made to the code segment is to a far address (both segment and offset).  The second byte is a 1, which means that the far address in the code segment must be set to an address of a routine in a dynamic link library that is identified by an "ordinal number."
  78.     This is followed by the word 131h.  This is an offset relative to the beginning of the code segment where the adjustment is to be made.  This is actually offset 231h in the DUMP.EXE file, which corresponds to the last DosExit call.  The entry in the relocation table continues with two words--a 1 and a 5.  The 1 indicates a particular dynamic link library.  The 5 indicates the ordinal number of the function in that library.
  79.     Hold onto your hats.  This gets insane: The 1 in the relocation table that indicates the particular dynamic link library is actually an index into the "module reference table," which is another table in the header section.  The offset of the module reference table relative to NEWHDR is stored at (NEWHDR + 28h), which contains the word 58h.  Thus, the module reference table begins at (NEWHDR + 58h) or D8h.  The first word found there (since we're dealing with an index of 1) is another 1.
  80.     This number represents an offset into the "imported names table." The offset of the imported names table relative to NEWHDR is stored at (NEWHDR + 2Ah), which contains 5Ah.  The imported names table thus begins at (NEWHDR + 5Ah), or DAh.  One byte into the imported names table is the number 8, followed by the string "DOSCALLS." (The 8 is the number of characters in "DOSCALLS.") These tables are shown in Figure 8.
  81.     What this means is that the far address at offset 131h in DUMP.EXE's code segment must be set by OS/2 to the address of function 5 in the DOSCALLS dynamic link library.  This function happens to be DosExit.  (OS/2 does not really have a DOSCALLS.DLL dynamic link library.  The DOSCALLS functions are actually part of IBMDOS.COM.)
  82.     The far address at offset 131h in DUMP.EXE's code segment is not 0000:FFFF (like most of the others), but 0000:0059.  This means that there is another call to DosExit in DUMP.EXE.  It is located at 59h bytes from the beginning of the code segment, i.e. at offset 159h in DUMP.EXE.  The far address at 159h is 0000:FFFF.  This marks the end of a chain of DosExit calls in the segment.
  83.     OS/2 uses the other four entries in the relocation table similarly.  This is shown in the table "DUMP.EXE's OS/2 Function Calls."  When LINK is creating the DUMP.EXE file, how does it know that DosExit is function 5 in the DOSCALLS dynamic link library?  That information is in the import library DOSCALLS.LIB.  The sole purpose of DOSCALLS.LIB is to provide this information to LINK so LINK can construct this relocation table.
  84.  
  85. JUST A LITTLE MORE COMPLEX  Of course, we haven't looked at all the information in the header section or at other ways the relocation table can be coded.  For example, in OS/2 programs that contain calls to the VIOCALLS, KBDCALLS, and other dynamic link libraries, the functions are identified by name rather than ordinal number.  Without a doubt, the OS/2 .EXE format is necessarily a bit more complex than the DOS .EXE format.  Fortunately, as I said at the outset, you don't have to understand the new .EXE format to program for OS/2.
  86.  
  87. ;-----------------------------------------------------
  88. ; DUMP.ASM -- OS/2 Hex Dump Program
  89. ;             (C) 1988, Ziff-Davis Communications Co.
  90. ;             Programmed by Charles Petzold, 12/87
  91. ;-----------------------------------------------------
  92.  
  93.                EXTRN  DosOpen:FAR,  DosRead:FAR, DosWrite:FAR
  94.                EXTRN  DosClose:FAR, DosExit:FAR
  95.  
  96.                DOSSEG
  97.                .286
  98.                .MODEL SMALL
  99.                .STACK 200h
  100.                                         ;--------------------------
  101.                .DATA                    ; Initialized Data Segment
  102.                                         ;--------------------------
  103.  
  104. SyntaxMsg      db   13, 10,     "Syntax: DUMP filename"
  105.                db   13, 10, 10, "(C) 1988, Ziff-Davis Communications Co."
  106.                db   13, 10,     "Programmed by Charles Petzold, 12/87"
  107.                db   13, 10
  108. SyntaxMsgLen   equ  $ - SyntaxMsg
  109.  
  110. FileSpecMsg    db   "DUMP: File not found or cannot be opened"
  111. FileSpecMsgLen equ  $ - FileSpecMsg
  112.  
  113. Delimiters     db   9, " ,;=", 0
  114. Address        dw   0, 0
  115.                                         ;----------------------------
  116.                 .DATA?                  ; Uninitialized Data Segment
  117.                                         ;----------------------------
  118. FileHandle     dw   ?
  119. OpenAction     dw   ?
  120. BytesRead      dw   ?
  121. BytesWritten   dw   ?
  122. InputBuffer    db   16 dup (?)
  123. OutputBuffer   db   80 dup (?)
  124.                                         ;--------------
  125.                 .CODE                   ; Code Segment
  126.                                         ;--------------
  127.  
  128. ;----------------------------------------------
  129. ; Parse command line to get file specification
  130. ;----------------------------------------------
  131.  
  132. Entry:         Push DS                       ; Data segment selector
  133.                Pop  ES                       ; Transfer it to ES
  134.                Mov  DS, AX                   ; DS = Environment selector
  135.                Mov  SI, BX                   ; SI = Start of command line
  136.  
  137. SkipProgName:  Lodsb                         ; Pull a command line byte
  138.                Or   AL, AL                   ; Check if it's zero
  139.                Jnz  SkipProgName             ; If not, continue
  140.  
  141. SkipDelims:    Lodsb                         ; Get byte from parameter
  142.                Or   AL, AL                   ; Check if it's zero
  143.                Jz   DisplaySyntax            ; If so, exit with message
  144.  
  145.                Mov  DI, Offset Delimiters    ; Check if delimiter
  146.                Mov  CX, 5                    ; There are 5 of them
  147.                Repne Scasb                   ; Scan the string
  148.                Jz   SkipDelims               ; If delimiter, loop back
  149.  
  150.                Mov  DX, SI                   ; Pointer to file name + 1
  151.                Dec  DX                       ; Pointer to file name
  152.  
  153. SearchFileEnd: Lodsb                         ; Get a byte
  154.                Mov  DI, Offset Delimiters    ; Check if delimiter
  155.                Mov  CX, 6                    ; 6 of them now including 0
  156.                Repne Scasb                   ; Scan the string
  157.                Jnz  SearchFileEnd            ; If not delimiter, do it again
  158.  
  159.                Mov  Byte Ptr [SI - 1], 0     ; Terminate with zero byte
  160.                Jmp  Short OpenFile
  161.  
  162. ;------------
  163. ; Error Exit
  164. ;------------
  165.  
  166. DisplaySyntax: Push ES                       ; Otherwise, set DS to 
  167.                Pop  DS                       ;   data segment
  168.                Mov  DX, Offset SyntaxMsg     ; Syntax message offset
  169.                Mov  CX, SyntaxMsgLen         ; Syntax message length
  170.  
  171. ErrorExit:     Push 2                        ; Standard error handle
  172.                Push DS                       ; Segment of string
  173.                Push DX                       ; Offset of string
  174.                Push CX                       ; Length of string
  175.                Push DS                       ; Segment for bytes written
  176.                Push Offset BytesWritten      ; Offset for bytes written
  177.                Call DosWrite                 ; Display the message
  178.  
  179.                Push 1                        ; Terminte all threads
  180.                Push 1                        ; Return code
  181.                Call DosExit                  ; Exit
  182.  
  183. ;-------------------------
  184. ; Open file using DosOpen
  185. ;-------------------------
  186.  
  187. OpenFile:      Push DS                       ; Exchange DS and ES
  188.                Push ES
  189.                Pop  DS
  190.                Pop  ES
  191.  
  192.                Push ES                       ; Segment of file name
  193.                Push DX                       ; Offset of file name
  194.                Push DS                       ; Segment for file handle
  195.                Push Offset FileHandle        ; Offset for file handle
  196.                Push DS                       ; Segment for action
  197.                Push Offset OpenAction        ; Offset for action
  198.                Push 0                        ; High size (not used)
  199.                Push 0                        ; Low size (not used)
  200.                Push 0                        ; Attribute (not used)
  201.                Push 1                        ; Open flag (open if file exists)
  202.                Push 20h                      ; Open mode (read, deny write)
  203.                Push 0                        ; Reserved
  204.                Push 0                        ; Reserved
  205.                Call DosOpen                  ; Open the file
  206.  
  207.                Or   AX, AX                   ; Check for error
  208.                Jz   ReadAndDump              ; If none, continue
  209.  
  210.                Mov  DX, Offset FileSpecMsg   ; Error message
  211.                Mov  CX, FileSpecMsgLen       ; Length of message
  212.  
  213.                Jmp  ErrorExit                ; Print it and exit
  214.  
  215. ;---------------------------------------------
  216. ; Read 16 bytes from file and display address
  217. ;---------------------------------------------
  218.  
  219. ReadAndDump:   Push DS                       ; Set ES to DS
  220.                Pop  ES
  221.  
  222. MainLoop:      Push [FileHandle]             ; File Handle
  223.                Push DS                       ; Segment of buffer
  224.                Push Offset InputBuffer       ; Offset of buffer
  225.                Push 16                       ; Length of buffer
  226.                Push DS                       ; Segment for bytes read
  227.                Push Offset BytesRead         ; Offset for bytes read
  228.                Call DosRead                  ; Read the file
  229.  
  230.                Cmp  [BytesRead], 0           ; See if no bytes read
  231.                Jnz  DoLine                   ; If bytes read, continue
  232.  
  233.                Jmp  AllDone                  ; If zero bytes read, end program
  234.  
  235. DoLine:        Mov  DI, Offset OutputBuffer  ; Destination
  236.  
  237.                Mov  AX, [Address + 2]        ; High address within file
  238.                Call HexWordOut               ; Display the value
  239.                Mov  AL, '-'                  ; A dash
  240.                Stosb
  241.                Mov  AX, [Address]            ; Low offset within file
  242.                Call HexWordOut               ; Display it
  243.  
  244.                Mov  AL, ' '                  ; Follow it with a blank
  245.                Stosb
  246.  
  247. ;---------------------
  248. ; Prepare Hex Display
  249. ;---------------------
  250.  
  251.                Mov  SI, Offset InputBuffer   ; Source
  252.                Mov  CX, [BytesRead]          ; Number of bytes read
  253.                Sub  BX, BX                   ; Initialize counter
  254.  
  255. HexLoop:       Mov  AL, ' '                  ; A blank normally precedes
  256.                Cmp  BX, 8                    ; But check if counter is 8
  257.                Jnz  DoTheSpace               ; If not, a blank is OK
  258.  
  259.                Mov  AL, '-'                  ; Otherwise, use a dash
  260. DoTheSpace:    Stosb                         ; Display it
  261.  
  262.                Lodsb                         ; Get a byte
  263.                Call HexByteOut               ; Convert it to hex
  264.                
  265.                Inc  BX                       ; Kick up the counter
  266.                Loop HexLoop                  ; And loop for next byte
  267.  
  268.                Mov  CX, 16                   ; 16 possible bytes
  269.                Sub  CX, BX                   ; Subtract those already done
  270.                IMul CX, 3                    ; Multiply by 3
  271.                Add  CX, 2                    ; And add 2 for the end
  272.                Mov  AL, ' '                  ; This is all blank
  273.                Rep  Stosb                    ; Store the blanks
  274.  
  275. ;---------------------------
  276. ; Prepare Character Display
  277. ;---------------------------                                        
  278.  
  279.                Mov  SI, Offset InputBuffer   ; Source
  280.                Mov  CX, [BytesRead]          ; Number of bytes
  281.  
  282. CharLoop:      Lodsb                         ; Get the character
  283.                Cmp  AL, ' '                  ; See if displayable ASCII
  284.                Jb   DisplayPeriod            ; If below space, use dot
  285.  
  286.                Cmp  AL, 7Fh                  ; If DEL or above, use dot
  287.                Jb   DisplayChar
  288.  
  289. DisplayPeriod: Mov  AL, '.'                  ; Display period
  290.  
  291. DisplayChar:   Stosb                         ; Display character
  292.                Loop CharLoop                 ; Do next character
  293.         
  294.                Mov  AL, 13                   ; Carriage return
  295.                Stosb       
  296.                Mov  AL, 10                   ; And line feed
  297.                Stosb       
  298.  
  299. ;-----------------------------
  300. ; Display Line using DosWrite
  301. ;-----------------------------
  302.  
  303.                Sub  DI, Offset OutputBuffer  ; Length of output line
  304.  
  305.                Push 1                        ; File Handle: Standard Output
  306.                Push DS                       ; Segment of buffer
  307.                Push Offset OutputBuffer      ; Offset of buffer
  308.                Push DI                       ; Length of buffer
  309.                Push DS                       ; Segment for bytes written
  310.                Push Offset BytesWritten      ; Offset for bytes written
  311.                Call DosWrite                 ; Display it
  312.  
  313.                Add  [Address], 16            ; Kick up address
  314.                Adc  [Address + 2], 0
  315.                Jmp  MainLoop                 ; Do another line
  316.  
  317. AllDone:       Push [FileHandle]             ; File handle
  318.                Call DosClose                 ; Close the file
  319.  
  320.                Push 1                        ; Exit program
  321.                Push 0
  322.                Call DosExit
  323.  
  324. ;----------------------------------
  325. ; Subroutines to store line output
  326. ;----------------------------------
  327.  
  328. HexWordOut:    Xchg AL, AH
  329.                Call HexByteOut               ; Do high byte first
  330.                Xchg AL, AH
  331.                                              ; Fall through
  332. HexByteOut:    Push AX
  333.                Shr  AL, 4
  334.                Call HexDigitOut              ; Do high digit first
  335.                Pop  AX
  336.                And  AL, 0Fh
  337.                                              ; Fall through
  338. HexDigitOut:   Add  AL, 90h
  339.                Daa                           ; Common trick to convert
  340.                Adc  AL, 40h                  ;   hex digit to ASCII
  341.                Daa
  342.  
  343.                Stosb                         ; Store in line buffer
  344.                Ret
  345.  
  346.                END  Entry
  347.  
  348.  
  349.  
  350.  
  351. Figure 1:  DUMP.ASM is an OS/2 hex dump program.
  352.  
  353. 100 REM -- BASIC PROGRAM TO CREATE DUMP.EXE
  354. 110 OPEN "DUMP.EXE" AS #1 LEN = 1
  355. 120 FIELD #1,1 AS A$
  356. 130 CHECKSUM = 0
  357. 140 FOR I% = 1 TO 99
  358. 150    LINESUM% = 0
  359. 160    FOR J% = 1 TO 8
  360. 170       READ BYTE%
  361. 180       CHECKSUM = CHECKSUM + BYTE%
  362. 190       LINESUM% = LINESUM% + BYTE%
  363. 200       LSET A$ = CHR$(BYTE%)
  364. 210       PUT #1
  365. 220    NEXT J%
  366. 230    READ LINECHECK%
  367. 240    IF LINECHECK% <> LINESUM% THEN PRINT "Error in Line"; 280 + 10 * I%
  368. 250 NEXT I%
  369. 260 CLOSE
  370. 270 IF CHECKSUM = 53829 THEN PRINT "Successful Completion!" : END
  371. 280 PRINT "EXE file is not valid!" : END
  372. 290 DATA    77,   90,   22,    1,    2,    0,    0,    0,  192
  373. 300 DATA     4,    0,    0,    0,  255,  255,    0,    0,  514
  374. 310 DATA   184,    0,    0,    0,    0,    0,    0,    0,  184
  375. 320 DATA    64,    0,    0,    0,    0,    0,    0,    0,   64
  376. 330 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  377. 340 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  378. 350 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  379. 360 DATA     0,    0,    0,    0,  128,    0,    0,    0,  128
  380. 370 DATA    14,   31,  186,   14,    0,  180,    9,  205,  639
  381. 380 DATA    33,  184,    1,   76,  205,   33,   84,  104,  720
  382. 390 DATA   105,  115,   32,  112,  114,  111,  103,  114,  806
  383. 400 DATA    97,  109,   32,   99,   97,  110,  110,  111,  765
  384. 410 DATA   116,   32,   98,  101,   32,  114,  117,  110,  720
  385. 420 DATA    32,  105,  110,   32,   68,   79,   83,   32,  541
  386. 430 DATA   109,  111,  100,  101,   46,   13,   10,   36,  526
  387. 440 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  388. 450 DATA    78,   69,    5,    0,  100,    0,    2,    0,  254
  389. 460 DATA    41,    9,   32,  161,    2,    0,    2,    0,  247
  390. 470 DATA     0,    0,    0,    0,   16,    0,    1,    0,   17
  391. 480 DATA    16,    3,    2,    0,    2,    0,    1,    0,   24
  392. 490 DATA    12,    0,   64,    0,   80,    0,   80,    0,  236
  393. 500 DATA    88,    0,   90,    0,  230,    0,    0,    0,  408
  394. 510 DATA     0,    0,    4,    0,    0,    0,    0,    0,    4
  395. 520 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  396. 530 DATA    16,    0,   78,    1,    0,   13,   78,    1,  187
  397. 540 DATA    40,    0,  150,    0,    1,   12,   16,    3,  222
  398. 550 DATA     4,   68,   85,   77,   80,    0,    0,    0,  314
  399. 560 DATA     1,    0,    0,    8,   68,   79,   83,   67,  306
  400. 570 DATA    65,   76,   76,   83,    0,    0,    8,   68,  376
  401. 580 DATA    85,   77,   80,   46,   69,   88,   69,    0,  514
  402. 590 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  403. 600 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  404. 610 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  405. 620 DATA     0,    0,    0,    0,    0,    0,    0,    0,    0
  406. 630 DATA    30,    7,  142,  216,  139,  243,  172,   10,  959
  407. 640 DATA   192,  117,  251,  172,   10,  192,  116,   30, 1080
  408. 650 DATA   191,  145,    0,  185,    5,    0,  242,  174,  942
  409. 660 DATA   116,  241,  139,  214,   74,  172,  191,  145, 1292
  410. 670 DATA     0,  185,    6,    0,  242,  174,  117,  245,  969
  411. 680 DATA   198,   68,  255,    0,  235,   31,    6,   31,  824
  412. 690 DATA   186,    0,    0,  185,  105,    0,  106,    2,  584
  413. 700 DATA    30,   82,   81,   30,  104,  162,    0,  154,  643
  414. 710 DATA   255,  255,    0,    0,  106,    1,  106,    1,  724
  415. 720 DATA   154,  255,  255,    0,    0,   30,    6,   31,  731
  416. 730 DATA     7,    6,   82,   30,  104,  156,    0,   30,  415
  417. 740 DATA   104,  158,    0,  106,    0,  106,    0,  106,  580
  418. 750 DATA     0,  106,    1,  106,   32,  106,    0,  106,  457
  419. 760 DATA     0,  154,  255,  255,    0,    0,   11,  192,  867
  420. 770 DATA   116,    8,  186,  105,    0,  185,   40,    0,  640
  421. 780 DATA   235,  188,   30,    7,  255,   54,  156,    0,  925
  422. 790 DATA    30,  104,  164,    0,  106,   16,   30,  104,  554
  423. 800 DATA   160,    0,  154,  255,  255,    0,    0,  131,  955
  424. 810 DATA    62,  160,    0,    0,  117,    3,  235,  123,  700
  425. 820 DATA   144,  191,  180,    0,  161,  153,    0,  232, 1061
  426. 830 DATA   131,    0,  176,   45,  170,  161,  151,    0,  834
  427. 840 DATA   232,  122,    0,  176,   32,  170,  190,  164, 1086
  428. 850 DATA     0,  139,   14,  160,    0,   43,  219,  176,  751
  429. 860 DATA    32,  131,  251,    8,  117,    2,  176,   45,  762
  430. 870 DATA   170,  172,  232,  103,    0,   67,  226,  239, 1209
  431. 880 DATA   185,   16,    0,   43,  203,  107,  201,    3,  758
  432. 890 DATA   131,  193,    2,  176,   32,  243,  170,  190, 1137
  433. 900 DATA   164,    0,  139,   14,  160,    0,  172,   60,  709
  434. 910 DATA    32,  114,    4,   60,  127,  114,    2,  176,  629
  435. 920 DATA    46,  170,  226,  242,  176,   13,  170,  176, 1219
  436. 930 DATA    10,  170,  129,  239,  180,    0,  106,    1,  835
  437. 940 DATA    30,  104,  180,    0,   87,   30,  104,  162,  697
  438. 950 DATA     0,  154,   80,    0,    0,    0,  131,    6,  371
  439. 960 DATA   151,    0,   16,  131,   22,  153,    0,    0,  473
  440. 970 DATA   233,  105,  255,  255,   54,  156,    0,  154, 1212
  441. 980 DATA   255,  255,    0,    0,  106,    1,  106,    0,  723
  442. 990 DATA   154,   89,    0,    0,    0,  134,  196,  232,  805
  443. 1000 DATA    2,    0,  134,  196,   80,  192,  232,    4,  840
  444. 1010 DATA  232,    3,    0,   88,   36,   15,    4,  144,  522
  445. 1020 DATA   39,   20,   64,   39,  170,  195,    5,    0,  532
  446. 1030 DATA    3,    1,   49,    1,    1,    0,    5,    0,   60
  447. 1040 DATA    3,    1,  155,    0,    1,    0,  137,    0,  297
  448. 1050 DATA    3,    1,   18,    1,    1,    0,  138,    0,  162
  449. 1060 DATA    3,    1,   40,    1,    1,    0,   59,    0,  105
  450. 1070 DATA    3,    1,  122,    0,    1,    0,   70,    0,  197
  451. 1080 DATA    0,    0,    0,    0,    0,    0,    0,    0,    0
  452. 1090 DATA   13,   10,   83,  121,  110,  116,   97,  120,  670
  453. 1100 DATA   58,   32,   68,   85,   77,   80,   32,  102,  534
  454. 1110 DATA  105,  108,  101,  110,   97,  109,  101,   13,  744
  455. 1120 DATA   10,   10,   40,   67,   41,   32,   49,   57,  306
  456. 1130 DATA   56,   56,   44,   32,   90,  105,  102,  102,  587
  457. 1140 DATA   45,   68,   97,  118,  105,  115,   32,   67,  647
  458. 1150 DATA  111,  109,  109,  117,  110,  105,   99,   97,  857
  459. 1160 DATA  116,  105,  111,  110,  115,   32,   67,  111,  767
  460. 1170 DATA   46,   13,   10,   80,  114,  111,  103,  114,  591
  461. 1180 DATA   97,  109,  109,  101,  100,   32,   98,  121,  767
  462. 1190 DATA   32,   67,  104,   97,  114,  108,  101,  115,  738
  463. 1200 DATA   32,   80,  101,  116,  122,  111,  108,  100,  770
  464. 1210 DATA   44,   32,   49,   50,   47,   56,   55,   13,  346
  465. 1220 DATA   10,   68,   85,   77,   80,   58,   32,   70,  480
  466. 1230 DATA  105,  108,  101,   32,  110,  111,  116,   32,  715
  467. 1240 DATA  102,  111,  117,  110,  100,   32,  111,  114,  797
  468. 1250 DATA   32,   99,   97,  110,  110,  111,  116,   32,  707
  469. 1260 DATA   98,  101,   32,  111,  112,  101,  110,  101,  766
  470. 1270 DATA  100,    9,   32,   44,   59,   61,    0,    0,  305
  471.  
  472.  
  473.  
  474.  
  475. Figure 2:  A DUMP.BAS program that will create DUMP.EXE.
  476.  
  477.  
  478.  
  479. 0000-0000  4D 5A 16 01 02 00 00 00-04 00 00 00 FF FF 00 00  MZ..............
  480. 0000-0010  B8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
  481. 0000-0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  482. 0000-0030  00 00 00 00 00 00 00 00-00 00 00 00 80 00 00 00  ................
  483. 0000-0040  0E 1F BA 0E 00 B4 09 CD-21 B8 01 4C CD 21 54 68  ........!..L.!Th
  484. 0000-0050  69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F  is program canno
  485. 0000-0060  74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20  t be run in DOS 
  486. 0000-0070  6D 6F 64 65 2E 0D 0A 24-00 00 00 00 00 00 00 00  mode...$........
  487. 0000-0080  4E 45 05 00 64 00 02 00-29 09 20 A1 02 00 02 00  NE..d...). .....
  488. 0000-0090  00 00 00 00 10 00 01 00-10 03 02 00 02 00 01 00  ................
  489. 0000-00A0  0C 00 40 00 50 00 50 00-58 00 5A 00 E6 00 00 00  ..@.P.P.X.Z.....
  490. 0000-00B0  00 00 04 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  491. 0000-00C0  10 00 4E 01 00 0D 4E 01-28 00 96 00 01 0C 10 03  ..N...N.(.......
  492. 0000-00D0  04 44 55 4D 50 00 00 00-01 00 00 08 44 4F 53 43  .DUMP.......DOSC
  493. 0000-00E0  41 4C 4C 53 00 00 08 44-55 4D 50 2E 45 58 45 00  ALLS...DUMP.EXE.
  494. 0000-00F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  495. 0000-0100  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  496. 0000-0110  1E 07 8E D8 8B F3 AC 0A-C0 75 FB AC 0A C0 74 1E  .........u....t.
  497. 0000-0120  BF 91 00 B9 05 00 F2 AE-74 F1 8B D6 4A AC BF 91  ........t...J...
  498. 0000-0130  00 B9 06 00 F2 AE 75 F5-C6 44 FF 00 EB 1F 06 1F  ......u..D......
  499. 0000-0140  BA 00 00 B9 69 00 6A 02-1E 52 51 1E 68 A2 00 9A  ....i.j..RQ.h...
  500. 0000-0150  FF FF 00 00 6A 01 6A 01-9A FF FF 00 00 1E 06 1F  ....j.j.........
  501. 0000-0160  07 06 52 1E 68 9C 00 1E-68 9E 00 6A 00 6A 00 6A  ..R.h...h..j.j.j
  502. 0000-0170  00 6A 01 6A 20 6A 00 6A-00 9A FF FF 00 00 0B C0  .j.j j.j........
  503. 0000-0180  74 08 BA 69 00 B9 28 00-EB BC 1E 07 FF 36 9C 00  t..i..(......6..
  504. 0000-0190  1E 68 A4 00 6A 10 1E 68-A0 00 9A FF FF 00 00 83  .h..j..h........
  505. 0000-01A0  3E A0 00 00 75 03 EB 7B-90 BF B4 00 A1 99 00 E8  >...u..{........
  506. 0000-01B0  83 00 B0 2D AA A1 97 00-E8 7A 00 B0 20 AA BE A4  ...-.....z.. ...
  507. 0000-01C0  00 8B 0E A0 00 2B DB B0-20 83 FB 08 75 02 B0 2D  .....+.. ...u..-
  508. 0000-01D0  AA AC E8 67 00 43 E2 EF-B9 10 00 2B CB 6B C9 03  ...g.C.....+.k..
  509. 0000-01E0  83 C1 02 B0 20 F3 AA BE-A4 00 8B 0E A0 00 AC 3C  .... ..........<
  510. 0000-01F0  20 72 04 3C 7F 72 02 B0-2E AA E2 F2 B0 0D AA B0   r.<.r..........
  511. 0000-0200  0A AA 81 EF B4 00 6A 01-1E 68 B4 00 57 1E 68 A2  ......j..h..W.h.
  512. 0000-0210  00 9A 50 00 00 00 83 06-97 00 10 83 16 99 00 00  ..P.............
  513. 0000-0220  E9 69 FF FF 36 9C 00 9A-FF FF 00 00 6A 01 6A 00  .i..6.......j.j.
  514. 0000-0230  9A 59 00 00 00 86 C4 E8-02 00 86 C4 50 C0 E8 04  .Y..........P...
  515. 0000-0240  E8 03 00 58 24 0F 04 90-27 14 40 27 AA C3 05 00  ...X$...'.@'....
  516. 0000-0250  03 01 31 01 01 00 05 00-03 01 9B 00 01 00 89 00  ..1.............
  517. 0000-0260  03 01 12 01 01 00 8A 00-03 01 28 01 01 00 3B 00  ..........(...;.
  518. 0000-0270  03 01 7A 00 01 00 46 00-00 00 00 00 00 00 00 00  ..z...F.........
  519. 0000-0280  0D 0A 53 79 6E 74 61 78-3A 20 44 55 4D 50 20 66  ..Syntax: DUMP f
  520. 0000-0290  69 6C 65 6E 61 6D 65 0D-0A 0A 28 43 29 20 31 39  ilename...(C) 19
  521. 0000-02A0  38 38 2C 20 5A 69 66 66-2D 44 61 76 69 73 20 43  88, Ziff-Davis C
  522. 0000-02B0  6F 6D 6D 75 6E 69 63 61-74 69 6F 6E 73 20 43 6F  ommunications Co
  523. 0000-02C0  2E 0D 0A 50 72 6F 67 72-61 6D 6D 65 64 20 62 79  ...Programmed by
  524. 0000-02D0  20 43 68 61 72 6C 65 73-20 50 65 74 7A 6F 6C 64   Charles Petzold
  525. 0000-02E0  2C 20 31 32 2F 38 37 0D-0A 44 55 4D 50 3A 20 46  , 12/87..DUMP: F
  526. 0000-02F0  69 6C 65 20 6E 6F 74 20-66 6F 75 6E 64 20 6F 72  ile not found or
  527. 0000-0300  20 63 61 6E 6E 6F 74 20-62 65 20 6F 70 65 6E 65   cannot be opene
  528. 0000-0310  64 09 20 2C 3B 3D                                d. ,;=
  529.  
  530.  
  531.  
  532.  
  533. Figure 3:  The five major sections of the OS/2 DUMP.EXE file.
  534.  
  535.  
  536. Offset in file where new .EXE header begins. 
  537.  
  538.  
  539. 0000-0000  4D 5A 16 01 02 00 00 00-04 00 00 00 FF FF 00 00  MZ..............
  540. 0000-0010  B8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
  541. 0000-0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  542. 0000-0030  00 00 00 00 00 00 00 00-00 00 00 00 80 00 00 00  ................
  543.  
  544.  
  545. Figure 4:  OS/2 uses the double word at 3Ch to determine where the new .EXE header is located.
  546.  
  547.  
  548. Figure 5 labels:
  549.  
  550.           Number of segments in the file
  551.           Offset of segment table relative to NEWHDR
  552.           Alignment shift count
  553.           Segment table
  554.  
  555. [Figure 5 begins]
  556.  
  557. 0000-0040  0E 1F BA 0E 00 B4 09 CD-21 B8 01 4C CD 21 54 68  ........!..L.!Th
  558. 0000-0050  69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F  is program canno
  559. 0000-0060  74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20  t be run in DOS 
  560. 0000-0070  6D 6F 64 65 2E 0D 0A 24-00 00 00 00 00 00 00 00  mode...$........
  561.  
  562.  
  563.  
  564. Figure 5:  OS/2 uses information in the new header to identify the code and data segments of the program.
  565.  
  566.  
  567.  
  568.   DUMP.EXE's Segment Table
  569.  
  570.  
  571.                               Segment 1      Segment 2
  572.                               ---------      ---------
  573. Location of segment in file:     0010           0028
  574. Size of segment in file:         014E           0096
  575. Flags:                           0D00           0C01
  576. Size of segment in memory:       014E           0310
  577.  
  578.  
  579.  
  580.   The segment table in an OS/2 .EXE file has four words for each code and data segment in the program.
  581.  
  582.  
  583.  
  584.  
  585. 0000-0080  4E 45 05 00 64 00 02 00-29 09 20 A1 02 00 02 00  NE..d...). .....
  586. 0000-0090  00 00 00 00 10 00 01 00-10 03 02 00 02 00 01 00  ................
  587. 0000-00A0  0C 00 40 00 50 00 50 00-58 00 5A 00 E6 00 00 00  ..@.P.P.X.Z.....
  588. 0000-00B0  00 00 04 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  589. 0000-00C0  10 00 4E 01 00 0D 4E 01-28 00 96 00 01 0C 10 03  ..N...N.(.......
  590. 0000-00D0  04 44 55 4D 50 00 00 00-01 00 00 08 44 4F 53 43  .DUMP.......DOSC
  591. 0000-00E0  41 4C 4C 53 00 00 08 44-55 4D 50 2E 45 58 45 00  ALLS...DUMP.EXE.
  592. 0000-00F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  593.  
  594.  
  595.  
  596.  
  597. Figure 6:  Information in the header section indicates entry conditions for the program.
  598.  
  599.  
  600.  
  601.  
  602. 0000-0100  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
  603. 0000-0110  1E 07 8E D8 8B F3 AC 0A-C0 75 FB AC 0A C0 74 1E  .........u....t.
  604. 0000-0120  BF 91 00 B9 05 00 F2 AE-74 F1 8B D6 4A AC BF 91  ........t...J...
  605. 0000-0130  00 B9 06 00 F2 AE 75 F5-C6 44 FF 00 EB 1F 06 1F  ......u..D......
  606. 0000-0140  BA 00 00 B9 69 00 6A 02-1E 52 51 1E 68 A2 00 9A  ....i.j..RQ.h...
  607. 0000-0150  FF FF 00 00 6A 01 6A 01-9A FF FF 00 00 1E 06 1F  ....j.j.........
  608. 0000-0160  07 06 52 1E 68 9C 00 1E-68 9E 00 6A 00 6A 00 6A  ..R.h...h..j.j.j
  609. 0000-0170  00 6A 01 6A 20 6A 00 6A-00 9A FF FF 00 00 0B C0  .j.j j.j........
  610. 0000-0180  74 08 BA 69 00 B9 28 00-EB BC 1E 07 FF 36 9C 00  t..i..(......6..
  611. 0000-0190  1E 68 A4 00 6A 10 1E 68-A0 00 9A FF FF 00 00 83  .h..j..h........
  612. 0000-01A0  3E A0 00 00 75 03 EB 7B-90 BF B4 00 A1 99 00 E8  >...u..{........
  613. 0000-01B0  83 00 B0 2D AA A1 97 00-E8 7A 00 B0 20 AA BE A4  ...-.....z.. ...
  614. 0000-01C0  00 8B 0E A0 00 2B DB B0-20 83 FB 08 75 02 B0 2D  .....+.. ...u..-
  615. 0000-01D0  AA AC E8 67 00 43 E2 EF-B9 10 00 2B CB 6B C9 03  ...g.C.....+.k..
  616. 0000-01E0  83 C1 02 B0 20 F3 AA BE-A4 00 8B 0E A0 00 AC 3C  .... ..........<
  617. 0000-01F0  20 72 04 3C 7F 72 02 B0-2E AA E2 F2 B0 0D AA B0   r.<.r..........
  618. 0000-0200  0A AA 81 EF B4 00 6A 01-1E 68 B4 00 57 1E 68 A2  ......j..h..W.h.
  619. 0000-0210  00 9A 50 00 00 00 83 06-97 00 10 83 16 99 00 00  ..P.............
  620. 0000-0220  E9 69 FF FF 36 9C 00 9A-FF FF 00 00 6A 01 6A 00  .i..6.......j.j.
  621. 0000-0230  9A 59 00 00 00 86 C4 E8-02 00 86 C4 50 C0 E8 04  .Y..........P...
  622. 0000-0240  E8 03 00 58 24 0F 04 90-27 14 40 27 AA C3 05 00  ...X$...'.@'....
  623. 0000-0250  03 01 31 01 01 00 05 00-03 01 9B 00 01 00 89 00  ..1.............
  624. 0000-0260  03 01 12 01 01 00 8A 00-03 01 28 01 01 00 3B 00  ..........(...;.
  625. 0000-0270  03 01 7A 00 01 00 46 00-00 00 00 00 00 00 00 00  ..z...F.........
  626.  
  627.  
  628.  
  629. Figure 7:  The code segment in DUMP.EXE contains relocation information for dynamic linking.
  630.  
  631.  
  632.  
  633. 0000-0040  0E 1F BA 0E 00 B4 09 CD-21 B8 01 4C CD 21 54 68  ........!..L.!Th
  634. 0000-0050  69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F  is program canno
  635. 0000-0060  74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20  t be run in DOS 
  636. 0000-0070  6D 6F 64 65 2E 0D 0A 24-00 00 00 00 00 00 00 00  mode...$........
  637.  
  638.  
  639.  
  640.  
  641. Figure 8:  Tables in the header also aid in resolving calls to dynamic link libraries.
  642.  
  643.  
  644.   DUMP.EXE's OS/2 Function Calls
  645.  
  646.      Offset in Code Segment   Ordinal Number   Function
  647.      ----------------------   --------------   --------
  648.         131h (also 59h)              5h        DosExit
  649.          9Bh                        89h        DosRead
  650.         112h (also 50h)             8Ah        DosWrite
  651.         128h                        3Bh        DosClose
  652.          7Ah                        46h        DosOpen
  653.  
  654.  
  655.  
  656.   OS/2 uses the relocation table to identify and fix all the calls a program makes to OS/2 functions.
  657.