D
Daniel Pitts
- Jan 1, 1970
- 0
Actually _Real_ men program with switches and buttons
Actually _Real_ men program with switches and buttons
John Larkin said:Real men build dams and chop down trees and sail ships. We're
engineers.
John
So what do real engineers do?
John said:A program is easy to maintain if it's logical, has sensible data
structures, and most importantly if it's thoroughly and correctly
commented.
Most C programmers comment little if any, apparently by
tradition and training. My assembly programs are extensively commented
- roughly 4x as many characters of comment compared to code - and are
easy to understand and maintain years later.
And I always have a
single batch file, GO.BAT, that completely rebuilds the entire project
and makes a new rom file, and we archive all the tools.
I think the one-operation-per-line and resulting ease of commenting
make assembly a lot easier to read than the
monkeys-pounding-typewriters look of C. If you read my comments,
you'll know exactly what's happening and why.
.SBTTL . XMAC : MACRO EXECUTION ENGINE
; THIS IS ENTERED WITH A0 AIMING AT A MACRO CODE FOLLOWED BY A
; PARAMETER LIST. THIS IS USUALLY IN VME SPACE, BUT CAN BE IN ROM
; WHEN THAT'S USEFUL. WE ALWAYS COPY THE COMMAND AND PARAMETERS
; INTO THE 'MAC' SPACE IN CPU RAM, TO ALLOW ROM INVOCATIONS AND
; TO SPEED UP MACRO EXECUTIONS, ESPECIALLY FOURIER FUNCTIONS.
;
; WE'LL TRY TO EXECUTE THE MACRO, AND WILL RETURN STATUS
; IN D7. B15 WILL BE UP IF WE DETECT AN ERROR.
XMAC: CLR.W AFLAG.W ; NUKE 'ADD WAVE' REQUEST
MOVE.W # 0FF00h, D7 ; ERROR CODE 255 WILL BE 'BAD MACRO'
MOVE.W (A0), D0 ; NAB CALLER'S COMMAND CODE
ANDI.W # 255, D0 ; ISOLATE LOW BYTE
CMPI.W # MAXIM, D0 ; CHECK AGAINST LIMIT
BHI BADMAC ; POST ERROR IF OUT OF RANGE.
; NOW COPY THE ENTIRE COMMAND BLOCK...
MOVEA.W # MAC, A1 ; AIM AT DESTINATION IN CPU RAM
MOVE.W # 110, D6 ; MAKE DBF COUNT FOR COMMAND+110 PARAMS
FILCH: MOVE.W (A0)+, (A1)+ ; COPY, WORDWISE.
DBF D6, FILCH
ASL.W # 1, D0 ; SCALE CMD * 2 FOR WORD LOOKUP
ADDI.W # DISMAL, D0 ; ADD IN TABLE START
MOVEA.W D0, A1 ; COPY TO AN ADDRESS REG
MOVEA.W (A1), A1 ; POP THE ROUTINE ADDRESS
JMP (A1) ; AND HOP TO IT.
; ALL COMMAND ERRORS JUMP HERE:
BADMAC: ORI.W # B15, D7 ; POST THE 'MACRO ERROR' CODE
CLR.B D7 ; AND NUKE 'COMMAND CODE' FIELD
RTS ; (BITS 8-14 HOLD ERROR CODES)
; AND SUCESSFUL MACROS EXIT HERE:
OKAY: CLR.W D7 ; HERE, INDICATE GOODNESS
RTS
.SBTTL . MACRO COMMAND DISPATCH TABLE
DISMAL: .WORD BADMAC ; 00 ILLEGAL COMMAND
.WORD FOURS ; 01 BUILD FOURIER SERIES
<<SNIP>>
.WORD URAM ; 26 TEST CPU SRAM
MAXIM = 26h ; LAST LEGAL MACRO CODE
John said:A program is easy to maintain if it's logical, has sensible data
structures, and most importantly if it's thoroughly and correctly
commented.
Hear, hear!
Most C programmers comment little if any, apparently by
tradition and training. My assembly programs are extensively commented
- roughly 4x as many characters of comment compared to code - and are
easy to understand and maintain years later.
If variables, functions etc are named properly, then code in high-level
languages is much more self documenting (than if it's not - this is not
necessarily in comparison to assembler), and the need for comments is
reduced. By no means removed.
And I always have a
single batch file, GO.BAT, that completely rebuilds the entire project
and makes a new rom file, and we archive all the tools.
Ahah - a Makefile! B-)I think the one-operation-per-line and resulting ease of commenting
make assembly a lot easier to read than the
monkeys-pounding-typewriters look of C. If you read my comments,
you'll know exactly what's happening and why.
But you need so many lines! And the comments have to be kept up-to-date
and accurate (or they're worse than not having any at all), which adds
to the maintenance burden which is already exacerbated by having 10
times as many lines of code in the first place...
.SBTTL . XMAC : MACRO EXECUTION ENGINE
; THIS IS ENTERED WITH A0 AIMING AT A MACRO CODE FOLLOWED BY A
; PARAMETER LIST. THIS IS USUALLY IN VME SPACE, BUT CAN BE IN ROM
; WHEN THAT'S USEFUL. WE ALWAYS COPY THE COMMAND AND PARAMETERS
; INTO THE 'MAC' SPACE IN CPU RAM, TO ALLOW ROM INVOCATIONS AND
; TO SPEED UP MACRO EXECUTIONS, ESPECIALLY FOURIER FUNCTIONS.
;
; WE'LL TRY TO EXECUTE THE MACRO, AND WILL RETURN STATUS
; IN D7. B15 WILL BE UP IF WE DETECT AN ERROR.
XMAC: CLR.W AFLAG.W ; NUKE 'ADD WAVE' REQUEST
MOVE.W # 0FF00h, D7 ; ERROR CODE 255 WILL BE 'BAD MACRO'
MOVE.W (A0), D0 ; NAB CALLER'S COMMAND CODE
ANDI.W # 255, D0 ; ISOLATE LOW BYTE
CMPI.W # MAXIM, D0 ; CHECK AGAINST LIMIT
BHI BADMAC ; POST ERROR IF OUT OF RANGE.
; NOW COPY THE ENTIRE COMMAND BLOCK...
MOVEA.W # MAC, A1 ; AIM AT DESTINATION IN CPU RAM
MOVE.W # 110, D6 ; MAKE DBF COUNT FOR COMMAND+110 PARAMS
FILCH: MOVE.W (A0)+, (A1)+ ; COPY, WORDWISE.
DBF D6, FILCH
ASL.W # 1, D0 ; SCALE CMD * 2 FOR WORD LOOKUP
ADDI.W # DISMAL, D0 ; ADD IN TABLE START
MOVEA.W D0, A1 ; COPY TO AN ADDRESS REG
MOVEA.W (A1), A1 ; POP THE ROUTINE ADDRESS
JMP (A1) ; AND HOP TO IT.
; ALL COMMAND ERRORS JUMP HERE:
BADMAC: ORI.W # B15, D7 ; POST THE 'MACRO ERROR' CODE
CLR.B D7 ; AND NUKE 'COMMAND CODE' FIELD
RTS ; (BITS 8-14 HOLD ERROR CODES)
; AND SUCESSFUL MACROS EXIT HERE:
OKAY: CLR.W D7 ; HERE, INDICATE GOODNESS
RTS
.SBTTL . MACRO COMMAND DISPATCH TABLE
DISMAL: .WORD BADMAC ; 00 ILLEGAL COMMAND
.WORD FOURS ; 01 BUILD FOURIER SERIES
<<SNIP>>
.WORD URAM ; 26 TEST CPU SRAM
MAXIM = 26h ; LAST LEGAL MACRO CODE
I think this would be a fair replacement for the above code (but my C
and Assembler are both a bit rusty, and this is completely uncompiled
and untested so I'm probably wrong...):
#define MAXIM 0x26
int BADMAC(int *args) {
return 0x80ff;
}
/* other function definitions/prototypes... */
int *DISMAL[] = {
BADMAC,
FOURS,
...,
URAM
};
/* Given an index into the DISMAL table, and a 110-element array
of integer arguments, execute the specified function.
All the called functions must have the same signature as
BADMAC, above. */
int XMAC(int cmd, int *args) {
/* Check the parameter */
if (cmd > MAXIM) {
return 0x80ff;
}
/* Index the array and call the function */
return (DISMAL[cmd])(args);
}
IMO, the C is easier, shorter and more succinct. Being so much shorter,
it also will lead to fewer defects and therefore shorter development and
test times.
Note that I'm not saying this is the best way to do this in C...
I guess my real point is that since C programs are shorter, they need
less comments, but still need "enough".
Except that, in real life, it doesn't. See below.
Not "enough". Your code has no top-level introduction.
The list of
dispatch functions in neither numbered nor commented, so if I want to
know what the function code for "Gear" is, I have to count the list,
and there's no comment about what each one does. The def of MAXIM is
unconnected to the dispatch list, except by manual counting.
I wind up programming a *lot* faster than most C programmers, if you
include "programming" to mean "fielding a bug-free program."
Actually,
many C programmers take infinite time to meet this definition.
The holy grail of self-commenting languages is crazy. Comments tell
why things are done, and code tells what was done. Programmers are
notoriously impatient and inarticulate, which is why they hate to
comment.
There's nothing really wrong with C as a language, apart from its
brutal ugliness, but accepted C practice is stunningly sloppy, and C
leads on on to C++ and other levels of abstraction.
I wonder how much (if any) of their code is still in assembler - I guessMicrosoft, who writes the OS and the compilers, one of the biggest
programming factories on the planet, has released something like
100,000 bugs in their various products. Clearly the existing
programming paradigm, what everybody is learning in "computer science"
classes, sucks.
I think one point is that Assembler *needs* more comments.
In C, you
have (I think) at least 32 characters for each variable or function name
(anyone got K&R somewhere?); in Assembler you get 6-8 and no lowercase,
so a function can't be "Build_Gear" - it has to be "GEAR", and therefore
requires a comment.
Actually, I'd use "BuildGear()" these days (I've been Java-fied), and I
just realised that C-style would dictate "build_gear()" anyway, I think.
Oh well...
"D7" makes my point for me (I believe it's a register?) - it *needs* to
be commented for the reader to have any idea what's going on. Same with
the other registers...
BTW - I apologise for not noticing the form-feeds(?) in the code I quoted...
Ignoring everything except the actual XMAC function and its equivalent,
there are 6 lines (*including* braces) where something is executed in
the C version. (Some of the braces could be removed, but this is the
style I like; others have only syntactical use).
Comparing this to 15 lines (17 if I should be including the OKAY group)
where something can go wrong in the assembler version - how can it
possibly be quicker to develop and test the latter?
Possibly you're one of the few programmers who are just more productive
than the average - there's a measured difference in productivity of
something like 10x(?) between the worst and the best (I think in
Peopleware, by Tom DeMarco)
Well, whenever the budget permitted it. Sometimes, we were
forced to use toenail clippings...
Bob M.