     1                                  ;*********************************************************************
     2                                  ;*   MLPASS2D.ASM                                                    *
     3                                  ;*                                                                   *
     4                                  ;*   By:            Michael Devore                                   *
     5                                  ;*   Date:          12/22/92                                         *
     6                                  ;*   Model:         Small                                            *
     7                                  ;*   Version:       2.5                                              *
     8                                  ;*   Assembler:     MASM 5.0                                         *
     9                                  ;*   Environment:   MS-DOS 2.x+                                      *
    10                                  ;*                                                                   *
    11                                  ;*   linker pass 2 routines part D                                   *
    12                                  ;*                                                                   *
    13                                  ;*********************************************************************
    14                                  
    15                                  ;TITLE   WARPLINK mlpass2d
    16                                  ;PAGE    50,80
    17                                  
    18                                  ;.MODEL  SMALL
    19                                  
    20                                  ;*****************************
    21                                  ;* Include files             *
    22                                  ;*****************************
    23                                  
    24                                  [list -]
    29                                       
    30                                  ;*****************************
    31                                  ;* Public declarations       *
    32                                  ;*****************************
    33                                  
    34                                  ; procedures
    35                                  PUBLIC  proc2_fixupp,save_thread
    36                                  PUBLIC  check_index,get_target_addr,get_frame_addr
    37                                  PUBLIC  fixupp_offset_err
    38                                  
    39                                  ; variables
    40                                  PUBLIC  frame_method,target_method,target_disp
    41                                  PUBLIC  frame_ent_ptr,targ_ent_ptr,frext_ingroup
    42                                  PUBLIC  frame_index,target_index,loc,is_resolved
    43                                  PUBLIC  fixup_pos,target_prog_off,target_segment
    44                                  PUBLIC  locat
    45                                  PUBLIC  is_ind_call,is_relocatable,data_rec_offset,no_fixbyte_flag
    46                                  PUBLIC  gen_flags
    47                                  
    48                                  ;*****************************
    49                                  ;* Data begins               *
    50                                  ;*****************************
    51                                  
    52                                  .DATA
    53                                  
    54                                  ; variables
    55                                  EXTRN   data_offset:DWORD,prev_data_ptr:WORD,filename:BYTE
    56                                  EXTRN   is_absseg:BYTE
    57                                  EXTRN   seg_fix_frame:WORD,data_seg_part:WORD
    58                                  EXTRN   seg_ovl_class_flag:BYTE
    59                                  EXTRN	is_clipper5:BYTE,compress_this:BYTE,which_ledata:BYTE
    60                                  EXTRN	current_segind:WORD,clipper_segindex:WORD
    61                                  EXTRN	ignore_fixupp_flag:BYTE
    62                                  
    63                                  ;*****************************
    64                                  ;* External declarations     *
    65                                  ;*****************************
    66                                  
    67                                  ; initialized local variables
    68                                  
    69                                  EVEN                        ; maximize speed on 8086 and better
    70                                  
    71                                  ; byte values
    72                                  EVEN
    73 00000000 00                      is_entry_point  DB  0       ; nonzero if have an entry point from modend record
    74 00000001 00                      clipper_fixflag	DB	0		; nonzero if previous clipper procedure fixed up
    75 00000002 FF001500FF03            bounds_check    DW  SEGDEF_MAX,GRPDEF_MAX,EXTDEF_MAX
    76                                  
    77                                  ; jump table words
    78 00000008 [0E05][C505]            targ_jmp_table  DW  OFFSET gta_seg wrt _TEXT,OFFSET gta_grp wrt _TEXT
    79 0000000C [EF05][0000]                            DW  OFFSET gta_ext wrt _TEXT,OFFSET link_error wrt _TEXT
    80 00000010 [0E05][C505]                            DW  OFFSET gta_seg wrt _TEXT,OFFSET gta_grp wrt _TEXT
    81 00000014 [EF05][0000]                            DW  OFFSET gta_ext wrt _TEXT,OFFSET link_error wrt _TEXT
    82                                  
    83                                  .DATA?
    84                                  
    85                                  ; uninitialized local variables
    86                                  
    87                                  ; byte values
    88                                  EVEN                        ; maximize speed on 8086 and better
    89 00000000 ??                      loc     DB  ?               ; loc field
    90 00000001 ??                      EVEN
    91 00000002 ??                      frame_method    DB  ?       ; frame method for fixup
    92 00000003 ??                      EVEN
    93 00000004 ??                      target_method   DB  ?       ; target method for fixup
    94 00000005 ??                      EVEN
    95 00000006 ??                      thread_method   DB  ?       ; thread method for fixup
    96 00000007 ??                      EVEN
    97 00000008 ??                      is_relocatable  DB  ?       ; nonzero if target segment is relocatable
    98 00000009 ??                      EVEN
    99 0000000A ??                      is_resolved DB  ?           ; nonzero if external index is unresolved
   100 0000000B ??                      EVEN
   101                                   global is_abspub
   102 0000000C ??                      is_abspub   DB  ?           ; nonzero if absolute public declaration
   103 0000000D ??                      EVEN
   104 0000000E ??                      frext_ingroup   DB  ?       ; nonzero if FRAME external index is in group
   105 0000000F ??                      EVEN
   106 00000010 ??                      no_fixbyte_flag DB  ?       ; nonzero if fixup location shouldn't have nonzero bytes
   107 00000011 ??                      EVEN
   108 00000012 ??                      is_ind_call DB  ?           ; nonzero if indirect call to overlaid public, or far call via segment fixup
   109 00000013 ??                      EVEN
   110 00000014 ??                      gen_flags   DB  ?           ; general flags used for miscellaneous purposes
   111                                                              ; bit 0 no vector address changes in frame computation
   112                                  
   113                                  ; word values
   114 00000015 ??                      EVEN
   115 00000016 ????                    locat   DW  ?               ; locat field
   116 00000018 ????                    data_rec_offset DW  ?       ; data record offset field
   117 0000001A ????                    frame_index DW  ?           ; frame index
   118 0000001C ????                    target_index    DW  ?       ; target index
   119 0000001E ????                    thread_index    DW  ?       ; thread index
   120 00000020 ????                    target_segment  DW  ?       ; target segment
   121 00000022 ????                    fixup_pos   DW  ?           ; position of current fixup field in fixupp record
   122 00000024 ????                    frame_ent_ptr   DW  ?       ; pointer to segment holding FRAME group or segment entry
   123 00000026 ????                    targ_ent_ptr    DW  ?       ; pointer to segment holding TARGET group, segment, or symbol entry
   124 00000028 ????                    symbol_segbase	DW	?		; initial symbol segment base value for Clipper compression
   125                                  
   126                                  ; doubleword values
   127 0000002A ????????                target_prog_off DD  ?       ; target program offset
   128 0000002E ????????                target_disp DD  ?           ; target displacement field
   129 00000032 ????????                lseg_canon      DD  ?       ; use to compute canonical (normalized) segment value
   130                                                              ; of LSEG (logical segment), used for LOC type fixup
   131                                  
   132                                  ;*****************************
   133                                  ;* Code begins               *
   134                                  ;*****************************
   135                                  
   136                                  .CODE
   137                                  
   138                                  ;*****************************
   139                                  ;* External declarations     *
   140                                  ;*****************************
   141                                  
   142                                  ; procedures
   143                                  EXTRN   link_error:NEAR,dos_error:NEAR,load_file:NEAR,link_warning:NEAR
   144                                  EXTRN   get_data_off_seg:NEAR,proc2_data:NEAR,fixup_warning:NEAR
   145                                  EXTRN   fixup_ovl_extdef:NEAR,fixup_ind_ref_extdef:NEAR
   146                                  EXTRN   fixup_seg_ref:NEAR
   147                                  EXTRN	compsym_fixup:NEAR
   148                                  
   149                                  ;*****************************
   150                                  ;* PROC2_FIXUPP              *
   151                                  ;*****************************
   152                                  
   153                                  ; pass 2 fixupp record processing
   154                                  ; upon entry cx=record length,bp=buffer_end,al=record type
   155                                  ; es:si -> first byte of record past record length
   156                                  ; destroys ax,bx,dx,di
   157                                  ; updates si
   158                                  
   159                                  proc2_fixupp    PROC
   160 00000000 803E[0000]00            	cmp	byte [ignore_fixupp_flag],0	; see if ignoring this fixupp
   161 00000005 7403                    	je	pf_0				; no
   162 00000007 E9F200                  	jmp	NEAR PTR pf_out		; yes, ignore it
   163                                  
   164                                  pf_0:
   165 0000000A 803E[0000]00                cmp byte [prev_flag],0         ; check if previous L?DATA record
   166 0000000F 7409                        je  pf_1                ; no previous data record (should be thread fixups)
   167                                  
   168 00000011 06                          push    es              ; save critical registers used by get_data_off_seg procedure
   169 00000012 56                          push    si
   170 00000013 51                          push    cx
   171 00000014 E8(0000)                    call    get_data_off_seg    ; get data record offset and segment
   172 00000017 59                          pop cx                  ; restore critical registers
   173 00000018 5E                          pop si
   174 00000019 07                          pop es
   175                                  
   176                                  pf_1:
   177 0000001A C706[0000]0000              mov word [data_fixup_count],0  ; init count of relocation items in array
   178                                  
   179                                  pf_loop1:
   180                                  ; get byte value, but don't increment past it
   181 00000020 8936[2200]                  mov [fixup_pos],si        ; keep -> fixup in case of error
   182 00000024 268A04                      mov al,[es:si]          ; get first byte of either thread or fixup field
   183 00000027 2480                        and al,80h              ; check fixup field, high bit set
   184 00000029 7425                        je  pf_3                ; no, thread field
   185                                  
   186 0000002B 803E[0000]00                cmp byte [prev_flag],0         ; check if previous L?DATA record
   187 00000030 7514                        jne pf_2                ; yes
   188                                  
   189                                  ; fixup field given with no preceding L?DATA record
   190 00000032 B82000                      mov ax,FIXUPP_DATA_ERR  ; FIXUPP contains a fixup without preceding data record
   191 00000035 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   192 00000038 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   193                                  
   194                                  ; inner loop without previous flag check to speed things up
   195                                  pf_loop2:
   196                                  ; get byte value, but don't increment past it
   197 0000003B 8936[2200]                  mov [fixup_pos],si        ; keep -> fixup in case of error
   198 0000003F 268A04                      mov al,[es:si]          ; get first byte of either thread or fixup field
   199 00000042 2480                        and al,80h              ; check fixup field, high bit set
   200 00000044 740A                        je  pf_3                ; no, thread field
   201                                  
   202                                  pf_2:
   203 00000046 E8B900                      call    perform_fixup   ; do fixup field code
   204 00000049 83F901                      cmp cx,1                ; check if at checksum byte
   205 0000004C 77ED                        ja  pf_loop2            ; no, loop back for next fixup/thread field
   206 0000004E EB08                        jmp SHORT pf_eat_chksum ; yes, eat it and continue
   207                                  
   208                                  pf_3:
   209 00000050 E8BE07                      call    save_thread     ; do thread field code
   210 00000053 83F901                      cmp cx,1                ; check if at checksum byte
   211 00000056 77C8                        ja  pf_loop1            ; no, loop back for next fixup/thread field
   212                                  
   213                                  pf_eat_chksum:
   214 00000058 46                          inc si                  ; bump past checksum byte, to next record byte
   215 00000059 49                          dec cx
   216 0000005A 39EE                        cmp si,bp               ; check boundary conditions
   217 0000005C 7203                        jb  pf_next_rec         ; okay
   218 0000005E E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   219                                  
   220                                  ; check the next record.  if another fixupp record, process it.
   221                                  ; this allows multiple FIXUPP records after a L?DATA record as needed
   222                                  ; by Clipper, Force, and possibly others.
   223                                  
   224                                  pf_next_rec:
   225 00000061 268A04                      mov al,[es:si]          ; get next record type
   226 00000064 3C9C                        cmp al,FIXUPP           ; see if fixupp record
   227 00000066 7540                        jne pf_proc_data        ; no
   228 00000068 8936[0000]                  mov [read_buff_ptr],si    ; keep beginning of object record
   229 0000006C 46                          inc si                  ; bump si past record type
   230 0000006D 39EE                        cmp si,bp               ; check boundary conditions
   231 0000006F 7203                        jb  pf_4                ; okay
   232 00000071 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   233                                  pf_4:
   234 00000074 268A0C                      mov cl,[es:si]          ; get record length low byte
   235 00000077 46                          inc si
   236 00000078 39EE                        cmp si,bp               ; check boundary conditions
   237 0000007A 7203                        jb  pf_5                ; okay
   238 0000007C E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   239                                  
   240                                  pf_5:
   241 0000007F 268A2C                      mov ch,[es:si]          ; get record length high byte
   242 00000082 46                          inc si                  ; bump si past length word
   243 00000083 39EE                        cmp si,bp               ; check boundary conditions
   244 00000085 7203                        jb  pf_6                ; okay
   245 00000087 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   246                                  
   247                                  pf_6:
   248                                  ; check if a null record
   249 0000008A 83F901                      cmp cx,1                ; see if null record
   250 0000008D 76C9                        jbe pf_eat_chksum       ; yes, ignore it
   251                                  
   252                                  ; check that record doesn't exceed file length
   253 0000008F A0[0000]                    mov al,[eof_flag]
   254 00000092 08C0                        or  al,al               ; see if end of file encountered
   255 00000094 748A                        je  pf_loop1            ; nope, loop back and process next FIXUPP record
   256 00000096 89CA                        mov dx,cx               ; get record length
   257 00000098 01F2                        add dx,si               ; add in current position
   258 0000009A 7309                        jnc pf_7                ; no overflow
   259                                  
   260                                  pf_unexpected_eof:
   261 0000009C BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   262 0000009F B80A00                      mov ax,UNEXPECT_EOF_ERR ; unexpected end of file
   263 000000A2 E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   264                                  
   265                                  pf_7:
   266 000000A5 E978FF                      jmp NEAR PTR pf_loop1       ; loop back and process next FIXUPP record
   267                                  
   268                                  ; process the modified LEDATA or LIDATA record, if any
   269                                  pf_proc_data:
   270 000000A8 803E[0000]00                cmp byte [prev_flag],0         ; check if previous L?DATA record
   271 000000AD 7452                        je  pf_ret              ; no previous data record (thread fixup only)
   272                                  
   273 000000AF 803E[0000]00            	cmp	byte [compress_this],0		; see if compressing Clipper code
   274 000000B4 7443                    	je	pf_proc2			; no
   275 000000B6 A1[0000]                	mov	ax,[current_segind]
   276 000000B9 3B06[0000]              	cmp	ax,[clipper_segindex]
   277 000000BD 733A                    	jae	pf_proc2			; not Clipper code
   278                                  
   279 000000BF 8B1E[0000]                  mov bx,[prev_data_ptr]    ; bx -> previous record position data bytes/block
   280 000000C3 803E[0100]00            	cmp	byte [clipper_fixflag],0	; see if first Clipper procedure fixed up
   281 000000C8 751B                    	jne	pf_notfirst
   282                                  
   283                                  ; first clipper procedure fixed up
   284                                  ; save fixup value at offset 0bh for S'87 or offset 4 for Clipper 5
   285 000000CA C606[0100]01            	mov	byte [clipper_fixflag],1	; flag following Clipper procedures as not first
   286 000000CF 803E[0000]00            	cmp	byte [is_clipper5],0		; see if clipper 5 code
   287 000000D4 7409                    	je	pf_s87save			; no
   288 000000D6 268B4704                	mov	ax,[es:bx+4]		; get initial segment base value for Clipper 5
   289                                  
   290                                  pf_basesave:
   291 000000DA A3[2800]                	mov	[symbol_segbase],ax	; save the initial symbol segment base value
   292 000000DD EB1A                    	jmp	SHORT pf_proc2
   293                                  
   294                                  pf_s87save:
   295 000000DF 268B470B                	mov	ax,[es:bx+0bh]		; get initial segment base value for Summer 87
   296 000000E3 EBF5                    	jmp	SHORT pf_basesave
   297                                  
   298                                  ; subsequent clipper procedure
   299                                  ; place saved fixup symbol segment base value at offset 0bh or offset 4
   300                                  pf_notfirst:
   301 000000E5 A1[2800]                	mov	ax,[symbol_segbase]	; get the initial segment base value
   302 000000E8 803E[0000]00            	cmp	byte [is_clipper5],0		; see if clipper 5 code
   303 000000ED 7406                    	je	pf_s87store			; no
   304 000000EF 26894704                	mov	[es:bx+4],ax		; store initial segment base value for Clipper 5
   305 000000F3 EB04                    	jmp	SHORT pf_proc2
   306                                  
   307                                  pf_s87store:
   308 000000F5 2689470B                	mov	[es:bx+0bh],ax		; store inital segment base value for Summer 87
   309                                  
   310                                  pf_proc2:
   311 000000F9 E8(0000)                    call    proc2_data
   312                                  
   313                                  pf_out:
   314 000000FC C606[0000]00                mov byte [prev_flag],0         ; reset previous record flag
   315                                  
   316                                  pf_ret:
   317 00000101 C3                          ret
   318                                  proc2_fixupp    ENDP
   319                                  
   320                                  ;*****************************
   321                                  ;* PERFORM_FIXUP             *
   322                                  ;*****************************
   323                                  
   324                                  ; parse the fixup field and perform the fixup
   325                                  ; destroys ax,bx,dx,di
   326                                  ; updates si record pointer, cx record length
   327                                  
   328                                  perform_fixup   PROC
   329 00000102 30C0                        xor al,al
   330 00000104 A2[0000]                    mov [is_absseg],al        ; init absolute flags
   331 00000107 A2[0C00]                    mov [is_abspub],al
   332 0000010A 268A04                      mov al,[es:si]          ; get low byte of locat field
   333 0000010D 46                          inc si
   334 0000010E 49                          dec cx                  ; decrement record length to parse
   335 0000010F 39EE                        cmp si,bp               ; check boundary conditions
   336 00000111 7203                        jb  pef_2               ; okay
   337 00000113 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   338                                  pef_2:
   339 00000116 268A24                      mov ah,[es:si]          ; get high byte of locat field
   340 00000119 46                          inc si
   341 0000011A 49                          dec cx                  ; decrement record length to parse
   342 0000011B 39EE                        cmp si,bp               ; check boundary conditions
   343 0000011D 7203                        jb  pef_3               ; okay
   344 0000011F E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   345                                  pef_3:
   346 00000122 A3[1600]                    mov [locat],ax            ; save locat field to memory variable
   347                                  
   348 00000125 88C2                        mov dl,al
   349 00000127 80E21C                      and dl,1ch              ; get loc field
   350 0000012A D0EA                        shr dl,1
   351 0000012C D0EA                        shr dl,1                ; make loc value relative zero
   352 0000012E 8816[0000]                  mov [loc],dl              ; save loc value
   353                                  
   354 00000132 8826[1800]                  mov BYTE PTR [data_rec_offset],ah ; save bit 7-0 of data record offset in locat high byte
   355 00000136 2403                        and al,3                ; get bit 9-8 of data record offset in locat low byte
   356 00000138 A2[1900]                    mov BYTE PTR [data_rec_offset+1],al   ; and save it
   357                                  
   358 0000013B 268A14                      mov dl,[es:si]          ; get fix dat field
   359 0000013E 46                          inc si
   360 0000013F 49                          dec cx                  ; decrement record length to parse
   361 00000140 39EE                        cmp si,bp               ; check boundary conditions
   362 00000142 7203                        jb  pef_4               ; okay
   363 00000144 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   364                                  pef_4:
   365 00000147 88D6                        mov dh,dl               ; dh holds fix dat field value
   366 00000149 80E670                      and dh,70h              ; get frame field in dh
   367 0000014C D0EE                        shr dh,1
   368 0000014E D0EE                        shr dh,1
   369 00000150 D0EE                        shr dh,1
   370 00000152 D0EE                        shr dh,1                ; make frame value relative zero
   371                                  
   372 00000154 88D0                        mov al,dl               ; get fix dat field
   373 00000156 A880                        test    al,80h          ; check if thread field for frame (fbit)
   374 00000158 7538                        jne pef_thrdframe       ; yes
   375                                  
   376                                  ; no thread field for frame
   377 0000015A 80FE02                      cmp dh,2                ; see if index specified for this frame
   378 0000015D 7725                        ja  pef_5               ; no
   379                                  
   380                                  ; index specified for this field
   381 0000015F 30E4                        xor ah,ah               ; zap high byte
   382 00000161 268A04                      mov al,[es:si]          ; get frame datum first byte
   383 00000164 46                          inc si
   384 00000165 49                          dec cx                  ; decrement record length to parse
   385 00000166 39EE                        cmp si,bp               ; check boundary conditions
   386 00000168 7203                        jb  pef_4a              ; okay
   387 0000016A E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   388                                  pef_4a:
   389 0000016D 3C80                        cmp al,80h              ; see if two byte field
   390 0000016F 7210                        jb  pef_4b              ; no
   391 00000171 247F                        and al,7fh              ; strip high bit
   392 00000173 88C4                        mov ah,al               ; move value to high byte
   393                                  
   394 00000175 268A04                      mov al,[es:si]          ; get frame datum second byte
   395 00000178 46                          inc si
   396 00000179 49                          dec cx                  ; decrement record length to parse
   397 0000017A 39EE                        cmp si,bp               ; check boundary conditions
   398 0000017C 7203                        jb  pef_4b              ; okay
   399 0000017E E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   400                                  
   401                                  pef_4b:
   402 00000181 A3[1A00]                    mov [frame_index],ax      ; frame index, if any
   403                                  
   404                                  pef_5:
   405 00000184 8836[0200]                  mov [frame_method],dh     ; frame method is the frame field
   406 00000188 EB2F                        jmp SHORT pef_6         ; bypass frame thread field code
   407                                  
   408                                  ; frame thread field exceeds 3
   409                                  pef_frthrd_err:
   410 0000018A 88C1                        mov cl,al
   411 0000018C B83400                      mov ax,FRAME_THRD_ERR
   412 0000018F E91F03                      jmp NEAR PTR fixupp_offset_err  ; transfer control to error handler
   413                                  
   414                                  ; thread field for frame
   415                                  pef_thrdframe:
   416 00000192 D0E8                        shr al,1                ; make frame field value relative zero
   417 00000194 D0E8                        shr al,1
   418 00000196 D0E8                        shr al,1
   419 00000198 D0E8                        shr al,1
   420 0000019A 2407                        and al,7                ; mask off F bit
   421 0000019C 3C03                        cmp al,3                ; make sure frame thread field doesn't exceed 3
   422 0000019E 77EA                        ja  pef_frthrd_err      ; bad frame thread field
   423                                  
   424 000001A0 30E4                        xor ah,ah               ; zap high byte
   425 000001A2 BB[0000]                    mov bx,OFFSET frame_thrd_meth wrt DGROUP    ; bx -> frame thread method array base
   426 000001A5 01C3                        add bx,ax               ; bx -> proper byte array element
   427 000001A7 8A1F                        mov bl,[bx]             ; get frame method
   428 000001A9 881E[0200]                  mov [frame_method],bl     ; save to memory variable
   429                                  
   430 000001AD D1E0                        shl ax,1                ; convert to word offset
   431 000001AF BB[0000]                    mov bx,OFFSET frame_thrd_index wrt DGROUP   ; bx -> frame thread index array base
   432 000001B2 01C3                        add bx,ax               ; bx -> proper word array element
   433 000001B4 8B07                        mov ax,[bx]             ; get frame index
   434 000001B6 A3[1A00]                    mov [frame_index],ax      ; save to memory variable
   435                                  
   436                                  pef_6:
   437 000001B9 88D0                        mov al,dl               ; get fix dat field
   438 000001BB A808                        test    al,8            ; check if thread field for target (tbit)
   439 000001BD 7541                        jne pef_thrdtarg        ; yes
   440                                  
   441                                  ; no thread field for target
   442 000001BF 30E4                        xor ah,ah               ; zap high byte
   443 000001C1 268A04                      mov al,[es:si]          ; get target datum first byte
   444 000001C4 46                          inc si
   445 000001C5 49                          dec cx                  ; decrement record length to parse
   446 000001C6 39EE                        cmp si,bp               ; check boundary conditions
   447 000001C8 7203                        jb  pef_6a              ; okay
   448 000001CA E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   449                                  pef_6a:
   450 000001CD 3C80                        cmp al,80h              ; see if two byte field
   451 000001CF 7210                        jb  pef_6b              ; no
   452 000001D1 247F                        and al,7fh              ; strip high bit
   453 000001D3 88C4                        mov ah,al               ; move value to high byte
   454                                  
   455 000001D5 268A04                      mov al,[es:si]          ; get target datum second byte
   456 000001D8 46                          inc si
   457 000001D9 49                          dec cx                  ; decrement record length to parse
   458 000001DA 39EE                        cmp si,bp               ; check boundary conditions
   459 000001DC 7203                        jb  pef_6b              ; okay
   460 000001DE E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   461                                  
   462                                  pef_6b:
   463 000001E1 A3[1C00]                    mov [target_index],ax     ; target index, if any
   464 000001E4 88D0                        mov al,dl               ; get fix dat field
   465 000001E6 2403                        and al,3                ; break out targt field
   466 000001E8 A2[0400]                    mov [target_method],al    ; target method is the targt field
   467 000001EB EB2E                        jmp SHORT pef_7         ; bypass target thread field code
   468                                  
   469                                  ; illegal frame method is 3, 6, or 7
   470                                  pef_bad_frame:
   471 000001ED 88D9                        mov cl,bl
   472 000001EF B83500                      mov ax,FRAME_METH_ERR
   473 000001F2 E9BC02                      jmp NEAR PTR fixupp_offset_err  ; transfer control to error handler
   474                                  
   475                                  ; bad target method of 3 (prior to P bit modifier)
   476                                  pef_bad_target:
   477 000001F5 88D9                        mov cl,bl
   478 000001F7 B83600                      mov ax,TARGET_METH_ERR
   479 000001FA E9B402                      jmp NEAR PTR fixupp_offset_err  ; transfer control to error handler
   480                                  
   481                                  ; segment, group, or external index was out of bounds
   482                                  pef_oob:
   483 000001FD E9DB02                      jmp NEAR PTR ci_oob
   484                                  
   485                                  ; thread field for target
   486                                  pef_thrdtarg:
   487 00000200 2403                        and al,3                ; get targt field value in al
   488 00000202 30E4                        xor ah,ah               ; zap high byte
   489 00000204 BB[0000]                    mov bx,OFFSET target_thrd_meth wrt DGROUP   ; bx -> target thread method array base
   490 00000207 01C3                        add bx,ax               ; bx -> proper byte array element
   491 00000209 8A1F                        mov bl,[bx]             ; get target method
   492 0000020B 881E[0400]                  mov [target_method],bl    ; save to memory variable
   493                                  
   494 0000020F D1E0                        shl ax,1                ; convert to word offset
   495 00000211 BB[0000]                    mov bx,OFFSET target_thrd_index wrt DGROUP  ; bx -> target thread index array base
   496 00000214 01C3                        add bx,ax               ; bx -> proper word array element
   497 00000216 8B07                        mov ax,[bx]             ; get target index
   498 00000218 A3[1C00]                    mov [target_index],ax     ; save to memory variable
   499                                  
   500                                  ; check index validity
   501                                  pef_7:
   502 0000021B 8A1E[0200]                  mov bl,[frame_method]
   503 0000021F 80FB05                      cmp bl,5
   504 00000222 77C9                        ja  pef_bad_frame       ; frame method above 5, invalid
   505 00000224 80FB03                      cmp bl,3
   506 00000227 74C4                        je  pef_bad_frame       ; frame method is 3, invalid
   507 00000229 770F                        ja  pef_8               ; frame method okay and no index specified
   508                                  
   509 0000022B A1[1A00]                    mov ax,[frame_index]      ; get frame index for check_index routine
   510 0000022E D0E3                        shl bl,1                ; make word offset
   511 00000230 30FF                        xor bh,bh
   512 00000232 81C3[0200]                  add bx,OFFSET bounds_check wrt DGROUP
   513 00000236 3B07                        cmp ax,[bx]             ; see if out of bounds
   514 00000238 77C3                        ja  pef_oob             ; yes
   515                                  
   516                                  pef_8:
   517 0000023A A1[1C00]                    mov ax,[target_index]     ; get target index for check_index
   518 0000023D 8A1E[0400]                  mov bl,[target_method]
   519 00000241 80FB03                      cmp bl,3                ; check for bad target method
   520 00000244 74AF                        je  pef_bad_target      ; bad target method
   521                                  
   522 00000246 D0E3                        shl bl,1                ; make word offset
   523 00000248 30FF                        xor bh,bh
   524 0000024A 81C3[0200]                  add bx,OFFSET bounds_check wrt DGROUP
   525 0000024E 85C0                    	test ax, ax
   526 00000250 74AB                    	jz pef_oob
   527 00000252 3B07                        cmp ax,[bx]             ; see if out of bounds
   528 00000254 77A7                        ja  pef_oob             ; yes
   529                                  
   530 00000256 88D0                        mov al,dl               ; get fix dat field
   531 00000258 2404                        and al,4                ; get P bit field
   532 0000025A 0806[0400]                  or  [target_method],al    ; P bit modifies target method, merge it in
   533                                  
   534 0000025E 08C0                        or  al,al               ; check if P bit set
   535 00000260 B80000                      mov ax,0                ; assume it is, setup for zero'ing target displacment, don't change flags via xor
   536 00000263 7518                        jne pef_10              ; yes, P bit set, force target displacement value to zero
   537                                  
   538                                  ; get target displacement field if P bit is zero
   539 00000265 268A04                      mov al,[es:si]          ; get low byte of target displacement
   540 00000268 46                          inc si
   541 00000269 49                          dec cx                  ; decrement record length to parse
   542 0000026A 39EE                        cmp si,bp               ; check boundary conditions
   543 0000026C 7203                        jb  pef_8b              ; okay
   544 0000026E E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   545                                  pef_8b:
   546 00000271 268A24                      mov ah,[es:si]          ; get high byte of target displacement
   547 00000274 46                          inc si
   548 00000275 49                          dec cx                  ; decrement record length to parse
   549 00000276 39EE                        cmp si,bp               ; check boundary conditions
   550 00000278 7203                        jb  pef_10              ; okay
   551 0000027A E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
   552                                  
   553                                  pef_10:
   554 0000027D A3[2E00]                    mov WORD PTR [target_disp],ax ; save target displacement value
   555 00000280 99                          cwd
   556 00000281 8916[3000]                  mov WORD PTR [target_disp+2],dx   ; save sign extension of target displacement
   557                                  
   558                                  ; compute program offset of target address and its frame
   559 00000285 30C0                        xor al,al
   560 00000287 A2[1200]                    mov [is_ind_call],al      ; init indirect call to overlaid public flag
   561 0000028A A2[1000]                    mov [no_fixbyte_flag],al  ; init flag for fixup bytes
   562 0000028D A2[1400]                    mov [gen_flags],al        ; init general flags
   563                                  
   564 00000290 FEC0                        inc al
   565 00000292 A2[0A00]                    mov [is_resolved],al      ; init is_resolved flag to assume fixup okay
   566 00000295 E86102                      call    get_target_addr
   567                                  
   568 00000298 803E[1200]00                cmp byte [is_ind_call],0       ; see if indirect call flag set
   569 0000029D 7549                        jne pef_resolved        ; yes, bypass the frame computation, not needed
   570                                  
   571                                  ; see if absolute segment or absolute public declaration, no frame computation
   572 0000029F A0[0000]                    mov al,[is_absseg]
   573 000002A2 0A06[0C00]                  or  al,[is_abspub]
   574 000002A6 7540                        jne pef_resolved        ; either absolute segment or absolute public declaration
   575                                  
   576 000002A8 A0[0200]                    mov al,[frame_method]
   577 000002AB 3C04                        cmp al,4                ; check if frame determined by location segment
   578 000002AD 7521                        jne pef_11              ; no
   579                                  
   580 000002AF A1[3200]                    mov ax,WORD PTR [lseg_canon]  ; get canonical segment low word offset containing lseg
   581 000002B2 8B1E[3400]                  mov bx,WORD PTR [lseg_canon+2]    ; get high word
   582                                  
   583 000002B6 D1EB                        shr bx,1
   584 000002B8 D1D8                        rcr ax,1                ; /2
   585 000002BA D1EB                        shr bx,1
   586 000002BC D1D8                        rcr ax,1                ; /4
   587 000002BE D1EB                        shr bx,1
   588 000002C0 D1D8                        rcr ax,1                ; /8
   589 000002C2 D1EB                        shr bx,1
   590 000002C4 D1D8                        rcr ax,1                ; /16, paragraph value (largest possible frame number)
   591 000002C6 A3[2000]                    mov [target_segment],ax
   592                                  
   593 000002C9 B001                        mov al,1
   594 000002CB A2[0800]                    mov [is_relocatable],al   ; flag that this is a relocatable segment
   595 000002CE EB11                        jmp SHORT pef_13        ; bypass other target segment computation code
   596                                  
   597                                  pef_11:
   598 000002D0 3C05                        cmp al,5                ; check if frame determined by target's index
   599 000002D2 7508                        jne pef_12              ; no
   600 000002D4 B001                        mov al,1                ; flag to get_frame_addr procedure to use target data
   601 000002D6 E8DC03                      call    get_frame_addr
   602 000002D9 EB06                        jmp SHORT pef_13        ; bypass other target segment computation code
   603                                  
   604                                  pef_ret:
   605 000002DB C3                          ret                     ; early return from routine
   606                                  
   607                                  ; frame determined by segment, group, or external index
   608                                  pef_12:
   609 000002DC 30C0                        xor al,al               ; flag to get_frame_addr procedure to use frame data
   610 000002DE E8D403                      call    get_frame_addr
   611                                  
   612                                  pef_13:
   613 000002E1 A0[0A00]                    mov al,[is_resolved]
   614 000002E4 08C0                        or  al,al               ; check if reference to unresolved external
   615 000002E6 74F3                        je  pef_ret             ; yes, don't perform a fixup
   616                                  
   617                                  ; convert target segment and target program offset to segment:offset format
   618                                  pef_resolved:
   619 000002E8 55                          push    bp              ; save critical register
   620 000002E9 A1[0000]                    mov ax,[buffer_end]
   621 000002EC 89C5                        mov bp,ax               ; check only for end of physical buffer overflow
   622                                  
   623                                  ; see if absolute segment or absolute public declaration, no address adjustment
   624 000002EE A0[0000]                    mov al,[is_absseg]
   625 000002F1 0A06[0C00]                  or  al,[is_abspub]
   626 000002F5 7507                        jne pef_seg_rel         ; either absolute segment or absolute public declaration
   627                                  
   628                                  ; check M bit for self-relative fixup
   629 000002F7 A0[1600]                    mov al,BYTE PTR [locat]   ; get locat field low byte
   630 000002FA 2440                        and al,40h              ; get M bit field value
   631 000002FC 742F                        je  pef_self_rel        ; M bit reset, fixup self-relative
   632                                  
   633                                  ; fixup segment relative
   634                                  pef_seg_rel:
   635 000002FE A1[2000]                    mov ax,[target_segment]
   636 00000301 31DB                        xor bx,bx               ; bx:ax will hold byte value of target segment
   637 00000303 D1E0                        shl ax,1
   638 00000305 D1D3                        rcl bx,1                ; x2
   639 00000307 D1E0                        shl ax,1
   640 00000309 D1D3                        rcl bx,1                ; x4
   641 0000030B D1E0                        shl ax,1
   642 0000030D D1D3                        rcl bx,1                ; x8
   643 0000030F D1E0                        shl ax,1
   644 00000311 D1D3                        rcl bx,1                ; x16
   645                                  
   646                                  ; get target offset in bx:di
   647 00000313 8B3E[2A00]                  mov di,WORD PTR [target_prog_off] ; get absolute offset low word
   648 00000317 29C7                        sub di,ax               ; compute low word difference
   649 00000319 89D8                        mov ax,bx
   650 0000031B 8B1E[2C00]                  mov bx,WORD PTR [target_prog_off+2]   ; get absolute offset high word
   651 0000031F 19C3                        sbb bx,ax               ; compute high word difference, with borrow
   652 00000321 EB53                        jmp SHORT pef_14        ; bypass self-relative fixup code
   653                                  
   654                                  ; intersegment self-relative fixup, fatal error
   655                                  fsr_inv:
   656 00000323 8A0E[0000]                  mov cl,[loc]
   657 00000327 B83200                      mov ax,SELF_REL_FIX_ERR ; intersegment self-relative fixup error
   658 0000032A E98401                      jmp NEAR PTR fixupp_offset_err  ; transfer control to error handler
   659                                  
   660                                  ; fixup is self-relative
   661                                  pef_self_rel:
   662                                  
   663 0000032D A0[1200]                    mov al,[is_ind_call]
   664 00000330 3C02                        cmp al,2                ; don't do self-relative fixup code if flag set for current segment fixup
   665 00000332 74CA                        je  pef_seg_rel
   666                                  
   667 00000334 803E[0000]02                cmp byte [loc],2               ; can't have self-relative segment/base fixups
   668 00000339 74E8                        je  fsr_inv             ; invalid loc value
   669 0000033B 803E[0000]03                cmp byte [loc],3               ; can't have self-relative pointer (segment:offset) fixups
   670 00000340 74E1                        je  fsr_inv             ; invalid loc value
   671                                  
   672 00000342 8B3E[2A00]                  mov di,WORD PTR [target_prog_off] ; get absolute offset low word
   673 00000346 8B1E[2C00]                  mov bx,WORD PTR [target_prog_off+2]   ; get absolute offset high word
   674 0000034A 2B3E[0000]                  sub di,WORD PTR [data_offset]
   675 0000034E 1B1E[0200]                  sbb bx,WORD PTR [data_offset+2]   ; borrow to high word
   676 00000352 2B3E[1800]                  sub di,[data_rec_offset]  ; make target offset relative to location
   677 00000356 83DB00                      sbb bx,0                ; borrow to high word
   678                                  
   679 00000359 A0[0000]                    mov al,[loc]
   680 0000035C 08C0                        or  al,al               ; check if low-order byte
   681 0000035E 7508                        jne pef_13a             ; no
   682 00000360 83EF01                      sub di,1                ; adjust for one byte length
   683 00000363 83DB00                      sbb bx,0                ; borrow to high word
   684 00000366 EB0E                        jmp SHORT pef_14        ; bypass remaining adjustment code
   685                                  
   686                                  pef_13a:
   687 00000368 3C01                        cmp al,1                ; check if offset
   688 0000036A 7404                        je  pef_13b             ; yes
   689 0000036C 3C05                        cmp al,5                ; check if loader-resolved (same as offset)
   690 0000036E 7506                        jne pef_14              ; no, perform no adjustments
   691                                  
   692                                  pef_13b:
   693 00000370 83EF02                      sub di,2                ; adjust for two byte length
   694 00000373 83DB00                      sbb bx,0                ; borrow to high word
   695                                  
   696                                  ;ready to fixup the address
   697                                  pef_14:
   698                                  
   699                                  ; check if fixup overflow, bx should be 0 or 0ffffh (-64K >= offset <= 64K)
   700 00000376 43                          inc bx
   701 00000377 83FB01                      cmp bx,1
   702 0000037A 7610                        jbe pef_14a             ; no fixup overflow
   703                                  
   704                                  ; check if possible lack of sign extension in data_offset vs. target_prog_off
   705 0000037C 83FBFF                      cmp bx,0ffffh
   706 0000037F 7508                        jne pef_fixwarn         ; bx not equal to -1
   707                                  
   708                                  ; lack of sign extension only if target_disp+2==0FFFFh
   709 00000381 A1[3000]                    mov ax,WORD PTR [target_disp+2]
   710 00000384 83F8FF                      cmp ax,0ffffh
   711 00000387 7403                        je  pef_14a             ; target_disp+2 == 0FFFFh
   712                                  
   713                                  pef_fixwarn:
   714 00000389 E8(0000)                    call    fixup_warning   ; yes, print warning message
   715                                  
   716                                  pef_14a:
   717 0000038C 803E[0000]00            	cmp	byte [compress_this],0		; see if compressing Clipper code
   718 00000391 740E                    	je	pef_notsymcomp		; no
   719 00000393 A1[0000]                	mov	ax,[current_segind]
   720 00000396 3B06[0000]              	cmp	ax,[clipper_segindex]	; see if fixing up a SYMBOLS table during compression
   721 0000039A 7505                    	jne	pef_notsymcomp		; not
   722 0000039C E8(0000)                	call	compsym_fixup	; fixup of compressed symbols, modify data_rec_offset if compress
   723 0000039F 724D                    	jc	pef_out				; return carry flag set if throw away fixup
   724                                  
   725                                  pef_notsymcomp:
   726 000003A1 89F8                        mov ax,di               ; get 2-byte offset in ax
   727 000003A3 8B1E[0000]                  mov bx,[prev_data_ptr]    ; point to previous record position data bytes/block
   728 000003A7 8B3E[1800]                  mov di,[data_rec_offset]  ; di holds offset into data record bytes/block
   729 000003AB 89DA                        mov dx,bx
   730 000003AD 01FA                        add dx,di               ; see if data bytes read past buffer end
   731                                  
   732 000003AF 7204                        jc  pef_overflow        ; overflow occurred, bypass buffer end check
   733                                  
   734                                  pef_14b:
   735 000003B1 39EA                        cmp dx,bp               ; check if past buffer
   736 000003B3 7206                        jb  pef_14c             ; no
   737                                  
   738                                  pef_overflow:
   739 000003B5 29EA                        sub dx,bp               ; adjust data record offset
   740                                  
   741 000003B7 31DB                        xor bx,bx               ; zero bx base
   742 000003B9 89D7                        mov di,dx               ; and adjust di record offset, overflow amount
   743                                  
   744                                  pef_14c:
   745 000003BB 8A16[0000]                  mov dl,[loc]
   746 000003BF 08D2                        or  dl,dl               ; check if low_order byte
   747 000003C1 7505                        jne pef_15              ; no
   748                                  
   749                                  ; low order byte
   750 000003C3 260001                      add [es:bx+di],al       ; save new offset value back to data record
   751 000003C6 5D                          pop bp                  ; restore critical register
   752 000003C7 C3                          ret                     ; done
   753                                  
   754                                  pef_15:
   755 000003C8 80FA01                      cmp dl,1                ; check if offset
   756 000003CB 7405                        je  pef_15a             ; yes
   757 000003CD 80FA05                      cmp dl,5                ; check if loader-resolved offset, treat as offset
   758 000003D0 7553                        jne pef_16              ; no
   759                                  
   760                                  ; offset or loader-resolved offset
   761                                  pef_15a:
   762 000003D2 01FB                        add bx,di               ; bx -> data record byte
   763 000003D4 268A37                      mov dh,[es:bx]          ; dh holds pre-existing fixup bytes
   764 000003D7 260007                      add [es:bx],al          ; save new offset low byte value back to data record
   765 000003DA 80D400                      adc ah,0                ; carry to high byte
   766 000003DD 43                          inc bx                  ; point to next byte
   767 000003DE 39EB                        cmp bx,bp               ; check if past buffer end
   768 000003E0 7202                        jb  pef_15b             ; no
   769                                  
   770 000003E2 31DB                        xor bx,bx               ; wrap to first byte in buffer by zero'ing bx
   771                                  
   772                                  ; offset, base, and pointer all vector here for return
   773                                  pef_15b:
   774 000003E4 260A37                      or  dh,[es:bx]          ; dh holds pre-existing fixup bytes
   775 000003E7 260027                      add [es:bx],ah          ; save new value back to data record
   776                                  
   777 000003EA 08F6                        or  dh,dh               ; see if any pre-existing fixup bytes
   778 000003EC 7502                        jne pef_chkovl          ; yes, check if overlaid reference
   779                                  
   780                                  pef_out:
   781 000003EE 5D                          pop bp                  ; restore critical register
   782 000003EF C3                          ret                     ; done
   783                                  
   784                                  ; nonzero bytes in fixup location, check if overlaid reference
   785                                  ; if so, generate warning
   786                                  pef_chkovl:
   787 000003F0 A0[1000]                    mov al,[no_fixbyte_flag]  ; get fixup byte flag
   788 000003F3 08C0                        or  al,al               ; see if set
   789 000003F5 74F7                        je  pef_out             ; no
   790                                  
   791                                  pef_ovl_warn:
   792 000003F7 06                          push    es              ; save critical register
   793                                  
   794 000003F8 8B1E[2600]                  mov bx,[targ_ent_ptr]
   795 000003FC A0[0400]                    mov al,[target_method]
   796 000003FF 2403                        and al,3
   797 00000401 750F                        jne pef_ovl_ext         ; target extdef
   798                                  
   799                                  ; target segment
   800 00000403 B84300                      mov ax,NONOVL_SEG_WARN  ; nonoverlayable segment warning
   801 00000406 8EC3                        mov es,bx
   802 00000408 26C43E0800                  les di,[es:8]
   803 0000040D 83C708                      add di,8                ; es:di -> segment name
   804 00000410 EB0A                        jmp SHORT pef_printwarn
   805                                  
   806                                  ; target extdef
   807                                  pef_ovl_ext:
   808 00000412 B84400                      mov ax,NONOVL_SYM_WARN  ; nonoverlayable symbol warning
   809 00000415 8EC3                        mov es,bx
   810 00000417 26C43E0400                  les di,[es:4]           ; es:di -> symbol name
   811                                  
   812                                  pef_printwarn:
   813 0000041C BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   814 0000041F E8(0000)                    call    link_warning
   815 00000422 07                          pop es
   816                                  
   817 00000423 5D                          pop bp                  ; restore critical register
   818 00000424 C3                          ret                     ; done
   819                                  
   820                                  pef_16:
   821 00000425 80FA02                      cmp dl,2                ; check if segment
   822 00000428 7537                        jne pef_17              ; no
   823                                  
   824                                  ; segment
   825                                  pef_segment:
   826 0000042A 803E[0800]00                cmp byte [is_relocatable],0    ; check if relocatable segment
   827 0000042F 7417                        je  pef_seg2            ; no
   828                                  
   829 00000431 89DA                        mov dx,bx               ; save record position
   830 00000433 BB[0000]                    mov bx,OFFSET data_fixup_flag wrt DGROUP    ; bx -> base of fixup flag array
   831 00000436 A1[0000]                    mov ax,[data_fixup_count] ; get count of fixups in data record
   832 00000439 FF06[0000]                  inc word [data_fixup_count]    ; bump count of fixups
   833 0000043D D1E0                        shl ax,1                ; convert to word offset
   834 0000043F 01C3                        add bx,ax               ; bx -> first free array element to store fixup
   835 00000441 A1[1800]                    mov ax,[data_rec_offset]  ; get fixup position in data record
   836 00000444 8907                        mov [bx],ax             ; store in array
   837 00000446 89D3                        mov bx,dx               ; restore record position
   838                                  
   839                                  pef_seg2:
   840 00000448 01FB                        add bx,di               ; bx -> data record byte
   841 0000044A 30F6                        xor dh,dh
   842                                  
   843                                  ; code shared with pointer (segment:offset) fixup
   844                                  pef_seg3:
   845 0000044C A1[2000]                    mov ax,[target_segment]
   846 0000044F 260A37                      or  dh,[es:bx]          ; dh holds pre-existing fixup bytes
   847 00000452 260007                      add [es:bx],al          ; save new segment low byte value back to data record
   848 00000455 80D400                      adc ah,0                ; carry to high byte
   849 00000458 43                          inc bx                  ; point to next byte
   850 00000459 39EB                        cmp bx,bp               ; check if past buffer end
   851 0000045B 7287                        jb  pef_15b             ; no
   852                                  
   853 0000045D 31DB                        xor bx,bx               ; wrap to first byte in buffer by zero'ing bx
   854 0000045F EB83                        jmp SHORT pef_15b
   855                                  
   856                                  pef_17:
   857 00000461 80FA03                      cmp dl,3                ; check if pointer (segment:offset)
   858 00000464 7544                        jne pef_bad_loc         ; no, bad loc field value
   859                                  
   860                                  ; pointer fixup
   861                                  pef_pointer:
   862 00000466 803E[0800]00                cmp byte [is_relocatable],0    ; check if relocatable segment
   863 0000046B 741C                        je  pef_point2          ; no
   864                                  
   865 0000046D 53                          push    bx              ; save record position
   866 0000046E 89C2                        mov dx,ax               ; save offset in dx
   867 00000470 BB[0000]                    mov bx,OFFSET data_fixup_flag wrt DGROUP    ; bx -> base of fixup flag array
   868 00000473 A1[0000]                    mov ax,[data_fixup_count] ; get count of fixups in data record
   869 00000476 FF06[0000]                  inc word [data_fixup_count]    ; bump count of fixups
   870 0000047A D1E0                        shl ax,1                ; convert to word offset
   871 0000047C 01C3                        add bx,ax               ; bx -> first free array element to store fixup
   872 0000047E A1[1800]                    mov ax,[data_rec_offset]  ; get fixup position in data record
   873 00000481 83C002                      add ax,2                ; position past two offset bytes
   874 00000484 8907                        mov [bx],ax             ; store in array
   875 00000486 89D0                        mov ax,dx               ; restore offset to ax
   876 00000488 5B                          pop bx                  ; restore record position
   877                                  
   878                                  pef_point2:
   879 00000489 01FB                        add bx,di               ; bx -> data record byte
   880 0000048B 268A37                      mov dh,[es:bx]          ; dh holds pre-existing fixup bytes
   881 0000048E 260007                      add [es:bx],al          ; save new offset low byte value back to data record
   882 00000491 80D400                      adc ah,0                ; carry to high byte
   883 00000494 43                          inc bx                  ; point to next byte
   884 00000495 39EB                        cmp bx,bp               ; check if past buffer end
   885 00000497 7202                        jb  pef_18a             ; no
   886                                  
   887 00000499 31DB                        xor bx,bx               ; wrap to first byte in buffer by zero'ing bx
   888                                  
   889                                  pef_18a:
   890 0000049B 260A37                      or  dh,[es:bx]          ; dh holds pre-existing fixup bytes
   891 0000049E 260027                      add [es:bx],ah          ; save new value back to data record
   892 000004A1 43                          inc bx                  ; point to next byte
   893 000004A2 39EB                        cmp bx,bp               ; check if past buffer end
   894 000004A4 7202                        jb  pef_18b             ; no
   895                                  
   896 000004A6 31DB                        xor bx,bx               ; wrap to first byte in buffer by zero'ing bx
   897                                  
   898                                  pef_18b:
   899 000004A8 EBA2                        jmp pef_seg3   ; do segment code as well
   900                                  
   901                                  ; illegal loc values 4, 6, or 7
   902                                  pef_bad_loc:
   903 000004AA 88D1                        mov cl,dl
   904 000004AC B81A00                      mov ax,LOC_VAL_ERR      ; bad loc field value in FIXUPP record
   905 000004AF EB00                        jmp NEAR PTR fixupp_offset_err  ; transfer control to error handler
   906                                  
   907                                  perform_fixup   ENDP
   908                                  
   909                                  ;*****************************
   910                                  ;* FIXUPP_OFFSET_ERR         *
   911                                  ;*****************************
   912                                  
   913                                  ; passes proper file offset in fixupp record and file name to link error
   914                                  ; terminates WarpLink, all non-error reporting registers are trashable
   915                                  ; ax holds error code upon entry
   916                                  ; cx holds associated error value, if any
   917                                  
   918                                  fixupp_offset_err   PROC
   919 000004B1 3B36[2200]                  cmp si,[fixup_pos]        ; check if si is less than fixup_pos (buffer wrapped)
   920 000004B5 730D                        jae foe_2               ; no
   921                                  
   922                                  ; back buffer_end bytes off of file_pos_adj, error occurred before buffer wrap
   923 000004B7 8B1E[0000]                  mov bx,[buffer_end]
   924 000004BB 291E[0000]                  sub WORD PTR [file_pos_adj],bx    ; update low word
   925 000004BF 831E[0200]00                sbb WORD [file_pos_adj+2],0   ; borrow to high word
   926                                  
   927                                  foe_2:
   928 000004C4 8B36[2200]                  mov si,[fixup_pos]        ; get proper fixup record offset
   929 000004C8 BA[0000]                    mov dx,OFFSET filename wrt DGROUP
   930 000004CB E9(0000)                    jmp NEAR PTR link_error ; transfer control to error handler
   931                                  fixupp_offset_err   ENDP
   932                                  
   933                                  ;*****************************
   934                                  ;* CHECK_INDEX               *
   935                                  ;*****************************
   936                                  
   937                                  ; check that a segdef, grpdef, or extdef index is not out of bounds
   938                                  ; upon entry ax holds index
   939                                  ; bl holds method, segment, group, or external
   940                                  ; destroys ax,bx
   941                                  
   942                                  check_index PROC
   943 000004CE D0E3                        shl bl,1                ; make word offset
   944 000004D0 30FF                        xor bh,bh
   945 000004D2 81C3[0200]                  add bx,OFFSET bounds_check wrt DGROUP
   946 000004D6 3B07                        cmp ax,[bx]             ; see if out of bounds
   947 000004D8 7701                        ja  ci_oob              ; yes
   948 000004DA C3                          ret                     ; no
   949                                  
   950                                  ci_oob:
   951 000004DB 08DB                        or  bl,bl               ; check if segment index
   952 000004DD 7507                        jne ci_grpchk           ; no
   953                                  
   954 000004DF 89C1                        mov cx,ax
   955 000004E1 B80900                      mov ax,SEGDEF_VAL_ERR   ; segment index too large
   956 000004E4 EBCB                        jmp fixupp_offset_err  ; transfer control to error handler
   957                                  
   958                                  ci_grpchk:
   959 000004E6 80FB02                      cmp bl,2                ; check if a group index
   960 000004E9 7507                        jne ci_ext              ; no
   961                                  
   962 000004EB 89C1                        mov cx,ax
   963 000004ED B80800                      mov ax,GRPDEF_VAL_ERR   ; group index too large
   964 000004F0 EBBF                        jmp fixupp_offset_err  ; transfer control to error handler
   965                                  
   966                                  ; assume external index
   967                                  ci_ext:
   968 000004F2 89C1                        mov cx,ax
   969 000004F4 B81B00                      mov ax,EXTDEF_VAL_ERR   ; external index too large
   970 000004F7 EBB8                        jmp fixupp_offset_err  ; transfer control to error handler
   971                                  check_index ENDP
   972                                  
   973                                  ;*****************************
   974                                  ;* GET_TARGET_ADDR           *
   975                                  ;*****************************
   976                                  
   977                                  ; compute target program offset for fixupp address
   978                                  ; uses target_method,target_index,target_disp memory variables
   979                                  ; can reset is_resolved memory variable flag
   980                                  ; return target program offset in memory variable target_prog_off
   981                                  ; destroys ax,bx
   982                                  
   983                                  get_target_addr PROC
   984 000004F9 06                          push    es              ; save critical register
   985 000004FA A1[1C00]                    mov ax,[target_index]     ; get target index
   986 000004FD 48                          dec ax                  ; make ax relative zero offset
   987 000004FE D1E0                        shl ax,1                ; convert ax to word offset in arrays
   988 00000500 8A1E[0400]                  mov bl,[target_method]
   989                                  
   990 00000504 30FF                        xor bh,bh               ; zero high byte
   991 00000506 D1E3                        shl bx,1                ; make word offset
   992 00000508 81C3[0800]                  add bx,OFFSET targ_jmp_table wrt DGROUP ; point to proper jump table address
   993 0000050C FF27                        jmp WORD PTR [bx]
   994                                  
   995                                  ; segment index, method 0 or 4
   996                                  gta_seg:
   997 0000050E BB[0000]                    mov bx,OFFSET seg_partent_indptr wrt DGROUP  ; set bx to base of segment partition address array
   998 00000511 01C3                        add bx,ax               ; bx -> array element holding segment partition entry address
   999 00000513 8E07                        mov es,[bx]             ; es -> segment partition entry
  1000                                  
  1001                                  ; check if absolute segment
  1002 00000515 26A10400                    mov ax,[es:4]           ; zero if absolute segment (es -> absolute segdef entry)
  1003 00000519 09C0                        or  ax,ax
  1004 0000051B 7471                        je  gta_is_abs          ; zero, absolute segment
  1005                                  
  1006                                  ; not an absolute segment, see if overlaid
  1007 0000051D 26F6060F0080                test    BYTE PTR [es:15],80h    ; see if overlaid segment
  1008 00000523 7434                        je  gta_not_overlaid    ; no
  1009                                  
  1010 00000525 8CC0                        mov ax,es               ; get segment partition entry of segment fixup
  1011 00000527 3B06[0000]                  cmp ax,[data_seg_part]    ; see if matches L?DATA segment partition entry
  1012 0000052B 7407                        je  gta_seg_fix         ; yes, overlaid segment matches current segment
  1013                                  
  1014 0000052D 803E[0000]03                cmp byte [loc],3               ; see if a pointer fixup (overlaid segment <> current)
  1015 00000532 7505                        jne gta_not_point
  1016                                  
  1017                                  gta_seg_fix:
  1018 00000534 E8(0000)                    call    fixup_seg_ref   ; fixup the far reference to an overlaid segment
  1019 00000537 EB0C                        jmp SHORT gta_ovl_seg   ; do housekeeping code and return
  1020                                  
  1021                                  gta_not_point:
  1022 00000539 A1[2E00]                    mov ax,WORD PTR [target_disp]     ; use target displacement only as target program offset
  1023 0000053C A3[2A00]                    mov WORD PTR [target_prog_off],ax ; update target program offset low word
  1024 0000053F A1[3000]                    mov ax,WORD PTR [target_disp+2]   ; get sign extension
  1025 00000542 A3[2C00]                    mov WORD PTR [target_prog_off+2],ax   ; update offset high word
  1026                                  
  1027                                  ; es -> segment partition entry
  1028                                  gta_ovl_seg:
  1029 00000545 268B1E0400                  mov bx,[es:4]           ; get overlay identifier
  1030 0000054A 4B                          dec bx                  ; make relative zero
  1031 0000054B D1E3                        shl bx,1                ; convert to word offset
  1032 0000054D 8E06[0000]                  mov es,[master_segblk]    ; es:bx -> master segdef entry
  1033 00000551 268B07                      mov ax,[es:bx]
  1034 00000554 A3[2600]                    mov [targ_ent_ptr],ax     ; save segment owner
  1035                                  
  1036 00000557 07                          pop es
  1037 00000558 C3                          ret
  1038                                  
  1039                                  gta_not_overlaid:
  1040 00000559 A1[2E00]                    mov ax,WORD PTR [target_disp] ; get original target displacement
  1041 0000055C 2603060000                  add ax,[es:0]           ; add in offset of segment partition entry
  1042 00000561 A3[2A00]                    mov WORD PTR [target_prog_off],ax ; update target program offset low word
  1043 00000564 A1[3000]                    mov ax,WORD PTR [target_disp+2]   ; get sign extension
  1044 00000567 83D000                      adc ax,0                ; carry to high word
  1045 0000056A A3[2C00]                    mov WORD PTR [target_prog_off+2],ax   ; update target program offset high word
  1046 0000056D 26A10400                    mov ax,[es:4]           ; get master segdef entry from segment partition entry back pointer
  1047 00000571 A3[2600]                    mov [targ_ent_ptr],ax     ; save pointer to target entry
  1048                                  
  1049                                  gta_segdef_entry:
  1050 00000574 8EC0                        mov es,ax               ; es -> master segdef entry
  1051 00000576 26A10200                    mov ax,[es:2]           ; get low word of segment offset
  1052 0000057A A3[3200]                    mov WORD PTR [lseg_canon],ax  ; save low word of offset for canonical computation
  1053 0000057D 0106[2A00]                  add WORD PTR [target_prog_off],ax ; add to target program offset low word
  1054 00000581 26A10400                    mov ax,[es:4]           ; get high word of segment offset
  1055 00000585 A3[3400]                    mov WORD PTR [lseg_canon+2],ax    ; save high word of offset for canonical computation
  1056 00000588 1106[2C00]                  adc WORD PTR [target_prog_off+2],ax   ; add to target program offset high word with carry
  1057 0000058C 07                          pop es
  1058 0000058D C3                          ret
  1059                                  
  1060                                  ; absolute segment
  1061                                  gta_is_abs:
  1062 0000058E 31C0                        xor ax,ax
  1063 00000590 A2[0800]                    mov [is_relocatable],al   ; nonrelocatable segment
  1064 00000593 A3[2600]                    mov [targ_ent_ptr],ax     ; zero frame entry pointer
  1065 00000596 FEC0                        inc al
  1066 00000598 A2[0000]                    mov [is_absseg],al        ; set absolute segment flag
  1067 0000059B 26A10000                    mov ax,[es:0]           ; get frame number, convert to bytes
  1068 0000059F A3[2000]                    mov [target_segment],ax   ; get frame number in target_segment in case of LOC frame fixup
  1069 000005A2 31DB                        xor bx,bx               ; zero high word of target program offset
  1070 000005A4 D1E0                        shl ax,1
  1071 000005A6 D1D3                        rcl bx,1                ; x2
  1072 000005A8 D1E0                        shl ax,1
  1073 000005AA D1D3                        rcl bx,1                ; x4
  1074 000005AC D1E0                        shl ax,1
  1075 000005AE D1D3                        rcl bx,1                ; x8
  1076 000005B0 D1E0                        shl ax,1
  1077 000005B2 D1D3                        rcl bx,1                ; x16
  1078 000005B4 0306[2E00]                  add ax,WORD PTR [target_disp] ; add in original target displacement
  1079 000005B8 131E[3000]                  adc bx,WORD PTR [target_disp+2]   ; carry to high word
  1080 000005BC A3[2A00]                    mov WORD PTR [target_prog_off],ax ; update low word
  1081 000005BF 891E[2C00]                  mov WORD PTR [target_prog_off+2],bx   ; update high word
  1082 000005C3 07                          pop es
  1083 000005C4 C3                          ret
  1084                                  
  1085                                  ; group index, method 1 or 5
  1086                                  gta_grp:
  1087 000005C5 BB[0000]                    mov bx,OFFSET grp_ent_indptr wrt DGROUP ; set bx to base of group entry array address
  1088 000005C8 01C3                        add bx,ax               ; bx -> array element holding group entry address 
  1089 000005CA 8E07                        mov es,[bx]             ; es -> group entry
  1090 000005CC 8CC0                        mov ax,es
  1091 000005CE A3[2600]                    mov [targ_ent_ptr],ax     ; save pointer to target entry
  1092                                  
  1093 000005D1 26A10000                    mov ax,[es:0]           ; get low word of group offset
  1094 000005D5 A3[3200]                    mov WORD PTR [lseg_canon],ax  ; save low word of offset for canonical computation
  1095 000005D8 0306[2E00]                  add ax,WORD PTR [target_disp] ; add in original target displacement
  1096                                  
  1097 000005DC A3[2A00]                    mov WORD PTR [target_prog_off],ax ; update target program offset low word
  1098 000005DF 26A10200                    mov ax,[es:2]
  1099 000005E3 A3[3400]                    mov WORD PTR [lseg_canon+2],ax    ; save high word of offset for canonical computation
  1100 000005E6 1306[3000]                  adc ax,WORD PTR [target_disp+2]   ; add high word of group offset with carry
  1101 000005EA A3[2C00]                    mov WORD PTR [target_prog_off+2],ax   ; update target program offset high word
  1102 000005ED 07                          pop es                  ; restore critical register
  1103 000005EE C3                          ret
  1104                                  
  1105                                  ; external index, method 2 or 6
  1106                                  gta_ext:
  1107 000005EF BB[0000]                    mov bx,OFFSET ext_defent_indptr wrt DGROUP  ; set bx to base of pubdef declarations entry address array
  1108 000005F2 01C3                        add bx,ax               ; bx -> array element holding pubdef declarations entry address
  1109 000005F4 8E07                        mov es,[bx]             ; es -> pubdef declarations entry
  1110                                  
  1111 000005F6 26800E0E0040                or  BYTE PTR [es:14],40h    ; flag that used in fixup
  1112                                  
  1113 000005FC 8CC0                        mov ax,es
  1114 000005FE A3[2600]                    mov [targ_ent_ptr],ax     ; save pointer to target entry
  1115                                  
  1116                                  ;***    test    BYTE PTR [es:15],4  ; see if local public
  1117                                  ;***    jne gta_2               ; yes, don't vector it
  1118                                  
  1119 00000601 803E[0000]00                cmp byte [seg_ovl_class_flag],0    ; see if overlay class segment
  1120 00000606 7516                        jne gta_chk_dir_vect    ; yes
  1121                                  
  1122 00000608 26F6060F0001                test    BYTE PTR [es:15],1  ; see if public is overlaid
  1123 0000060E 743C                        je  gta_2               ; no
  1124                                  
  1125 00000610 A0[0000]                    mov al,[loc]
  1126 00000613 08C0                        or  al,al               ; see if lobyte fixup
  1127 00000615 7435                        je  gta_2               ; yes
  1128 00000617 30FF                        xor bh,bh               ; flag to give nonzero target displacement warning if necessary
  1129 00000619 E8(0000)                    call    fixup_ind_ref_extdef    ; fixup the indirect far reference to overlaid public
  1130                                  
  1131                                  gta_ret:
  1132 0000061C 07                          pop es                  ; restore critical register
  1133 0000061D C3                          ret
  1134                                  
  1135                                  ; check if need to vector a direct call to overlay class public
  1136                                  gta_chk_dir_vect:
  1137 0000061E 26F6060F0001                test    BYTE PTR [es:15],1  ; see if overlaid public
  1138 00000624 751F                        jne gta_chk_ovl_ext     ; yes
  1139 00000626 833E[0000]00                cmp word [ovl_code_id],0       ; see if current segment is overlaid
  1140 0000062B 741F                        je  gta_2               ; no
  1141                                  
  1142 0000062D 803E[0000]00                cmp byte [nonovl_rvect],0      ; see if nonvector root call flag is set
  1143 00000632 7518                        jne gta_2               ; yes, bypass vector code
  1144 00000634 26F6060F0008                test    BYTE PTR [es:15],8  ; see if public is overlay class
  1145 0000063A 7410                        je  gta_2               ; no
  1146                                  
  1147                                  ; special case to allow accessing overlay class nonoverlaid code address from
  1148                                  ; an overlaid segment.  If target displacement is nonzero then assume
  1149                                  ; that the program really wants the address and not a vectored address.
  1150 0000063C A1[2E00]                    mov ax,WORD PTR [target_disp]
  1151 0000063F 0B06[3000]                  or  ax,WORD PTR [target_disp+2]   ; see if nonzero target displacement
  1152 00000643 7507                        jne gta_2               ; yes
  1153                                  
  1154                                  gta_chk_ovl_ext:
  1155 00000645 E8(0000)                    call    fixup_ovl_extdef    ; check if should change public offset to vector
  1156 00000648 08C0                        or  al,al               ; al return value is 0 if should continue
  1157 0000064A 75D0                        jne gta_ret             ; nonzero, done
  1158                                  
  1159                                  gta_2:
  1160 0000064C A1[2E00]                    mov ax,WORD PTR [target_disp] ; get original target displacement
  1161 0000064F 2603060800                  add ax,[es:8]           ; add in offset of pubdef declarations entry
  1162 00000654 A3[2A00]                    mov WORD PTR [target_prog_off],ax ; update target program offset low word
  1163 00000657 A1[3000]                    mov ax,WORD PTR [target_disp+2]
  1164 0000065A 83D000                      adc ax,0                ; carry to high word
  1165 0000065D A3[2C00]                    mov WORD PTR [target_prog_off+2],ax   ; carry to target program offset high word
  1166                                  
  1167 00000660 26F6060F0001                test    BYTE PTR [es:15],1  ; see if overlaid public (referenced within same segment)
  1168 00000666 75B4                        jne gta_ret             ; yes, don't add in segment partition/sefdef offsets
  1169                                  
  1170 00000668 26A00E00                    mov al,[es:14]          ; get definitions byte value
  1171 0000066C 2403                        and al,3                ; only keep pubdef/extdef/comdef field
  1172 0000066E 3C02                        cmp al,2                ; check if unresolved external
  1173 00000670 7225                        jb gta_3                ; unresolved external
  1174                                  
  1175                                  ; external resolved, fixup okay
  1176 00000672 3C03                        cmp al,3                ; see if absolute public declaration
  1177 00000674 7429                        je  gta_4               ; yes
  1178                                  
  1179                                  ; pubdef, not absolute
  1180 00000676 268E060000                  mov es,[es:0]           ; es -> segment partition entry
  1181 0000067B 26F6060F0080                test    BYTE PTR [es:15],80h    ; see if overlaid segment (local public with overlaid flag not set)
  1182 00000681 7599                        jne gta_ret             ; yes, don't add in segment partition/sefdef offsets
  1183 00000683 26A10000                    mov ax,[es:0]           ; get offset of segment partition entry
  1184 00000687 0106[2A00]                  add WORD PTR [target_prog_off],ax ; update target program offset low word
  1185 0000068B 8316[2C00]00                adc WORD [target_prog_off+2],0    ; carry to target program offset high word
  1186 00000690 26A10400                    mov ax,[es:4]           ; get master segdef entry from segment partition entry back pointer
  1187 00000694 E9DDFE                      jmp NEAR PTR gta_segdef_entry   ; do segdef entry offset addition
  1188                                  
  1189                                  ; unresolved external, no fixup
  1190                                  gta_3:
  1191 00000697 C606[0A00]00                mov byte [is_resolved],0       ; flag no fixup
  1192 0000069C E97DFF                      jmp NEAR PTR gta_ret    ; exit without further processing
  1193                                  
  1194                                  ; absolute, no segment partition or segdef entry offsets
  1195                                  gta_4:
  1196 0000069F 31C0                        xor ax,ax
  1197 000006A1 A2[0800]                    mov [is_relocatable],al   ; nonrelocatable segment
  1198 000006A4 A3[2600]                    mov [targ_ent_ptr],ax     ; zero frame entry pointer
  1199 000006A7 FEC0                        inc al
  1200 000006A9 A2[0C00]                    mov [is_abspub],al        ; flag absolute public declaration
  1201 000006AC 26A10200                    mov ax,[es:2]           ; get frame number in target_segment in case of LOC frame fixup
  1202 000006B0 A3[2000]                    mov [target_segment],ax
  1203 000006B3 07                          pop es                  ; restore critical register
  1204 000006B4 C3                          ret
  1205                                  
  1206                                  get_target_addr ENDP
  1207                                  
  1208                                  ;*****************************
  1209                                  ;* GET_FRAME_ADDR            *
  1210                                  ;*****************************
  1211                                  
  1212                                  ; compute frame for fixupp address
  1213                                  ; upon entry al==0 if use frame data, al==1 if use target data
  1214                                  ; uses frame_method,frame_index or target_method,target_index memory variables
  1215                                  ; can reset is_resolved memory variable flag
  1216                                  ; return frame in memory variable target_segment
  1217                                  ; destroys ax,bx
  1218                                  
  1219                                  get_frame_addr  PROC
  1220 000006B5 06                          push    es              ; save critical register
  1221 000006B6 08C0                        or  al,al               ; check if using frame data
  1222 000006B8 7509                        jne gfa_2               ; no
  1223 000006BA A1[1A00]                    mov ax,[frame_index]      ; get frame index
  1224 000006BD 8A1E[0200]                  mov bl,[frame_method]
  1225 000006C1 EB0A                        jmp SHORT gfa_3         ; bypass target code
  1226                                  
  1227                                  gfa_2:
  1228 000006C3 A1[1C00]                    mov ax,[target_index]     ; get target index
  1229 000006C6 8A1E[0400]                  mov bl,[target_method]
  1230 000006CA 80E303                      and bl,3                ; mask off high bit to convert to segment/group/external value
  1231                                  
  1232                                  gfa_3:
  1233 000006CD 48                          dec ax                  ; make ax relative zero offset
  1234 000006CE D1E0                        shl ax,1                ; convert ax to word offset in arrays
  1235 000006D0 08DB                        or  bl,bl               ; check if segment index
  1236 000006D2 7403                        je  gfa_segind          ; yes
  1237 000006D4 E9AB00                      jmp NEAR PTR gfa_4      ; no
  1238                                  
  1239                                  ; segment index
  1240                                  gfa_segind:
  1241 000006D7 BB[0000]                    mov bx,OFFSET seg_partent_indptr wrt DGROUP  ; set bx to base of segment partition address array
  1242 000006DA 01C3                        add bx,ax               ; bx -> array element holding segment partition entry address
  1243 000006DC 8E07                        mov es,[bx]             ; es -> segment partition entry
  1244                                  
  1245                                  ; check if absolute segment
  1246 000006DE 26A10400                    mov ax,[es:4]           ; zero if absolute segment (es -> absolute segdef entry)
  1247 000006E2 09C0                        or  ax,ax
  1248 000006E4 7514                        jne gfa_spart_entry     ; not an absolute segment
  1249                                  
  1250                                  ; absolute segment, ax is zero
  1251 000006E6 A2[0800]                    mov [is_relocatable],al   ; nonrelocatable segment
  1252 000006E9 A3[2400]                    mov [frame_ent_ptr],ax    ; zero frame entry pointer
  1253 000006EC FEC0                        inc al
  1254 000006EE A2[0000]                    mov [is_absseg],al        ; set absolute segment flag
  1255 000006F1 26A10000                    mov ax,[es:0]           ; get frame number
  1256 000006F5 A3[2000]                    mov [target_segment],ax   ; save to memory variable
  1257 000006F8 07                          pop es
  1258 000006F9 C3                          ret
  1259                                  
  1260                                  gfa_spart_entry:
  1261 000006FA 26F6060F0080                test    BYTE PTR [es:15],80h    ; see if overlaid segment
  1262 00000700 752C                        jne gfa_overlaid        ; yes
  1263                                  
  1264 00000702 26A10400                    mov ax,[es:4]           ; get master segdef entry
  1265 00000706 8EC0                        mov es,ax               ; es -> segdef entry
  1266                                  
  1267 00000708 26F6061C0001                test    BYTE PTR [es:28],1  ; see if segment if overlay class
  1268 0000070E 7451                        je  gfa_3a              ; no
  1269 00000710 833E[0000]00                cmp word [ovl_code_id],0       ; see if current L?DATA is owned by overlaid segment
  1270 00000715 744A                        je  gfa_3a              ; no
  1271 00000717 803E[0000]00                cmp byte [nonovl_rvect],0      ; see if nonvector root calls flag set
  1272 0000071C 7543                        jne gfa_3a              ; yes, bypass vectoring
  1273                                  
  1274                                  ; special case to allow accessing overlay class nonoverlaid code address from
  1275                                  ; an overlaid segment.  If target displacement is nonzero then assume
  1276                                  ; that the program really wants the address and not a vectored address.
  1277                                  
  1278 0000071E A1[2E00]                    mov ax,WORD PTR [target_disp]
  1279 00000721 0B06[3000]                  or  ax,WORD PTR [target_disp+2]   ; see if nonzero target displacement
  1280 00000725 753A                        jne gfa_3a              ; yes
  1281                                  
  1282                                  ; if gen_flags bit 0 is set, then do no vector address changes
  1283                                  ; Near/offset reference to different segment with no matching base references
  1284                                  ; in fixup_ovl_extdef
  1285                                  
  1286 00000727 A0[1400]                    mov al,[gen_flags]
  1287 0000072A 2401                        and al,1                ; see if no vector address change flag set
  1288 0000072C 7533                        jne gfa_3a              ; yes
  1289                                  
  1290                                  ; frame is overlay class within an overlaid segment
  1291                                  ; or frame is an overlaid segment
  1292                                  ; es -> segment partition entry
  1293                                  gfa_overlaid:
  1294 0000072E 268B1E0400                  mov bx,[es:4]           ; get overlay identifier
  1295 00000733 4B                          dec bx                  ; make relative zero
  1296 00000734 D1E3                        shl bx,1                ; convert to word offset
  1297 00000736 8E06[0000]                  mov es,[master_segblk]    ; es:bx -> master segdef entry
  1298 0000073A 268B07                      mov ax,[es:bx]
  1299 0000073D A3[2400]                    mov [frame_ent_ptr],ax    ; save segment owner
  1300                                  
  1301 00000740 A1[0000]                    mov ax,[seg_fix_frame]    ; use current segment fixup frame
  1302 00000743 50                          push    ax              ; save target segment value
  1303                                  
  1304                                  ; add segment byte value to target_prog_off so calculates back down to target displacement
  1305 00000744 31DB                        xor bx,bx               ; zero high word
  1306 00000746 D1E0                        shl ax,1
  1307 00000748 D1D3                        rcl bx,1                ; x2
  1308 0000074A D1E0                        shl ax,1
  1309 0000074C D1D3                        rcl bx,1                ; x4
  1310 0000074E D1E0                        shl ax,1
  1311 00000750 D1D3                        rcl bx,1                ; x8
  1312 00000752 D1E0                        shl ax,1
  1313 00000754 D1D3                        rcl bx,1                ; x16
  1314 00000756 0106[2A00]                  add WORD PTR [target_prog_off],ax ; update target_prog_off variable
  1315 0000075A 111E[2C00]                  adc WORD PTR [target_prog_off+2],bx
  1316 0000075E 58                          pop ax                  ; restore target segment value
  1317 0000075F EB1C                        jmp SHORT gfa_save_seg  ; bypass nonoverlaid calculations
  1318                                  
  1319                                  gfa_3a:
  1320 00000761 A3[2400]                    mov [frame_ent_ptr],ax    ; save pointer to frame entry
  1321 00000764 26A10200                    mov ax,[es:2]           ; get low word of segment offset
  1322 00000768 268B1E0400                  mov bx,[es:4]           ; get high word of segment offset
  1323 0000076D D1EB                        shr bx,1
  1324 0000076F D1D8                        rcr ax,1                ; /2
  1325 00000771 D1EB                        shr bx,1
  1326 00000773 D1D8                        rcr ax,1                ; /4
  1327 00000775 D1EB                        shr bx,1
  1328 00000777 D1D8                        rcr ax,1                ; /8
  1329 00000779 D1EB                        shr bx,1
  1330 0000077B D1D8                        rcr ax,1                ; /16, have paragraph value of offset (segment value)
  1331                                  
  1332                                  gfa_save_seg:
  1333 0000077D A3[2000]                    mov [target_segment],ax   ; save to memory variable
  1334 00000780 EB2D                        jmp SHORT gfa_reloc
  1335                                  
  1336                                  gfa_4:
  1337 00000782 80FB01                      cmp bl,1                ; check if group index
  1338 00000785 752F                        jne gfa_5               ; no
  1339                                  
  1340                                  ; group index
  1341 00000787 BB[0000]                    mov bx,OFFSET grp_ent_indptr wrt DGROUP ; set bx to base of group entry array address
  1342 0000078A 01C3                        add bx,ax               ; bx -> array element holding group entry address 
  1343 0000078C 8E07                        mov es,[bx]             ; es -> group entry
  1344                                  
  1345                                  gfa_group_entry:
  1346 0000078E 8CC0                        mov ax,es
  1347 00000790 A3[2400]                    mov [frame_ent_ptr],ax    ; save pointer to frame entry
  1348 00000793 26A10000                    mov ax,[es:0]           ; get low word of group offset
  1349 00000797 268B1E0200                  mov bx,[es:2]           ; get high word of group offset
  1350 0000079C D1EB                        shr bx,1
  1351 0000079E D1D8                        rcr ax,1                ; /2
  1352 000007A0 D1EB                        shr bx,1
  1353 000007A2 D1D8                        rcr ax,1                ; /4
  1354 000007A4 D1EB                        shr bx,1
  1355 000007A6 D1D8                        rcr ax,1                ; /8
  1356 000007A8 D1EB                        shr bx,1
  1357 000007AA D1D8                        rcr ax,1                ; /16, have paragraph value of offset (segment value)
  1358 000007AC A3[2000]                    mov [target_segment],ax   ; save to memory variable
  1359                                  
  1360                                  gfa_reloc:
  1361 000007AF B001                        mov al,1
  1362 000007B1 A2[0800]                    mov [is_relocatable],al   ; relocatable segment (assume group is always relocatable)
  1363 000007B4 07                          pop es
  1364 000007B5 C3                          ret
  1365                                  
  1366                                  ; external index
  1367                                  gfa_5:
  1368 000007B6 BB[0000]                    mov bx,OFFSET ext_defent_indptr wrt DGROUP  ; set bx to base of pubdef declarations entry address array
  1369 000007B9 01C3                        add bx,ax               ; bx -> array element holding pubdef declarations entry address
  1370 000007BB 8E07                        mov es,[bx]             ; es -> pubdef declarations entry
  1371                                  
  1372 000007BD 26800E0E0040                or  BYTE PTR [es:14],40h    ; flag that used in fixup
  1373                                  
  1374 000007C3 26A00E00                    mov al,[es:14]          ; get definitions byte value
  1375 000007C7 2403                        and al,3                ; only keep pubdef/extdef/comdef/absolute field
  1376 000007C9 3C02                        cmp al,2                ; check if unresolved external
  1377 000007CB 723D                        jb  gfa_unres_ext       ; unresolved external
  1378 000007CD 7725                        ja  gfa_abs             ; absolute public declaration
  1379                                  
  1380                                  ; pubdef declaration (not absolute)
  1381                                  
  1382                                  ; check if pubdef has a group associated with it
  1383 000007CF 26A00F00                    mov al,[es:15]
  1384 000007D3 A880                        test    al,80h          ; high bit set if group associated with public declaration
  1385 000007D5 7410                        je  gfa_6               ; no group
  1386                                  
  1387 000007D7 2401                        and al,1                ; see if overlaid public
  1388 000007D9 750C                        jne gfa_6               ; yes, flush group association
  1389                                  
  1390 000007DB B001                        mov al,1
  1391 000007DD A2[0E00]                    mov [frext_ingroup],al    ; flag external has associated group
  1392 000007E0 268E060200                  mov es,[es:2]           ; es -> group entry
  1393 000007E5 EBA7                        jmp SHORT gfa_group_entry   ; perform code in common with group index
  1394                                  
  1395                                  gfa_6:
  1396 000007E7 30C0                        xor al,al
  1397 000007E9 A2[0E00]                    mov [frext_ingroup],al    ; flag external has no associated group
  1398 000007EC 268E060000                  mov es,[es:0]           ; es -> segment partition entry
  1399 000007F1 E906FF                      jmp NEAR PTR gfa_spart_entry     ; external resolved, perform code in common with segment index
  1400                                  
  1401                                  ; absolute public declaration
  1402                                  gfa_abs:
  1403 000007F4 31C0                        xor ax,ax
  1404 000007F6 A2[0800]                    mov [is_relocatable],al   ; nonrelocatable segment
  1405 000007F9 A3[2400]                    mov [frame_ent_ptr],ax    ; zero frame entry pointer
  1406 000007FC FEC0                        inc al
  1407 000007FE A2[0C00]                    mov [is_abspub],al        ; flag absolute public declaration
  1408 00000801 26A10200                    mov ax,[es:2]           ; get frame number of public entry
  1409 00000805 A3[2000]                    mov [target_segment],ax   ; save to target segment
  1410 00000808 07                          pop es
  1411 00000809 C3                          ret
  1412                                  
  1413                                  ; unresolved external, no fixup
  1414                                  gfa_unres_ext:
  1415 0000080A C606[0A00]00                mov byte [is_resolved],0       ; flag no fixup
  1416 0000080F 07                          pop es                  ; restore critical register
  1417 00000810 C3                          ret
  1418                                  
  1419                                  get_frame_addr  ENDP
  1420                                  
  1421                                  ;*****************************
  1422                                  ;* SAVE_THREAD               *
  1423                                  ;*****************************
  1424                                  
  1425                                  ; parse and save thread information
  1426                                  ; updates si record pointer,cx record length
  1427                                  ; destroys ax,bx,dx,di
  1428                                  
  1429                                  save_thread PROC
  1430 00000811 8936[2200]                  mov [fixup_pos],si        ; keep -> fixup in case of error
  1431 00000815 268A1C                      mov bl,[es:si]          ; get thread data byte
  1432 00000818 46                          inc si
  1433 00000819 49                          dec cx                  ; decrement record length to parse
  1434 0000081A 39EE                        cmp si,bp               ; check boundary conditions
  1435 0000081C 7203                        jb  st_2                ; okay
  1436 0000081E E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1437                                  st_2:
  1438 00000821 88D8                        mov al,bl               ; get thread field
  1439 00000823 241C                        and al,1ch              ; break out thread method
  1440 00000825 D0E8                        shr al,1
  1441 00000827 D0E8                        shr al,1                ; adjust method value to relative zero (right justify bit field)
  1442 00000829 A2[0600]                    mov [thread_method],al    ; save thread method to memory variable
  1443 0000082C 3C03                        cmp al,3                ; check if explicit frame number type, unsupported
  1444 0000082E 7508                        jne st_3                ; no
  1445                                  
  1446                                  ; bad method field
  1447                                  st_bad_meth:
  1448 00000830 88C1                        mov cl,al
  1449 00000832 B81C00                      mov ax,INV_THRD_METH_ERR    ; invalid thread method field value
  1450 00000835 E979FC                      jmp NEAR PTR fixupp_offset_err  ; transfer control to error handler
  1451                                  
  1452                                  st_3:
  1453 00000838 88DF                        mov bh,bl               ; get thread data byte in bh
  1454 0000083A 80E740                      and bh,40h              ; get D field bit
  1455 0000083D 7406                        je  st_4                ; D bit reset
  1456                                  
  1457                                  ; D bit set
  1458 0000083F 3C05                        cmp al,5                ; check if invalid method value
  1459 00000841 7606                        jbe st_5                ; okay
  1460 00000843 EBEB                        jmp SHORT st_bad_meth   ; bad value
  1461                                  
  1462                                  ; D bit reset
  1463                                  st_4:
  1464 00000845 3C02                        cmp al,2                ; check if invalid method value
  1465 00000847 77E7                        ja  st_bad_meth         ; bad value
  1466                                  
  1467                                  st_5:
  1468 00000849 30E4                        xor ah,ah               ; zero high byte of thread index
  1469 0000084B 268A04                      mov al,[es:si]          ; get thread index byte(s)
  1470 0000084E 46                          inc si
  1471 0000084F 49                          dec cx                  ; decrement record length to parse
  1472 00000850 39EE                        cmp si,bp               ; check boundary conditions
  1473 00000852 7203                        jb  st_6                ; okay
  1474 00000854 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1475                                  st_6:
  1476 00000857 3C80                        cmp al,80h              ; see if two byte field
  1477 00000859 7210                        jb  st_7                ; no
  1478 0000085B 247F                        and al,7fh              ; strip high bit
  1479 0000085D 88C4                        mov ah,al               ; move value to high byte
  1480                                  
  1481 0000085F 268A04                      mov al,[es:si]          ; get thread index second byte
  1482 00000862 46                          inc si
  1483 00000863 49                          dec cx                  ; decrement record length to parse
  1484 00000864 39EE                        cmp si,bp               ; check boundary conditions
  1485 00000866 7203                        jb  st_7                ; okay
  1486 00000868 E8(0000)                    call    load_file       ; load next portion of file into buffer, at end position
  1487                                  
  1488                                  st_7:
  1489 0000086B A3[1E00]                    mov [thread_index],ax     ; save thread index value
  1490 0000086E 53                          push    bx              ; save thread data byte in bl
  1491 0000086F A1[1E00]                    mov ax,[thread_index]     ; get thread index for check_index
  1492 00000872 8A1E[0600]                  mov bl,[thread_method]
  1493 00000876 E855FC                      call    check_index     ; check index validity
  1494 00000879 5B                          pop bx                  ; restore thread data byte in bl
  1495 0000087A 88DA                        mov dl,bl
  1496 0000087C 80E203                      and dl,3                ; get thread number in dl
  1497 0000087F 30F6                        xor dh,dh               ; zap high byte
  1498 00000881 80E340                      and bl,40h              ; get D bit field value in bl
  1499 00000884 7417                        je  st_8                ; D bit reset, target thread field
  1500                                  
  1501                                  ; frame thread field
  1502 00000886 BB[0000]                    mov bx,OFFSET frame_thrd_meth wrt DGROUP    ; bx -> base of frame thread method array
  1503 00000889 BF[0000]                    mov di,OFFSET frame_thrd_index wrt DGROUP   ; di -> base of frame thread index array
  1504                                  
  1505                                  st_array_save:
  1506 0000088C 01D3                        add bx,dx               ; bx -> proper array element (thread number'th)
  1507 0000088E A0[0600]                    mov al,[thread_method]
  1508 00000891 8807                        mov [bx],al             ; save method type in array
  1509 00000893 D1E2                        shl dx,1                ; convert dx to word offset
  1510 00000895 01D7                        add di,dx               ; di -> proper array element (thread number'th)
  1511 00000897 A1[1E00]                    mov ax,[thread_index]
  1512 0000089A 8905                        mov [di],ax             ; save index type to array
  1513 0000089C C3                          ret
  1514                                  
  1515                                  ; target thread field
  1516                                  st_8:
  1517 0000089D BB[0000]                    mov bx,OFFSET target_thrd_meth wrt DGROUP   ; bx -> base of target thread method array
  1518 000008A0 BF[0000]                    mov di,OFFSET target_thrd_index wrt DGROUP  ; di -> base of target thread index array
  1519 000008A3 EBE7                        jmp SHORT st_array_save ; save thread method and index to arrays
  1520                                  
  1521                                  save_thread ENDP 
  1522                                  
  1523                                  END
