Is there any real advantage to using code pointers to point to a user written subprocedure inbedded in the main module? If so, what is the advantage?
Announcement
Collapse
No announcement yet.
Code Pointers
Collapse
X
-
I have used code pointers in my Virtual Micro Code Simulator. I have
150 subroutines, each sub handles one instruction. I keep all the
code pointers in an array syncronized with several other arrays. During
a dissassembly operation when I have identified the instruction, the
index is used to get the code pointer from the array and then I call
the sub. If I did not have this feature, I would have had to pass on
a number to a huge Select Case Block(or several broken down blocks).
It just made it alot cleaner for my application.
i.e.
Code:GLOBAL op16() AS STRING '16 bit opcode lookup table GLOBAL m16() As Integer '16 bit mask GLOBAL c16() As Integer '16 bit compare word GLOBAL op32() As String '32 bit opcode lookup table GLOBAL m132() As Integer '1st 32 bit mask GLOBAL m232() As Integer '2nd 32 bit mask GLOBAL c132() As Integer '1st 32 bit compare word GLOBAL c232() As Integer '2nd 32 bit compare word GLOBAL Diss() AS ASCIIZ*100 'Dissassembled strings GLOBAL RunOp() AS DWORD 'Code pointers to 16 bit Run opcodes GLOBAL RunOp2() AS DWORD 'Code pointers to 32 bit Run opcodes GLOBAL DisOp() AS DWORD 'Code pointers to 16 bit dissassemble opcodes GLOBAL DisOp2() AS DWORD 'Code pointers to 32 bit dissassemble opcodes ...etc '--------------------------------------------------------- 'Note1: Array is sorted 0000 to FFFF, so I can do a value 'compare and divide the large array in 1/2 or 1/4 to narrow 'the search inside the for/next loop. 'Note2: With PBDLL5 I can change to a structure. 'This structure of opcode string as follows: '[string ] [xxxx] [xxxx ] [subroutine] '[nmemonic string] [mask] [opcode] [code pointer] '---------------------------------------------------------- op16$(1) = "NOP" m16%(1) = Val("&H" + "FFFF" + "%") c16%(1) = Val("&H" + "0000" + "%") RunOp(1) = CODEPTR(NOP1) DisOp(1) = CODEPTR(dNOP1) op16$(2) = "SLEEP" m16%(2) = Val("&H" + "FFFF" + "%") c16%(2) = Val("&H" + "0180" + "%") RunOp(2) = CODEPTR(SLEEP2) DisOp(2) = CODEPTR(dSLEEP2) op16$(3) = "STC CCR,Rd" m16%(3) = Val("&H" + "FF00" + "%") c16%(3) = Val("&H" + "0200" + "%") RunOp(3) = CODEPTR(STC3) DisOp(3) = CODEPTR(dSTC3) op16$(4) = "LDC Rs,CCR" m16%(4) = Val("&H" + "FF00" + "%") c16%(4) = Val("&H" + "0300" + "%") RunOp(4) = CODEPTR(LDC4) DisOp(4) = CODEPTR(dLDC4) op16$(5) = "ORC #xx,CCR" m16%(5) = Val("&H" + "FF00" + "%") c16%(5) = Val("&H" + "0400" + "%") RunOp(5) = CODEPTR(ORC5) DisOp(5) = CODEPTR(dORC5) ...etc ' ** Initialize all opcode arrays ** ' ============================ Dim op16(1:100) '16 bit opcode strings Dim op32(1:50) '32 bit opcode strings Dim m16(1:100) '16 bit mask word Dim c16(1:100) '16 bit compare word Dim m132(1:50) '32 bit 1st mask word Dim m232(1:50) '32 bit 2nd mask word Dim c132(1:50) '32 bit 1st compare word Dim c232(1:50) '32 bit 2nd compare word Dim RunOp(1:100) 'Run/Sim 16 bit opcodes Dim RunOp2(1:50) 'Run/Sim 32 bit opcodes Dim DisOp(1:100) 'Dissassemble 16 bit opcodes Dim DisOp2(1:50) 'Dissassemble 32 bit opcodes ...etc '********************************************************** '16/32 bit Instruction routines: 16 bit = 100x subs total ' ' 32 bit = 50x subs total ' 'Dissassemble opcodes, convert them to strings and display 'them to the Code Window. '********************************************************** $INCLUDE "C:\PROJECTS\MCHILD\RESOLVE.INC" '------------------------------------------------------------- ' First the 16 bit instructions, 100x subs. Addressing mode ' already broken down for each sub. ' Opcode Place holder strings found in op16(i) array. '------------------------------------------------------------- SUB dNOP1() 'NOP [0 0 0 0] operand$ = op16$(i) END SUB '--- SUB dSLEEP2() 'SLEEP [0 1 8 0] operand$ = op16$(i) END SUB '--- SUB dSTC3() 'STC CCR,Rd [0 2 0 rd] Call resolve_rd_8() END SUB '--- SUB dLDC4() 'LDC Rs,CCR [0 3 0 rs] Call resolve_rs_8_R() END SUB ...etc '********************************************************** '16/32 bit Instruction routines: 16 bit = 100x subs total ' ' 32 bit = 50x subs total ' ' ' '********************************************************** '------------------------------------------------------------- ' First the 16 bit instructions, 100x subs. Addressing mode ' already broken down for each sub. ' Opcode Place holder strings found in op16(i) array. '------------------------------------------------------------- SUB NOP1() 'NOP [0 0 0 0] 'Simulate instruction END SUB '--- SUB SLEEP2() 'SLEEP [0 1 8 0] 'simulate instruction END SUB '--- SUB STC3() 'STC CCR,Rd [0 2 0 rd] 'Simulate instruction END SUB '--- SUB LDC4() 'LDC Rs,CCR [0 3 0 rs] 'simulate instruction END SUB '--- SUB ORC5() 'ORC #xx,CCR [0 4 imm imm] 'simulate instruction END SUB ...etc '------------------------------------------------------ 'Simulate an instruction and return the results. ' 'Single Step, Animate or Run mode. 'Entry: Lines ' 'Returns: '------------------------------------------------------ SUB SimInstruct() Local x as word Local y as word Local z as word Local r as word Local xx as word Local yy as word Local zz as word Local rr as word adr = 0 'lines = Len(rom$)/2 'average out to 2 bytes per line fDiss = 0 'set simulation flag SimNext: '**Main Simulator Loop** While lines > 0 And adr < Len(rom$) Call adrs_cnvt() Call getword() x = mWord 'Bytes12 = mWord mem1$ = h1$ + h2$ For i = 1 To 100 y = m16%(i) z = c16%(i) r = y And x If r = z Then '**Resolve operand and simulate CALL DWORD RunOp(i) <---- **** lines = lines - 1 GoTo SimNext End If Next i '**Fall thru and test for 32 bit opcodes mem1$ = h1$ + h2$ Call getword() xx = mWord 'Bytes34 = mWord mem2$ = h1$ + h2$ For i = 1 To 50 y = m132%(i) z = c132%(i) r = y And x yy = m232%(i) zz = c232%(i) rr = yy And xx If r = z And rr = zz Then '***Resolve operand and simulate CALL DWORD RunOp2(i) lines = lines - 1 GoTo SimNext End If Next i '**Invalid instruction, initiate error handler '**Hopefully, I will never need to do this!!! adr = adr - 2 lines = lines - 1 GoTo SimNext WEND END SUB
There are other reasons in general, but I will let others post them.
Regards, Jules
[This message has been edited by Jules Marchildon (edited January 04, 2000).]
-
I have used them for several different things. One example is in a large program I work on. It has a couple routines we use for user input. In these routines, one thing they do is check a global code pointer...if it's set, it will call this sub every so often. This allows us to do things like update the date/time from anywhere in the program, no matter where on the screen the date/time is, or what it looks like. The user input code dosen't know what it's calling, it just knows to call it every 30 seconds or so.
Another example from that same program... the program stores it's version information in a database. If we put a newer version of the program on, it may need to change something in some databases...it can look at the stored version, compare it to it's own internal version, and figure out what needs to happen. The way I implemented this was to use pointers to functions.
The program will look at what version the data is and build a list of functions (in an array) to call to bring the data up to date with the current version of the program. This enables us to put any version of the program with any version of the data and the program can convert the data to the correct format. This could be handled differently, but it makes the code easy to maintain...as Jules pointed out, it saves us from having a huge case statement or multiple IF statements.
Jason
Comment
-
Thanks for the info. I haven't been involved with PB for long, so I've decided to work out things I don't understand or have little feel for in a consiencious manner. I've been working with the pointers to get a feel for how things work, and the code pointers were next on the agenda.
Thanks again.Walt Decker
Comment
-
Another use of CODEPTR:
In the Source Code section, I found two good examples how to connect
an interrupt to PB code. This code uses CODEPTR in order to tell the
interrupt where to find its handler. (I had tried to do the same
before, but I was not able to find out how to set up the stack for the
interrupt handler. Thank you at PB Inc. for posting that code!
- If you write the entire interrupt handler in inline assembler,
it is even easier to connect the routine to the interrupt:
IntHandler:
! ... (all ASM statements go here
! IRET
and then you establish CODEPTR32(IntHandler) as the new interrupt vector.
Comment
Comment