porting win16 masm code to win32 masm code 
Author Message
 porting win16 masm code to win32 masm code

Has anyone here ported any Win16 masm programs to win32 ?
I have 25,000 lines (comments included) of win16 masm code
that I would love to get working as a win32 program.  Unfortunately,
this code does extensively use segment registers and masm macros.

If so, do you have any words of advice (other than don't bother,
it is too difficult) ?  Or, would you recommend translating the masm
code to c instead (got a converter ?) ?

I did try masm2c http://www.*-*-*.com/
it did not handle masm macros which extensively used in the source
code.  I can provide some of the source code if necessary.

Thanks,
Lynn



Sat, 25 Dec 2004 12:35:43 GMT  
 porting win16 masm code to win32 masm code

Quote:

> Has anyone here ported any Win16 masm programs to win32 ?

Minor things, on occasion...

Quote:
> I have 25,000 lines (comments included) of win16 masm code
> that I would love to get working as a win32 program.  Unfortunately,
> this code does extensively use segment registers and masm macros.

Unfortunately, this is the underlying problem with any sort of
conversion...more things than just the register size changed as things
went 32-bit...the whole paradigm changed so that some of the previous
methods of going about things have been totally invalidated and
require often vastly different solutions...

Although, if you mean the 16-bit Windows (Win3.x and stuff :) by
"Win16" rather than DOS, it's not quite so bad because then at least
you're in the correct event-driven, calling API functions
mindset...and the Win32 API is essentially a superset of the API used
for Win16...but, even then, most of the data types altered in size,
which could prove a pain to convert (not just all the "ax -> eax" but,
also, in some cases, things are still logically 16-bit even though
they are in 32-bit quantities...e.g. WPARAM was upgraded to a 32-bit
value but many of the message values are still inherently 16-bit so
you not only have to "upgrade" the size but have to add truncation
back down to only 16-bits again)...

Quote:
> If so, do you have any words of advice (other than don't bother,
> it is too difficult)?

Well, generally, it's not that it's "too difficult", it's more that
it's "intensely tedious and very time-consuming"...often to the point
where it's easier to just recode it but using the original program as
a template...which, generally speaking, tends to be the best approach
(although, your specific code might be okay but, without seeing it, I
have to give the generic advice instead :)...

Also, _why_ do you want to convert this Win16 code to Win32? Windows
should still be perfectly capable of executing the old Win16 code
(and, where it can't, we have a compatibility problem that any sort of
automatic translation of the code won't fix without help, anyway
:)...is it just the case that it has to be translated at some point,
so now is as good a time as any or are you expecting an increase in
performance or something? But if translated too literally - mapped
directly across - then improvements probably won't be all that amazing
(much like directly translating C code into ASM doesn't necessarily
improve it at all unless you start applying some "ASM thinking" to the
problem :)...saying goodbye to segment registers will be good and
speed things up but, otherwise, there's probably little to gain
because most of the time will be spent inside API functions, anyway...

Quote:
> Or, would you recommend translating the masm
> code to c instead (got a converter ?) ?

This _could_ be a nice solution, _if_ you could get it somewhat easily
translated to C...but that is rarely a clear-cut matter because C ->
ASM (compiling :) is inherently very much a one-way process and
reversing it automatically tends not to work too well...worse still if
this code was coded in MASM32 and never been anywhere near C because,
basically, there are many, many things completely possible in ASM that
are simply _impossible_ to express in C...and, even when an automated
tool can manage to process something, it'll tend to produce very ugly
C code that'll need a lot of cleaning up...

Quote:
> I did try masm2c http://www.*-*-*.com/
> it did not handle masm macros which extensively used in the source
> code.

Yes; The basic problem is that ASM and C often think in completely
different ways...and go about things in a different mindset...this is
often hard for even a human to reasonably translate and we have the
distinct advantage of being able to think things through...machines
just follow rules and when something is this much different, there are
too many complex rules...it's theoretically achievable to do much of
this stuff but, in practice, creating tools to do it all automatically
is just too much hard work...

As I say, generally speaking, the approach that works best is to
recode using the original as a "template" (so you're only "upgrading"
it, really, and not completely starting it all from scratch
:)...although, in your case, 25,000 lines is a lot to be doing
manually...in which case, any tool help at all - even {*filter*}tool help -
would be welcomed...

Quote:
> I can provide some of the source code if necessary.

Perhaps a short snippet just to get a feel of what's involved may help
refine the advice...although, perhaps more useful is more of an idea
of the overall structure of the program because, with 25,000 lines,
it's unlikely any short snippet of the code would cover and illustrate
the whole thing...I don't know, you know the program, what do you
reckon would be the most revealing thing to do?

