Writing Code in Assembly

Jack Overby
Level Up Coding
Published in
4 min readJan 11, 2021

--

Shoutout to Wikipedia for all the detailed accounts of the early days of computing

So far, almost all the code featured in my weekly Medium articles has been written in JavaScript. There are several reasons for this- JavaScript was the main language used for functional programming in my bootcamp, so I became well-acquainted with it on a daily basis. Another reason, just as important, is that Google’s DevTools make it very easy to run JavaScript code in the browser. I frequently create functions and variables and test out my code before pasting the snippets in my articles.

Yet another reason is that, frankly, JavaScript is a pretty darn simple language to use. It’s probably the simplest OOP language out there. The commands are self-descriptive. It’s very easy to handle data, as you don’t have to declare the data types of variables (unlike C, C++ and others), and you can easily manipulate arrays and objects without having to invoke dreaded (for non-CS major schlubs like me, at least) pointers. That makes it an ideal language for coding bootcamps; someone with no knowledge of coding can, after a few hours of tutorials, write functions with loops, conditional statements, maps… that actually do things! It don’t take no genius to program in JavaScript (or Python, Ruby, R…).

The same cannot be said for low-level Assembly languages. Honestly, I think you do have to be some sort of genius to program in Assembly.

According to Wikipedia…

Kathleen Booth “is credited with inventing assembly language” based on theoretical work she began in 1947, while working on the ARC2 at Birkbeck, University of London following consultation by Andrew Booth (later her husband) with mathematician John von Neumann and physicist Herman Goldstine at the Institute for Advanced Study.

Yep, John von Neumann, a popular candidate for the Most Brilliant Human Being in the History of the World award- i.e. a bona fide genius. When Johnny V is involved, you know you’re dealing with some heady stuff!

Here’s an example of Assembly, used by the mid 1970s Motorola 6800 microprocessor:

; memcpy --
; Copy a block of memory from one location to another.
; Called as a subroutine, note return to saved PC addr on exit
; Entry parameters
; cnt - Number of bytes to copy
; src - Address of source data block
; dst - Address of target data block

cnt dw $0000 ; sets aside space for memory addr
src dw $0000 ; sets aside space for memory addr
dst dw $0000 ; sets aside space for memory addr

memcpy public
ldab cnt+1 ;Set B = cnt.L
beq check ;If cnt.L=0, goto check
loop ldx src ;Set IX = src
lda ix ;Load A from (src)
inx ;Set src = src+1
stx src
ldx dst ;Set IX = dst
sta ix ;Store A to (dst)
inx ;Set dst = dst+1
stx dst
decb ;Decr B
bne loop ;Repeat the loop
stab cnt+1 ;Set cnt.L = 0
check tst cnt+0 ;If cnt.H=0,
beq done ;Then quit
dec cnt+0 ;Decr cnt.H
; loop back and do 256*(cnt.H+1) more copies (B=0)
bra loop ;Repeat the loop
done rts ;Return

Apparently this a subroutine takes a block of memory from one place to another. Without the helpful comments, I would have guessed that this was the output of one of the million monkeys and their millions of typewriters trying to recreate Shakespeare. If I were to recreate this in JavaScript, it might look something like this… apologies in advance for the incomprehensibility, but I can barely understand this code myself!

function memcpy(cnt, src, dst) {
let B = cnt.L;
while (true) {
let ix = src;
src++;
ix = dst;
A = dst;
dst++;
B--;
if (cnt.L===0) {
if (cnt.H===0) return;
cnt.H--;
}
}
return;
}

Apparently this loop is performed 256*(cnt.H+1) times. 256 = 2⁸ = number of possible values of one byte, right? Who even knows.

Although this example was totally incoherent, here’s one more example of Assembly code that’s a bit easier to follow and whose output (the string “Hello, world!”) is far more sensible. Thanks to TutorialsPoint.com for this snippet:

section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov edx, len ;message length
mov ecx, msg ;message to write
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .datamsg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string

So basically, the program takes the length of the message (len), the message itself (msg), several “system call numbers” and then loops through and prints each character of the message, with the length of the loop being equal to the message length, as specified with len.

Conclusion

I hope you enjoyed this brief foray into Assembly programming. As befits a low-level language, the keywords are much less intuitive than for higher-level languages. Whereas you can glance at a JS, C++, Java or Python snippet and more or less follow what’s going on, Assembly is utterly bewildering even with line-by-line comments. Thanks to all the brilliant mathematicians, physicist and computer scientists who have made programming far more accessible and user-friendly over the years. Cheers to the geniuses!

P.S. Here’s a very nice repository of even more challenging Assembly code. Caveat programmator!

--

--