Written and Maintained by Gregory Nacu

Featured Posts

C64OS.com has grown to be more than just a blog about one developer's progress, it is becoming a resource to surround and support a type of C64 user that wants to benefit from the Commodore community and get the most out of modern hardware expansions for their beloved platform.

After writing many posts on the C64 OS weblog, the unfortunate reality is that some of my best work gets lost in the stream of news and developments. Be sure not to miss these full–length editorial reviews:

May 16, 2017Editorial

Review: FREEZE64 Fanzine

December 5, 2016Editorial

World of Commodore '16

Programming Reference

August 4, 2017Programming Reference

6502 / 6510 Instruction Set

August 4, 2017Programming Reference

Commodore 64 PETSCII Codes

August 3, 2017Programming Reference

Commodore 64 Screen Codes


Needs some ideas? Trying searching for:
PETSCII, Animation, Memory or Pointers

Recent Posts

August 15, 2017Programming Theory

Organizing Module Layout

August 4, 2017Programming Reference

6502 / 6510 Instruction Set

August 4, 2017Programming Reference

Commodore 64 PETSCII Codes

August 3, 2017Programming Reference

Commodore 64 Screen Codes

August 1, 2017Programming Theory

Base Conversion in 6502 (2/2)

July 21, 2017Hardware

Commodore Logo Mark Patch

July 5, 2017Programming Theory

Object Orientation in 6502

June 30, 2017Programming Theory

Base Conversion in 6502 (1/2)

June 20, 2017Software

Huge Site Update

June 5, 2017Software

Recursive File Copier in BASIC

May 29, 2017Technical Deep Dive

Implementing Factorial in 6502

May 16, 2017Editorial

Review: FREEZE64 Fanzine

May 9, 2017Programming Theory

Pointers in Practice, Menus

May 1, 2017Programming Theory

Loading Sequential Files

April 27, 2017Programming Theory

HomeBase Applications

April 21, 2017Programming Theory

Application Loading

April 6, 2017Programming Theory

Memory Manager Development

March 27, 2017Software

Petscii Art Animation

March 27, 2017Programming Theory

Making Course Corrections, Timers

March 21, 2017Software

PETSCII Art Renderer

March 6, 2017Programming Theory

Code Module Exports Table

March 1, 2017Technical Deep Dive

Recursion and C64 OS's Menu UI (3/3)

February 22, 2017Technical Deep Dive

C-Style Structures in 6502 (2/3)

February 14, 2017Technical Deep Dive

What is a pointer? (1/3)

February 6, 2017Programming Theory

Memory Managed Loader

Older Posts

Full Post Archive

Subscribe to C64OS.com with your favorite RSS Reader

News, Editorials, Progress and Reference

March 6, 2017Programming Theory

Code Module Exports Table

In an earlier post, Organizing A Big Project, I discussed how one can use a double jumptable to gain access to the inner offsets of a module of code. I've since discovered a much more sensible way to solve this problem. It's a variant of the same concept.

To recap, the problem is that a big project is more than can be handled by a single file of assembly code. The code has to be broken down into modules of code that can be independently assembled. This leads to certain difficulties however. JMPs from the jump table that exist in one module, "memory.o" in C64 OS, have to know where to jump to. Typically, one uses a label to mark the position in some code. Then a JMP can specify the label, and the actual address of the label and where the JMP has to go get resolved at assemble time.

A problem arises when the code is assembled in different modules. How can the jump table in one module know exactly where it ought to jump to in a completely different module of code that is assembled independently? Matters are made worse because the code inside the module could be rearranged at any time. Well, we know how to handle the situation of code being rearranged, you use a jump table! So my initial solution was as follows: Put a jump table at the very top of every module of code. Thus, their offsets start at 0 and skip 3 bytes for each jump. Then, in the main system jump table, the only thing that needs to be known is where the module starts in memory. The main jump table can then jump to the module's jump table, which jumps to the right code.

The theory is perfect, in practice it also works incredibly well. But, as it turns out there is a way to do it that is somewhat smarter. I just didn't know about it because I've only been doing real programming in 6502 assembly since last October.

In my fairly recent post on pointers I was reading about the memory addressing modes of the various instructions, and discovered that JMP has two variant op-codes. The first is the one we know and love, jumps to an absolute address. The second variant takes an inline pointer. And not just to zero page, but an inline pointer to anywhere in memory. Reads the address from the pointer and jumps to that address. This is exactly what we need.

Now, instead of having a full jump table at the top of each module, there is a table of pointers. And as it turns out, these are very easy to build in Turbo Macro Pro. Here's how a table of pointers looks at the top of a module.

The .word keyword reserves two bytes, in little endian format. And it can get that address from a label. The series of .word declarations are a table of pointers to the labels further down in this file. Note that each pointer is only two bytes, whereas the old jump table required three bytes, an extra byte for the extra JMP instruction. Note also that the exports are the first code that appears in this file, so the pointer to initmouse is at exactly $c7c4.

In order for other modules to be able to use the code in this module, they include the header for this module. The example I'm using is the input module. Which contains the code for keyboard and mouse scanning and event generation. Including the code for reading and dequeueing each of the event types.

Not much has changed here. inpuths is set to the address within the system jump table where the jumps to the exports exist. Note that these labels increment by three bytes at a time. That is because they are referring to the main jump table, which includes the JMP instructions. The last part is the system jump table itself and its offsets.

The label input has to be declared the same as the start of where the module is actually assembled to. In this case $c7c4 as we saw earlier. The offset of these entries into the jump table is there in the comments just for reference and to help updating the header file. Each JMP now uses the notation for indirect addressing, those are the parentheses around the address.

Note that these offsets increment by 2. That's because they're offsets into the table of export pointers in the module. The comments specify the routine this indirect jump is jumping to, just for clarity.

Let's review the savings. Before, two direct jumps were required. A direct jump takes 3 cycles for a total of 6 cycles per call through the main jump table. An indirect jump takes 5 cycles, so one cycle is saved per call. Before, two direct jumps required 6 bytes of memory. An indirect jump requires 5, so one byte saved per call. Not a huge saving, but everything counts when you have only 64K of ram. The other small advantage is that counting by twos in the main jump table feels easier to do than counting by threes. Also, over all the .word table at the top of a module just feels cleaner.

Here's the code in screenshots.

Screenshots showing the above sample code as it appears in TMP.