Beth :)



Sun, 26 Dec 2004 01:20:15 GMT  
 porting win16 masm code to win32 masm code
Hi Beth,

Thanks for the long thought out answer.  BTW, this Win16 asm
code is the old Whitewater Actor windows programming
environment.  It is an Forth program with Object Oriented
extensions for compiling and interpreting a typeless, garbage
collected child of Smalltalk and Pascal.

Quote:
> Also, _why_ do you want to convert this Win16 code to Win32? Windows
> should still be perfectly capable of executing the old Win16 code
> (and, where it can't, we have a compatibility problem that any sort of
> automatic translation of the code won't fix without help, anyway
> :)...is it just the case that it has to be translated at some point,
> so now is as good a time as any or are you expecting an increase in
> performance or something? But if translated too literally - mapped
> directly across - then improvements probably won't be all that amazing
> (much like directly translating C code into ASM doesn't necessarily
> improve it at all unless you start applying some "ASM thinking" to the
> problem :)...saying goodbye to segment registers will be good and
> speed things up but, otherwise, there's probably little to gain
> because most of the time will be spent inside API functions, anyway...

I have reached the max of internal variable space that the Win16
model will handle.  I just need more space than the 64K addresses
per segment that can be realized right now.

Here is the Window Procedure code:

  PAGE ,132

 TITLE Kernel for ACTOR

 .xlist
.286

?WINPROLOGUE = 1

 include win.inc
 include arecs.inc
if1
 include amacros.inc
endif
 .list

;--------------------------------------
; Actor/PC register model:

; SI = IP Threaded instruction pointer
; DI = OP holds the object ptr fetched at IP by NEXT
; SP = SP System stack ptr
; BP = BP Ptr to stack frame base in a high-level function
; CS = CP Ptr to base of family jump table, primitive segment
; ES = OT Object table ptr
; DS = SG Segment of current object

; Start of DATA segment.

_DATA SEGMENT DWORD PUBLIC 'DATA'
DGROUP GROUP _DATA

 extern _hprevinst:word,s_defWndProc:word,codeSelTbl:word
 extern CurrentWindow:word,windproc:word,s_wProcNotify:word
 extern transmsg:word,tagswitch:word,s_exception:word
 extern sysglobals_dat:word
 extern as_symbols_dat:word
 extern WindowsVersion:word,s_translatemsg:word,SelTbl:word,toseg:word
 extern start:word,sp0:word,bp0:word,hInstance_dat:word,cshow_dat:word
 extern cbFunc_dat:word,lpWFunc_dat:word,wmsg_dict:word,wunnest:word
 extern lpDFunc_dat:word,string_put:word,object_at:word
 extern block_ctxt_eval:word,string_repl:word,s_error:word,s_fail:word
 extern s_getIVFail:word,s_setIVFail:word,VMInterrupt:word
 extern otfree:word,awork:byte,aStack:word
 extern aStack_bot:word,argTypes:word,winDisp:word
 extern s_data:word,s_fill:word,s_ivar:word,s_longdata:word
 extern OCIndex:word,OCValue:word,OCType:word
 extern actProp:byte
 extern act_sp:word,act_bp:word,error_state:word
 extern otfree:word,awork:byte,aStack:word,wind_sp:word,wind_bp:word
 extern tabseg:word
 extern st_mark:word  ; marks top of last frame for scavenge
 extern st_base:word
 extern JMPTBL:word
 extern Long:word
 extern as_userMessages_dat:word
 extern s_at:word
 extern System:abs,pDLL:abs,cDLL:abs,wcall:abs
 extern last_prim:word
 extern block_ctxt:abs,mdict:abs

; ------------------------------------
; stack for Windows->Actor activations
wcall_stack dd wcall_maxDepth dup(0)
public wcall_stack
wcall_tos dw 0  ; activation stack ptr
public wcall_tos
; ------------------------------------
; stack for Actor->Windows relocation information
wFrame_stack dw 80 dup(0) ; room for 16 levels
public wFrame_stack
wFrame_tos dw 0
public wFrame_tos
; ------------------------------------

; DLL access variables
dll_maxdepth = 16
dll_offs dw 0
dll_seg  dw 0
dll_func dw 0
dll_stack dw dll_maxdepth dup(0)
dll_TOS  dw offset dll_stack ;must be right after dll_stack
public dll_TOS, dll_stack

_DATA ENDS

