PDA

View Full Version : A Model for Object Oriented Programming



Charles Pegge
09-03-2008, 13:56
Well I tried to keep it simple, but this is the best I could come up with for ThinBasic so far.

The machine code string now contains methods and a jump table to access them. This works like a SELECT CASE or ON..GOTO according to the function number.

Each object contains a very small piece of code (8bytes long) to call the methods string. This allows the address of the object's elements to be recovered from the stack for use by the methods.

There are any number of variations for this technique but this one is quite simple to use in the ThinBasic environment.



' Using Machine Code with ThinBasic
'---------------------------------------------------------------------------
'---Reference:
' Intel x86 Architecture Ref Manual Vol 2
'---http://developer.intel.com/design/pentiumii/manuals/243191.htm
'---------------------------------------------------------------------------
' Syntax rules:
' #Variable patches in long address of Variable (4 bytes)
' NLn patches in long decimal value n (4 bytes)
' comments are indicated by a quote mark '
' all other words are read as hexadecimal bytes.
' An error during MC_Eval$ will produce a string containing &hc3 (ret) only.

'----------------------------------------------
' accessing functions by number
'----------------------------------------------
dim fun as long ' function number
dim sMC as string = MC_Eval$ "
5a ' pop ' obj elements pointer
42 ' inc edx ' adjust pointer to the start of data elements
8b 05 #fun ' mov eax,fun ' get function number
c1 e0 03 ' shl eax,3 ' *8 step
83 c0 05 ' add eax,5 ' add 5 to reach jump table
e8 00 00 00 00 ' call null ' where am I ? identify absolute address
59 ' pop ecx ' pop my address here intp ecx
03 c1 ' add eax,ecx ' add to jump offset to get abs address
ff e0 ' jmp eax ' indirect jump to jump table
'-------------------------------'
' long jump table ' relative jumps with stride of 8
c3 00 00 00 00 00 00 00 ' ret ' ret if fun number =0
e9 0b 00 00 00 00 00 00 ' jmp long function_1 ' fun number = 1
e9 0b 00 00 00 00 00 00 ' jmp long function_2 ' fun number = 2 '
'-------------------------------'
' function 1 '
8b 42 00 ' mov eax,[edx+12] ' load .x element
40 ' inc eax ' increment
89 42 0c ' mov [edx+16],eax ' save in .a element
c3 ' ret '
'-------------------------------'
' function 2 '
8b 42 00 ' mov eax,[edx+12] ' load .x element
48 ' dec eax ' decrement
89 42 0c ' mov [edx+16],eax ' save in .a element
c3 ' ret '
'-------------------------------'
"
' Define Object structure
'
type an_obj_type
'---------'
' linking procedure (8 bytes)
g as byte ' b8 load eax immediate
p as long ' calling adress
c as word ' ff d0 call eax
b as byte ' padding
'---------'
' data elements
x as long ' offset 0
y as long ' offset 4
z as long ' offset 8
a as long ' offset c
end type
'
' create obj
'
dim myobj as an_obj_type
dim pMyObj as long = varptr(myobj)
myobj.g=&hb8 ' b8 load eax
myobj.p=strptr(sMC) ' address for MC methods
myobj.c=&hd0ff ' ffd0 call eax
' b is left for alignment padding
'
' initial data
'
myobj.x=08
myobj.y=16
myobj.z=24
myobj.a=32
'
fun=1 : call dword pMyObj ' fun can be 0 or 1 or 2
'
msgbox 0, myobj.a

Petr Schreiber
09-03-2008, 15:15
Thanks,

again very nice sample.
I think one of the shortest OOP code I have ever seen :)


Petr

RobertoBianchi
09-03-2008, 16:46
Hi Charles,

seems that you have goot much alredy done machine code (and assembler code of corse) to handle standar BASIC statement.
Did you have tried to write a simple BASIC interpreter or compiler?

Roberto

Charles Pegge
09-03-2008, 17:47
Hi Roberto
I have written, various languages compiled at scripted, some implemented in live applications, some just experimental, but I have not tried Basic yet! This language business becomes a habit! - I seem to be most at home in machine code - my electronics background with microprocessors :)

RobertoBianchi
09-03-2008, 18:34
Today it is difficult to find who handles (like you) code machine.
When I need it, I use writing the code in assembler and then take the object code from the listing producted by the assembler compiler.

Congratulations,
Roberto

