Hi again, > Questions over how a CPU works, what an assembler does, and how it all > fits together. I always recommend this book that explains Boolean > logic first and has you built a tiny CPU, write an assembler, > compiler, and virtual-machine runtime for a little language. The > Elements of Computing Systems: Building a Modern Computer from First > Principles. http://amzn.to/1qlmwCy
I'll try and give a very brief overview of the questions' subject. A high-level programming language lets one write code that looks like this. lives = lives - 1 if lives == 0 { print("Game Over!") } Even if you don't program, it's fairly understandly given the meaningful variable name, "lives", and the clue from the text string that's being printed. A compiler is a program that understands a particular high-level programming language and produces an equivalent program in assembly language. This is low-level. The above becomes LDA lives // Load the accumulator with the contents of address live. DEC A // Decrement accumulator. STA lives // Store the accumulator back to address live. BNZ endif // If the accumulator is non-zero, branch to endif. ADR str0 // Place the address str0 into the accumulator. PSH A // Push the accumulator onto the stack. JSR print // Jump to the subroutine, it will return here. .endif // ...Further on. .lives .EQUB 3 // Initial number of lives. (POKE this for more!) .str0 .EQUS "Game Over!" .EQUB 0 // ASCII NUL terminator. An assembly language is specific to a processor's instruction set, e.g. x86, amd64, ARM, 6502, Z80, Sparc, POWER, PIC, ... This means writing in assembly isn't portable between processors. In comparison, that high-level program above can be, and the high-level language needs learning once to program on many processors whereas assembly language needs learning afresh each time. A symbolic assembler is another program that takes the text file containing that assembly language and assembles it into a file of bytes containing the bit patterns that the processor needs. It's a one-to-one translation, for example a DEC instruction might be a byte where the top seven bits are ten, 0001010, and the bottom bit is 0 for the accumulator and 1 for the X register. `DEC A' is then `00010101' in binary, or 21 in decimal. Because binary numbers get long quickly, they're often written in base 16, hexadecimal. 00010101 is 15 in hex. The above assembly code becomes 10000100 // LDA lives 00010101 // DEC A 10100100 // STA lives 11101000 // BNZ endif 01000101 // ADR str0 00010001 // PSH A 00111001 // JSR print // ...Further on. 00000011 // .EQUB 3 01000111 // 'G'. 01100001 // 'a'. 01101101 // 'm'. 01100101 // 'e'. 00100000 // Space. 01001111 // 'O'. 01110110 // 'v'. 01100101 // 'e'. 01110010 // 'r'. 00100001 // '!'. 00000000 // .EQUB 0 Or as hex, 84 15 a4 e8 45 11 39 ... 03 47 61 6d 65 20 4f 76 65 72 21 00 Life without an assembler got boring quickly, forging life-long synapses, as those of us that have done it by hand can attest. (10 REM 0123456789012... RET is c9.) The output from the assembler is the "executable" that later ends up somewhere where the processor starts to execute it, one instruction at a time on each signal from the CPU's clock. The CPU's logic circuits made from transistors, the embodiment of the instruction set, are fed the bits making the instruction, with 1 bits being a voltage, and 0 being ground. They have the side effect the instruction represents, e.g. `DEC A', and the CPU starts on the next instruction on the next clock pulse. There's a bunch of videos working through from the electronics side from the guy that built the Megaprocessor. http://www.megaprocessor.com/stepping-stones.html Unlike the book, they're free. :-) Cheers, Ralph. -- Next meeting: Bournemouth, Tuesday, 2016-11-01 20:00 Meets, Mailing list, IRC, LinkedIn, ... http://dorset.lug.org.uk/ New thread: mailto:dorset@mailman.lug.org.uk / CHECK IF YOU'RE REPLYING Reporting bugs well: http://goo.gl/4Xue / TO THE LIST OR THE AUTHOR