Structure is in the eye of the beholder
Assembly and VB6 being my preferred languages, I cop a lot of flak from ‘real programmers’. The most common are that VB isn’t OO (which is in fact the main reason I use it) and that ASM is ‘spaghetti code’. I’m not going to touch the VB one, but I intend to show (using examples, and hopefully I can get Geshi to highlight everything right) that the choice of language doesn’t necessarily determine the quality of the structure.
I’ve tried my hardest to contrive a fair example to use to compare C and Assembly; the result is massively optimisable (though my [old] version of GCC didn’t do a very good job when I tried it…) but uses nested if’s and function calls
Consider the following C code, part of an ‘initialisation’ procedure:
int value1, value2; int checkCondition1(); int checkCondition2(); void main() { if(checkCondition1() != 0) { value1 = 1; } else { if(checkCondition2() == 0) { value1 = 2; } else { value1 = 3; } } if(value1*2 < 3) { value2 = value1; } else { value2 = 0; } } int checkCondition1() { return (1*1); } int checkCondition2() { return (24-24); }
The actual purpose and content of the code is irrelevant, it’s contrived solely to demonstrate that structure is determined by the programmer, not the language.
The above example is ‘good’ structure. Lets convert it to ‘bad’ structure:
int value1, value2; void main(){ if((1*1)!=0) value1 = 1; else {if((24-24)==0) value1 = 2; else value1 = 3;} if(value1*2 < 3) value2 = value1; else value2 = 0; }
Infinitely harder to read, separate (and probably more complicated) operations have been inlined and all structure is gone. Yet C still understands, compiles and executes it.
Now lets look at the equivalent assembly language code:
.data? value1 DWORD ? value2 DWORD ? .code Main: call CheckCondition1 cmp eax, 0 je @F mov value1, 1 jmp Value1Set @@: call CheckCondition2 cmp eax, 0 jne @F mov value1, 2 jmp Value1Set @@: mov value1, 3 Value1Set: mov eax, value1 add eax, eax cmp eax, 3 jge @F mov eax, value1 mov value2, eax jmp Value2Set @@: mov value2, 0 Value2Set: xor eax, eax retn CheckCondition1: mov eax, 1 imul eax, 1 retn CheckCondition2: mov eax, 24 sub eax, 24 retn END
Looks a bit messy, doesn’t it. Of course, very few people program in ‘pure’ assembly anymore (obviously the purists do… and some of them don’t even use indents), many (most?) use the high level abilities of MASM, Microsoft’s Assembler.
.data? value1 DWORD ? value2 DWORD ? .code Main PROC call CheckCondition1 .if(eax) mov value1, 1 .else call CheckCondition2 .if(eax) mov value1, 2 .else mov value1, 3 .endif .endif mov eax, value1 add eax, eax .if(eax < 3) mov eax, value1 mov value2, eax .else mov value2, 0 .endif xor eax, eax ret Main ENDP CheckCondition1 PROC mov eax, 1 imul eax, 1 ret CheckCondition1 ENDP CheckCondition2 PROC mov eax, 24 sub eax, 24 ret CheckCondition2 ENDP END
Of course, once you add lines between procedures it becomes easier to read still. And the ‘PROC’ directive gives a stack-frame for free. And really, once the fear of one-operation-per-line has passed, it’s really not any harder to read than well structured C.
Poor programmers aren’t allowed to give a tool a bad name.
