ORIGINALLY PUBLISHED IN LIMA NEWSLETTER MARCH 1994 Assembler Executing #4 By Bob Carmany I'm not sure whether it was out of friendship or revenge but Ron Kleinschafer sent along a great heap of A/L source code for me to examine. Not just a few files but an entire disk full of the stuff! Commented source code --this ought to be easy enough to understand ---WRONG!!! After a couple of hours (with my trusty elementary text in hand) a few rays of light penetrated the darkness! This was great stuff and I was even starting to understand a bit of what he did! It did make my head ache, though! Anyway, I learned a couple of things from reading all of that code --- It takes a heap of code to construct a meaningful program and there are several ways to get the same job done. As an example, let's take a look at something simple --a loop. That is an easy and painless start! For the purposes of this illustration, we will assume that the guts of the loop are coded identically and only a few selected lines will change. You will see what I mean when we get into the program segment. Let's start with the first one: LI R6,4 Load the loop limit (4) into register 6 | | LOOP | loop contents and instructions | | | | AI R6,-1 Add -1 to the loop counter in R6 after each pass JNE LOOP Compare the result of the arithmetic function to zero and jump back to rerun LOOP if not equal to zero Easy enough so far! But, being a sneaky and devious language, there is another simple way to do the very same thing. LI R6,4 Load loop limit (4) into register 6 | | LOOP | | loop contents and instructions | | | | DEC R6 Decrement R6 by one JNE LOOP Same as the first example These are just two examples of how to code the very same idea in different ways. In the examples we used A(dd)I(mmediate) and DEC(rement) to effectively reduce the value in R6 by one in each iteration of the loop until a value of zero was reached at which time control was passed to another program segment. Of course, the converse is true as well. By using a positive value after AI, we can create an incrementing loop. The AI instruction can be replaced just as easily by INC(rement). So we have created to instructions that perform the same function. AI R6,1 and INC R6 An incrementing loop takes a bit more "engineering" to switch control when the loop limit has been reached but that is a minor inconvenience. In fact, even with my feeble experience in A/L programming I can think of four or five other ways to construct a basic loop --either decrementing or incrementing it as the case may be. I guess that we are just about done with the preliminaries. We have covered addressing modes, number conversions, and figured out that there is no "right way" to write an A/L program --just different ways. Now we can start a bit of poking about! Before we get started, there are a few definitions that we have to become familiar with so we know what we are doing (?). Bit - a single binary digit Niblet - two bits Nibble - Four bits Byte - eight bits Word - two bytes (16 bits) Ok, since I've hacked about a bit in A/L I have discovered that there are some instructions that are used a lot more than others. The whole lot of them fits into a series of categories. It's time to look at one of them. These are the instructions that move data about in a program Name OpCode Comments ~~~~ ~~~~~~ ~~~~~~~~ Move Word MOV This instruction can use any of the 5 general addressing modes Move Byte MOVB Same as above Swap Bytes SWPB Same as above Load Immediate LI Register direct mode using immediate addressing Load Wkspace poi LWPI Immediate addressing Load Int Mask Im LIMI Immediate addressing Store Wkspace P STWP Register direct mode Store Status STST Register direct mode Shift Rt Logical SRL Register direct mode with a count value Shift Rt Arith SRA Same as above Shift Rt Circ. SRC Same as above Shift Left Arith SLA Same as above The most commonly used instructions are the first five and the last four in the list. Even amongst that group, there are a couple that do most of the work and we will take a look at them now. MOV Source operand, Destination Operand example: MOV R1,R6 moves (or copies) the contents of R1 into R6 MOVB does the same thing except that it moves just 8 bits instead of 16 like MOV does. LI Register, Operand example: LI R1,10 loads 10 into R1 LWPI functions the same except that the operand is loaded into a workspace. SWPB Register example: SWPB R7 Swaps or switches the right and left bytes of the word in R7. All of this has made me a bit thirsty. It's time to satisfy the inner man. I hope that you will see where all of this is headed as I try to cope with the rest of this A/L stuff that Tony and Ron got me started on. Oh well, jot down some notes and I'll continue this next month and hopefully it will lead somewhere besides insanity!