Although related and relevant to stacks, this gets a bit off-topic for 6502 assembly language, so it's an appendix. It's a portion of an email I wrote to a smart nephew who was thinking about what direction he wanted to go in programming and robotics as he started college.
Many programmable calculators use keystroke programming which means there's a single operation per program line, instead of many
operations on a line. For example, as you key in a program and need the cos function, you press the cos key and a line is added with
that single instruction. Here's an example, a portion from an actual test program we used where my HP-41cx calculator controlled the
automated testing of headsets. I added comments beyond the normal so you can better understand how a keystroke-programmed calculator
can control external instruments. I hope your monitor doesn't wrap the lines (here or in any of the other code).
90 LBL 04 \ Numeric label. Alphanumeric labels are allowed too, but they're less efficient in this case.
91 FC? 10 \ If it was testing the right earphone before (indicated by Flag 10 being Clear),
92 "0046" \ then connect the left instead. This string of digits (as text) is a command to the Cytec relay box.
93 "├01471145 " \ Add to string: Disconnect +13V from DMM line, and connect microphone DC voltage line to DMM line.
95 SELECT \ Now select the Cytec relay unit to talk to (whose address is #7 on the HPIB bus). It has 128 relays.
96 OUTA \ OUTput the Alpha register (now containing the text string of digits formed above) to it.
98 SELECT \ Now select the DMM (digital multimeter) to talk to (whose address is #22 on the bus),
99 IND \ and INput a Decimal number from it, which from previous set-up, makes it take a voltage reading and send it.
100 STO 17 \ STOre it in register 17.
101 FIX 02 \ Put the display mode in FIXed-point, showing two decimal places.
102 VIEW X \ Put the resulting reading in the display. It is also stored and will be printed later if operator chooses.
103 "01451142" \ Disconnect the mic DCV line from the DMM and connect the mic plug tip voltage (for push-to-talk test).
104 7 \ (The string of digits is a command to the relay box.)
105 SELECT \ As above, select the Cytec relay box to talk to.
106 OUTA \ Like line 96. The string in line 103 gets sent to the relay box.
108 SELECT \ Select the DMM again.
109 IND \ Like line 99. Get mic plug tip voltage to check for shorts to center ring or ground.
110 STO 14 \ STOre the voltage in register 14.
112 X<Y? \ Is 9V less than the tip voltage? (ie, is the tip voltage over 9V?)
113 GTO 05 \ If so, skip the problem message and go down to label 05. Normally it's at the voltage of the 13V power supply.
114 SF 08 \ Set Flag 08, signaling a problem.
115 FS? 09 \ Is Flag 09 Set? A "yes" mean it's in printout mode and should not stop with each problem but rather continue,
116 GTO 05 \ and skip the problem message in the display. (Resume down at label 05, and print all test results at the end.)
138 SELECT \ Get ready to talk to the DMM again. (22 is the bus address of the DMM.)
139 "ACV;R,5,.02" \ Tell it to get ready to measure AC voltage with a maximum of 5V input and give .02% (1mV) precision
140 OUTA \ (This sets the range and number of digits.)
151 SELECT \ Get ready to talk to the signal generator (which is at address 9 on the bus).
152 CLRDEV \ CLeaR DEVice (like a software reset).
153 INSTAT \ INput STATus to clear any error conditions that may exist.
154 "A.05P1I" \ Set Amplitude of signal generator to .05V (50mV) and enable output. The "I" makes it go ahead and execute
155 OUTA \ the command string. (Frequencies and amplitude adjustments come later.)
The program was 20 pages long and accessed a half-dozen files. Even from this little bit, you can see the workings of RPN keystroke
programming controlling a rack of equipment. Each piece of equipment also has its own command language like you see in the quoted
strings above. When people saw this in the 1980's, controlled by something that would fit in your pocket, they nearly needed a change
of clothes! :D As alluded here, the HP-41 does not allow variables, flags, and constants to have names, although labels
can, and programs and files always do. In most languages, you'll usually use names for variables, arrays, flags, constants,
etc.. The equivalent above would be to say for example DMM SELECT instead of
22 SELECT, where DMM would return the address of the DMM (digital multimeter); also something
like TIP_VOLTAGE (a variable's name) would be used in place of 14 which is the register number I chose to store
I suppose it's called "keystroke programming" because in the early days of programmable calculators, before they had way too many functions to give them all their own key (like my HP-41 with potentially thousands of functions), you'd just press the key (for example SIN, COS, LOG, etc.) giving the desired function when you're in program mode and it would be put in the program as a single step, without having to spell things out like you have to in other programming environments.
My very first programmable calculator (a TI-58c) did not have an alphanumeric display; so the display would show the program step number and just a number representing the function by the row and column of its key, making it kind of like the machine language corresponding to the keystroke programming being like the assembly language. (I don't know anything about its processor, or its true assembly and machine languages, but you can see the analogy I'm making.)
Calculator keystroke programming seems to bring quite a benefit later for grasping assembly language. Today, the grasp of assembly seems to be getting lost, and the common mentality is that the way around it is to just throw more processing power at the problem because it is getting cheaper and more available to waste.
So why would we still use assembly for anything? Suppose you need events on output pins to be .000001 seconds (1µs), ±5%, apart. (This would be irrelevant to the kind of programming <our daughter-in-law> does, but not to technical programming for controlling circuitry on the workbench, possibly including robotics.) If the processor is fast enough and a compiler for it produces efficient code, you may have the speed to do it; but you will not have control of the exact amount of time taken. For that, you need to use assembly. You won't have that kind of control in a higher-level language. (That's not to say the entire application needs to be written in assembly. Often it only takes a little assembly to meet the requirements, and the rest can be in a higher-level language.)
Some of the highest-performing microprocessors however have assembly languages that are totally impractical for a casual user to learn well; so people who can dedicate a large amount of time to understanding it write compilers so their customers (who are programmers) can use a common language like C and not bother with assembly. It seems to partly defeat the purpose, since assembly is the way to get maximum performance, yet to get maximum performance they have designed a processor you almost can't program in assembly! Still, good compilers can bring out some pretty good performance. (That's not to say all compilers do. For some processors, I've read of performance ratios of 5:1 or more from the best compiler to the worst, all for the same processor!)
Major arguments against assembly language are that you cannot do structured programming (which is not true at all), and the number of lines of code needed to do things. People making these arguments however are ignoring how much you can do with assembly macros. A macro is like a subroutine that the assembler executes in order to assemble portions of code exactly the way you defined in the macro, taking in the various parameters you specify when you call the macro in your source code. Macros offer a ton of flexibility—far more than initially meets the eye—and leave you in full control of the internal details without making you write them out or look them up every time you need them. They allow you to effectively raise the level of the language a lot, without losing any of the benefits of assembly. I have an article on my website about them, at http://wilsonminesco.com/StructureMacros/ which will interest you later. (Another criticism of assembly is the lack of portability. That is indeed a valid point; but note that when you use assembly to get the best performance from a given processor, the same processor can be used for a wider array of jobs, so the need to upgrade for the next one is reduced.)
[There's more on the relevance of assembly language today in my 6502-oriented article, "Assembly Language: Still Relevant Today."]
When I was starting out, I thought I wanted to learn every language out there that was related to my field (meaning I didn't care about ones like COBOL which is mostly for business applications, not science & engineering). I collected a half-dozen languages (which is a drop in the bucket compared to how many there are), but after I found Forth in about 1990, I didn't want any more. I was hooked, and I use it on the workbench computer for all kinds of things. Actually, it was originally developed primarily for robotics-type applications. Although a lot of spacecraft and some large commercial operations are programmed in Forth, Forth will never be very popular in industry, partly because it gives the programmer such freedom and flexibility that a supplier can't say, "You need to buy my new update because it adds this and that and the other capability," because the programmer will just say, "Good idea!" and go implement it himself and not buy the update; because Forth allows you to "get under the hood" and modify and extend even the compiler itself. Want a new operator? A new kind of structure? A very different kind of function? Make it. It's no problem, and your creation actually becomes part of the language. I don't know of any other language that allows that. It had the tools to do object-oriented programming (OOP) even before it was even called that. It kind of makes life difficult for a salesman. (Another interesting effect is that it makes good programmers better, and bad ones worse. So if you hear someone say it's an unreadable language, blame the programmer, not the language.) Managers might also feel less in control when the programmer has so much freedom. I will probably always work in tiny companies in niche markets though where I'm the whole department (or close to it), so I can do things however I want! :D :D I can still mix in some assembly whenever I need maximum performance and the tightest control of timing though.
Here's a teensy taste of what Forth looks like, heavily commented for non-Forth-speaking people. This routine called
232TYPE is for outputting a string of characters (like to print it) on the RS-232 device.
: 232TYPE ( addr len -- ) \ Start with the address and length of the string on the data stack, and return nothing at the end.
BOUNDS \ Turn address and length of string into beginning address and ending addresses.
?DO \ Do this loop once per character. If beginning and end address match, length is 0, so skip the loop.
I C@ 232EMIT \ Get loop counter (the address of next character), fetch character at that address, & call "232EMIT".
232ERR @ \ Read variable 232ERR to see if 232EMIT flagged any error conditions. (0 means no errors.)
IF CONSOLE LEAVE THEN \ If it did, put the output device back to console (primary display), and leave the loop.
There is no punctuation in Forth, and almost no syntax requirements. (Even the things that look like punctuation are actually words with
very short names.) There are no piles of parentheses. Parentheses are for comments, particularly where you might want to continue
compiling after the comment, on the same line.
last updated Nov 7, 2017