die  PROTO  PASCAL
mfind  PROTO  PASCAL
MakeNum  PROTO  PASCAL
MakeLong PROTO  PASCAL
DoDatPDBXBX PROTO PASCAL
DoDatPDDIBX PROTO PASCAL
DoDatPDDIDI PROTO PASCAL
DoDatPEDIDI PROTO PASCAL

_TEXT SEGMENT WORD PUBLIC 'CODE'

 Assume DS:_DATA
 Assume SS:_DATA

; extern  Dispatch:near
; extern  VBRegisterModel:near
 extern pushobj_code:near,var_code:near,unnest_code:near
 extern integer_add_code:near,integer_sub_code:near
 extern integer_lt_code:near,integer_gt_code:near,integer_eq_code:near
 extern integer_ne_code:near,integer_mul_code:near
 extern integer_div_code:near,integer_mod_code:near
 extern stchk:near
 extern signal:near
 extern NativeOBMove:far
 extern NetBIOSCall:far
 extern perf1_code:near
 extern perf1_code:near,perf4_code:near
 extern fnest:near

; ------------------------------------------
; Is there an entry in UserMessages for this message ID?
; IN:  message parameter
;      DI == UserMessages Dictionary OP
; OUT: DI == nil if no entry, Symbol OP if there is an entry.
; ------------------------------------------
UserMessage PROC NEAR PASCAL PRIVATE USES  si ds, mssg:word

 mov ax,mssg
 mov cx,di

; save the windows stack pointer
 mov [wind_sp],sp
 mov [wind_bp],bp

; switch to the actor stack.
 mov sp,[act_sp]
 mov bp,[act_bp]

; assume that DI holds a dictionary
; send a message to get the symbol
 mark
 xor dx,dx
 Invoke MakeNum
 push di   ; argument for at message
 mov ax,offset s_at
 push ax
 push cx   ; dictionary OP
 mov ax,cs
 mov ds,ax
 lea si,um1   ; point DS:SI to unnest OP

 jmp perf1_code  ; "nest" into function

; return after after de-nest, DI contains result - we're done!
 align ;4
um1:
 dw wunnest

; restore Windows stack pointer
 mov sp,ss:[wind_sp]
 mov bp,ss:[wind_bp]

UMexit:
 ret
UserMessage ENDP

; ------------------------------------------
; The Window function for the main Actor window.
; ------------------------------------------
HelloWndProc PROC FAR PASCAL PUBLIC USES si di,
  hWindow:HWND, msgID:word, wParm:WPARAM, lParm:LPARAM
 LOCAL defProc:word, wf_rcvr:word, defWndProc:word

 mov defProc,0
 mov defWndProc,0
 mov ax,msgID  ;Convert message number to a symbol OP
 shl ax,1   ;Convert to an Int
 inc ax
 mov di,offset wmsg_dict ;WMessages
 call mfind
 or di,di   ;Message in WMessages?
 jnz wndp3
 mov di,offset as_userMessages_dat ;Does UserMessages exist?
 mov di,[di+2]
 or di,di
 jz wndp3
 Invoke UserMessage, msgID ;Message in UserMessages? (DI is dict)
wndp3:     ;DI == message symbol OR nil
; get the window OP into AX (from property)
 Invoke GetProp, hWindow, ADDR actProp
 or ax,ax   ;Is there a property yet?
 jnz wndp2
 cmp msgID,WM_NCCREATE ;WM_NCCREATE message?

 cmp msgID,WM_INITDIALOG ;WM_INITDIALOG message?

 mov ax,[CurrentWindow] ;AX == window OP (from hi-level create)
 or ax,ax
 xjz wmsg_nf   ;No window OP, do def proc
 push di
; Set the property to the window OP
 Invoke SetProp, hWindow, ADDR actProp, [CurrentWindow]
 mov ax,hWindow  ;Store handle in hWind IVar (IVar 0)
 sub dx,dx
 Invoke MakeLong  ;Store it in a Long - DI
 push di   ;Save the Long OP
 mov ax,[CurrentWindow] ;Get window OP in AX
 mov di,ax   ;Address the Window object
 DatPDDIBX   ;  InvokeeLong must be before this)
 pop di   ;Restore the Long OP
 mov word ptr[bx],di  ;Store handle in ivar
 mov ss:[CurrentWindow],0 ;put nil into CurrentWindow
 pop di
