Quantcast
Channel: Oracle Bloggers
Viewing all articles
Browse latest Browse all 19780

Retro computing, looking backwards?

$
0
0

One of the areas of computing that fascinates me is that of retro computing. I grew up with the ZX Spectrum in the late 80s / early 90s, and have continued using it ever since, mostly under emulation these days, although the hardware still works perfectly when I have the chance to get it out! This was a home computer line using the Z80A CPU at its heart, and I guess I could say I cut my programming teeth on it, first BASIC then later making the switch to assembler.

I enjoy seeing those old home micros do things that at the time would have been deemed impossible. I've seen full-screen video, in colour (which if you're familiar with the Spectrum's quirky display file, is impressive), complete with audio, streaming from a hard disk. I've seen a Twitter client via a Spectranet ethernet interface. I've seen TV-beam-racing visual effects giving a higher colour resolution than is technically possible given the hardware. All of these things are as a result of squeezing every last ounce of power out of the hardware available.

One of my current personal projects is the creation of a Unix-style kernel for the disc-based Spectrum +3 system, implementing preemptive multitasking, and separation of kernel from userland.

Whilst developing on such a limited platform, I have had cause to examine the efficiency of code produced either by hand or by compiler, and realised that sometimes we can get something almost free. One such example is a test to coalesce adjacent free memory blocks into a single free block. Originally, this was created using a pair of if() statements, to coalesce with the adjacent block, in both directions:

f = l = seg_to_free;if (f->seg_prev && f->seg_prev->seg_state == FREE) {
  f = f->seg_prev;
}if (l->seg_next && l->seg_next->seg_state == FREE) {
  l = l->seg_next;
} 

At the end of this, 'f' will point to the first consecutive segment which is free, and 'l' points to the last. Either or both may still point to the original 'seg_to_free', which is perfectly valid, and everything from f->l (inclusive) is also free and can be coalesced into one single free segment.

Whilst there's nothing wrong with this, we can improve the robustness of this by making them into loops. In practice, there should only ever be one free segment either side, but what if there was an unexpected condition or a bug which broke this assumption? Code based on "if" would only ever coalesce at most 3 segments into one, and the error would effectively propagate throughout the system until perhaps something crashed, or memory was leaked or fragmented beyond repair.

Now here's the beauty of it - there is little difference between an if() and a while() in this case. They both break down to the following pseudo-code sequence:

Using 'if' Using 'while'
start:
  Test f->prev
  - Jump to 'end' if NULL
  Test f->prev->state
  - Jump to 'end' if not FREE
  Assign f->prev to 'f'.

 

end:
start:
  Test f->prev
  - Jump to 'end' if NULL
  Test f->prev->state
  - Jump to 'end' if not FREE
  Assign f->prev to 'f'.
  *Jump to start*
end: 

So in this little example, the only additional cost for a while loop is the "jump to start" instruction, and for a Z80 chip, that only costs 2 bytes - one for the 'jr' (jump relative) opcode, and a one byte, two's complement displacement.

Now the cost is a little higher for the Studio 12 C compiler (using -xO2 optimisation) for x86, but there are other considerations on modern hardware such as branch prediction and avoiding disruption to the instruction pipeline with unnecessary jumps where possible. Hence there is a certain amount of loop unrolling with regards to the expression being tested, but the gain in robustness of the code may well outweigh the (modest) increase in instruction stream.

Obviously, in this particular case, this approach could potentially hide a bug, but I'd rather have a stable platform on which to diagnose such an issue instead of constant memory corruption and, in the case of a Spectrum, a complete memory wipe if something goes wrong - not the easiest of things to diagnose!

OK, this is a fairly trivial example, and each situation needs to be assessed on its own merits, but sometimes programming in a limited environment can give a different perspective on how to write code efficiently for modern systems. At least, I like to think it's helped me to do so.



Viewing all articles
Browse latest Browse all 19780

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>