Charles Pegge
10-03-2008, 00:22
Assembler is often easier to write than to read. So you must be very determined to work your way through compiler assembler. Compilers don't write many comments in their asm listings :)


Here is a version written in PowerBasic with some Inline assembler. The code string is a little simpler - I will be able to improve it slightly for ThinBasic too.




#COMPILE EXE
#DIM ALL


TYPE an_obj_type
'---------'
' linking procedure (8 bytes)
g AS BYTE ' b8 load eax immediate
p AS LONG ' calling adress
c AS WORD ' ff d0 call eax
b AS BYTE ' padding
'---------'
' data elements
x AS LONG ' offset 0
y AS LONG ' offset 4
z AS LONG ' offset 8
a AS LONG ' offset c
END TYPE

SUB HexMC(s AS STRING,t AS STRING)
#REGISTER NONE
t=STRING$(LEN(s)/2,CHR$(0))
DIM i AS LONG
DIM j AS LONG
DIM l AS LONG
i=STRPTR(s)
j=STRPTR(t)
l=LEN(s)+i
DO
IF i>=l THEN EXIT DO
IF PEEK(BYTE,i)>32 THEN
' convert hexbyte but no error check
! mov ecx,i
! mov al,[ecx]
! sub al,&h30
! cmp al,9
! jle nup1
! and al,&h1f ' mask if lowercase
! sub al,7
nup1:
! shl al,4
! mov ah,al
! inc ecx
! mov al,[ecx]
! sub al,&h30
! cmp al,9
! jle nup2
! and al,&h1f ' mask if lowercase
! sub al,7
nup2:
! add al,ah
! mov i,ecx
! mov ecx,j
! mov [ecx],al
! inc ecx
! mov j,ecx
END IF
INCR i
LOOP
j=j-STRPTR(t)
t=LEFT$(t,j)
'msgbox hex$(asc(t,8))
END SUB


FUNCTION PBMAIN () AS LONG

' Using Machine Code with ThinBasic
'---------------------------------------------------------------------------
'---Reference:
' Intel x86 Architecture Ref Manual Vol 2
'---http://developer.intel.com/design/pentiumii/manuals/243191.htm
'---------------------------------------------------------------------------

'----------------------------------------------
' accessing functions by number
'----------------------------------------------
DIM fun AS LONG ' function number
DIM s AS STRING
DIM sMC AS STRING
s=_ ' call address in eax
" 5a "+_ ' pop ' obj elements pointer
" 42 "+_ ' inc edx ' adjust pointer to the start of data elements
" c1 e1 03 "+_ ' shl ecx,3 ' *8 step
" 83 c1 0c "+_ ' add ecx,12 ' add 12 to reach jump table
" 03 c1 "+_ ' add eax,ecx ' add to jump offset to get abs address
" ff e0 "+_ ' jmp eax ' indirect jump to jump table
_ ' '
_ ' long jump table ' ' relative jumps with stride of 8
" c3 00 00 00 00 00 00 00 "+_ ' ret ' ret if fun number =0
" e9 0b 00 00 00 00 00 00 "+_ ' jmp long function_1
" e9 0b 00 00 00 00 00 00 "+_ ' jmp long function_2
_ '
_ ' function 1 '
" 8b 42 00 "+_ ' mov eax,[edx+12] ' load .x element
" 40 "+_ ' inc eax ' increment
" 89 42 0c "+_ ' mov [edx+16],eax ' save in .a element
" c3 "+_ ' ret '
_ '
_ ' function 2 '
" 8b 42 00 "+_ ' mov eax,[edx+12] ' load .x element
" 48 "+_ ' dec eax ' decrement
" 89 42 0c "+_ ' mov [edx+16],eax ' save in .a element
" c3 "+_ ' ret '
"" '

HExMC s,sMC ' convert to binary
'
' create obj
'
DIM myobj AS an_obj_type
DIM pMyObj AS LONG: pMyObj = VARPTR(myobj)
myobj.g=&hb8 ' b8 load eax
myobj.p=STRPTR(sMC) ' address for MC methods
myobj.c=&hd0ff ' ffd0 call eax
' b is left for alignment padding
'
' initial data
'
myobj.x=08
myobj.y=16
myobj.z=24
myobj.a=32
'
' invoke a method
'
! mov ecx,1 ' fun=2 (0 1 or 2)
! call pMyObj '
' '
MSGBOX STR$(myobj.a) ' result


END FUNCTION