flat assembler
Message board for the users of flat assembler.

Index > Windows > playing with 16bit winincludes

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 441
Location: Russian Federation, Sochi
ProMiNick
by analogy to 32/64 winuser.inc(structures):
Code:
; USER.DLL structures

struct WNDCLASS
  style         dw ?
  lpfnWndProc   dd ?
  cbClsExtra    dw ?
  cbWndExtra    dw ?
  hInstance     dw ?
  hIcon         dw ?
  hCursor       dw ?
  hbrBackground dw ?
  lpszMenuName  dd ?
  lpszClassName dd ?
ends

struct CREATESTRUCT
  lpCreateParams dd ?
  hInstance      dw ?
  hMenu          dw ?
  hwndParent     dw ?
  cy             dw ?
  cx             dw ?
  y              dw ?
  x              dw ?
  style          dd ?
  lpszName       dd ?
  lpszClass      dd ?
  dwExStyle      dd ?
ends

struct CLIENTCREATESTRUCT
  hWindowMenu  dw ?
  idFirstChild dw ?
ends

struct MDICREATESTRUCT
  szClass dd ?
  szTitle dd ?
  hOwner  dw ?
  x       dw ?
  y       dw ?
  cx      dw ?
  cy      dw ?
  style   dd ?
  lParam  dd ?
ends

struct MSG
  hwnd    dw ?
  message dw ?
  wParam  dw ?
  lParam  dd ?
  time    dd ?
  pt      POINTS
ends

struct MINMAXINFO
  ptReserved     POINTS
  ptMaxSize      POINTS
  ptMaxPosition  POINTS
  ptMinTrackSize POINTS
  ptMaxTrackSize POINTS
ends

struct WINDOWPLACEMENT
  length           dw ?
  flags            dw ?
  showCmd          dw ?
  ptMinPosition    POINTS
  ptMaxPosition    POINTS
  rcNormalPosition RECTS
ends

struct WINDOWPOS
  hwnd            dw ?
  hwndInsertAfter dw ?
  x               dw ?
  y               dw ?
  cx              dw ?
  cy              dw ?
  flags           dw ?
ends

struct PAINTSTRUCT
  hdc         dw ?
  fErase      dw ?
  rcPaint     RECTS
  fRestore    dw ?
  fIncUpdate  dw ?
  rgbReserved db 16 dup (?)
ends

struct DRAWITEMSTRUCT
  CtlType    dw ?
  CtlID      dw ?
  itemID     dw ?
  itemAction dw ?
  itemState  dw ?
  hwndItem   dw ?
  hDC        dw ?
  rcItem     RECTS
  itemData   dd ?
ends

struct MEASUREITEMSTRUCT
  CtlType    dw ?
  CtlID      dw ?
  itemID     dw ?
  itemWidth  dw ?
  itemHeight dw ?
  itemData   dd ?
ends    


proc16.inc by analogy to proc32.inc/proc64.inc (it is still pretty raw, I suppose not everything convinient):
Code:
; Macroinstructions for defining and calling procedures

macro x16 statement& {
        match =stdcall sttmnt,statement \{ stdcall16 sttmnt \}
        match =farcall sttmnt,statement \{ farcall16 sttmnt \}
        match =far =stdcall sttmnt,statement \{ farcall16 sttmnt \}
        match =invoke sttmnt,statement \{ invoke16 sttmnt \}
        match =far =invoke sttmnt,statement \{ farinvk16 sttmnt \}
        match =ccall sttmnt,statement \{ ccall16 sttmnt \}
        match =far =ccall sttmnt,statement \{ farccall16 sttmnt \}
        match =cinvoke sttmnt,statement \{ cinvoke16 sttmnt \}
        match =far =cinvoke sttmnt,statement \{ farcinvoke16 sttmnt \} }

macro stdcall16 proc,[arg]              ; directly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
    pushw arg
   common
    end if
    call proc }

macro farcall16 proc,[arg]              ; directly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
    pushw arg
   common
    end if
    push cs
    call proc }

macro invoke16 proc,[arg]               ; indirectly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
     pushw arg
   common
    end if
    call [proc] }

macro farinvk16 proc,[arg]              ; indirectly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
     pushw arg
   common
    end if
    push cs
    call [proc] }

macro ccall16 proc,[arg]                ; directly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    call proc
    if size@ccall
    add esp,size@ccall
    end if }

macro farccall16 proc,[arg]             ; directly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    push cs
    call proc
    if size@ccall
    add esp,size@ccall
    end if }

macro cinvoke16 proc,[arg]              ; indirectly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    call [proc]
    if size@ccall
    add esp,size@ccall
    end if }

macro farcinvoke16 proc,[arg]              ; indirectly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    push cs
    call [proc]
    if size@ccall
    add esp,size@ccall
    end if }

macro proc16 [args]                     ; define procedure
 { common
    match name params, args>
    \{ define@proc16 name,<params \} }

prologue@proc16 equ prologuedef16

macro prologuedef16 procname,flag,parmbytes,localbytes,reglist
 { local loc
   loc = (localbytes+1) and (not 1)
   parmbase@proc16 equ bp+4
   localbase@proc16 equ bp-loc
   if parmbytes | localbytes
    push bp
    mov bp,sp
    if localbytes
     sub sp,loc
    end if
   end if
   irps reg, reglist \{ push reg \} }

epilogue@proc16 equ epiloguedef16

macro epiloguedef16 procname,flag,parmbytes,localbytes,reglist
 { irps reg, reglist \{ reverse pop reg \}
   if parmbytes | localbytes
    leave
   end if
   if flag and 100000b
    if flag and 10000b
     retf
    else
     retf parmbytes
    end if
   else
    if flag and 10000b
     retn
    else
     retn parmbytes
    end if
   end if }

close@proc16 equ

