home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
PCACHSRC.ZIP
/
OBJECT.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-05-08
|
7KB
|
215 lines
;exe format. demonstrates OOP. B.Kauler 1991
;Note that this listing is very cluttered with comments and suggestions.
;after basically digesting them you might like to erase them, to be
;able to more clearly see the overall program.
;
;...................................................
stack1 SEGMENT stack 'stack'
db 128 DUP(0)
stack1 ENDS
;...................................................
data SEGMENT 'data'
; ......
;The structure SHAPES contains "variables" and also
;pointers to methods -- but note that we cannot specify the
;the address of a method, as MASM will not accept a forward
;reference from within a STRUC.
;(A solutiion is to put the STRUC definitions after the code is
; assembled, but that introduces other problems).
;The STRUC definition below is only used by Asm -- it is the
;instances that are actually assembled (BOX1, BOX2). When
;defining the instances we can initialise the fields, including
;insertion of the procedure addresses for each method.
;(Note that in the case of dynamically allocated objects, the
; pointers would have to be inserted by code, and if they are
; far pointers then the structure would have to use DD).
;Note that TASM allows nested STRUCs and MASM doesn't. The definition
;of BOX below shows the case for TASM, which is conceptually neater.
;the comment alongside shows what you would have to replace it with
;for MASM. Either way, there is a problem when you come to declare
;instances, as you cannot initialise the fields inherited from SHAPE
;(only the first field). Whatever fields have been declared in BOX
;can be initialised (in this case there's just one; ROUNDED).
;hence the rather messy macro (that I've called "instance_box").
;Note also that TASM has an "ideal mode" in which structure field-
;labels are local to that structure, thus allowing other structures
;to have identical labels -- which is what we ideally want for OOP --
;but the NOW override no longer works -- perhaps someone can find a
;fix for this. At the moment, structure field-labels are global.
SHAPES STRUC
REDRAW DW ? ;dummy pointer. **see below
VERT DB 5
HORIZ DB 10
SYZE DW ? ;near pointer to SIZE_SHAPES **see below
ROW DB 0
COL DB 0
PLACE DW ? ;near pointer to PLACE_SHAPES **see below
SHAPES ENDS
;** the pointers would have to be Define
;Doubleword (DD) if program has multiple
;code segments.
; .......
BOX STRUC
SHAPES <> ;TASM only. MASM; replace with (SIZE SHAPES) DUP(?)
ROUNDED DB 0
BOX ENDS
; .....
;macro to create instance of BOX, with data initialisations....
;(messy, due to limitations of Asm -- have to create an instance of BOX
; then overwrite part of it with an instance of SHAPES)
MAKE_BOX MACRO ibox
ibox BOX < ,0> ;cant initialise SHAPE's inherited data here.
ORG ibox ;backtrack.
SHAPES <REDRAW_BOX,,,SIZE_SHAPES,2,5,PLACE_SHAPES>
ORG ibox+(SIZE BOX) ;ret. location ptr to normal position.
ENDM
;create instances of BOX....
MAKE_BOX BOX1
MAKE_BOX BOX2
; ......
NOW EQU [bx] ;es:[bx] required for multiple data segments. see below.
;note: TASM treats "THIS" as reserved word, so use NOW.
; .....
data ENDS
;........................................................
code SEGMENT 'code'
ASSUME cs:code
; ......
NOWIS MACRO instance_label
mov bx,OFFSET instance_label
;note: For multiple data segments, ES:BX must be loaded, by replacing
; the above code with the instruction below, however
; instance_label is no longer the actual address loaded to ES:BX
; but is the label of a memory location that contains the
; far address.(instance_label DD far_address).
; Extra steps are required to set up the program for this.
; les bx,instance_label
ENDM
; ......
;..........................................................
main PROC FAR
mov ax,data
mov ds,ax
ASSUME ds:data
; .......
; .....
NOWIS BOX1
mov dx,0105h ;change row & col
call NOW.PLACE ;update ROW & COL of BOX1.
call NOW.REDRAW ;display the box.
;note: at this point should only call those methods belonging to BOX1.
; If you want to call CIRCLE1.REDRAW (for example), first execute
; NOWIS CIRCLE1
;note2: procedure calls to execute only one or two instructions, is
; very wasteful, and C++ optimises this situation by treating
; some small methods like macros, expanding them in-line.
; Thus, although it is not good OOP practice, you can do what
; C++ does anyway -- instead of calling PLACE, just put the two
; instructions straight in
; -- or define the method as a macro. No, don't do it.
;note3: one thing you may have noticed in the Figure (textbook
; hierarchy diagram of the objects) is that I created variable
; ROUNDED, attached to BOX, but I did not create a method for it.
; I should have, as all data must only be changed by methods
; attached to the same object. However I left the Figure
; uncluttered as I haven't actually implemented any setting
; of ROUNDED in this demo program.
NOWIS BOX2
mov dx,1020h ;row & col
call NOW.PLACE
call NOW.REDRAW ;draws box2
mov ax,4C00h ;back to DOS
int 21h
main ENDP
;...........................................................
PLACE_SHAPES PROC NEAR
;the new row and column coordinates are
;passed to PLACE via DX. DH=row (0-24)
;DL=column (0-79).
mov NOW.ROW,dh
mov NOW.COL,dl
;note: a method can call other methods, even methods belonging to
; other objects. The standard rule is always use NOWIS before
; calling any object that is not the current one.
ret
PLACE_SHAPES ENDP
;..........................................................
REDRAW_BOX PROC NEAR
;no parameters passed to this one. It just
;uses ROW, COL, VERT, HORIZ
;& ROUNDED to redraw the box.
;note again that NOW override is used to
;access only the data at the currently pointed
;-to instance.
; ......
;some code here to draw box on scrn....
;note: don't forget when writing code that BX (or ES:BX) is/are used
; for the NOW override, which means that we have to save it/them
; if we want to use it/them for anything else.
mov dh,NOW.ROW
mov ch,0
mov cl,NOW.VERT
vertloop:
mov dl,NOW.COL
push cx ;save vert loop count
mov ch,0
mov cl,NOW.HORIZ ;horiz loop count
push bx ;save NOW override
horizloop:
push cx ;save horiz loop count
mov bh,0
mov ah,2 ;set_cursor
int 10h
mov cx,1
mov al,219 ;ibm block-character.
mov bx,0003h ;page, colour.
mov ah,0Ah ;write_char
int 10h
pop cx ;restore horiz loop count
inc dl ;row no. for set_cursor
loop horizloop ;next horizontal char
pop bx ;restore NOW override
pop cx ;restore vert loop count
inc dh ;col no. for set_cursor
loop vertloop ;next line
; ......
ret
REDRAW_BOX ENDP
;..........................................................
SIZE_SHAPES PROC NEAR
;perhaps this could have some parameters
;passed to it, to update VERT & HORIZ,
;then return with a pass/fail in AX.
; ......
; .....
ret
SIZE_SHAPES ENDP
;.......................................................
code ENDS
END main
;NOTE ON USING TURBO-DEBUGGER:
; The debugger's Watch window is particularly nice for viewing
; all the data for an object, since all you have to do is change
; to the Watch window by pressing <F6> then type the name of the
; instance you want to view, for example "BOX1".