wndp2:  ;Given the window OP and symbol, find the method
  ;Note: DI may be nil, so check and skip look-up if so.
 mov wf_rcvr,ax  ;Save the receiver
 xchg di,ax   ;DI==window OP,AX==symbol
 DatPDDIBX   ;Receiver data
 mov cx,2[bx]  ;Get the defProc (IVar 1)
 mov defProc,cx
 cmp ss:[error_state],0 ;If in error state, don't go into
 xjnz wmsg_nf   ;Actor - execute DefWindowProc
 cmp ss:[windproc],1  ;wProc notification enabled?
 xjb wndp13


 push di   ;Window OP
 push ax   ;Symbol
 mov dx,ax   ;Save symbol in DX
 mov bx,ss
 mov ds,bx
 mov bx,bp   ;Point to windows stack with SS:BX
 mov [wind_sp],sp  ;Save the Windows stack
 mov [wind_bp],bp
 mov sp,[act_sp]  ;Use the Actor stack
 mov bp,[act_bp]
 wcPush
 mark

; Set up to send wProcNotify(System, window, messageSymorID, wP, lP)
 push di   ;Window - arg1
 mov di,dx   ;Symbol OP
 or dx,dx

 mov ax,word ptr[bx+0ch] ;Message ID
 sub dx,dx

 push di   ;Arg2
 mark
 mov ax,word ptr[bx+0ah] ;wParam is a word (unsigned)
 sub dx,dx
 Invoke MakeNum
 push di   ;Arg 3
 mark
 mov ax,word ptr[bx+6] ;lParam is a Long (signed or unsigned)
 mov dx,word ptr[bx+8]
 Invoke MakeLong
 push di   ;Arg 4
 mov ax,offset s_wProcNotify ;Message symbol
 push ax
 mov ax,offset System ;Send to system class
 push ax
 mov si,cs   ;DS:SI -> wunnest for return
 mov ds,si

 jmp perf4_code  ;Send high-level message

 dw wunnest
 wcPop    ;Switch from Actor to Windows stack
 cmp di,1   ;Check action value (nil, 0, other)
 pop ax   ;Message symbol
 pop di   ;Window OP

 xje wmsg_nf   ;Do default proc
 xor ax,ax   ;Do nothing
 xor dx,dx

 DatPDDIBX   ;Re-address the window object for below

; ---------------------------------------
; now look up the symbol in the window's superclass chain
; Also look for a "defWndProc" method, if message not found.
wndp13:
 mov di,word ptr[bx+ClassOffs] ;Class OP
 or ax,ax   ;Is message supported?
 jnz wmsg1
 cmp defProc,0  ;Is there a defProc ?
 xjne wmsg_proc  ;Yes, CallWindowProc
wmsg1:
 DatPDDIBX   ;Get data ptr to class
 mov dx,[bx+ClassOffs].CLASS_DEF.ancest ;Save superclass OP
 mov di,[bx+ClassOffs].CLASS_DEF.methods ;Get OP of dictionary
 or di,di
 jz wmsg_super  ;No method dictionary
wmsg2:
 call mfind   ;Look up the method
 or di,di   ;Was a method found?
 jnz wmsg3   ;Yes, nest into it
 cmp defWndProc,0  ;Already found?
 jne wmsg_super  ;Yes, stop looking
 push ax   ;Save msg sym
 mov ax,offset s_defWndProc
 mov
...

read more »



Sun, 26 Dec 2004 04:22:39 GMT  
 porting win16 masm code to win32 masm code
BTW, here is some of the macro code:

;
; Constants, Records, and structures for the Actor kernel
;
; Object related constants
HdrSize   equ 4  ; 4 byte object header
ClassOffs  equ -4  ; class is 4 bytes back
SizeOffs  equ -2  ; size is 2 bytes back
OPSize   equ 2  ; 16-bit OPs

;Actor Stack constants
ArgSize   equ 2  ; for 16-bit system
      ; will be 4 for 32-bit
      ; OPs or Win32
; Object Table constants
EntrySize  equ size OTENTRY  ; 4 byte entry per object

; The scavenge list size
scsize   equ 512

; object swapping defines
swappedIndex  equ 48

;Virtual Interrupt constants
;CompactInterrupt equ 1
;AgeInterrupt  equ 2
BreakInterrupt  equ 4

; bits in SwapFlags needed by other modules
;CallMakesDirty  equ 4000H ; force objects passed to be dirty
;Swapping  equ 400H ; we are swapping with a swap file

; String table constants
IDSNAME   equ 100
IDSABOUT  equ 200
IDSTITLE  equ 300
IDSAPP   equ 500

; Window messages
WM_NCCREATE  equ 81h
WM_INITDIALOG  equ 110h

; Windows memory management call parameters
LMEM_FIXED  equ 0
LMEM_MOVEABLE  equ 2
LMEM_ZEROINIT  equ 64
GMEM_FIXED  equ 0
GMEM_MOVEABLE  equ 2
GMEM_ZEROINIT  equ 64
OF_SHARE_DENY_WRITE equ 0020h