macro define@proc16 name,statement {
 local params,flag,regs,parmbytes,localbytes,current
        if used name
                name:
                flag = 0
                params equ statement:
                match =far args, params \{
                        flag = 100000b
                        params equ args \}
                match =farcall args, params \{
                        flag = 100011b
                        params equ args \}
                match =stdcall args, params \{
                        flag = flag or 11b
                        params equ args \}
                match =c args, params \{
                        flag = flag or 10001b
                        params equ args \}
                match =uses reglist=,args, params \{
                        regs equ reglist
                        params equ args \}
                match =regs =uses reglist:, regs params \{
                        regs equ reglist
                        params equ \}
                match =regs, regs \{ regs equ \}
                match args:, params \{ params equ args \}
                match :, params \{ params equ \}
                match prologue:reglist, prologue@proc16:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
                virtual at parmbase@proc16
                        match =,args, params \{ defargs@proc16 args \}
                        match =args@proc16 args, args@proc16 params \{ defargs@proc16 args \}
                        parmbytes = $-(parmbase@proc16)
                end virtual
                name # % = parmbytes/2
                all@vars equ
                current = 0
                macro locals
                \{ virtual at localbase@proc16+current
                        macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
                        struc db [val] \\{ \common deflocal@proc .,db,val \\}
                        struc du [val] \\{ \common deflocal@proc .,du,val \\}
                        struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
                        struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
                        struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
                        struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
                        struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
                        struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
                        struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
                        struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
                        struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
                        struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
                        struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
                macro endl
                \{ purge label
                        restruc db,du,dw,dp,dd,dt,dq
                        restruc rb,rw,rp,rd,rt,rq
                        current = $-(localbase@proc16)
                        end virtual \}
                macro ret operand
                \{ match any, operand \\{ retn operand \\}
                        match , operand \\{ match epilogue:reglist, epilogue@proc16:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
   macro finish@proc16
   \{ localbytes = current
      match close:reglist, close@proc16:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
      end if \} }

macro defargs@proc16 [arg]
 { common
    if ~ arg eq
   forward
     local ..arg,current@arg
     match argname:type, arg
      \{ current@arg equ argname
         label ..arg type
         argname equ ..arg
         if qqword eq type
           dw ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
         else if dqword eq type
           dw ?,?,?,?,?,?,?,?
         else if tbyte eq type
           dw ?,?,?,?,?,?
         else if qword eq type | pword eq type
           dw ?,?,?,?
         else if dword eq type
           dw ?,?
         else
           dw ?
         end if \}
     match =current@arg,current@arg
      \{ current@arg equ arg
         arg equ ..arg
         ..arg dw ? \}
   common
     args@proc16 equ current@arg
   forward
     restore current@arg
   common
    end if }

macro deflocal@proc name,def,[val] { name def val }

macro deflocal@proc name,def,[val]
 { common
    match vars, all@vars \{ all@vars equ all@vars, \}
    all@vars equ all@vars name
   forward
    local ..var,..tmp
    ..var def val
    match =?, val \{ ..tmp equ \}
    match any =?, val \{ ..tmp equ \}
    match any (=?), val \{ ..tmp equ \}
    match =label, def \{ ..tmp equ \}
    match tmp : value, ..tmp : val
     \{ tmp: end virtual
        initlocal@proc ..var,def value
        virtual at tmp\}
   common
    match first rest, ..var, \{ name equ first \} }

struc label type { label . type }

macro initlocal@proc name,def
 { virtual at name
    def
    size@initlocal = $ - name
   end virtual
   position@initlocal = 0
   while size@initlocal > position@initlocal
    virtual at name
     def
     if size@initlocal - position@initlocal < 2
      current@initlocal = 1
      load byte@initlocal byte from name+position@initlocal
     else if size@initlocal - position@initlocal < 4
      current@initlocal = 2
      load word@initlocal word from name+position@initlocal
     else
      current@initlocal = 4
      load dword@initlocal dword from name+position@initlocal
     end if
    end virtual
    if current@initlocal = 1
     mov byte [name+position@initlocal],byte@initlocal
    else if current@initlocal = 2
     mov word [name+position@initlocal],word@initlocal
    else
     mov dword [name+position@initlocal],dword@initlocal
    end if
    position@initlocal = position@initlocal + current@initlocal
   end while }

macro endp
 { purge ret,locals,endl
   finish@proc16
   purge finish@proc16
   restore regs@proc
   match all,args@proc16 \{ restore all \}
   restore args@proc16
   match all,all@vars \{ restore all \} }

macro local [var]
 { common
    locals
   forward done@local equ
    match varname[count]:vartype, var
    \{ match =BYTE, vartype \\{ varname rb count
                                restore done@local \\}
       match =WORD, vartype \\{ varname rw count
                                restore done@local \\}
       match =DWORD, vartype \\{ varname rd count
                                 restore done@local \\}
       match =PWORD, vartype \\{ varname rp count
                                 restore done@local \\}
       match =QWORD, vartype \\{ varname rq count
                                 restore done@local \\}
       match =TBYTE, vartype \\{ varname rt count
                                 restore done@local \\}
       match =DQWORD, vartype \\{ label varname dqword
                                  rq count*2
                                  restore done@local \\}
       match =QQWORD, vartype \\{ label varname qqword
                                  rq count*4
                                  restore done@local \\}
       match =XWORD, vartype \\{ label varname xword
                                 rq count*2
                                 restore done@local \\}
       match =YWORD, vartype \\{ label varname yword
                                 rq count*4
                                 restore done@local \\}
       match , done@local \\{ virtual
                               varname vartype
                              end virtual
                              rb count*sizeof.\#vartype
                              restore done@local \\} \}
    match :varname:vartype, done@local:var
    \{ match =BYTE, vartype \\{ varname db ?
                                restore done@local \\}
       match =WORD, vartype \\{ varname dw ?
                                restore done@local \\}
       match =DWORD, vartype \\{ varname dd ?
                                 restore done@local \\}
       match =PWORD, vartype \\{ varname dp ?
                                 restore done@local \\}
       match =QWORD, vartype \\{ varname dq ?
                                 restore done@local \\}
       match =TBYTE, vartype \\{ varname dt ?
                                 restore done@local \\}
       match =DQWORD, vartype \\{ label varname dqword
                                  dq ?,?
                                  restore done@local \\}
       match =QQWORD, vartype \\{ label varname qqword
                                  dq ?,?,?,?
                                  restore done@local \\}
       match =XWORD, vartype \\{ label varname xword
                                 dq ?,?
                                 restore done@local \\}
       match =YWORD, vartype \\{ label varname yword
                                 dq ?,?,?,?
                                 restore done@local \\}
       match , done@local \\{ varname vartype
                              restore done@local \\} \}
    match ,done@local
    \{ var
       restore done@local \}
   common
    endl }    


win16w.inc by analogy to win32w.inc/win64w.inc:
Code:
; Win16 programming headers (WideChar)

datadef@directives equ db,dw,du,dd,dp,dq,dt
datarsv@directives equ rb,rw,rd,rp,rq,rt
algnmnt@directives equ
def.rb equ db
def.rw equ dw
def.rd equ dd
def.rp equ dp
def.rq equ dq
def.rt equ dt
db.align = 1
dw.align = 2
du.align = 2
dd.align = 4
dq.align = 8

sizeof.PTR =2
sizeof.FARPTR =2
struc PTR [value:?] { common . dw value }
struc FARPTR [value:?] { common . dd value }
macro PTR [value:?] { common dw value }
macro FARPTR [value:?] { common dd value }

;====== fundamental macros ======================
include 'generic/macro/struct.inc'
include 'generic/macro/interface.inc'
include 'generic/macro/guid.inc'
;====== OS specific macros ======================
include 'os specific/windows/macro/x86/proc16.inc'
;include 'os specific/windows/macro/x86/com32.inc'
;====== file format specific macros =============
;include 'file formats/pe coff/macro/import32.inc'
;include 'file formats/pe coff/macro/export.inc'
;include 'file formats/pe coff/macro/resource.inc'
;include 'file formats/pe coff/equates/imagebase.inc'
include 'file formats/pe coff/equates/resource.inc'

struc TCHAR [val:?] { common . du val }
sizeof.TCHAR = 2
struc ACHAR [val:?] { common . db val }
sizeof.ACHAR = 1
struc WCHAR [val:?] { common . du val }
sizeof.WCHAR = 2

;====== fundamental equates =====================
include 'generic/equates/fundamental.inc'
;====== OS specific equates =====================
include 'os specific/windows/equates/windef.inc'
include 'os specific/windows/equates/winver.inc'
include 'os specific/windows/equates/winbase.inc'
include 'os specific/windows/equates/wingdi.inc'
include 'os specific/windows/equates/winuser.inc' ; winuser - next level of abstraction after wingdi
include 'os specific/windows/equates/comctl.inc'
include 'os specific/windows/equates/comdlg.inc'
include 'os specific/windows/equates/shell.inc'
include 'os specific/windows/equates/winsock2.inc'
;====== Internet technology equates =============
include 'technologies/internet/equates/socket.inc'
include 'technologies/internet/equates/ipproto.inc'
;====== COM technology equates ==================
include 'os specific/windows/equates/com.inc'
include 'os specific/windows/equates/shobjidl_core.inc'

;====== fundamental structures ==================
include 'generic/structures/coordinates.inc'
;====== OS specific structures ==================
;include 'os specific/windows/structures/windef.inc'
;include 'os specific/windows/structures/x32/ntdef.inc'
;include 'os specific/windows/structures/x32/sysinfo.inc'
;include 'os specific/windows/structures/x32/processthreads.inc'
;include 'os specific/windows/structures/x32/synch.inc'
;include 'os specific/windows/structures/x32/winbase.inc'
;include 'os specific/windows/structures/x32/winternl.inc'
;include 'os specific/windows/structures/x32/wingdi.inc'
include 'os specific/windows/structures/x16/winuser.inc'
;include 'os specific/windows/structures/x32/comctl.inc'
;include 'os specific/windows/structures/x32/comdlg.inc'
;include 'os specific/windows/structures/x32/shell.inc'
;include 'os specific/windows/structures/x32/winsock2.inc'
;====== COM technology structures ===============
;include 'os specific/windows/structures/x32/objidl.inc'
;include 'os specific/windows/structures/x32/shobjidl_core.inc'

;====== COM technology interfaces ===============
;include 'os specific/windows/interfaces/iunknwn.inc'
;include 'os specific/windows/interfaces/objidl.inc'
;include 'os specific/windows/interfaces/shobjidl_core.inc'

;macro api [name] { if used name
;                    label name dword at name#W
;                   end if }
    


test itself (chosen format NE)
because of that:
Code:
include 'file formats\ne\equates\flags.inc'    
(InProcess - missed consts for making relocs) - it content here too:
Code:
; Program flags
NE_SOLO         = $01
NE_INST         = $02
NE_PPLI         = $04
NE_PROT         = $08
NE_I086         = $10
NE_I286         = $20
NE_I386         = $40
NE_FLTP         = $80

; Application  flags
NE_NOTWINCOMPAT = $01 ; fullscreen
NE_WINCOMPAT    = $02
NE_WINAPI       = $03
NE_APPTYPEMASK  = $07
NE_OS2APP       = $08
; reserved        $10
NE_IERR         = $20
NE_NONCOMFORM   = $40
NE_DLL          = $80

; TargetOS
NE_UNKNOWN      = 0
NE_OS2          = 1
NE_WINDOWS      = 2 ;Win16
NE_DOS4         = 3
NE_WIN386       = 4 ;Win32s
NE_BOSS         = 5

; Additional flags
NE_LONGFILENAMES        = 1
NE_PMODE                = 2
NE_PFONT                = 4
NE_GANGL                = 8 ; file contains a fast-load area

; Segment flags
NE_NSCODE               = $0000
NE_NSDATA               = $0001
NE_NSALLOC              = $0002
NE_NSLOADED             = $0004
NE_NSITER               = $0008
NE_NSMOVE               = $0010
NE_NSSHARED             = $0020
NE_NSPRELOAD            = $0040
NE_NSEXRD               = $0080
NE_NSRELOC              = $0100
NE_NSCONFORM            = $0200
NE_NSDPL                = $0C00
NE_NSDISCARD            = $1000
NE_NS32BIT              = $2000
NE_NSHUGE               = $4000

; Segment predefined numbers for Entry Table
NE_SEGNDX_MOVABLE       = $FF
NE_SEGNDX_REFCONST      = $FE

; Entry table flags
NE_ET_EXPORTED          = 1
NE_ET_SHARED            = 2    


because fasm dont support NE natively build it in style as it done in file format tutorials but in fasm syntax, not fasmg
Code:
format binary as 'exe'

include 'win16a.inc'
include 'file formats\ne\equates\flags.inc'

FILE_ALIGNMENT_SHIFT = 4
RSRC_ALIGNMENT_SHIFT = 4
FILE_ALIGNMENT = 1 shl FILE_ALIGNMENT_SHIFT

stub:
        .Signature                      dw 'MZ'
        .BytesInLastSector              dw SIZE_OF_STUB mod 512
        .NumberOfSectors                dw (SIZE_OF_STUB-1)/512 + 1
        .NumberOfRelocations            dw 0
        .NumberOfHeaderParagraphs       dw SIZE_OF_STUB_HEADER / 16
                                        db 0x3C - ($-stub) dup 0
        .NewHeaderOffset                dd Header;-IMAGE_BASE

align 16

SIZE_OF_STUB_HEADER = $ - stub

        ; The code of a DOS program would go here.

SIZE_OF_STUB = $ - stub

align 8
align $80

Header:
        .Signature                      dw "NE",0
        .MajorLinkerVersion             db 0
        .MinorLinkerVersion             db 0
        .EntryTable                     dw EntryTable-Header
        .SizeOfEntryTable               dw ?
        .CheckSum                       dd 0
        .ProgramFlags                   db NE_INST
        .Applicationflags               db NE_WINAPI
        .AutoDataSegIndex               dw 2
        .InitHeapSize                   dw $800
        .InitStackSize                  dw $2400
        .EntryPoint                     dd 1:start
        .InitialStackPointer            dd 2:0
        .SegCount                       dw 2
        .ModRefs                        dw 6
        .SizeOfNonResNamesTable         dw ?
        .SegTableOffset                 dw SegmentTable-Header
        .ResTableOffset                 dw ResourceTable-Header
        .ResNamesTable                  dw ResidentNamesTable-Header
        .ModRefTable                    dw ModRefTable-Header
        .ImportNamesTable               dw ImportNamesTable-Header
        .OffStartNonResNamesTable       dd NonResNamesTable
        .MovEntryCount                  dw ?
        .FileAlnSzShftCnt               dw FILE_ALIGNMENT_SHIFT
        .nResTableEntries               dw 6
        .TargetOS                       db NE_WINDOWS
        .OS2EXEFlags                    db NE_GANGL
        .RetThunksOffset:
        .GangloadStart                  dw GangloadStart
        .SegRefThunksOffset:
        .GangloadSize                   dw ?
        .MinCodeSwap                    dw ?
        .MinorOperatingSystemVersion    db 10
        .MajorOperatingSystemVersion    db 3

SegmentTable:

        .1.Offset                       dw Segment.1 shr 4
        .1.Length                       dw Segment.1.End - Segment.1
        .1.Flags                        dw NE_NSCODE or NE_NSMOVE or NE_NSPRELOAD or NE_NSRELOC or (NE_NSDPL and (3 shl 10))
        .1.MinAlloc                     dw Segment.1.End - Segment.1

        .2.Offset                       dw Segment.2 shr 4
        .2.Length                       dw Segment.2.End - Segment.2
        .2.Flags                        dw NE_NSDATA or NE_NSMOVE or NE_NSPRELOAD or NE_NSRELOC or (NE_NSDPL and (3 shl 10))
        .2.MinAlloc                     dw Segment.2.End - Segment.2

ResourceTable:

        .RsrcAlnSzShftCnt               dw RSRC_ALIGNMENT_SHIFT

        .RsrcTypes:

        .1.TypeID                       dw $8000 or RT_GROUP_ICON
        .1.Count                        dw 1
        .1.Reserved                     dd 0
        .1.NameInfo:

        .1.NameInfo.1.rnOffset          dw rsrc.1 shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .1.NameInfo.1.rnLength          dw (rsrc.1.End - rsrc.1) shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .1.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .1.NameInfo.1.rnID              dw $8000 or $93
        .1.NameInfo.1.rnHandle          dw 0
        .1.NameInfo.1.rnUsage           dw 0

        .2.TypeID                       dw $8000 or RT_STRING
        .2.Count                        dw 2
        .2.Reserved                     dd 0
        .2.NameInfo:

        .2.NameInfo.1.rnOffset          dw rsrc.2 shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .2.NameInfo.1.rnLength          dw (rsrc.2.End - rsrc.2) shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .2.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSSHARED or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .2.NameInfo.1.rnID              dw $8000 or 1
        .2.NameInfo.1.rnHandle          dw 0
        .2.NameInfo.1.rnUsage           dw 0

        .2.NameInfo.2.rnOffset          dw rsrc.3 shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .2.NameInfo.2.rnLength          dw (rsrc.3.End - rsrc.3) shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .2.NameInfo.2.rnFlags           dw NE_NSMOVE or NE_NSSHARED or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .2.NameInfo.2.rnID              dw $8000 or 2
        .2.NameInfo.2.rnHandle          dw 0
        .2.NameInfo.2.rnUsage           dw 0

        .3.TypeID                       dw $8000 or RT_VERSION
        .3.Count                        dw 1
        .3.Reserved                     dd 0
        .3.NameInfo:

        .3.NameInfo.1.rnOffset          dw rsrc.4 shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .3.NameInfo.1.rnLength          dw (rsrc.4.End - rsrc.4) shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .3.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10))
        .3.NameInfo.1.rnID              dw $8000 or 1
        .3.NameInfo.1.rnHandle          dw 0
        .3.NameInfo.1.rnUsage           dw 0

        .4.TypeID                       dw $8000 or RT_STRING
        .4.Count                        dw 2
        .4.Reserved                     dd 0
        .4.NameInfo:

        .4.NameInfo.1.rnOffset          dw rsrc.5 shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .4.NameInfo.1.rnLength          dw (rsrc.5.End - rsrc.5) shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .4.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .4.NameInfo.1.rnID              dw $8000 or 1
        .4.NameInfo.1.rnHandle          dw 0
        .4.NameInfo.1.rnUsage           dw 0

        .4.NameInfo.2.rnOffset          dw rsrc.6 shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .4.NameInfo.2.rnLength          dw (rsrc.6.End - rsrc.6) shr (1 shl RSRC_ALIGNMENT_SHIFT)
        .4.NameInfo.2.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .4.NameInfo.2.rnID              dw $8000 or 2
        .4.NameInfo.2.rnHandle          dw 0
        .4.NameInfo.2.rnUsage           dw 0

        .RsrcTypes.End                  dw 0
        .RsrcNames                      db 0
        .RsrcNames.End                  db 0

ResidentNamesTable:

        .Export.1.Str                   db 8,'BOOTSTRP'
        .Export.1.Ord                   dw 0

        .Export.2.Str                   db 8,'___EXPORTEDSTUB'
        .Export.2.Ord                   dw 2

                                        db 0

ModRefTable:
        .1.Offset                       dw ImportNamesTable.1.Lib-ImportNamesTable
        .2.Offset                       dw ImportNamesTable.2.Lib-ImportNamesTable
        .3.Offset                       dw ImportNamesTable.3.Lib-ImportNamesTable
        .4.Offset                       dw ImportNamesTable.4.Lib-ImportNamesTable
        .5.Offset                       dw ImportNamesTable.5.Lib-ImportNamesTable
        .6.Offset                       dw ImportNamesTable.6.Lib-ImportNamesTable

ImportNamesTable:
                                        db 0
        .1.Lib                          db 6,'KERNEL'

        .1.Imports:

        .1.Imports.1                    db 16,'LOADLIBRARYEX32W'
        .1.Imports.2                    db 14,'FREELIBRARY32W'
        .1.Imports.3                    db 17,'GETPROCADDRESS32W'
        .1.Imports.4                    db 16,'GETVDMPOINTER32W'
        .1.Imports.5                    db 11,'CALLPROC32W'

        .2.Lib                          db 3,'GDI'
        .3.Lib                          db 4,'USER'
        .4.Lib                          db 8,'KEYBOARD'
        .5.Lib                          db 8,'LZEXPAND'
        .6.Lib                          db 5,'SHELL'

EntryTable:

        .1.Count                        db 2
        .1.SegNDX                       db NE_SEGNDX_MOVABLE

        .1.Movables:

        .1.Movable.1.flags              db NE_ET_EXPORTED
        .1.Movable.1.int3f              db $CD,$3F
        .1.Movable.1.SegNum             db 1
        .1.Movable.1.SegOffset          dw $A3F6

        .1.Movable.2.flags              db NE_ET_EXPORTED
        .1.Movable.2.int3f              db $CD,$3F
        .1.Movable.2.SegNum             db 1
        .1.Movable.2.SegOffset          dw $3178

                                        db 0

NonResNamesTable:

        .1.Str                          db 15,'MS-Setup Loader'
        .1.Ord                          dw 0

        .2.Str                          db 11,'BOOTWNDPROC'
        .2.Ord                          dw 1

                                        db 0

align $40
Segment.1: ; CODE MOVEABLE PRELOADED RELOCATED DPL:3
org 0

                db $10 dup (0)
        off_10   dw __WINFLAGS
error:
        mov     al,-1
    x16 stdcall 0:__exit,ax

proc16 start
        xor     bp, bp
        push    bp
    x16 stdcall $11CC:INITTASK
        or      ax, ax
        jz      error
        mov     [word_CA58], es
        add     cx, $100
        jb      error
        mov     [word_C8F6], cx
        mov     [word_C8F8], si
        mov     [word_C8FA], di
        mov     [word_C8FC], bx
        mov     [word_C8FE], es
        mov     [word_C900], dx
        mov     ax, -1
    x16 stdcall $11CC:LOCKSEGMENT,ax
    x16 stdcall $11CC:GETVERSION
        xchg    al, ah
        mov     [word_CA5A], ax
        mov     ah, $30
        test    [cs:off_10], 1
        jz      short .loc_6D
        call    DOS3CALL
        jmp     short .loc_6F
  .loc_6D:
        int     $21
  .loc_6F:
        mov     [word_CA5E], ax
        xchg    al, ah
        mov     [word_CA5C], ax
        test    [cs:off_10], 1
        jnz     short .loc_85
        mov     al, 0
        mov     [byte_CA61], al
  .loc_85:
        xor     ax, ax
    x16 stdcall $11CC:WAITEVENT,ax
    x16 stdcall $11CC:INITAPP,[word_C8FA]
        or      ax, ax
        jnz     short .loc_9D
        jmp     error
  .loc_9D:
        call    0:__cinit
        call    0:__setargv
        call    0:__setenvp
        call    __wcinit
    x16 ccall   0:__stubmain,[word_CA92],[word_CA94],[word_CA96],[word_CA98],[word_CA9A]
    x16 stdcall 0:__exit,ax
endp
__exit:
__WINFLAGS:
INITTASK:
LOCKSEGMENT:
GETVERSION:
DOS3CALL:
WAITEVENT:
INITAPP:
WINMAIN:
__setargv:
__setenvp:
__wcinit:
proc16 __stubmain farcall,arg0,arg1,arg2,arg3,arg4
        mov     ax, ds
        push    ds
    x16 stdcall 0:WINMAIN,[word_C900],[word_C8FC],[word_C8FE],[word_C8F8],[word_C8FA]
        pop     ds
        ret
endp

proc16 __cinit farcall
        mov     ax, ds
        push    ds
        mov     ax, $3500
        test    [cs:off_10], 1
        jz      short .loc_173B
        call    DOS3CALL
        jmp     short .loc_173D
  .loc_173B:
        int     $21
  .loc_173D:
        mov     word [dword_CA44], bx
        mov     word [dword_CA44+2], es
        push    cs
        pop     ds
        mov     ax, $2500
        mov     dx, $1BBE
        test    [cs:off_10], 1
        jz      short .loc_175D
        call    DOS3CALL
        jmp     short .loc_175F
  .loc_175D:
        int     $21
  .loc_175F:











endp

Segment.1.End:

Segment.2:
word_C8F6:
word_C8F8:
word_C8FA:
word_C8FC:
word_C8FE:
word_C900:
dword_CA44:
word_CA58:
word_CA5A:;OSVERSION
word_CA5E:
word_CA5C:
byte_CA61:
word_CA92:
word_CA94:
word_CA96:
word_CA98:
word_CA9A:
Segment.2.End:

GangloadStart:

rsrc.1:
rsrc.1.End:

rsrc.2:
rsrc.2.End:

rsrc.3:
rsrc.3.End:

rsrc.4:
rsrc.4.End:

rsrc.5:
rsrc.5.End:

rsrc.6:
rsrc.6.End:    


For now it is unworked dummy, I using NE format donor to reproduce aspects of NE in fasm syntax (donor payload I wish to replace with hello world window because register class & window creation in donor present but there are many other unneeded for example things).

Topic has no practical sense (NE is obsolete - I just tryed to make set of 16 bit includes in addition to 32/64bit ones).

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.


Last edited by ProMiNick on 27 Jan 2020, 05:32; edited 1 time in total
Post 24 Jan 2020, 07:05
View user's profile Send private message Send e-mail Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7572
Location: Kraków, Poland
Tomasz Grysztar
Amazing! I never thought that I would see an NE framework done in fasm 1 before fasmg. Smile Although with fasmg you could probably make it more maintainable (and relocations are really hard to do well with fasm 1).

As someone that would like to test it on my Windows 3.11, I might suggest using 8.3 filenames for all the headers. Wink
Post 24 Jan 2020, 09:52
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 441
Location: Russian Federation, Sochi
ProMiNick
I am stuck for a days...
before I add stub.relocations_offset my exe was never identified as NE.
And even after I got "bad relocation chain".
In my donor exe I searched everywhere for import ordinals or for relocation implementation - it is too trickery hidden.
Moreover every call to import is "call 0:-1"

fixes: esp macro rudiments replaced to sp:
Code:
; Macroinstructions for defining and calling procedures

macro x16 statement& {
        match =stdcall sttmnt,statement \{ stdcall16 sttmnt \}
        match =farcall sttmnt,statement \{ farcall16 sttmnt \}
        match =far =stdcall sttmnt,statement \{ farcall16 sttmnt \}
        match =invoke sttmnt,statement \{ invoke16 sttmnt \}
        match =far =invoke sttmnt,statement \{ farinvk16 sttmnt \}
        match =ccall sttmnt,statement \{ ccall16 sttmnt \}
        match =far =ccall sttmnt,statement \{ farccall16 sttmnt \}
        match =cinvoke sttmnt,statement \{ cinvoke16 sttmnt \}
        match =far =cinvoke sttmnt,statement \{ farcinvoke16 sttmnt \} }

macro stdcall16 proc,[arg]              ; directly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
    pushw arg
   common
    end if
    call proc }

