Rendered at 04:52:14 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
femto 5 hours ago [-]
What Woz did was the default way of writing assembly language programs for owners of 8-bit computers (mostly hobbyists). You didn't have money for a second machine, so you wrote your program on paper, you entered it then tested it in situ. Mostly you got it right, as doing it on paper was slow and meant you had the opportunity to put lots of thought into it. 8-bit instruction sets were simple enough that you eventually learned the most common instructions by heart. There was a point where I could mostly translate a Z80 program from assembly to machine code from (my) memory.
Maybe that is part of the nostalgia for the 8-bit days: the practice of "slow programming"? It was relaxing, sort of like those "slow tv" shows.
dhosek 59 minutes ago [-]
I find it amusing that so many of the comments were surprised about hand-assembling 6502 code. When I came to the Apple ][, assemblers were relatively more accessible, but even at around $200, it was well beyond my financial means so I would write code longhand in spiral bound graph paper notebooks in four columns: Addresses, labels, hex codes (up to three bytes per opcode) and then the assembly code.
And that $200 being out of bounds went pretty low: for the first couple years of my programming life, floppy disks were beyond my means, so any code I wrote lived in its official version as hand-written code and would have to be retyped any time I wanted it.
Keyframe 2 hours ago [-]
That's how I learned to program. I didn't have access to computer as a kid, so I read books, wrote programs on paper and when I got access to a computer I would type in the program and see if it worked. I now have an abundance of computers at home. What a weird timeline all in all.
billforsternz 5 hours ago [-]
Yes. My first serious program was done this way. At the start of the project (final year of EE degree, 1981) I didn't really understand what a program was, but I learned by studying the technical reference manual for the Intel 8085 CPU. It kind of seemed like magic, I can mold the functionality by storing codes in memory? Wow!
I figured out exactly what I wanted to do, wrote it out very carefully on paper, looked up all the hex codes, wrote those out very carefully, adjusted addresses etc. as needed. This took many hours spread over weeks. Then I entered the whole thing on the hex keyboard and display of a primitive development board each time I needed it, perhaps an hour or so each time (I think I only did it twice). It worked first time, because why wouldn't it if you were sufficiently meticulous about your work in a process that was very obviously very intolerant of the tiniest mistake?
I must admit my program (gather input information from some transducers, do some calculations, present some results) was likely somewhere between one and two orders of magnitude simpler than a complete Basic interpreter!
marai2 27 minutes ago [-]
I think this comment is gold. Thanks for writing this. It feels like such a visceral description of the experience of "programming" back then. I've read a bunch of old books on programming or those that explain low level programming, but they mostly detailed the mechanics of programming, it feels like your comment captured something of the actual experience of it!
tverbeure 5 hours ago [-]
I got my first computer, a C64, when I was 14 in 1985, and wrote my 6510 assembly in paper as well.
You had to carefully calculate the address distance for a branch instruction. The release of DISMON was a revolution: suddenly the computer did all of that for you. It even supported moving pieces of code to a different address to make space for inserting more instructions somewhere!
intrasight 4 hours ago [-]
All I had was computer manuals in 1981. I wrote several assembly language programs on paper.
analog31 1 hours ago [-]
Since I learned to write machine code this way, I'll add a little bit of color.
You can take the instruction set of a simple microprocessor, and lay out its instruction set in a tabular format. This made it relatively easy to see the correspondence between an instruction in assembly language and its numerical code.
Handy "reference cards" were published for looking up the codes, printed on nice thick plastic. You can find these in a google image search for your favorite micro. I got by with a photocopy. Along with that, a programmer would have their own notes and diagrams taped to the walls for quick reference. Machines were simple enough that you really could have all of the vital information available at a glance.
Today, the "datasheet" for a sophisticated 32 bit microcontroller is many thousands of pages.
Microprocessors had relatively few transistors by today's standards, so the instruction decode logic had to be simple. Logical, if I may say so. This resulted in being able to describe operators and their operands as blocks of bits in an instruction word.
I arrived late enough in the game that personal computers already existed, yet I got myself started by hand assembling for the microprocessor circuits that I brought up from scratch.
jibalt 1 hours ago [-]
Long before 8-bit computers, I had 15 minutes of access every Saturday to an IBM 1620, so I had a week to write (and erase) code (initially FORTRAN II, later 1620 ASM) before getting anywhere near the computer. When I got to the machine room I had to punch the code on cards using an IBM 026 card punch. For my larger FORTRAN programs, it took most of the 15 minutes to compile them and punch an object deck, which I couldn't run until the next week.
MarkusWandel 5 hours ago [-]
My first exposure was Commodore PET computers at the high school (I'm old). Nobody had home computers then, this stuff was crazy expensive, even a floppy disk (singular!) to save your work on the shared drive (on a dolly - it could be hotplugged) was >$20 in today's money. But what you could use all you want was the line printer (a CBM 2022) and its consumables. So at the end of whatever computer room time you could scrounge (lunch, who needs lunch?) you'd print off your 3-4 page epic program to continue coding and debugging with a pencil, on the long school bus ride. This does form "slow" habits. To this day I detest autocomplete, autoindent, syntax highlighters and the like. Never did hand assemble though.
wernam 4 hours ago [-]
You can observe the same behavior from modern LLMs, when working on firmware or closed library and they need to fix or bypass a small thing, sometimes they just directly modify the binary without any disassembler. At least the Chinese non de-cybered LLMs.
abecedarius 5 hours ago [-]
There was a #hexcoders channel on IRC back in the 90s, admittedly very dead, and not just because octal is better for x86 code.
JKCalhoun 2 hours ago [-]
Yep. I've been playing with a KIM-1 lately—modernizing The First Book of KIM.
I've been staring at, fixing up enough 6502 op-codes ands their machine code equivalents that I'm beginning to remember the common ones too.
mandeepj 2 hours ago [-]
> so you wrote your program on paper
I guess whiteboard interview technique came from there. Probably rational was - If they can do it, why can’t you?
fasterik 4 hours ago [-]
I was born too late for that era of computing, but I've spent enough time programming that I can easily "run" a program in my head and reason about how it works, find bugs, etc. I would imagine that muscle was even more developed for the people who had to do it out of necessity, though.
ashleyn 5 hours ago [-]
How exactly did you "enter it" without a second computer though? Was there a simple test rig or something that you would make as an electronics project, where you would input opcodes and ascii and it would write it to a rom? Only real thing i can think of.
sowbug 4 hours ago [-]
The Apple II had a thing called the monitor, which was a tiny CLI program in ROM that you could invoke from the BASIC command line (CALL -151). With it you got the ability to disassemble memory (300L would spit out 6502 opcodes starting at address 768), set memory regions to sequences of hex digits (300: A9 21 20 FO FD 60 would write a tiny program on an Apple II Plus that printed an exclamation point, if my memory serves), and execute memory (300G).
With these three commands, and a working memory of the hex that corresponded to the opcodes, you could be reasonably productive writing short 6502 programs.
Fun and extremely niche fact: the typo CALL -161 jumped into the monitor, but only after the weird side effect of unhooking the sniffer that watched for DOS 3.3 commands sent via the ROM's text I/O. Not only did this make text print faster -- useful when you were visually dumping memory to the screen to find something quickly, but it also protected against accidentally destroying your disk if you unwittingly printed a sequence like ^M^DINIT HELLO^M, which would trigger the disk initialization routine.
tmoertel 3 hours ago [-]
> 300: A9 21 20 FO FD 60 would write a tiny program on an Apple II Plus that printed an exclamation point, if my memory serves.
Ancient assembly hacker tip: A JSR/RTS sequence can be simplified to a JMP. To continue your example, the bytes you provided decompile as follows (assuming Apple 2 monitor ROM at $F800):
So, you load the A register with #$21, which is the ASCII code for `!` in hexadecimal, and then call COUT1 which will output the character in the A register, printing the exclamation point. When COUT1 is finished, it will return to you using an RTS instruction, and then you'll return to your caller using another RTS instruction.
Since the call to COUT1 is a tail call, you can borrow its RTS instruction to return to your caller and save one instruction. So the following code is equivalent to yours but a little bit smaller and faster:
PRINTBANG:
A9 21 LDA #$21
4C F0 FD JMP COUT1
Notice that the JSR instruction has become a JMP.
Another related trick: When you have a routine that callers often want to call twice—say to print `!!` for extreme exclamations—you may be tempted to create a do-it-twice call:
But we can do even better! We can eliminate the jump and save three more bytes by placing our do-it-twice routine immediately before the routine it is calling:
When PRINTBANG2 is called, it calls PRINTBANG to print an exclamation point, but when PRINTBANG returns, it returns to PRINTBANG2, which promplty falls through to PRINTBANG, calling it again and printing a second exclamation point. This time, however, when PRINTBANG returns, it will return to the original caller.
Back when every byte mattered, these tricks were useful to know.
flopsamjetsam 1 hours ago [-]
> CALL -151
I haven't seen that in a long time! Young me was too young to understand 2s complement arithmetic, or that addresses would wrap around. I just thought it was some kind of magic.
holgerschurig 4 hours ago [-]
Can't tell it for 6502... but for Z80. Because was my first own "computer":
* a single Z80 (which was nicer than 8080, because the latter needed an extra clock IC)
* 256 bytes of static RAM
* 1 8bit D-Latch (Flipflop) with 8 LEDs
* 1 8bit D-Latch with 8 dip switches
* 2 8bit buffers that can go tristrate between the hex-thingies and the address & data bus
* 2 rotating hex thingies: you could rotate them between 0-f for data
* 2 rotating hex ones for address
Now, how did it work? I pulled nBUSRQ down (bus request). This made the Z80 go tri-state. It also made my buffers non-tristate.
Then I used 2 of the hex-thingies to set the address and 2 of them to set the data. Now I set nWR to low and that would write the entered data byte into the SRAM.
When I was done, I turned nBUSRQ back to high, so the Z80 again was the boss of the bus. And then I simply used nRESET to low to make the Z80 execute my program starting at address 0.
I did only tiny programs, like adder, some PWN/sound wave program, an traffic light simulator.
But, since I soldered this all by myself, I had no "monitor program" like the KIM-1 had. So I had to do all of that by hardware.
eichin 1 hours ago [-]
For later hardware like the TRS-80, the BASIC interpreter had an escape hatch: PEEK(addr), POKE addr, value, and USR1(). Basically you could read and write single bytes to RAM, and there was a magic 2-byte value which was a branch address that calling USR1() would jump into. So you could bootstrap some simple tooling that way. (I'd been writing hex machine code before I got any hardware, just pencil and graph paper, so it wasn't a big step to go from that to stuffing bytes into memory.) Of course there were tools available but actually paying for them was enough of a challenge that a lot of bootstrapping got done entirely anti-economically :-) (Once floppy drives and disk operating systems were a thing, you'd usually have a simple debugger where you could just type hex digits in, and load register values directly - so if you wanted to read raw disk sectors, you'd drop CD 75 46 18 FB somewhere, R DE track/sector, R HL where to read, R BC 0001 and then single step the code and it would read a single sector.)
(Note that while a lot of this was unjustifiable even then - my first real paying job in computers was down a step, working on a Z80-modded IMSAI so while most code was on 8" floppies, doing machine code in binary on toggle switches "just to fix something quick" was a legitimate skill :-)
asdefghyk 4 hours ago [-]
RE "...How exactly did you "enter it" without a second computer though...."
You would use the "monitor program" to poke hex data into memory locations, starting at a nominated RAM memory address. Needed to be done VERY CAREFULLY. one bad hex digit and your program likely crash.
After entering all the program into memory, you would use a monitor program , command to get tell the CPU to jump to a certain address and start executing a program there. OLD computer magazines often had such hex listings printed in them.
generuso 52 minutes ago [-]
In case of Wozniak, he had access to a commercial programmer at work.
Some people did burn the code into electrically programmable PROMs completely by hand, using just a power supply, some wires and switches. Anyone could do this at home, but it was extremely tedious even for a tiny 256 byte chip.
JKCalhoun 2 hours ago [-]
The KIM-1 has a hexadecimal keypad and six 7-segment LEDs.
You go to a start address, switch to data mode, and just start plugging in hex…
AnimalMuppet 4 hours ago [-]
Front panel switches?
bryancoxwell 3 hours ago [-]
I’d read more on what you have to say about this
Ericson2314 1 hours ago [-]
This is why we forgot how to program long before AI slop :)
II2II 3 hours ago [-]
Follow-up question: how did Woz get BASIC into ROM?
The handwritten interpreter is fairly common knowledge since Woz has told that story many times, but I don't recall any accounts of how he bridged the gap from paper to silicon. All of the discussion about the machine language monitor doesn't really address the question. At best, it moves the question from programming a ROM for BASIC to programming a ROM with the machine language monitor. Even with the monitor, additional hardware would be required to program a ROM. At the very least, a latch would be required to hold the address and data. Of course, it is possible that he did it without the computer (using a rig that let him "toggle" the pins). It is also possible that he used another computer to program the ROM, but, as he said, he didn't have the money to program BASIC on a computer so why would that be different for a ROM?
skissane 2 hours ago [-]
> Follow-up question: how did Woz get BASIC into ROM?
Edit: Actually, I think the Apple I only had the monitor in ROM; Basic was typed in using the monitor, and then saved/loaded using cassette. Apple II put Basic in ROM; the shipping version used mask ROM; maybe they used PROMs in development, although at the time PROMs generally had half the capacity of mask ROMs.
nostrademons 1 hours ago [-]
Which is why technically HP would've owned some of the IP for the Apple I. I remember hearing some account in a book where he told jobs "Wait a second; I did some of this at work, I used their equipment, I think my employer owns this." But then they got HP to sign a release that they had no interest in the IP, and then they were all good to start the company and get funding. Bet HP is kicking themselves for signing that release, though.
asdefghyk 5 hours ago [-]
I would say bit by bit, I mean "small part" and then keep making small extensions to the program(s)
First for new hardware would be a monitor program.
Either write one, or port one from other hardware.
A monitor program allows the inspection and edit of memory data and also to run programs in such memory.
The monitor program often placed in ROM for convenance.
A 6502 cross assembler, could be used to avoid the need for hand assembly the program to 6502 machine code.
Probably where WOZMON came from.
Then using WOZMON start writing a VERY simple basic interpreter.
Maybe the monitor program was borrowed from other hardware that used a 6502 ( would need slight mods for the Apple 1 ) NOTE This is just a possibility - I actually have NO idea
I suspect WOZ would have invented his own in any case ...
(OFF TOPIC - I messed around with a 68008 chip in mid 1980s?? and I recall I found a book with a complete montor program in for this chip - I can not recall the name of the book. )
epylar 4 hours ago [-]
Wow, cool to see the 68008 mentioned here! I actually went through 'The Art of Electronics Student Manual Hayes, Thomas C.; Horowitz, Paul' when I was a teenager in the late 90s and the course included wiring up the 68008 into a breadboard and attaching a keypad to key in hand-assembled hex! That was so fun.
mrandish 4 hours ago [-]
I got my first computer in 1981, a 4K Radio Shack Color Computer for $500 (a huge purchase decision at the time). So I missed hand assembling for bare metal and Altair-type toggles.
However, there was an interesting period of a few years where assembler tools were either unavailable or fairly expensive, so it was common to use the computer's BASIC to write an assembly language monitor program. Such program listings were pretty common in early hobbyist 'zines. It was also pretty common to use BASIC to POKE in a quick bootstrap program to load a value in a register and jump to an address, which I could usually do from memory. After 40 years I still remember the 6809 RTS was $39 and NOP was $12, two very handy instructions to POKE a quick mod into a program.
valeena 3 hours ago [-]
I'm sorry I don't understand - you had to buy instructions?
rbehrends 2 hours ago [-]
$XX was a form of hex code notation, used by the 6502 and Motorola processors assembly language. But not universal: in 8080 or Z80 assembly, hex values were denoted by a `H` suffix (this required adding a `0` at the front if the leading digit was in the A-F range to distinguish them from idenitifiers).
valeena 2 hours ago [-]
Thanks for the answer! Wow, the Assembly from back then seems very different from today's - I'm learning it In uni currently. I'll have to ask my teacher
mrandish 37 minutes ago [-]
Oh, yeah... didn't even think of that. Sorry!
Since I was entirely self-taught on that first computer with zero prior education and no books other than the included manuals and a 6809 CPU reference card a very kind sales rep at Motorola mailed to me for free, I learned hex representation that way. It actually still seems a bit weird when I see other hex notations. :-)
totallymike 3 hours ago [-]
$nn was a common way to write numeric literals (specifically in hexadecimal, if memory serves) in assembly languages, to differentiate from memory addresses or other uses for values
valeena 2 hours ago [-]
Ah ok, it does make sense now! Super interesting to read about the devices from back then and the difference from the then-Assembly and the one we use nowadays
And then he wrote SWEET16 which was also amazing. Him and Niklaus Wirth are two people I truly admire; they knew so much and shared so freely.
1 hours ago [-]
rootedbox 1 hours ago [-]
Ada Lovelace.. wrote the first language before any physical computer.
jibalt 1 hours ago [-]
No, she didn't write a language. She published an algorithm to calculate Bernoulli numbers for Babbage's "Analytical Engine", which he never built.
wewewedxfgdf 5 hours ago [-]
It's taken me more than 40 years to learn a fraction of a % of what Woz knew in 1975.
lysace 4 hours ago [-]
Same, but you probably learned lots of other stuff too.
david-gpu 5 hours ago [-]
I only had to assemble instructions by hand three times in my career. It is not difficult if you are already familiar with the ISA of that particular processor, but it is tedious.
The first time was in my first job writing OpenGL ES 2.0 blending operations for the Imagination Technologies SGX 535, which was a remarkably advanced little GPU for its time. Alpha blending happened through special instructions in the fragment/pixel shader. We did have a compiler, but it didn't handle blending, for whatever reason.
Through testing I noticed that NVidia GPUs performed blending incorrectly, according to the specification, which was a big surprise. Only years later I figured out that the specification had some errors; I now would bet that NVidia was doing the correct thing.
The second time I had to assemble instructions by hand happened while working on a stripped down version of the Radeon 7xxx series that shipped on some mobile phones. I don't recall what the problem was, whether we were adding a feature or optimizing the microcode generated for a particular OpenGL operation, but it involved a rarely-used feature called user-defined clipping planes. We didn't have an assembler for that GPU; all microcode was assembled by hand.
The third time happened at NVidia, and I will be vague, as not enough time has passed for me to be comfortable going into any detail. I had an idea for how to provide hardware acceleration for persistent CUDA kernels, which eventually was marketed as Cluster Launch Control (CLC). In order to quantify the benefit of adding some hardware, when it was possible to approximate that functionality in software, I needed to test the most efficient software implementation that was possible, and the compiler wasn't quite giving the assembly I wanted, so I had to manually patch some instructions post-compilation. Why did I not use the assembler that was available? I couldn't, because the assembly language did not provide a way to express the exact feature I had to patch.
johndubchak 5 hours ago [-]
I was such a nerd, happily learning 6802 assembly on the II+...those were the days...I miss it.
saagarjha 53 minutes ago [-]
Control codes had you down? ;)
iberator 4 hours ago [-]
It's easy to relearn those skills:
Just design and build a virtual CPU architecture in the language of your choice:) (not verilog but php, c, rust, zig or whatever)
You create architecture, then OPCODES, then you can write simple programs in machine code.
Then its SUPER EASY to write an assembler and disassembler.
Then forth compiler.
I did it all once as I was homeless on my phone in the mall .
Fun and educational, even if you don't know assembly prior.
le-mark 3 hours ago [-]
I read a book on C that had this as an excercise; blew my mind at the time. It’s really a great excercise. I created and simulated an equihash machine this way many years ago; back when gpus were used for such thing as crypto mining and not ai!
heisenbit 4 hours ago [-]
Did he really write the BASIC before he wrote the monitor program which sits at the top of the address space? The monitor was documented as part of the systems manual of the Apple ][ and contained a small disassembler which helped a lot when coding some instructions or jumps wrong. I learned a lot from that code.
phire 2 hours ago [-]
It's not entirely clear, but not much point in writing a monitor for a computer you haven't even designed yet.
I assume he wrote BASIC first to make sure he knew the computer he was building would be capable of running BASIC. And also not too capable, since the goal was a cheap computer capable of running BASIC.
But, he did write a simple monitor (and burn it into PROM) before actually running BASIC. Just 256 bytes: No disassembler, just the ability to read/modify and execute hex bytes. Before Woz created the tape interface, you had to type BAISC into the monitor as hex every time you powered up the computer.
xgkickt 4 hours ago [-]
Simple answer: Because Woz is the wiz that was.
BarryGuff 3 hours ago [-]
You'll find he is a whiz of a Wiz, if ever a Wiz there was.
Grimeton 4 hours ago [-]
>How did Woz write the Apple 1 BASIC before building the computer?
Maybe that is part of the nostalgia for the 8-bit days: the practice of "slow programming"? It was relaxing, sort of like those "slow tv" shows.
And that $200 being out of bounds went pretty low: for the first couple years of my programming life, floppy disks were beyond my means, so any code I wrote lived in its official version as hand-written code and would have to be retyped any time I wanted it.
I figured out exactly what I wanted to do, wrote it out very carefully on paper, looked up all the hex codes, wrote those out very carefully, adjusted addresses etc. as needed. This took many hours spread over weeks. Then I entered the whole thing on the hex keyboard and display of a primitive development board each time I needed it, perhaps an hour or so each time (I think I only did it twice). It worked first time, because why wouldn't it if you were sufficiently meticulous about your work in a process that was very obviously very intolerant of the tiniest mistake?
I must admit my program (gather input information from some transducers, do some calculations, present some results) was likely somewhere between one and two orders of magnitude simpler than a complete Basic interpreter!
You had to carefully calculate the address distance for a branch instruction. The release of DISMON was a revolution: suddenly the computer did all of that for you. It even supported moving pieces of code to a different address to make space for inserting more instructions somewhere!
You can take the instruction set of a simple microprocessor, and lay out its instruction set in a tabular format. This made it relatively easy to see the correspondence between an instruction in assembly language and its numerical code.
Handy "reference cards" were published for looking up the codes, printed on nice thick plastic. You can find these in a google image search for your favorite micro. I got by with a photocopy. Along with that, a programmer would have their own notes and diagrams taped to the walls for quick reference. Machines were simple enough that you really could have all of the vital information available at a glance.
Today, the "datasheet" for a sophisticated 32 bit microcontroller is many thousands of pages.
Microprocessors had relatively few transistors by today's standards, so the instruction decode logic had to be simple. Logical, if I may say so. This resulted in being able to describe operators and their operands as blocks of bits in an instruction word.
I arrived late enough in the game that personal computers already existed, yet I got myself started by hand assembling for the microprocessor circuits that I brought up from scratch.
I've been staring at, fixing up enough 6502 op-codes ands their machine code equivalents that I'm beginning to remember the common ones too.
I guess whiteboard interview technique came from there. Probably rational was - If they can do it, why can’t you?
With these three commands, and a working memory of the hex that corresponded to the opcodes, you could be reasonably productive writing short 6502 programs.
Fun and extremely niche fact: the typo CALL -161 jumped into the monitor, but only after the weird side effect of unhooking the sniffer that watched for DOS 3.3 commands sent via the ROM's text I/O. Not only did this make text print faster -- useful when you were visually dumping memory to the screen to find something quickly, but it also protected against accidentally destroying your disk if you unwittingly printed a sequence like ^M^DINIT HELLO^M, which would trigger the disk initialization routine.
Ancient assembly hacker tip: A JSR/RTS sequence can be simplified to a JMP. To continue your example, the bytes you provided decompile as follows (assuming Apple 2 monitor ROM at $F800):
So, you load the A register with #$21, which is the ASCII code for `!` in hexadecimal, and then call COUT1 which will output the character in the A register, printing the exclamation point. When COUT1 is finished, it will return to you using an RTS instruction, and then you'll return to your caller using another RTS instruction.Since the call to COUT1 is a tail call, you can borrow its RTS instruction to return to your caller and save one instruction. So the following code is equivalent to yours but a little bit smaller and faster:
Notice that the JSR instruction has become a JMP.Another related trick: When you have a routine that callers often want to call twice—say to print `!!` for extreme exclamations—you may be tempted to create a do-it-twice call:
But now we know better and code it this way: But we can do even better! We can eliminate the jump and save three more bytes by placing our do-it-twice routine immediately before the routine it is calling: When PRINTBANG2 is called, it calls PRINTBANG to print an exclamation point, but when PRINTBANG returns, it returns to PRINTBANG2, which promplty falls through to PRINTBANG, calling it again and printing a second exclamation point. This time, however, when PRINTBANG returns, it will return to the original caller.Back when every byte mattered, these tricks were useful to know.
I haven't seen that in a long time! Young me was too young to understand 2s complement arithmetic, or that addresses would wrap around. I just thought it was some kind of magic.
* a single Z80 (which was nicer than 8080, because the latter needed an extra clock IC) * 256 bytes of static RAM * 1 8bit D-Latch (Flipflop) with 8 LEDs * 1 8bit D-Latch with 8 dip switches * 2 8bit buffers that can go tristrate between the hex-thingies and the address & data bus * 2 rotating hex thingies: you could rotate them between 0-f for data * 2 rotating hex ones for address
Now, how did it work? I pulled nBUSRQ down (bus request). This made the Z80 go tri-state. It also made my buffers non-tristate.
Then I used 2 of the hex-thingies to set the address and 2 of them to set the data. Now I set nWR to low and that would write the entered data byte into the SRAM.
When I was done, I turned nBUSRQ back to high, so the Z80 again was the boss of the bus. And then I simply used nRESET to low to make the Z80 execute my program starting at address 0.
I did only tiny programs, like adder, some PWN/sound wave program, an traffic light simulator.
But, since I soldered this all by myself, I had no "monitor program" like the KIM-1 had. So I had to do all of that by hardware.
(Note that while a lot of this was unjustifiable even then - my first real paying job in computers was down a step, working on a Z80-modded IMSAI so while most code was on 8" floppies, doing machine code in binary on toggle switches "just to fix something quick" was a legitimate skill :-)
You would use the "monitor program" to poke hex data into memory locations, starting at a nominated RAM memory address. Needed to be done VERY CAREFULLY. one bad hex digit and your program likely crash. After entering all the program into memory, you would use a monitor program , command to get tell the CPU to jump to a certain address and start executing a program there. OLD computer magazines often had such hex listings printed in them.
Some people did burn the code into electrically programmable PROMs completely by hand, using just a power supply, some wires and switches. Anyone could do this at home, but it was extremely tedious even for a tiny 256 byte chip.
You go to a start address, switch to data mode, and just start plugging in hex…
The handwritten interpreter is fairly common knowledge since Woz has told that story many times, but I don't recall any accounts of how he bridged the gap from paper to silicon. All of the discussion about the machine language monitor doesn't really address the question. At best, it moves the question from programming a ROM for BASIC to programming a ROM with the machine language monitor. Even with the monitor, additional hardware would be required to program a ROM. At the very least, a latch would be required to hold the address and data. Of course, it is possible that he did it without the computer (using a rig that let him "toggle" the pins). It is also possible that he used another computer to program the ROM, but, as he said, he didn't have the money to program BASIC on a computer so why would that be different for a ROM?
See: https://retrocomputing.stackexchange.com/questions/18321/how...
He used equipment at his day job at HP
Edit: Actually, I think the Apple I only had the monitor in ROM; Basic was typed in using the monitor, and then saved/loaded using cassette. Apple II put Basic in ROM; the shipping version used mask ROM; maybe they used PROMs in development, although at the time PROMs generally had half the capacity of mask ROMs.
First for new hardware would be a monitor program. Either write one, or port one from other hardware. A monitor program allows the inspection and edit of memory data and also to run programs in such memory. The monitor program often placed in ROM for convenance. A 6502 cross assembler, could be used to avoid the need for hand assembly the program to 6502 machine code.
Probably where WOZMON came from.
Then using WOZMON start writing a VERY simple basic interpreter.
Maybe the monitor program was borrowed from other hardware that used a 6502 ( would need slight mods for the Apple 1 ) NOTE This is just a possibility - I actually have NO idea I suspect WOZ would have invented his own in any case ...
(OFF TOPIC - I messed around with a 68008 chip in mid 1980s?? and I recall I found a book with a complete montor program in for this chip - I can not recall the name of the book. )
However, there was an interesting period of a few years where assembler tools were either unavailable or fairly expensive, so it was common to use the computer's BASIC to write an assembly language monitor program. Such program listings were pretty common in early hobbyist 'zines. It was also pretty common to use BASIC to POKE in a quick bootstrap program to load a value in a register and jump to an address, which I could usually do from memory. After 40 years I still remember the 6809 RTS was $39 and NOP was $12, two very handy instructions to POKE a quick mod into a program.
Since I was entirely self-taught on that first computer with zero prior education and no books other than the included manuals and a 6809 CPU reference card a very kind sales rep at Motorola mailed to me for free, I learned hex representation that way. It actually still seems a bit weird when I see other hex notations. :-)
https://www.folklore.org/MacBasic.html
The first time was in my first job writing OpenGL ES 2.0 blending operations for the Imagination Technologies SGX 535, which was a remarkably advanced little GPU for its time. Alpha blending happened through special instructions in the fragment/pixel shader. We did have a compiler, but it didn't handle blending, for whatever reason.
Through testing I noticed that NVidia GPUs performed blending incorrectly, according to the specification, which was a big surprise. Only years later I figured out that the specification had some errors; I now would bet that NVidia was doing the correct thing.
The second time I had to assemble instructions by hand happened while working on a stripped down version of the Radeon 7xxx series that shipped on some mobile phones. I don't recall what the problem was, whether we were adding a feature or optimizing the microcode generated for a particular OpenGL operation, but it involved a rarely-used feature called user-defined clipping planes. We didn't have an assembler for that GPU; all microcode was assembled by hand.
The third time happened at NVidia, and I will be vague, as not enough time has passed for me to be comfortable going into any detail. I had an idea for how to provide hardware acceleration for persistent CUDA kernels, which eventually was marketed as Cluster Launch Control (CLC). In order to quantify the benefit of adding some hardware, when it was possible to approximate that functionality in software, I needed to test the most efficient software implementation that was possible, and the compiler wasn't quite giving the assembly I wanted, so I had to manually patch some instructions post-compilation. Why did I not use the assembler that was available? I couldn't, because the assembly language did not provide a way to express the exact feature I had to patch.
Just design and build a virtual CPU architecture in the language of your choice:) (not verilog but php, c, rust, zig or whatever)
You create architecture, then OPCODES, then you can write simple programs in machine code.
Then its SUPER EASY to write an assembler and disassembler.
Then forth compiler.
I did it all once as I was homeless on my phone in the mall .
Fun and educational, even if you don't know assembly prior.
I assume he wrote BASIC first to make sure he knew the computer he was building would be capable of running BASIC. And also not too capable, since the goal was a cheap computer capable of running BASIC.
But, he did write a simple monitor (and burn it into PROM) before actually running BASIC. Just 256 bytes: No disassembler, just the ability to read/modify and execute hex bytes. Before Woz created the tape interface, you had to type BAISC into the monitor as hex every time you powered up the computer.
Time travel!