Skip to main content

Two-digit Numeric Display

Photo by Nick Hillier on Unsplash


Hi! I'm continuing my blog about my SPO classes. After a brief introduction in Assembly, we are good to hit Lab3. Our instructor kindly let us choose one project out of five. And of course, we decided to go with the easiest!

We had to do a two-digit numeric display where the numbers are incremented or decremented by pressing plus and minus key in the keyboard. Soon the challenges were reviled as we dive into how to code it. Should we treat every digit separated or together? How to print them into the display?

After a moment of reflection, we decided to handle the digits independently to facilitate the printing display. Also, we had to add a bit-map representation of the numbers because the 6502 chip doesn’t know any font.

In this post, I’ll show you the code with the logic to increment and decrement without displaying anything. You can monitor the address $13 and $14 to make sure that it is working.

Let me explain how it works. When the program starts, it will set $13 and $14 to zero, and then it will fall into the infinite loop called “main.” This loop will know if one of the keys was pressed and then jump to the proper function. Let’s say that you hit the plus key. It will call the “incr_l” subroutine,  incrementing the low digit and checking if it is more than 9 (#$0A). If so, it will call the “incr_h” that will increment the high digit and set the low digit to zero. If the high digit gets more than 9, the counter resets to zero. The same logic is applied to decrementing, but instead, it limits at zero and reset it to 99.

In the next post, I’ll add the numeric display. See you.


; zero-page variable locations
define NUM_H $13
define NUM_L $14
lda #$00
reset:
sta NUM_H
sta NUM_L
main:
lda $ff ; get a keystroke
ldx #$00 ; clear out the key buffer
stx $ff
cmp #$71 ; handle q -> increment
beq incr_l
cmp #$77 ; handle w -> decrement
beq decr_l
jmp main ; if no key pressed loop forever
incr_l:
ldy NUM_L
iny
cpy #$0A
beq incr_h
sty NUM_L
jmp main
incr_h:
ldy NUM_H
iny
cpy #$0A
beq reset_incr
sty NUM_H
ldy #$00
sty NUM_L
jmp main
reset_incr:
lda #$00
jmp reset
decr_l:
ldy NUM_L
dey
cpy #$FF
beq decr_h
sty NUM_L
jmp main
decr_h:
ldy NUM_H
dey
cpy #$FF
beq reset_decr
sty NUM_H
ldy #$09
sty NUM_L
jmp main
reset_decr:
lda #$09
jmp reset
view raw spo-lab3-1.s hosted with ❤ by GitHub

Comments

Popular posts from this blog

Going Faster

Photo by  Anders Jildén  on  Unsplash Today’s topic is compiler optimizations. Besides translating our source code into machine binary executable, the compiler, based on optimization parameters, can also produce faster executables. Just by adding some parameters to the compiler, we can get a better performance or a smaller executable, for example. There are hundreds of those parameters which we can turn on or off using the prefix -f and -fno. However, instead of doing one by one, we can use the features mode using the -O param. It ranges from 0 (no optimization – the default) to 3 (the highest). Using those parameters has a cost —usually, the faster, the larger executable. How does the compiler make it faster if my code is perfect? I’m going to put some methods here, but if you want, here is more detail . Also, bear in mind that most of the optimizations are done in the intermediate representation of the program. So, the examples below are rewritten just to...

Hello World in Assembly

Photo by  Martin Sanchez  on  Unsplash Assembly alert! I promised to talk more about the compiler, but before it, more assembly. It is for a good reason, though. I was surprised to see my professor doing the “hello world” in assembly! Not only on x86_64 but also in the ARMv8 – different source code. He coded just like C or C++, saved, compiled and run it. The output was exactly like any other language. Nobody knew, but he was doing the Lab 5! I wish I were recording it. Our goal in this class was to compare the compiler output with the hand-crafted assembly. As expected, the compiler produced non-optimal executables even when we played with some fine-tuning options that I mentioned in the last post. How to compile an assembly code? Here are the commands: - Using GNU Assembler > as -g -o test.o test.s > ld -o test test.o - Using NASM Assembler > nasm -g -f elf64 -o test.o test.s > ld -o test test.o - Using GCC > gcc -g -o test.o test.S ...

SIMD - Single Instruction Multiple Data

Photo by  Vladimir Patkachakov  on  Unsplash Hi! Today’s lecture, we learned SIMD - Single Instruction Multiple Data. This is a great tool to process data in a bulk fashion. So, instead of doing one by one, based on the variable size, we can do 16, 8, 4 or 2 at the time. This technique is called auto-vectorization resources, and it falls into the category of machine instruction optimization that I mentioned in my last post. If the machine is SIMD enabled, the compiler can use it when translating a sum loop, for example. If we are summing 8 bits numbers, using SIMD, it will be 16 times faster. However, the compiler can figure that it is not safe to use SIMD due to overlapping or non-aligned data. In fact, the compiler will not apply SIMD in most cases, so we need to get our hands dirty and inject some assembly. I’ll show you how to do it in a second. Here are the lanes of the 128-bit AArch64 Advanced SIMD: 16 x 8 bits 8 x 16 bits 4 x 32 bits 2 x 64 bits 1 x ...