macro farcall16 proc,[arg]              ; directly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
    pushw arg
   common
    end if
    push cs
    call proc }

macro invoke16 proc,[arg]               ; indirectly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
     pushw arg
   common
    end if
    call [proc] }

macro farinvk16 proc,[arg]              ; indirectly call STDCALL procedure
 { common
    if ~ arg eq
   reverse
     pushw arg
   common
    end if
    push cs
    call [proc] }

macro ccall16 proc,[arg]                ; directly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    call proc
    if size@ccall
    add sp,size@ccall
    end if }

macro farccall16 proc,[arg]             ; directly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    push cs
    call proc
    if size@ccall
    add sp,size@ccall
    end if }

macro cinvoke16 proc,[arg]              ; indirectly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    call [proc]
    if size@ccall
    add sp,size@ccall
    end if }

macro farcinvoke16 proc,[arg]              ; indirectly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushw arg
    size@ccall = size@ccall+2
   common
    end if
    push cs
    call [proc]
    if size@ccall
    add sp,size@ccall
    end if }

macro proc16 [args]                     ; define procedure
 { common
    match name params, args>
    \{ define@proc16 name,<params \} }

prologue@proc16 equ prologuedef16

macro prologuedef16 procname,flag,parmbytes,localbytes,reglist
 { local loc
   loc = (localbytes+1) and (not 1)
   parmbase@proc16 equ bp+4
   localbase@proc16 equ bp-loc
   if parmbytes | localbytes
    push bp
    mov bp,sp
    if localbytes
     sub sp,loc
    end if
   end if
   irps reg, reglist \{ push reg \} }

