Is there a difference between a programmer and coder, a program and code? If there are differences, what are they, and is there history behind them? Let's explore these questions by figuring out how to make a computer complete an often needed task, extracting substrings from a larger string.
Our test string for this algorithm will be:
...and I quote, "Seize the memes of production!", end quote. "monkaS"
What we want to do is extract everything enclosed in double quotes ("), putting it in one area of memory, and move the rest to another area of memory. The result should be an area of memory containing the enclosed substrings, each terminated by our chosen terminator character ($), and an area of memory with the rest of the string also terminated by the same character:
...and I quote, , end quote.$
Seize the memes of production!$monkaS$
What is a programmer? A programmer is simply someone who writes programs. Ok fine, then what is a program? The answer to this is just as simple, a program is a sequence of operations designed to perform a specific task. This task can be as mundane as moving data from an I/O port to RAM, or as complex as controlling and allocating a system's resources (aka a kernel or OS). Ideally a program is system-agnostic, that is, it's not dependent on the quirks of a particular hardware environment on which it is running or the language the program is implemented in. A programmer is the middle-man in the process of software development, between the software engineers and the coders. As time has progressed, these lines have become blurred, but are still relevant.
Figure 1 - Program Flowchart for Substring Extraction Algorithm
We know programmers can write programs without regard to a particular computer architecture. It follows, therefore, that programmer can write programs without ever touching a computer or any other electronics. In fact, in the early days of computing, programmers were kept away from computers and had to take their programs to an operator who would put them onto punchcards, then the programmers would submit their punchcards to computer operators who would run them on computers when there was time to do so. After the program was run, the operators would return the punchcards as well as the program's output (on punchcards or printouts) to the programmers for analysis.
Figure 2 - Program Implementation in IA-32 Assembly Language
In the 90s I wrote programs using graph paper and a pencil, and back then there was no shortage of books that included program flowcharts. These programs were implemented using a particular programming language, which in the books I read was usually some dialect of Assembly. Having the program flowcharts allowed readers to more easily understand the overall program flow and algorithms without knowing Assembly, as well as simplified coding the program using languages other than those in the books. This also brings up an unrelated point...programmers don't always need to be good at math. Many think of complex equations when they hear the word "algorithm"; however, an algorithm is just a better way of stating what we've already said - a set of steps to perform a function or solve a problem.
We see in Figure 1 an algorithm for extracting substrings from a string. The algorithm is given the address of a source string and the addresses of two destination strings, as well as a delimiter character and termination character. It goes through the source string looking for the delimeter character. In this program flowchart there is nothing that is architecture or language-specific; it is written as generically as is reasonably possible. We could implement this program for any architecutre, for example using Assembly language for the MCS-51 or the x86, as well as using any other language.
At this point we could throw the flowchart over the wall to some coders who would implement it in code. Figuring out how to get it to work in a specific language or in a particular system is their problem, not ours.
Figure 3 - Program Implementation in MCS-51 Assembly Language
But...what if we are the coder who has just been bonked in the head by a program carelessly tossed over the wall by a programmer who has zero regard for health and safety regulations or labor laws (you know, the type of person I am)?
Figure 4 - MCS-51 Output
Figure 2 shows the extraction algorithm implemented using IA-32 assembly language. This is the program's code written in that language. The code has plenty of comments, partially for the benefit of people who aren't familiar with assembly languages, and partially to allow you to match up portions of the code with steps in the program. Those who pay attention to details will notice the IA-32 implementation doesnt show address manipulations. This is because those manipulations are implicit in the processor's string instructions (LODS and STOS). Of course, the program could have been implemented with separate move (MOV) and increment (INC) instructions rather than string instructions. Good observers will notice the code makes use of word-sized instead of byte-sized string instructions. The reason for this is because the 386+ processors generally expect data to be aligned on even addresses, and 286 processors are a bit faster accessing even addresses over odd addresses. As an EE and x86 afficinado I could go on about why this is, but it's out of the scope of this post.
Moving to Figure 3, we see the 8051 implementation of our algorithm. Some of the instruction mnemonics are different, as is the register set and method used to access memory. In this implementation address manipulations are explicit (INC DPTR), and there is more code due to the need to exchange the contents of DPTR with other registers holding addresses (R0, R1, R2, R3). The method required to save registers also contributes to increased code size. Both of these issues can be somewhat alleviated by using direct-addressing of the registers (example PUSH 0x00 to push R0 onto the stack), but that reduces the flexibility of this implementation. Finally, we see this implementation is able to make use of hardware flags (F0 & F1), rather than bits within a general purpose register, for the delimiter found and data found flags.
The output of the MCS-51 implementation is shown in Figure 4. The original string appears in RAM at 0x1000, with the extracted substrings at 0x1140, and the "leftovers" at 0x1100.
The last code example in figure 5 is one that's not been tested. My MCS-80/85 is a bit dusty even though I used to write code for the 8080 and 8085 in the 90s, so this example probably has some minor bugs. It could have major bugs for all I know, I wrote it in one pass from start to finish. This is one great thing about writing a program flowchart before you begin coding. I was able to get the basic structure of the code written without thinking about how the program needs to flow.
Figure 5 - Draft Program Implementation in MCS-80/85 Assembly Language
Because this architecture doesn't have enough registers to hold all of the operands needed by the algorithm, we need to pass some via the stack. As someone who has done processor design, it irritates me to no end when people and compilers abuse...erm I mean use...the stack instead of registers for parameter passing. Sometimes we don't have much of a choice, and this is one of those times. Rather than make it odd by passing only two bytes via the stack, Ive placed all the parameters except the source address on the stack. During execution both destination addresses are altered in-situ on the stack, well, as close as the 8085 can get to doing that. The destination address being manipulated must still be brought into the processor for alteration, then written back out to the stack. The stack pointer is not altered here, which is important to maintain system stability. Stack locations are accessed using the DE register pair. On a related note, Zilog helped alleviate the problem of not having enough registers for addressing by adding IX and IY registers in their Z80 processor, which is largely binary-compatible with the 8080/85.
If you got this far, thanks for taking the time out of your day to give this a read! I hope you enjoyed this bit on the difference between a programmer/programming and a coder/coding. These days the two are often used interchangably because programmers are also usually able to code in at least one language. However, there is still a difference between the two, and as an electrical engineer who is accustomed to the need for specificity, it sometimes gets on my nerves when people toss around the wrong terms.
If anyone is looking for the code to copypasta, I don't give that out. I think there is far too much codepasta going on these days among hobbiests and people learning to code (even among veteran coders too). I'm not going to contribute to people being monkeys who just codepasta while hopping up and down on the keyboard. I want people to treat programming and coding as professionals would, even if its not their profession. It doesn't take much to do that. If you want to give the code a try, type it out, you'll actually use your brain and also learn something doing that way. Maybe you'll find some mistakes I missed while writing the code.