; primitive error codes
ec_div   equ 1 ; divide by 0
ec_bnds   equ 2 ; indexed object bounds exception
ec_idxarg  equ 5 ; index argument was not an Int
ec_nsize  equ 7 ; bad size to new
ec_gmem   equ 8 ; couldn't allocate global memory
ec_static  equ 10 ; static region is full
ec_blk   equ 16 ; wrong #args at block invocation
ec_intch  equ 20 ; integer value out of char range
ec_args   equ 21 ; wrong # of args for function
ec_argtype  equ 22 ; incorrect primitive argument type
ec_copyfrom  equ 27 ; range error in copyFrom primitive
ec_winarg  equ 32 ; can't convert to windows short arg
ec_lasint  equ 33 ; Long too large for Int conversion
ec_mungrange  equ 36 ; bad range input to munger
ec_nilrcvr  equ 40 ; primitive receiver was nil
ec_ctxbad  equ 45 ; invalid home context local access

; Offsets for Family jump table contained in _DATA.
; Offset is relative to JMPTBL, the start of the Jump offsets
FNOFF   equ 0
FOOFF   equ 4
JIOFF   equ 8
VCOFF   equ 12
F00OFF   equ 16
F10OFF   equ 20
F20OFF   equ 24
UCOFF   equ 28

; Mask used to test an OP to see if it is a Char
charMask  equ 0fc03h

; Windows call stack constants
wcall_maxDepth = 16
wcall_maxOffs = wcall_maxDepth * 4

; error string ids for resource file (these are technically defined as offsets)
emem_str = 152
escav_str = 154
eot_str  = 155
esnap_str = 156
ersnap_str = 157
estart_str = 158
sn_stat_str = 161
sn_dyn_str = 162
ewcovfl_str = 164
ewcufl_str = 165
estk_str = 166
ecnil_str = 167
estab_str = 168
actfr_str = 170
swapfull_str = 172
inswapde_str = 173
outswapde_str = 174
inswapst_str = 175

;---------------------------------------
; Structure definitions for various objects
;---------------------------------------
; Object format for classes
CLASS_DEF STRUC
class_ptr dw 0
class_size dw 0
ancest  dw 0
methods  dw 0
ivars  dw 0
class_format dw format_fld <>
CLASS_DEF ENDS

; Stack frame for function invocation
FRAME  STRUC
rcvr  dw 0
rtrn  dd 0
func_op  dw 0
link  dw 0
numtmps  dw 0
tmpz  dw 0
FRAME  ENDS

; define block context object
CTXT_DEF STRUC
home_vars dw 0  ; Int addr of home context var base
home_offs dw 0  ; offset from home function
home_func dw 0  ; OP of home function
argcnt  dw 0  ; args expected by block
locCnt  dw 0  ; locals used by block
blk_rcvr dw 0  ; receiver of home function
block1_bp dw 0  ; stack address of 1st enclosing blk
block2_bp dw 0  ; stack address of 2nd enclosing blk
CTXT_DEF ENDS

; Object table entry
OTENTRY  STRUC
offsbyt  db ?
statbyt  db ? ; Status: family code,etc.  See STATUS_FLD
datwd  dw ? ; Offset of primitive from CS or obj segment
OTENTRY  ENDS

; doubleword integer format
dblword  STRUC
loword  dw 0
hiword  dw 0
dblword  ENDS

; relocation information for Windows calls
WFRAME  STRUC
wf_func  dw 0
wf_si  dw 0
wf_ds  dw 0
wf_offs  dw 0
wf_seg  dw 0
WFRAME  ENDS

;--------------------------------------
; Record definitions for bit fields
;--------------------------------------
; Argument descriptor byte in Function hdr
arg_fld  RECORD aNUM_TEMPS:4,aNUM_LOCS:4,arg_onbit:1=1
ARG_descrip RECORD NUM_TEMPS:4,NUM_LOCS:4

; Status byte of OT entry (word 0, byte 1 - bits from highest to lowest)
; bit 7: 0=dynamic, 1=static
; bit 6: if dynamic, dynamic space #
;  if static, 0=runtime static, 1=compile time static
; bit 5: 0=even length, 1=odd length
; bit 2-4: Family code:
;   0:
;   1:
;   2:
;   3:
;   4:
;   5:
;   6:
;   7:
; bit 1: 0=normal, 1=tagged for change notification
; bit 0: 0=non-pointer object, 1=pointer object
STATUS_FLD RECORD static:1,tosp:1,oddlen:1,fam:3,reg:1=0,inst_ptrs:1=0