epilogue@proc16 equ epiloguedef16

macro epiloguedef16 procname,flag,parmbytes,localbytes,reglist
 { irps reg, reglist \{ reverse pop reg \}
   if parmbytes | localbytes
    leave
   end if
   if flag and 100000b
    if flag and 10000b
     retf
    else
     retf parmbytes
    end if
   else
    if flag and 10000b
     retn
    else
     retn parmbytes
    end if
   end if }

close@proc16 equ

macro define@proc16 name,statement {
 local params,flag,regs,parmbytes,localbytes,current
        if used name
                name:
                flag = 0
                params equ statement:
                match =far args, params \{
                        flag = 100000b
                        params equ args \}
                match =farcall args, params \{
                        flag = 100011b
                        params equ args \}
                match =stdcall args, params \{
                        flag = flag or 11b
                        params equ args \}
                match =c args, params \{
                        flag = flag or 10001b
                        params equ args \}
                match =uses reglist=,args, params \{
                        regs equ reglist
                        params equ args \}
                match =regs =uses reglist:, regs params \{
                        regs equ reglist
                        params equ \}
                match =regs, regs \{ regs equ \}
                match args:, params \{ params equ args \}
                match :, params \{ params equ \}
                match prologue:reglist, prologue@proc16:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
                virtual at parmbase@proc16
                        match =,args, params \{ defargs@proc16 args \}
                        match =args@proc16 args, args@proc16 params \{ defargs@proc16 args \}
                        parmbytes = $-(parmbase@proc16)
                end virtual
                name # % = parmbytes/2
                all@vars equ
                current = 0
                macro locals
                \{ virtual at localbase@proc16+current
                        macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
                        struc db [val] \\{ \common deflocal@proc .,db,val \\}
                        struc du [val] \\{ \common deflocal@proc .,du,val \\}
                        struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
                        struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
                        struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
                        struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
                        struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
                        struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
                        struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
                        struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
                        struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
                        struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
                        struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
                macro endl
                \{ purge label
                        restruc db,du,dw,dp,dd,dt,dq
                        restruc rb,rw,rp,rd,rt,rq
                        current = $-(localbase@proc16)
                        end virtual \}
                macro ret operand
                \{ match any, operand \\{ retn operand \\}
                        match , operand \\{ match epilogue:reglist, epilogue@proc16:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
   macro finish@proc16
   \{ localbytes = current
      match close:reglist, close@proc16:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
      end if \} }

macro defargs@proc16 [arg]
 { common
    if ~ arg eq
   forward
     local ..arg,current@arg
     match argname:type, arg
      \{ current@arg equ argname
         label ..arg type
         argname equ ..arg
         if qqword eq type
           dw ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
         else if dqword eq type
           dw ?,?,?,?,?,?,?,?
         else if tbyte eq type
           dw ?,?,?,?,?,?
         else if qword eq type | pword eq type
           dw ?,?,?,?
         else if dword eq type
           dw ?,?
         else
           dw ?
         end if \}
     match =current@arg,current@arg
      \{ current@arg equ arg
         arg equ ..arg
         ..arg dw ? \}
   common
     args@proc16 equ current@arg
   forward
     restore current@arg
   common
    end if }

macro deflocal@proc name,def,[val] { name def val }

macro deflocal@proc name,def,[val]
 { common
    match vars, all@vars \{ all@vars equ all@vars, \}
    all@vars equ all@vars name
   forward
    local ..var,..tmp
    ..var def val
    match =?, val \{ ..tmp equ \}
    match any =?, val \{ ..tmp equ \}
    match any (=?), val \{ ..tmp equ \}
    match =label, def \{ ..tmp equ \}
    match tmp : value, ..tmp : val
     \{ tmp: end virtual
        initlocal@proc ..var,def value
        virtual at tmp\}
   common
    match first rest, ..var, \{ name equ first \} }

struc label type { label . type }

macro initlocal@proc name,def
 { virtual at name
    def
    size@initlocal = $ - name
   end virtual
   position@initlocal = 0
   while size@initlocal > position@initlocal
    virtual at name
     def
     if size@initlocal - position@initlocal < 2
      current@initlocal = 1
      load byte@initlocal byte from name+position@initlocal
     else if size@initlocal - position@initlocal < 4
      current@initlocal = 2
      load word@initlocal word from name+position@initlocal
     else
      current@initlocal = 4
      load dword@initlocal dword from name+position@initlocal
     end if
    end virtual
    if current@initlocal = 1
     mov byte [name+position@initlocal],byte@initlocal
    else if current@initlocal = 2
     mov word [name+position@initlocal],word@initlocal
    else
     mov dword [name+position@initlocal],dword@initlocal
    end if
    position@initlocal = position@initlocal + current@initlocal
   end while }

macro endp
 { purge ret,locals,endl
   finish@proc16
   purge finish@proc16
   restore regs@proc
   match all,args@proc16 \{ restore all \}
   restore args@proc16
   match all,all@vars \{ restore all \} }

macro local [var]
 { common
    locals
   forward done@local equ
    match varname[count]:vartype, var
    \{ match =BYTE, vartype \\{ varname rb count
                                restore done@local \\}
       match =WORD, vartype \\{ varname rw count
                                restore done@local \\}
       match =DWORD, vartype \\{ varname rd count
                                 restore done@local \\}
       match =PWORD, vartype \\{ varname rp count
                                 restore done@local \\}
       match =QWORD, vartype \\{ varname rq count
                                 restore done@local \\}
       match =TBYTE, vartype \\{ varname rt count
                                 restore done@local \\}
       match =DQWORD, vartype \\{ label varname dqword
                                  rq count*2
                                  restore done@local \\}
       match =QQWORD, vartype \\{ label varname qqword
                                  rq count*4
                                  restore done@local \\}
       match =XWORD, vartype \\{ label varname xword
                                 rq count*2
                                 restore done@local \\}
       match =YWORD, vartype \\{ label varname yword
                                 rq count*4
                                 restore done@local \\}
       match , done@local \\{ virtual
                               varname vartype
                              end virtual
                              rb count*sizeof.\#vartype
                              restore done@local \\} \}
    match :varname:vartype, done@local:var
    \{ match =BYTE, vartype \\{ varname db ?
                                restore done@local \\}
       match =WORD, vartype \\{ varname dw ?
                                restore done@local \\}
       match =DWORD, vartype \\{ varname dd ?
                                 restore done@local \\}
       match =PWORD, vartype \\{ varname dp ?
                                 restore done@local \\}
       match =QWORD, vartype \\{ varname dq ?
                                 restore done@local \\}
       match =TBYTE, vartype \\{ varname dt ?
                                 restore done@local \\}
       match =DQWORD, vartype \\{ label varname dqword
                                  dq ?,?
                                  restore done@local \\}
       match =QQWORD, vartype \\{ label varname qqword
                                  dq ?,?,?,?
                                  restore done@local \\}
       match =XWORD, vartype \\{ label varname xword
                                 dq ?,?
                                 restore done@local \\}
       match =YWORD, vartype \\{ label varname yword
                                 dq ?,?,?,?
                                 restore done@local \\}
       match , done@local \\{ varname vartype
                              restore done@local \\} \}
    match ,done@local
    \{ var
       restore done@local \}
   common
    endl }    


I dont understand what Gangload is, but I locate where it is
And some minor fixes in fields calculations
And now I primary reffer to file conrent (not image conent as before) so some calls became "call 0:-1".
Code:
format binary as 'exe'

include 'win16a.inc'
include 'file formats\ne\equates\flags.inc'

macro align boundary,value:? { db (boundary-1)-($+boundary-1) mod boundary dup value }

FILE_ALIGNMENT_SHIFT = 4
RSRC_ALIGNMENT_SHIFT = 4
FILE_ALIGNMENT = 1 shl FILE_ALIGNMENT_SHIFT

stub:
        .Signature                      dw 'MZ'
        .BytesInLastSector              dw SIZE_OF_STUB mod 512
        .NumberOfSectors                dw (SIZE_OF_STUB-1)/512 + 1
        .NumberOfRelocations            dw 0
        .NumberOfHeaderParagraphs       dw SIZE_OF_STUB_HEADER / 16
                                        db 0x18 - ($-stub) dup 0
        .relocations_offset             dw SIZE_OF_STUB_HEADER
                                        db 0x3C - ($-stub) dup 0
        .NewHeaderOffset                dd Header;-IMAGE_BASE

align 16

SIZE_OF_STUB_HEADER = $ - stub

        ; The code of a DOS program would go here.
        org 0
        push    cs
        pop     ds
        mov     dx, noDOS
        mov     ah,9
        int     $21
        mov     ax,$4C01
        int     $21
        noDOS   db 'This program requires Microsoft Windows',$2E,13,10,'$',0
        org SIZE_OF_STUB_HEADER+$

SIZE_OF_STUB = $ - stub

align 8

Header: assert Header=$80
        .Signature                      dw "NE"
        .MajorLinkerVersion             db 0
        .MinorLinkerVersion             db 0
        .EntryTable                     dw EntryTable-Header
        .SizeOfEntryTable               dw EntryTable.End-EntryTable
        .CheckSum                       dd 0
        .ProgramFlags                   db NE_INST
        .Applicationflags               db NE_WINAPI
        .AutoDataSegIndex               dw 2
        .InitHeapSize                   dw $800
        .InitStackSize                  dw $2400
        .EntryPoint                     dd 1:start
        .InitialStackPointer            dd 2:0
        .SegCount                       dw 2
        .ModRefs                        dw 6
        .SizeOfNonResNamesTable         dw NonResNamesTable.End-NonResNamesTable
        .SegTableOffset                 dw SegmentTable-Header
        .ResTableOffset                 dw ResourceTable-Header
        .ResNamesTable                  dw ResidentNamesTable-Header
        .ModRefTable                    dw ModRefTable-Header
        .ImportNamesTable               dw ImportNamesTable-Header
        .OffStartNonResNamesTable       dd NonResNamesTable
        .MovEntryCount                  dw 2
        .FileAlnSzShftCnt               dw FILE_ALIGNMENT_SHIFT
        .nResTableEntries               dw 6
        .TargetOS                       db NE_WINDOWS
        .OS2EXEFlags                    db NE_GANGL
        .RetThunksOffset:
        .GangloadStart                  dw GangloadStart shr FILE_ALIGNMENT_SHIFT
        .SegRefThunksOffset:
        .GangloadSize                   dw (GangloadEnd-GangloadStart) shr FILE_ALIGNMENT_SHIFT
        .MinCodeSwap                    dw 0
        .MinorOperatingSystemVersion    db 10
        .MajorOperatingSystemVersion    db 3

SegmentTable: assert SegmentTable=$C0

        .1.Offset                       dw Segment.1 shr 4
        .1.Length                       dw Segment.1.End - Segment.1
        .1.Flags                        dw NE_NSCODE or NE_NSMOVE or NE_NSPRELOAD or NE_NSRELOC or (NE_NSDPL and (3 shl 10))
        .1.MinAlloc                     dw Segment.1.End - Segment.1

        .2.Offset                       dw Segment.2 shr 4
        .2.Length                       dw Segment.2.End - Segment.2
        .2.Flags                        dw NE_NSDATA or NE_NSMOVE or NE_NSPRELOAD or NE_NSRELOC or (NE_NSDPL and (3 shl 10))
        .2.MinAlloc                     dw Segment.2.End - Segment.2

ResourceTable: assert ResourceTable=$D0

        .RsrcAlnSzShftCnt               dw RSRC_ALIGNMENT_SHIFT

        .RsrcTypes:

        .1.TypeID                       dw $8000 or RT_GROUP_ICON
        .1.Count                        dw 1
        .1.Reserved                     dd 0
        .1.NameInfo:

        .1.NameInfo.1.rnOffset          dw rsrc.1 shr RSRC_ALIGNMENT_SHIFT
        .1.NameInfo.1.rnLength          dw (rsrc.1.End - rsrc.1) shr RSRC_ALIGNMENT_SHIFT
        .1.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .1.NameInfo.1.rnID              dw $8000 or $93
        .1.NameInfo.1.rnHandle          dw 0
        .1.NameInfo.1.rnUsage           dw 0

        .2.TypeID                       dw $8000 or RT_STRING
        .2.Count                        dw 2
        .2.Reserved                     dd 0
        .2.NameInfo:

        .2.NameInfo.1.rnOffset          dw rsrc.2 shr RSRC_ALIGNMENT_SHIFT
        .2.NameInfo.1.rnLength          dw (rsrc.2.End - rsrc.2) shr RSRC_ALIGNMENT_SHIFT
        .2.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSSHARED or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .2.NameInfo.1.rnID              dw $8000 or 1
        .2.NameInfo.1.rnHandle          dw 0
        .2.NameInfo.1.rnUsage           dw 0

        .2.NameInfo.2.rnOffset          dw rsrc.3 shr RSRC_ALIGNMENT_SHIFT
        .2.NameInfo.2.rnLength          dw (rsrc.3.End - rsrc.3) shr RSRC_ALIGNMENT_SHIFT
        .2.NameInfo.2.rnFlags           dw NE_NSMOVE or NE_NSSHARED or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .2.NameInfo.2.rnID              dw $8000 or 2
        .2.NameInfo.2.rnHandle          dw 0
        .2.NameInfo.2.rnUsage           dw 0

        .3.TypeID                       dw $8000 or RT_VERSION
        .3.Count                        dw 1
        .3.Reserved                     dd 0
        .3.NameInfo:

        .3.NameInfo.1.rnOffset          dw rsrc.4 shr RSRC_ALIGNMENT_SHIFT
        .3.NameInfo.1.rnLength          dw (rsrc.4.End - rsrc.4) shr RSRC_ALIGNMENT_SHIFT
        .3.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSSHARED or (NE_NSDPL and (3 shl 10))
        .3.NameInfo.1.rnID              dw $8000 or 1
        .3.NameInfo.1.rnHandle          dw 0
        .3.NameInfo.1.rnUsage           dw 0

        .4.TypeID                       dw $8000 or RT_ICON
        .4.Count                        dw 2
        .4.Reserved                     dd 0
        .4.NameInfo:

        .4.NameInfo.1.rnOffset          dw rsrc.5 shr RSRC_ALIGNMENT_SHIFT
        .4.NameInfo.1.rnLength          dw (rsrc.5.End - rsrc.5) shr RSRC_ALIGNMENT_SHIFT
        .4.NameInfo.1.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .4.NameInfo.1.rnID              dw $8000 or 1
        .4.NameInfo.1.rnHandle          dw 0
        .4.NameInfo.1.rnUsage           dw 0

        .4.NameInfo.2.rnOffset          dw rsrc.6 shr RSRC_ALIGNMENT_SHIFT
        .4.NameInfo.2.rnLength          dw (rsrc.6.End - rsrc.6) shr RSRC_ALIGNMENT_SHIFT
        .4.NameInfo.2.rnFlags           dw NE_NSMOVE or NE_NSPRELOAD or (NE_NSDPL and (3 shl 10)) or NE_NSDISCARD
        .4.NameInfo.2.rnID              dw $8000 or 2
        .4.NameInfo.2.rnHandle          dw 0
        .4.NameInfo.2.rnUsage           dw 0

        .RsrcTypes.End:                 ; dw 0
        .RsrcNames                      db 0
        .RsrcNames.End                  db 0

ResidentNamesTable: assert ResidentNamesTable=$13C

        .Export.1.Str                   db 8,'BOOTSTRP'
        .Export.1.Ord                   dw 0

        .Export.2.Str                   db 15,'___EXPORTEDSTUB'
        .Export.2.Ord                   dw 2

                                        db 0

ModRefTable: assert ModRefTable=$15A
        .1.Offset                       dw ImportNamesTable.1.Lib-ImportNamesTable
        .2.Offset                       dw ImportNamesTable.2.Lib-ImportNamesTable
        .3.Offset                       dw ImportNamesTable.3.Lib-ImportNamesTable
        .4.Offset                       dw ImportNamesTable.4.Lib-ImportNamesTable
        .5.Offset                       dw ImportNamesTable.5.Lib-ImportNamesTable
        .6.Offset                       dw ImportNamesTable.6.Lib-ImportNamesTable

ImportNamesTable: assert ImportNamesTable=$166
                                        db 0
        .1.Lib                          db 6,'KERNEL'

        .1.Imports:

        .1.Imports.1                    db 16,'LOADLIBRARYEX32W'
        .1.Imports.2                    db 14,'FREELIBRARY32W'
        .1.Imports.3                    db 17,'GETPROCADDRESS32W'
        .1.Imports.4                    db 16,'GETVDMPOINTER32W'
        .1.Imports.5                    db 11,'CALLPROC32W'

        .2.Lib                          db 3,'GDI'
        .3.Lib                          db 4,'USER'
        .4.Lib                          db 8,'KEYBOARD'
        .5.Lib                          db 8,'LZEXPAND'
        .6.Lib                          db 5,'SHELL'

EntryTable: assert EntryTable=$1DE

        .1.Count                        db 2
        .1.SegNDX                       db NE_SEGNDX_MOVABLE

        .1.Movables:

        .1.Movable.1.flags              db NE_ET_EXPORTED
        .1.Movable.1.int3f              db $CD,$3F
        .1.Movable.1.SegNum             db 1
        .1.Movable.1.SegOffset          dw $A3F6

        .1.Movable.2.flags              db NE_ET_EXPORTED
        .1.Movable.2.int3f              db $CD,$3F
        .1.Movable.2.SegNum             db 1
        .1.Movable.2.SegOffset          dw $3178

                                        db 0
        .End:

NonResNamesTable: assert NonResNamesTable=$1ED

        .1.Str                          db 15,'MS-Setup Loader'
        .1.Ord                          dw 0

        .2.Str                          db 11,'BOOTWNDPROC'
        .2.Ord                          dw 1

                                        db 0
        .End:

        STACKSLOP = 256                         ; amount of stack slop space required

align $20
GangloadStart:
align $40
Segment.1: assert Segment.1=$240; CODE MOVEABLE PRELOADED RELOCATED DPL:3
org 0

                db $10 dup (0)
        off_10   dw -1
error:
        mov     al,-1
    x16 stdcall 0:__exit,ax

start:
        xor     bp, bp
        push    bp
    x16 stdcall 0:-1;INITTASK
        or      ax, ax
        jz      error
        mov     [word_CA58], es
        add     cx, STACKSLOP
        jb      error
        mov     [StackSize], cx
        mov     [hPrev], si
        mov     [hInst], di
        mov     word [lpszCmd], bx
        mov     word [lpszCmd+2], es
        mov     [cmdShow], dx
        mov     ax, -1
    x16 stdcall 0:-1,ax ; LOCKSEGMENT
    x16 stdcall 0:GETVERSION
        xchg    al, ah
        mov     [word_CA5A], ax
        mov     ah, $30
        test    [cs:off_10], 1
        jz      short .loc_6D
        call    0:-1 ; DOS3CALL
        jmp     short .loc_6F
  .loc_6D:
        int     $21
  .loc_6F:
        mov     [word_CA5E], ax
        xchg    al, ah
        mov     [word_CA5C], ax
        test    [cs:off_10], 1
        jnz     short .loc_85
        mov     al, 0
        mov     [byte_CA61], al
  .loc_85:
        xor     ax, ax
    x16 stdcall 0:-1,ax ; WAITEVENT
    x16 stdcall 0:-1,[hInst] ; INITAPP
        or      ax, ax
        jnz     short .loc_9D
        jmp     error
  .loc_9D:
        call    $18:__cinit
        call    $A0:__setargv
        call    $A5:__setenvp
        nop
        nop
        nop
    x16 ccall   $AA:__stubmain,[word_CA92],[word_CA94],[word_CA96],[word_CA98],[word_CA9A]
    x16 stdcall $C6:_exit,ax

__nomain:
        mov     ax, $15
        jmp     __amsg_exit
        nop
proc16 fclose c, file.offs, file.seg

endp

__exit:
__WINFLAGS:
INITTASK:
LOCKSEGMENT:
GETVERSION:
DOS3CALL:
WAITEVENT:
INITAPP:
WINMAIN:
__setargv:
__setenvp:
__wcinit:
__GetDGROUP:
__fptrap:

rb $16F2-$
proc16 __stubmain farcall,arg0,arg1,arg2,arg3,arg4
        mov     ax, ds
        push    ds
    x16 stdcall 0:WINMAIN,[cmdShow],word [lpszCmd],word [lpszCmd+2],[hPrev],[hInst]
        pop     ds
        ret
endp

rb $171E-$
proc16 __cinit farcall
        mov     ax, ds
        push    ds
        mov     ax, $3500
        test    [cs:off_10], 1
        jz      short .loc_173B
        call    DOS3CALL
        jmp     short .loc_173D
  .loc_173B:
        int     $21
  .loc_173D:
        mov     word [dword_CA44], bx
        mov     word [dword_CA44+2], es
        push    cs
        pop     ds ; ds - codeseg
        mov     ax, $2500
        mov     dx, $1BBE
        test    [cs:off_10], 1
        jz      short .loc_175D
        call    DOS3CALL
        jmp     short .loc_175F
  .loc_175D:
        int     $21
  .loc_175F:
    x16 farcall __GetDGROUP
        mov     ds, ax ; ds - dataseg
        mov     cx, [word_CD98]
        jcxz    short .loc_1794
        mov     es, [word_CA58] ; es - nothing
        mov     si, [es:$2C]
        mov     ax, [word_CD9A]
        mov     dx, [word_CD9C]
        xor     bx, bx
        call    dword [unk_CD96]
        jnb     short .loc_1786
        jmp     __fptrap
  .loc_1786:
        mov     ax, [word_CD9E]
        mov     dx, [word_CDA0]
        mov     bx, 3
        call    dword [unk_CD96]
  .loc_1794:
        mov     es, [word_CA58]
        mov     cx, [es:$2C]
        jcxz    short .loc_17DD
        mov     es, cx
        xor     di, di
  .loc_17A3:
        cmp     byte [es:di], 0
        jz      short .loc_17DD
        mov     cx, $0D
        mov     si, word_CA36
        repe cmpsb
        jz      short .loc_17BE
        mov     cx, $7FFF
        xor     ax, ax
        repne scasb
        jnz     short .loc_17DD
        jmp     short .loc_17A3
  .loc_17BE:
        push    es ds
        pop     es ds ; es - dataseg
        mov     si, di
        mov     di, unk_CA6A
        mov     cl, 4
  .loc_17C9:
        lodsb
        sub     al, 'A'
        jb      short .loc_17DB
        shl     al, cl
        xchg    ax, dx
        lodsb
        sub     al, 'A'
        jb      short .loc_17DB
        or      al, dl
        stosb
        jmp     short .loc_17C9
  .loc_17DB:
        push    es
        pop     ds
  .loc_17DD:
        ret
endp

rb $1801-$
proc16 _exit farcall exitcode

endp

rb $1BC8-$
__amsg_exit:

        rb $C473-$

        org $+Segment.1

Segment.1.End:
rb $C9C0-$
align $10
Segment.2: assert Segment.2=$C9C0
org 0
                dd ?
                dd 5
                dw 0,0,0,0
                db 'LST',0
                db 'Params',0
                align 2
                db 'Files',0
                db 'Win3.x Params',0
                db 'Win3.x Files',0
                align 2
                db 'Windows 95 Params',0
                db 'Windows 95 Files',0
                align 2
                db 'NT Alpha Params',0
                db 'NT Alpha Files',0
                align 2
                db 'NT Mips Params',0
                align 2
                db 'NT Mips Files',0
                db 'NT PPC Params',0
                db 'NT PPC Files',0
                align 2
                db 'NT Intel Params',0
                db 'NT Intel Files',0
                align 2
                db 'NT3.51 Intel Params',0
                db 'NT3.51 Intel Files',0
                align 2
                dw 0,0,0,0
                db 'PROCESSOR_ARCHITECTURE',0
                align 2
                db 'X86',0
                db 'ALPHA',0
                db 'MIPS',0
                align 2
                db 'PPC',0
                db 'STUFF-BOOT',0
                align 2
                dw 9,0,0,0
                dw 0,0,0,0
                rb 260
                rb 260
                rb 260
                db 'Source Directory',9,0
                dd ?
StackSize       dw ?
hPrev           dw ?
hInst           dw ?
lpszCmd         dd ?
cmdShow         dw ?
word_CA36:
dword_CA44:
word_CA58:
word_CA5A:;OSVERSION
word_CA5E:
word_CA5C:
byte_CA61:
unk_CA6A:
word_CA92:
word_CA94:
word_CA96:
word_CA98:
word_CA9A:
unk_CD96:
word_CD98:
word_CD9A:
word_CD9C:
word_CD9E:
word_CDA0:

rb $B14-$
        db '<<NMSG>>'

        dw 0
        db 'R6000',13,10,'- stack overflow',13,10,0

        dw 3
        db 'R6003',13,10,'- integer divide by 0',13,10,0

        dw 9
        db 'R6009',13,10,'- not enough space for environment',13,10,0

        dw 18
        db 'R6018',13,10,'- unexpected heap error',13,10,0

        dw 20
        db 'R6020',13,10,'- unexpected QuickWin error',13,10,0

        dw 8
        db 'R6008',13,10,'- not enough space for arguments',13,10,0

        dw 21
        db 'R6021',13,10,'- no main procedure',13,10,0

        dw 252
        db 13,10,0

        dw 255
        db 'run-time error ',0

        dw 2
        db 'R6002',13,10,'- floating-point support not loaded',13,10,0


rb $4AF8-$
org Segment.2+$
Segment.2.End:

        dw 2,2,$928,1,0,2,$6B8,2,0,0,0,0
        align $20
rsrc.1: assert rsrc.1 = $114E0
        MainIcon:
                .idReserved     dw 0
                .idType         dw 1
                .idCount        dw 2

                .1.bWidth       db 32
                .1.bHeight      db 32
                .1.bColorCount  db 16
                .1.bReserved    db 0
                .1.wPlanes      dw 1
                .1.wBitCount    dw 4
                .1.dwBytesInRes dd Icon_1.End-Icon_1
                .1.nId          dw 1

                .2.bWidth       db 16
                .2.bHeight      db 16
                .2.bColorCount  db 16
                .2.bReserved    db 0
                .2.wPlanes      dw 1
                .2.wBitCount    dw 4
                .2.dwBytesInRes dd Icon_2.End-Icon_2
                .2.nId          dw 2
                align $10
rsrc.1.End:
        align $20
rsrc.5: assert rsrc.5 = $11520
        Icon_1:

        rb $2E8
        .End:
        rb 8
rsrc.5.End:
        align $20
rsrc.6: assert rsrc.6 = $11820
        Icon_2:
        rb $128
        .End:
        rb 8
rsrc.6.End:
        rb $30
GangloadEnd:
rsrc.2: assert rsrc.2 = $11980
        db 26,'Setup Initialization Error'
        db 35,'The application has been corrupted.'
        db 149,'Another copy of Setup is already running.',$A,$A,'Finish installing the other copy of the Setup program or restart Windows, then restart this copy of Setup.'
        db 58,'Setup cannot access the required initialization file ',$27,'%s',$27,'.'
        db 118,'There is insufficient memory or disk space to run Setup. The Setup program requires about %1ldkb of free disk space.',$A,$A
        db 47,'A Setup initialization file has been corrupted.'
        db 100,'There is insufficient memory to run Setup.',$A,$A,'Try closing any open applications or restarting Windows.'
        db 146,'There is insufficient disk space to run Setup. The Setup program requires about %1ldkb of free disk space.',$A,$A,'Free up some disk space and try again.'
        db 82,'Try closing any open applications, restarting Windows, or freeing some disk space.'
        db 21,'Please insert disk %s'
        db 54,'Setup cannot find the file %s.',$A,$A,'Please insert disk %s.'
        db 75,'This Setup program is not intended to be used with your version of Windows.'
        db 95,'Setup is unable to create a temporary file of size %s K for decompressing installation files.',$A,$A
        db 60,'Setup has encountered an error in the Registration Database.'
        db 0
        db 34,'Setup cannot find the file %s.',$A,$A,'%s'
        rb 4
rsrc.2.End:

rsrc.3: assert rsrc.3 = $11DE0
        db 50,'Setup cannot run without your program',$27,'s diskettes.'
        db 2,'%s'
        db 86,'Setup cannot find the files on ',$27,'%s',$27,' from which you originally installed the product.',$A,$A
        db 207,'To add/remove programs or options, run the Setup program from the CD or floppy Disk 1. If you installed from a network location, run Setup from the network location that currently contains the Setup program.'
        db 116,'The Setup configuration file ',$27,'%s',$27,' is missing or corrupted. Try running Setup again from where you originally ran it.'
        db 0
        db 20,'Insufficient memory.'
        db 26,'Setup initialization error'
        db 5,'Setup'
        rb 7
rsrc.3.End:

rsrc.4: assert rsrc.4 = $11FF0
        db $280 dup (0)
rsrc.4.End:    


May be someone have smaller NE than 75kb (I have only 1 donor), or literature where NE relocation mechanic described(I understand mechanic, but where it hided? overlapped with DosStubProc?)
Or I should explore IDA PRO loader NE.ldw - where it gets data to resolve relocations.
Post 30 Jan 2020, 22:03
View user's profile Send private message Send e-mail Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7572
Location: Kraków, Poland
Tomasz Grysztar
ProMiNick wrote:
May be someone have smaller NE than 75kb (I have only 1 donor), or literature where NE relocation mechanic described(I understand mechanic, but where it hided? overlapped with DosStubProc?)
Perhaps this might help?
Post 31 Jan 2020, 07:17
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 441
Location: Russian Federation, Sochi
ProMiNick
Thanks, looks helpful.
Post 31 Jan 2020, 08:41
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 441
Location: Russian Federation, Sochi
ProMiNick
Code:
NE_REL_TYPE_IMPORT_ORDINAL = 1
NE_REL_TYPE_IMPORT_NAME = 2
NE_REL_FARPTR = 3


macro library [name,string]
 { common
    module.references:
   forward
    if defined name#.%used & name#.%used
     name#.%libidx = 1 + ($- module.references) shr 1
     dw name
    end if
   common
    import.names:
    db 0
   forward local ..end
    if defined name#.%libidx
     label name byte at $-import.names
     db ..end-$-1,string
     ..end:
    end if }

macro import name,[labl,ord,fname]
 { common local %used
    if ~definite import.names
     .err library must precede to import
    end if
    %used = 0
   forward
    if used labl
     %used = %used + 1
     labl#.%libidx = name#.%libidx
     if fname eq
      labl#.%type = NE_REL_TYPE_IMPORT_ORDINAL
      label labl byte at ord
     else
      labl#.%type = NE_REL_TYPE_IMPORT_NAME
      local ..end
      label labl byte at $-import.names
      db ..end-$-1,fname
      ..end:
     end if
    end if
   common
    name#.%used = %used }

macro reloc statement&
 { match =call name,statement
    \{ call name-name:-1
       relocs equ relocs,NE_REL_FARPTR,name#.%type,$-4,name#.%libidx,name \}

}

macro fixup dummy,[reladdr,reltype,offs,data1,data2]
{ common local ..relstart,..relcount
   dw ..relcount
   ..relstart:
  forward
   db reladdr,reltype
   dw offs,data1,data2
  common
   ..relcount = ($-..relstart) shr 3 }


relocs equ
Segment.code:
reloc call InitTask
Segment.code.end:
fixup relocs
relocs equ

library krnl386,'KERNEL'

import krnl386,\
        InitTask,91,'INITTASK'     


fixup macro dosn`t works as expected
If I comment line "fixup relocs"
produced output
Code:
Segment.code:
$9A $FFFF $0000 ; call 0:-1
module.references:
$0001 ; import.names+1
import.names:
$00
$06 'KERNEL' ; import.names+1
$08 'INITTASK' ; import.names+8    

what wanted with fixup
Code:
Segment.code:
$9A $FFFF $0000 ; call 0:-1
$0001 ; reloc count
$03 ; reloc address = NE_REL_FARPTR
$02 ; reloc type = NE_REL_TYPE_IMPORT_NAME
$0001 ; Segment.code +1 (addr of opnd in call seg:offset)
$0001 ; Lib Index
$0008 ; Offset of funcname in import.names (import.names+8)
module.references:
$0001 ; import.names+1
import.names:
$00
$06 'KERNEL' ; import.names+1
$08 'INITTASK' ; import.names+8    
Post 06 Feb 2020, 01:27
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 441
Location: Russian Federation, Sochi
ProMiNick
I minimized context: macros below build valid imports, 2 segments code & data with correct relocations - not flexible but all as expected:
Code:
NE_RELFL_INTERNALREF    = 0
NE_RELFL_IMPORT_ORDINAL = 1
NE_RELFL_IMPORT_NAME = 2
NE_REL_FARPTR = 3
NE_REL_OFFSET16 = 5
END_RELOC_CHAIN = -1
DOS_QUIT_WITH_EXIT_CODE = $4C
MB_OK=0
RETURN_ERROR1 = 1

macro reloc instruction& {
        instruction
        match instr +++ opnd,instruction \{
        relocs equ relocs,NE_REL_OFFSET16,NE_RELFL_INTERNALREF,$-2,2,opnd \} }


macro library [name,string]
 { common
    module.references:
   forward
    if defined name#.%used & name#.%used
     name#.%libidx = 1 + ($- module.references) shr 1
     dw name
    end if
   common
    import.names:
    db 0
   forward local ..end
    if defined name#.%libidx
     label name byte at $-import.names
     db ..end-$-1,string
     ..end:
    end if }

macro import name,[labl,ord,fname]
 { common local %used
    if ~definite import.names
     .err library must precede to import
    end if
    %used = 0
   forward
    define labl#.@imported
    if used labl
     %used = %used + 1
     labl#.%libidx = name#.%libidx
     if fname eq
      labl#.%type = NE_RELFL_IMPORT_ORDINAL
      label labl byte at ord
     else
      labl#.%type = NE_RELFL_IMPORT_NAME
      local ..end
      label labl byte at $-import.names
      db ..end-$-1,fname
      ..end:
     end if
    end if
   common
    name#.%used = %used }

macro pushw value
{       match =addr var,value \{
                if +var relativeto 0 | +var relativeto $
                  reloc push    +++var
                else
                        lea     dx,[var]
                        push    dx
                end if
                pushw equ \}
        match pushw =far seg:offs,pushw value \{
                push seg
                if +offs relativeto 0 | +offs relativeto $
                  reloc push    +++offs
                else
                        lea     dx,[offs]
                        push    dx
                end if
                pushw equ \}
        match pushw =qword [var],pushw value \{
                push word [var+6]
                push word [var+4]
                push word [var+2]
                push word [var]
                pushw equ \}
        match pushw =dword [var],pushw value \{
                push word [var+2]
                push word [var]
                pushw equ \}
        match pushw,pushw \{
                push value
                pushw equ \}
        restore pushw }

macro doscall toAH*,toAL,toDX {
        if ~toAL eq
                mov     ax,toAH shl 8 + toAL
        else
                mov     ah,toAH
        end if
        if ~toDX eq
                mov     dx,toDX
        end if
        if defined REAL_MODE
                int     $21
        else
                invoke  Dos3Call
        end if }

macro invoke proc,[arg] {            ; indirectly call PASCAL procedure
 common local s$n1
        if ~ arg eq
 forward
                pushw arg
 common
        end if
        s$n1 = $+1
        match ++any,proc#.@current \{ store word (s$n1-proc#.@current) at proc#.@current \}
        proc#.@current equ ++s$n1
        match :no,proc#.@imported:proc#.@used \{ relocs equ relocs,NE_REL_FARPTR,proc#.%type,proc#.@current,proc#.%libidx,proc \}
        define proc#.@used
        call    proc-proc:END_RELOC_CHAIN }

macro fixup dummy,[reladdr,reltype,offs,data1,data2]
{ common local ..relstart,..relcount
   dw ..relcount
   ..relstart:
   if ~reladdr eq
  forward
    db reladdr,reltype
    dw offs,data1,data2
  common
   end if
   ..relcount = ($-..relstart) shr 3
   }



library krnl386,'KERNEL',\
        user,'USER'

import krnl386,\
        WaitEvent,30,'WAITEVENT',\
        InitTask,91,'INITTASK',\
        Dos3Call,102,'DOS3CALL'

import user,\
        MessageBox,1,'MESSAGEBOX',\
        InitApp,5,'INITAPP'


;segment code movable preloaded relocated DPL(3)
org 0
start:
        invoke  InitTask ; test relocation chain passed
        invoke  InitTask ;
        invoke  InitTask ;
        or      ax, ax
        jz      .err

        ;push    di ; hInstance
        ;push    si ; hPrevInstance
        ;pushw   far es:bx ; lpCmdLine
        ;push    dx ; nCmdShow
        invoke  WaitEvent, 0
        invoke  InitApp, di
        or      ax, ax
        jz      .err
        invoke  MessageBox,0,far ds:_message,far ds:_caption,MB_OK

        jmp     .exit
    .err:
        mov     al,RETURN_ERROR1
        jmp     .exit
     .exit:
        doscall DOS_QUIT_WITH_EXIT_CODE

match dummy=,relinfo,relocs { fixup ,relinfo }
relocs equ ()


;segment data movable preloaded DPL(3)
org 0
  _caption db 'Win16 assembly program',0
  _message db 'Hello World!',0     
Post 15 Feb 2020, 11:54
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar.

Powered by rwasa.