Length of a string
The same program in MIPS, RISC-V, Z80, x86.
A string sits at $2000 with a zero byte after it, and the program works out how long it is by
walking to that zero and subtracting the address it started from. The answer, 15, ends up in d0.
Nothing in memory records how long a string is. An array can be given a count next to it; a string
carries its own end instead, as a zero byte after the last character, and finding it is the
program's job every single time.
lea text, a0 ; a0 walks the string
move.l a0, d1 ; keep where it started
scan:
tst.b (a0)+ ; the terminator? and step on either way
bne scan
move.l a0, d0 ; a0 is one byte past the terminator
sub.l d1, d0 ; how far it walked
subq.l #1, d0 ; without the terminator itself
org $2000
text: dc.b 'Assembly is fun', 0
tst.b (a0)+ reads the byte, sets Z from it and steps a0 on by one, all in one instruction, so
bne scan under it means "if that byte was not zero, go round again". No cmp is needed, because
tst is cmp #0 written shorter and the postincrement mode does the walking.
When the loop falls out, a0 is 00002010, one byte past the terminator, and d1 still holds the
00002000 it was given before the loop. Their difference is 16, the whole string including the zero,
and the subq.l #1 takes the zero back off. The length was never counted, it was measured.
Counting with a register works too, an addq.l #1, d0 inside the loop and no subtraction at the end.
It costs one instruction per character instead of two instructions once.
Take the , 0 off the dc.b line and press Run. There is now nothing at the end of the string to
stop the loop, so it walks off into memory nobody wrote, and it keeps walking until the run stops
with "Execution limit of 2000000 instructions reached". Nothing about the string itself changed; you
removed the only thing that said where it ended.