; Segment byte of OT entry (word 0, byte 0 - bits from highest to lowest)
; bit 7: 0/1=not touched/touched since last GC sweep
; bit 1-6: Segment index
; bit 0: 0/1=has/doesn't have instance variables
OFFS_FLD RECORD touched:1,seg_bits:6,has_ivars:1

; Offset word of OT entry (word 1 - bits from highest to lowest)
; bit 2-15: Data offset / 4 (offset used is whole word with bits 0-1=00)
; bit 1: 0=normal, 1=Scavenge list member
; bit 0: 0=Evac Region, 1=New Region
OFFSET_WORD RECORD offset_bits:14=0,scavl:1=0,gcRegion:1=0

; Class format WORD
; bit 15: 0/1=instances are non-pointer/pointer objects
; bit 14: 0/1=static/variable length
; bit 13: 0/1=create as dynamic/static object
; bit 12: 0=byte oriented, 1=word oriented (not used if bit 15 is on)
; bit 11: Not Used
; bit 1-10: Number of instance variables
; bit 0: Always set to 1 so that this is an Actor Int
FORMAT_FLD RECORD cl_ptrs:1=1,VARBL:1=0,PERM:1=0,wrds:1=1,fjunk:1=0,IVCNT:10=0,ONBIT:1=1

;
; Macros for the Actor kernel
;

;-------------------------------
; NEXT is the instruction sequencer for the inner interpreter
;-------------------------------
next MACRO
 local l1
 lodsw
 mov di,ax
 and di,2
 mov es,ss:[tabseg+di]
 mov di,ax
 cmp ax,offset last_prim
 jae short l1
 jmp es:[di].datwd
l1: mov  bl,es:[di].statbyt
 and bx,mask fam
 jmp ss:[bx] + JMPTBL
ENDM

mark MACRO
 mov ss:[st_mark],sp
 mov ss:[st_base],bp
ENDM

; mark an already indexed swapping static object as changed
; ES assumed set for "op"
setDirty MACRO op
 local l1
 test byte ptr es:[op].statbyt,mask static
 jz l1
 or word ptr es:[op].datwd,mask gcRegion
l1:
ENDM

; change from Actor to windows stack
xWStack MACRO
 local lab0,lab1
 pushf
 cmp sp,offset aStack_bot ; check for already on wstack
 ja lab0
 popf
 mov ss:[act_sp],sp
 mov ss:[act_bp],bp
 mov sp,ss:[wind_sp]
 mov bp,ss:[wind_bp]
 jmp short lab1
lab0: popf
lab1:
ENDM

xAStack MACRO
 local lab0,lab1
 pushf
 cmp sp,offset aStack_bot
 jb lab0
 popf
 mov sp,ss:[act_sp]
 mov bp,ss:[act_bp]
 jmp short lab1
lab0: popf
lab1:
ENDM

ckIdx MACRO narg
 local lab0
ifndef  run_flag
 test word ptr ss:[bx+&narg],1
 jnz lab0
 mov ax,ec_idxarg
 jmp idx_Err
lab0:
endif
ENDM

; once this works, can be re-written to use less space
; jfl 10-27-88
markIdx MACRO args
ifndef  run_flag
 mov ax,ds   ; save incoming DS
 mov ss:[idx_caller],di
 mov ss:[idx_args],(&args*2)
 mov ss:[idx_dseg],ax  ; incoming DS
 mov ss:[idx_ip],si
 mov bx,sp
 mov cx,ss:[bx]
 mov ss:[idx_rcvr],cx
if args EQ 1
 mov cx,ss:[bx+2]
 mov ss:[idx_arg0],cx
 mov cx,bx
 add cx,4
 mov ss:[idx_tos],cx  ; set safe place to build frame
endif
if args EQ 2
 mov cx,ss:[bx+4]
 mov ss:[idx_arg0],cx
 mov cx,ss:[bx+2]
 mov ss:[idx_arg1],cx
 mov cx,bx
 add cx,6
 mov ss:[idx_tos],cx  ; set safe place to build frame
endif
if args EQ 3
 mov cx,ss:[bx+6]
 mov ss:[idx_arg0],cx
 mov cx,ss:[bx+4]
 mov ss:[idx_arg1],cx
 mov cx,ss:[bx+2]
 mov ss:[idx_arg2],cx
 mov cx,bx
 add cx,8
 mov ss:[idx_tos],cx  ; set safe place to build frame
