Wouter Verhelst: That's why C is usually preferred.
As I wrote
earlier, I've been playing with m68k assembly lately. My first
program looked somewhat like this:
.LFORMAT: .string "%c" .text .align 2 .LENDL: .string "\n" .text .align 2 .globl main .type main, @function main: link.w %a6,#-4 allocate a stack frame moveq #65,#-4(%a6) Move 65 (ASCII A) to an address on our local address space .L0: move.l #-4(%a6),-(%sp) push the address to the stack pea .LFORMAT push the format to the stack jbsr printf run printf add.l #1,#-4(%a6) add one to the letter cmpi.l #91,#-4(%a6) compare with 91 (ASCII Z + 1) jblt .L0 if less, jump to label L0 pea .LENDL push format to the stack jbsr printf run printf unlk %a6 clear stack frame clr.l %d0 store 0 in %d0 (return value) rts return .align 2 .size main, .-mainIOW, print out the alphabet. Nothing spectacular, and it worked. Then I decided to take it one step further, and rather than using an address in memory, I switched to using a register, which is supposed to be a tiny bit faster—even if that shouldn't be noticeable in this case:
main: link.w %a6,#-4 allocate a stack frame moveq #65,%d0 Move 65 (ASCII A) to %d0 .L0: move.l %d0,-(%sp) push the address to the stack pea .LFORMAT push the format to the stack jbsr printf run printf add.l #1,%d0 add one to the letter cmpi.l #91,%d0 compare with 91 (ASCII Z + 1) jblt .L0 if less, jump to label L0 pea .LENDL push format to the stack jbsr printf run printf unlk %a6 clear stack frame clr.l %d0 store 0 in %d0 (return value) rts return .align 2 .size main, .-main(that's only the main section, but please assume the rest is still there:-) When I ran that, it bombed. It would print out the A, and then whole lines of nothingness. When I ran it inside gdb, it wouldn't even print out the A. It took me quite some time to figure out what went wrong.
main: link.w %a6,#-4 allocate a stack frame moveq #65,%d7 Move 65 (ASCII A) to %d7 .L0: extb.l %d7 move.l %d7,-(%sp) push the address to the stack pea .LFORMAT push the format to the stack jbsr printf run printf add.l #1,%d7 add one to the letter cmpi.l #91,%d7 compare with 91 (ASCII Z + 1) jblt .L0 if less, jump to label L0 pea .LENDL push format to the stack jbsr printf run printf unlk %a6 clear stack frame clr.l %d0 store 0 in %d0 (return value) rts return .align 2 .size main, .-main%d0 is used to store a function's return value. If I store my data in %d0, then the next time I call a function, that data is overwritten. Since I do call a function inside my loop, that function overwrites my data every time. Using a different register (say, %d7) fixes this. Right. Apart from the fact that it's totally non-portable, assembly language also has quite a few quirks that you don't learn about when taught
structured programming. It'd be nice if there were a document somewhere that would explain how C functions expect to be called. I found out most of the above through trial and error, and through compiling stuff with -save-temps and looking at the result, comparing it with the 68k Programmers' Reference Manual. That works, but it's not really efficient—and not totally error-proof, too.





