Presentation
of assembler code for quick reader
|
Synopsis Some bloke wrote code that was difficult to understand. I rewrote it in such a way that the object code would be the same, and yet the source would be clear to the reader. I felt that some important principles were demonstrated. An Aside I returned to this in June 2006 because I just found the listings that illustrate the point I wanted to make. That is included below. September 2009. This item invoked a hostile response when posted in 2006, including the suggestion that I should do it in some easy and established way. I followed this up and explored some "Bit Font Editor" programs. One that looks as if it is free on the web, but what you get for nothing is only a 15 day evaluation, is "Bit Font Creator". This looks good, and I would use it if I had the work for it. In a task such as that described here, it won't do anything that you can't do just as easily here for nothing. If you use Bit Font Creator, your task might run smoothly, but you still will end up with code that is full of apparently meaningless magic numbers, and a maintenance problem. So unless you know how to incorporate a Bit Font program into your make file, read on for maintainable code. I still offer this suggestion to readers with my head held high. August 2015. I have just discovered that the version of this on my website is “broken”. Fixed now. You will see below that I have included the hex number fields (under shelter of the comment operator ";") to provide a contrast of the readability of the hex and pictorial representations, and to show how my contributions fit into the original code. In the 2006 posting of this, there was actually a mistake with the matching of the hex and pictorial, which I have only just discovered now. I hadn't picked it up before, and neither had those people who had read the article earlier and furnished comments. This proves my point. The mistake was obscure and not easily picked up BECAUSE it involved a mismatch of MAGIC NUMBERS. Here is the article that set me off: |
|
As I understand it, it is common for c compilers to have provision for entering data as hexadecimal, but not as binary. If the data to be entered has meaning as a pattern of bits, but not as a hex number, then this limitation can lead to obscurity. The obscurity in turn leads to increased probability of mistakes and more difficult maintenance. I have discussed this with expert c programmers, and we have surmised that the limitation can be overcome by establishing an ad hoc local presentation format with a bunch of #define statements. The example I have here is assembler code, not c, so the solution lies with the "equ" directive. The original author of the code snippet in question wanted to present some pixel patterns. Perhaps he laid out his pixel patterns on graph paper, and then worked out which bits should be "1" and which should be "0", then grouped them together into bytes and transformed them to hexadecimal numbers. Then he would have had to turn to his editor and entered them into his program. Alternatively, maybe he used a Bit Font Editor. If so, he didn't say that in his article. The result was:
Now look at that bit pattern. Look at the lovely curves of the
shape that is created by those pixels! Isn't it great!? NO IT
ISN'T. There is another way. The pixel pattern in question is an 8 by
8 pattern of dots in a dot matrix character presentation for a
liquid crystal display. Why not write out the desired pattern so
that we can see the character in the 8 by 8 format in the listing?
I chose the underscore character as a character that makes a
minimum impact on the white background, and the octothorp "#"
(sometimes called "hash") as a character that makes a
nice contrasty blotch that occupies the centre of the character
location. The particular requirement is for a byte to represent
each row of pixels. Thus we need to map a row of underscores and
octothorps that visually represent the row of pixels as they would
appear on the display to a form that the assembler can use. Here
is my mapping in a file called bit_patt.ern
You will notice that I have used the assembler's binary notion
facility here. If I had been writing a file of "#define"
to go into a c program, I could have made the file use hexadecimal
notation. It would have just taken longer to create. It would be
tedious indeed to write out that mapping, but this is a perfect
application for a simple BASIC compiler. Here
is my BASIC program that generates the mapping . I bet I wrote
the BASIC program and generated the file that establishes the
mapping in less time that the other bloke took to set out his
pixels with the graph paper. Now all I have to write in the
assembler file is: This enables me to write my program in a way that shows what the pixel pattern will look like. Now, just imagine that some special character has to be generated in the application and a new pixel pattern is required for it. Which program would be easiest to edit to add the new character? The one with the hexadecimal data, or mine? |
*----------------------------------------------------------------*
* FILENAME - DISP.ASM *
* Derived from - "Circle 521" Improved Lower Case On LCDs *
* by Jay Sarno *
* page 100 ELECTRONIC DESIGN AUGUST 1996 *
*----------------------------------------------------------------*
* SYNOPSYS *
* Work in Progress *
* *
* *
* *
*----------------------------------------------------------------*
* PROJECT I just wanted to make a point *
*----------------------------------------------------------------*
* REVISION HISTORY typed in from magazine. 07-10-96 *
* 1. Added EXTERN declaration to cover subroutines that are not *
* here *
* 2. Appended "a" to the beginning of all labels that start with *
* "1" *
* to meet X68C11 assembler requirements. *
* Assembles without error, but no listing generated. *
* 3. Added a "CODE" directive. *
* *
*----------------------------------------------------------------*
*
LINKLIST
LIST ON
EXTERN set_lcd_write,send_lcd_cntl,send_lcd_data
CODE
******************************************************************
* LOAD_CG - Call this routine as part of system *
* initialization. *
* It loads the first 5 programmable characters in the *
* LCD display with improved versions of *
* "g", "j", "p", "q" and "y". *
******************************************************************
load_cg:
jsr set_lcd_write ;display's R/W bit low (write)
ldab #$40 ;sets display to receive CG data
jsr send_lcd_cntl ;set the CG address register to 0
ldx #a1c_char_gen ;point to the table with the new
; g,j,p,q,y
ldy #40 ;set up a loopcounter
lcg_loop:
ldab 0,x ;get a row of CG bits
jsr send_lcd_data ;send it to the LCD display
inx ;advance the pointer
dey ;decrement the loopcounter
bne lcg_loop
rts
a1c_char_gen:
; Jay Sarno's pixel pattern table looked like this -
; fcb $00,$00,$0f,$11,$11,$0f,$01,$0e
; fcb $02,$00,$06,$02,$02,$02,$12,$0c
; fcb $00,$00,$1e,$11,$11,$1e,$10,$10
; fcb $00,$00,$0d,$13,$11,$0f,$01,$01
; fcb $00,$00,$11,$11,$11,$0f,$01,$0e
; Actual pixel patterns are completely obscured by this
; presentation.
; Try a binary presentation where each "1" is represented by a "#
; for maximum visual impression, and each "0" by a "_" for min.
; visual impact. This will cause each byte to be represented by a
; label made up of "#" and "_" characters.
; We need to provide a numeric value for each of these labels.
; The BASIC program DISPMAC.BAS builds a file bit_patt.ern
; that does this.
INCLUDE bit_patt.ern
; fcb $00,$00,$0f,$11,$11,$0f,$01,$0e
fcb A________
fcb A________
fcb A____####
fcb A___#___#
fcb A___#___#
fcb A____####
fcb A_______#
fcb A____###_
; fcb $02,$00,$06,$02,$02,$02,$12,$0c
fcb A______#_
fcb A________
fcb A_____##_
fcb A______#_
fcb A______#_
fcb A______#_
fcb A___#__#_
fcb A____##__
; fcb $00,$00,$1e,$11,$11,$1e,$10,$10
fcb A________
fcb A________
fcb A___####_
fcb A___#___#
fcb A___#___#
fcb A___####_
fcb A___#____
fcb A___#____
; This is the data he had for a "q"
; I guess you had to see it on the display
; It looks like a funny q to me. Anyway, it is very easy
; to edit the character in the field of "_" and "#" characters.
; fcb $00,$00,$0d,$13,$11,$0f,$01,$01
fcb A________
fcb A________
fcb A____##_#
fcb A___#__##
fcb A___#___#
fcb A____####
fcb A_______#
fcb A_______#
; fcb $00,$00,$11,$11,$11,$0f,$01,$0e
fcb A________
fcb A________
fcb A___#___#
fcb A___#___#
fcb A___#___#
fcb A____####
fcb A_______#
fcb A____###_
*****************************************************************
* DISPLAY_CHAR - The character in B is sent to the display.*
* Any lower case character with a descender is translated *
* to the "improved" character code. *
*****************************************************************
display_char:
jsr set_lcd_write ;display's R/W bit low (write)
clra ;count
ldx #chars_to_fix ;points to table of 1c chars to
;change
a1c_hunt_loop:
cmpb 0,x ;see if a match to a descender
;character
beq a1c_translate ;if it matches, translate it
inx ;next character to check
inca ;keep count
cmpa #5
blo a1c_hunt_loop
bra char_ok_as_is ;this char doesn't match any
;in the table
a1c_translate:
tab ;the "count" is the translated
;char code
char_ok_as_is:
jsr send_lcd_data ;send it to the LCD display
rts
chars_to_fix:
fcb 'g','j','p','q','y'
end