endif
if args EQ 4
 mov cx,ss:[bx+8]
 mov ss:[idx_arg0],cx
 mov cx,ss:[bx+6]
 mov ss:[idx_arg1],cx
 mov cx,ss:[bx+4]
 mov ss:[idx_arg2],cx
 mov cx,ss:[bx+2]
 mov ss:[idx_arg3],cx
 mov cx,bx
 add cx,10
 mov ss:[idx_tos],cx  ; set safe place to build frame
endif
if args EQ 5
 mov cx,ss:[bx+10]
 mov ss:[idx_arg0],cx
 mov cx,ss:[bx+8]
 mov ss:[idx_arg1],cx
 mov cx,ss:[bx+6]
 mov ss:[idx_arg2],cx
 mov cx,ss:[bx+4]
 mov ss:[idx_arg3],cx
 mov cx,ss:[bx+2]
 mov ss:[idx_arg4],cx
 mov cx,bx
 add cx,12
 mov ss:[idx_tos],cx  ; set safe place to build frame
endif
endif
ENDM

;Check the receiver for nil, leave the receiver in DI
;Uses DI,BX if it doesn't fail.
ckNil MACRO args
 local notNil
ifdef  run_flag
 pop di  ;receiver
else
 mov bx,di  ;op of primitive
 pop di  ;receiver
 or di,di
 jnz notNil
if args EQ 0
 push di  ;#arg bytes
else
 mov ax,args+args ;#arg bytes
 push ax
endif
 mov ax,ec_nilRcvr
 jmp signal
notNil:
endif
ENDM

sys MACRO name
name&_code:
public name&_code
ENDM

prim MACRO name,isbnd,args,fail_code
 arg_fld <args,0>
name&_code label word
public name&_code
ENDM

fprim MACRO name,isbnd,args,fail_code
_DATA segment dword PUBLIC 'DATA'
name&_f dw 0 ; for fail func
public name&_f
_DATA ends
 dw offset DGROUP:name&_f
 arg_fld <args,0>
name&_code label word
public name&_code
ENDM

; push an activation of actor
wcPush MACRO
 local wcpsh1
 mov ax,bx   ; save BX
 mov bx,[wcall_tos]
 cmp bx,wcall_maxOffs
 jb wcpsh1
        mov dx, offset ewcovfl_str
 call die
wcpsh1: mov word ptr [bx+wcall_stack],sp
 mov word ptr [bx+wcall_stack+2],bp
 add [wcall_tos],4
 mov bx,ax
ENDM

wcPop MACRO
 local wcpop1
 mov ax,ss
 mov ds,ax
 sub [wcall_tos],4
 jns wcpop1
 mov dx,offset ewcufl_str
 call die
wcpop1: mov bx,[wcall_tos]
 mov ax,word ptr [bx+wcall_stack]
 mov [act_sp],ax
 mov ax,word ptr [bx+wcall_stack+2]
 mov [act_bp],ax
 mov sp,[wind_sp]
 mov bp,[wind_bp]
ENDM

; push two byte values as proper op's
; all regs preserved, tmphigh must be high part of tmpword
; USES: spsave1 == temporary to save AX
; bpsave1 == temporary to split src into 2 bytes
push2bytes MACRO src
 mov word ptr ss:[spsave1],AX
 mov word ptr ss:[bpsave1],src
 mov AX,1
 mov AH,byte ptr ss:[bpsave1]
 push AX
 mov AH,byte ptr ss:[bpsave1+1]
 push AX
 mov AX,word ptr ss:[spsave1]
ENDM

; ...

read more »



Mon, 27 Dec 2004 00:09:29 GMT  
 porting win16 masm code to win32 masm code
Quote:

> BTW, here is some of the macro code:
> ;
> ; Constants, Records, and structures for the Actor kernel
> ;
> ; Object related constants
> HdrSize   equ 4  ; 4 byte object header
> ClassOffs  equ -4  ; class is 4 bytes back
> SizeOffs  equ -2  ; size is 2 bytes back
> OPSize   equ 2  ; 16-bit OPs

> ;Actor Stack constants
> ArgSize   equ 2  ; for 16-bit system
>       ; will be 4 for 32-bit
>       ; OPs or Win32
> ; Object Table constants
> EntrySize  equ size OTENTRY  ; 4 byte entry per object
[ snip ]
> ;---------------------------------------
> ; Structure definitions for various objects
> ;---------------------------------------
> ; Object format for classes
> CLASS_DEF STRUC
> class_ptr dw 0
> class_size dw 0
> ancest  dw 0
> methods  dw 0
> ivars  dw 0
> class_format dw format_fld <>
> CLASS_DEF ENDS
[ snip ]
> ;--------------------------------------
> ; Record definitions for bit fields
> ;--------------------------------------
> ; Argument descriptor byte in Function hdr
> arg_fld  RECORD aNUM_TEMPS:4,aNUM_LOCS:4,arg_onbit:1=1
> ARG_descrip RECORD NUM_TEMPS:4,NUM_LOCS:4

