An Old-School Introduction to Position Independent Code
Position‑independent code is fundamentally simple: it is machine code that can execute correctly regardless of the memory address at which it is loaded.
Most texts on the subject look intimidating though, including some very well written ones, such as Eli Bendersky’s Position Independent Code (PIC) in shared libraries. The topic often appears complicated because it is usually explained in the context of building shared libraries for Linux; a domain that requires discussing linkers, loaders, the ELF format, and other complex mechanisms. I felt it would be easier to understand the core idea of position‑independent code by using a much simpler computer, so I went back to the dawn of personal computing and picked the original Apple II.
Some of the reasons I chose Apple II for this exercise are:
It was built around the MOS 6502 - a very simple 8-bit CPU with a small address space, no virtual memory, one accumulator register. In one of my previous posts, I argued that 6502 is a Good Starting Point for Beginning Assembly Programming.
It includes a built‑in machine‑code monitor and mini‑assembler which are handy for entering and testing machine code. Most other machines from that era would require to use BASIC commands like PEEK and POKE which is doable but less comfortable.
I have never had a chance to work with an Apple II 1 and this is my excuse to finally try it.
To be clear: in this article, mu goal is simply to describe the concept of position-independent code. I am not going to investigate techniques making full Apple II programs position‑independent 2.
Setup
I do not have access to an actual Apple II computer. Instead, I used the AppleWin emulator in Apple ][ 48K mode which emulates the original Apple II from 1977 with 48 KB RAM and with Integer BASIC, Machine Language Monitor and Mini Assembler in ROM. I used APPLE II USER’S GUIDE by Lon Poole and Steven Cook to learn how to use the Monitor and Mini-Assembler; there was no need for BASIC.
To read this art…