(no title)
rep_lodsb | 14 days ago
VAR1 @ VAR2 @ + VAR3 !
will execute this at run time: ; push address of VAR1
inc bx
inc bx
push bx
; fetch and jump to next primitive
lodsw
mov bx,ax
jmp [bx]
; push contents of variable
pop bx
push [bx]
; next primitive...
; push address of VAR2, next...
; push contents of variable, next...
; add top two stack elements, push sum, next...
; push address of VAR3, next...
; store to address, next...
There are some "low-hanging fruits", like keeping top-of-stack in a register, which the Forth used here doesn't do though. Or direct threading.Still, an incredibly stupid compiler could do better (for execution speed, definitely not size) by outputting similar code fragments - including all the pushes and pops, who needs a register allocator? - just without the interpreter overhead (lodsw etc.) in between them.
A compiler producing worse code likely didn't exist before today's glorious world of vibe coding ;)
A slightly better compiler would directly load the variables instead of first pushing their addresses, etc. You don't need to be an expert in compiler theory to come up with enough ideas for boiling it down to the same three instructions that a competent assembly programmer would write for this operation. And at least for this case, Forth doesn't even have the size advantage anymore, the code would only take 10 bytes instead of 14.
ajross|14 days ago
rep_lodsb|14 days ago
It's somewhat closer for 8-bit processors, the most popular ones had either no convenient addressing mode for stack frames at all, or an extremely slow one, like IX/IY on the Z80. For even more primitive CPUs, you might already need a virtual machine to make it "general-purpose programmable" at all -- for example if there is only one memory address register, and no way to save its contents without clobbering another one. I think that some of Chuck Moore's earliest Forth implementations were for architectures like that.
Also memory constraints could have been more important than efficiency of course. I'm not saying Forth is worthless, but it's not competing with any compiled language in terms of speed, and IMHO it also does away with too many "niceties" like local variables or actually readable syntax. Your mileage may vary :)