> ; Status byte of OT entry (word 0, byte 1 - bits from highest to
lowest)
> ; bit 7: 0=dynamic, 1=static
> ; bit 6: if dynamic, dynamic space #
> ;  if static, 0=runtime static, 1=compile time static
> ; bit 5: 0=even length, 1=odd length
> ; bit 2-4: Family code:
> ;   0:
> ;   1:
> ;   2:
> ;   3:
> ;   4:
> ;   5:
> ;   6:
> ;   7:
> ; bit 1: 0=normal, 1=tagged for change notification
> ; bit 0: 0=non-pointer object, 1=pointer object
> STATUS_FLD RECORD

static:1,tosp:1,oddlen:1,fam:3,reg:1=0,inst_ptrs:1=0
[ snip ]

Up to this point, it's actually quite easily translated because it's
all 1:1 with similar structures in C/C++...e.g. "equ" -> "#define",
"struc" -> "typedef struct{};" and that sort of thing...

From here on, though, things aren't quite so easy because the two
languages basically "think differently" about macros and instructions,
and we lose the 1:1 thing...

- Show quoted text -

Quote:
> ; Macros for the Actor kernel

> ;-------------------------------
> ; NEXT is the instruction sequencer for the inner interpreter
> ;-------------------------------
> next MACRO
>  local l1
>  lodsw
>  mov di,ax
>  and di,2
>  mov es,ss:[tabseg+di]
>  mov di,ax
>  cmp ax,offset last_prim
>  jae short l1
>  jmp es:[di].datwd
> l1: mov  bl,es:[di].statbyt
>  and bx,mask fam
>  jmp ss:[bx] + JMPTBL
> ENDM
[ snip ]
> ckIdx MACRO narg
>  local lab0
> ifndef  run_flag
>  test word ptr ss:[bx+&narg],1
>  jnz lab0
>  mov ax,ec_idxarg
>  jmp idx_Err
> lab0:
> endif
> ENDM

> ; once this works, can be re-written to use less space
> ; jfl 10-27-88

hehehe...the old "comment of good intention that never sees fruition"
thing...a bit like the "reserved for future expansion" fields in the
DOS MZ header now that Microsoft have abandoned furthering DOS ;)...

[ snip ]

Yeah, you're right...they've gone "macro crazy" here...there's a macro
for every day in the year...and a leap year at that! hehehe ;)

Beth :)



Wed, 29 Dec 2004 00:54:01 GMT  
 porting win16 masm code to win32 masm code

Quote:
> Btw, where did you get this source code from? I doubt I could actually
> think of anything Earth-shatteringly useful to you...but I wouldn't
> say no to looking over the source code more thoroughly, if it's some
> sort of a download off a webpage or something...maybe one section is
> more easily done than another or something :)

The current copyright owner emailed the code to me a couple of years
ago. He also gave me the right to give a copy of it to anyone that I
want to.

If you want, I can put it up for you on my website.  Warning, it gets
nastier that deeper it gets (and it is 11 MB).  Just send a private email to

Thanks,
Lynn



Wed, 29 Dec 2004 01:25:44 GMT  
 porting win16 masm code to win32 masm code

Quote:
> Yeah, you're right...they've gone "macro crazy" here...there's a macro
> for every day in the year...and a leap year at that! hehehe ;)

The real problem is that they put code in for jumping segments
all over the place.  That code is very obtuse and is not needed
anymore in Win32.  However, I hesitate to place it into the code
because the code will swell greatly.

Thanks,
Lynn



Wed, 29 Dec 2004 01:30:31 GMT  
 
 [ 11 post ] 

 Relevant Pages 

1. translate code in TASM format to MASM format

2. MASM .Code

3. Is it possible to mix 16bit and 32bit code together in MASM

4. infrared control with parallel interface using MASM code-help me please

5. MASM 6.11 - Can I assemble raw code?

6. MASM coding

7. Sample MASM Code - For those who are interested.

8. Trying to make writeable code section in MASM with segment directives

9. translate code in TASM format to MASM format

10. Help with MASM/TASM 32bit code

11. Mixing 32 and 16 bits code with MASM 6.14

12. Compiling assemby code from DVF with MASM

 

 
Powered by phpBB® Forum Software