fprwards and backwards logic in IF statements (in assembly)

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Seven.FFF wrote: Tue Oct 17, 2023 12:19 pm I think this has gone way past confusing the OP. He can just do a bunch of simple condition checks chained together as originally suggested,but he seems to want to make it more complicated and use the stack.
I was suggesting that because the OP wants to write an adventure style game (menu driven) and is going to end up with a large amount of room/object specific functions so will soon see the limitations of that approach.

If you have to write lots of functions like

checkifinroom6andholdingkeyanddoorislocked:
; code
ret

Then you should start thinking about abstracting the logic into data and a simple evaluator.

I did say only when stuff starts getting complicated doing it with code though ;)
Last edited by ParadigmShifter on Tue Oct 17, 2023 1:09 pm, edited 1 time in total.
User avatar
Seven.FFF
Manic Miner
Posts: 753
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: fprwards and backwards logic in IF statements (in assembly)

Post by Seven.FFF »

I’m all for keeping it simple but stack manipulation and forced stack rebalancing are’t especially advanced techniques. I figured them out independently myself and used them in my very first z80 asm project.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Seven.FFF wrote: Tue Oct 17, 2023 12:26 pm I’m all for keeping it simple but stack manipulation and forced stack rebalancing are’t especially advanced techniques. I figured them out independently myself and used them in my very first z80 asm project.
Well yeah it's not that hard and can be useful, passing arguments on the stack requires that too but that makes things more complicated, so I'd recommend only passing arguments in registers for now.

This is where I did a double return in my console program, used for errors parsing escape codes, this was so the function which calls the escape code can just assume the escape code has been unescaped but if there was an error it returns to the function which called unescape which knows how to handle it. So like a very primitive version of exception handling ;)

Code: Select all

; String/character escape codes
;	\'	#27	allow to enter a ' in a character literal, e.g. '\''
;	\"	#22	allow to enter a " in a string literal, e.g. "this is the double quote (\") character"
;	\\	#5c	allow to enter a \ character in a character or string literal, e.g. '\\' or "this is the backslash (\\) character"
;	\0	#00	allow to enter the character with code 0
;	\b	#08	back-space
;	\f	#0c	form-feed (next page)
;	\n	#0d	carriage-return (move to the beginning of the line)
;	\r	#03 using "HOME" for this instead of CR, which is really \n
;	\t	#09	(horizontal-) tab
.unescape
	; if next char is null, it's an error
	inc hl
	ld a, (hl)
	or a
	jr z, .errorbadescape
	cp '\'
	jr z, .unescapebackslash
	cp ''''
	jr z, .unescapeprevious
	cp '"'
	jr z, .unescapeprevious
	; D will hold value we will replace escape code with
	ld d, 0
	cp '0'
	jr z, .unescapewithD
	ld d, BKSP
	cp 'b'
	jr z, .unescapewithD
	;ld d, HORZ_TAB = BKSP+1
	inc d
	cp 't'
	jr z, .unescapewithD
	ld d, FORM_FEED
	cp 'f'
	jr z, .unescapewithD
	;ld d, CR
	inc d ; CR = #0D = FORM_FEED+1
	cp 'n'
	jr z, .unescapewithD
	ld d, HOME
	cp 'r'
	jr z, .unescapewithD
	jr .errorbadescape
.unescapebackslash
	ld (hl), 1
	ret
.unescapewithD
	ld (hl), d
.unescapeprevious
	dec hl
	ld (hl), 1
	inc hl
	ret
.errorbadescape
	; we don't want to return to where we were called from,
	; we want to return to the one that called tokenize instead
	pop af ; throw away return address
	ld hl, str_err_unknownescape
	jr .errorret
That function just replaces stuff like \" in a string with (some unprintable character code - I used 1, meaning "ignore this character, it means an unescaped char follows) followed by the code for " (so the string length never has to change, which would complicate stuff).
Wall_Axe
Manic Miner
Posts: 501
Joined: Mon Nov 13, 2017 11:13 pm

Re: fprwards and backwards logic in IF statements (in assembly)

Post by Wall_Axe »

The idea of the second routine's ret acting that way is something I hadn't thought about (referring to a post on the previous page by paradign shifter)

If you want pseudo code of what I'm talking about a good example is just imagine two else statements.

Code: Select all

If enemy dead
MakeExplosion()

Else
If enemy-hp>1
DamageEnemy()
Else
Killenemy()
Endif
Endif
You can't just do a ret because that wouldn't do anything.
You can't just save a variable to ram (saying the enemy is dead) because you need to prevent any code after being run.

(Please ignore the fact that you could kill the enemy and create an explosion at the same time,as it's just an example of some situation)

So you need to ret AND set a variable.
The only solution I know is to use JP,NZ which creates unreadable spaghetti code. Which is fine for one-offs like reading the keyboard but bad for game logic.
Last edited by Wall_Axe on Tue Oct 17, 2023 1:31 pm, edited 1 time in total.
AndyC
Dynamite Dan
Posts: 1451
Joined: Mon Nov 13, 2017 5:12 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by AndyC »

Wall_Axe wrote: Tue Oct 17, 2023 1:26 pm The only solution I know is to use JP,NZ which creates unreadable spaghetti code. Which is fine for one-offs like reading the keyboard but bad for game logic.
JP NZ is the right solution.

And yes, it requires about a billion times more discipline than BASIC to avoid spaghetti code that becomes hard to follow. Welcome to assembly programming.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Wall_Axe wrote: Tue Oct 17, 2023 1:26 pm The idea of the second routine's ret acting that way is something I hadn't thought about (referring to a post on the previous page by paradign shifter)

If you want pseudo code of what I'm talking about a good example is just imagine two else statements.

Code: Select all

If enemy dead
MakeExplosion()

Else
If enemy-hp>1
DamageEnemy()
Else
Killenemy()
Endif
Endif
You can't just do a ret because that wouldn't do anything.
You can't just save a variable to ram (saying the enemy is dead) because you need to prevent any code after being run.

So you need to ret AND set a variable.
The only solution I know is to use JP,NZ which creates unreadable spaghetti code. Which is fine for one-offs like reading the keyboard but bad for game logic.
You can just do

if enemy dead
MakeExplosion()
return

if enemy->hp > 1
DamageEnemy()
else
KillEnemy()
return

or if you want to process the next enemy instead of return do jp GetNextEnemy which loops again back to start (if there are more enemies left)
Last edited by ParadigmShifter on Tue Oct 17, 2023 1:34 pm, edited 1 time in total.
Wall_Axe
Manic Miner
Posts: 501
Joined: Mon Nov 13, 2017 11:13 pm

Re: fprwards and backwards logic in IF statements (in assembly)

Post by Wall_Axe »

AndyC wrote: Tue Oct 17, 2023 1:28 pm JP NZ is the right solution.

And yes, it requires about a billion times more discipline than BASIC to avoid spaghetti code that becomes hard to follow. Welcome to assembly programming.
Okay :)
Yeah I was coding that way and wondering if there was any way around that.
The jumping to a function instead of calling might work though. I'm looking for readability and don't care about speed in my situation.
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Wall_Axe wrote: Tue Oct 17, 2023 1:34 pm Okay :)
Yeah I was coding that way and wondering if there was any way around that.
The jumping to a function instead of calling might work though. I'm looking for readability and don't care about speed in my situation.
Only jump to a function if you are replacing

call func
ret

with jp func

or if the function is only called from one place (in which case you could just paste the code but jumping makes it more readable of course). Otherwise you have to remember where to jump back to which is probably more complicated than doing a ret. You also can't do recursion or calling a function from another function unless you add extra code either (note - some processors don't support call e.g. R3000 used on the Playstation, which only has a link register which only saves 1 return address at a time, so they have to work like that. Although the compiler will push the link register to the stack for recursion or calling a function from another function but the compiler has to do that not the processor).
AndyC
Dynamite Dan
Posts: 1451
Joined: Mon Nov 13, 2017 5:12 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by AndyC »

Wall_Axe wrote: Tue Oct 17, 2023 1:34 pm Okay :)
Yeah I was coding that way and wondering if there was any way around that.
The jumping to a function instead of calling might work though. I'm looking for readability and don't care about speed in my situation.
The main thing is realising that:

IF x = q THEN y ELSE z

In assembly tends to be written in pseudocode as:

Compare x
If equal to q, JUMP to label1
Do z
JUMP to label2
Label1:
Do y
Label2:
... carry on ...

As long as you stick to that kind of pattern, the structure is still readable (especially with good indentation).

Don't start worrying about optimising CALLs to JPs until later. It literally won't make any noticeable difference in the early stages (but will likely confuse you when you try to read the code later on).
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

I don't agree that ASM coding is more spaghettified than BASIC either :)

You can move your code around in ASM easily (try doing that with line numbers) and you can give meaningful labels to stuff (unless you love basic so much you call everything l1000, l2000, l2040 etc.) ;)

I much prefer

call func

to GOSUB 1000

and jp label is better than GOTO 1206 as well

Once you get used to how to do things in ASM you will easily be able to look at common idioms and realise they are doing an if/then/else construction, it just takes a bit of experience.

Other common idioms

loops with djnz
nested loops with BC (or another register instead of C) djnz .innerloop : dec c : jp nz .outerloop

while translates to

while (condition)
// loop stuff

beginwhile
if !condition jp skiploop
; loop stuff
jp beginwhile
skiploop


with do.. while just checking at the end (although do..while is quite rare)
etc.

switch statements are a bit more complicated to do efficiently so don't worry about those for now (you can chain ifs together), more efficient way is to use a jump table (more complicated).

for loops are just a version of normal loops and you should get used to counting your loop variables down to 0 instead of up for most cases (since checking against 0 is easier/more efficient than comparing something to loopmax)
Last edited by ParadigmShifter on Tue Oct 17, 2023 2:03 pm, edited 3 times in total.
User avatar
Joefish
Rick Dangerous
Posts: 2084
Joined: Tue Nov 14, 2017 10:26 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by Joefish »

One thing I find helps is to redefine the conditional jumps and calls. I use my new versions in capitals to distinguish from the originals, but for example, you can use JPEQ instead of JPZ, JPNE instead of JPNZ, but more usefully to help you remember, JPLT instead of JPC, and JPGE instead of JPNC. So if you have a number in A and you do CP 10, Carry flag indicates A<10, so JPLT. No-Carry indicates A>=10, so JPGE. I think. I get it wrong, a lot! You can then also define JPLE and JPGT as things that deliberately flag an error as you can't do these in one operation.
User avatar
ketmar
Manic Miner
Posts: 740
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ketmar »

ParadigmShifter wrote: Tue Oct 17, 2023 12:09 pm Using the machine stack (SP) can be tricky since it stores the return address on the stack but it is easy to write stack functions which do not use SP if you need an independent (or several) stacks.
and… you just wrote one of the vital parts of a Forth system. ;-) you're so-o-o-o close to The Real Thing now! ;-)
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Yup, I started trying to do a LISP interpreter and realised it would have been a lot easier if I had done Forth instead ;) LISP stands for (L)ots of (I)rrelevant S(uperfluous) P(arentheses) of course :)

I'd use the Forth stack in the alt registers though like I hinted at earlier with H'L' containing current forth stack pointer. And then you can push D'E' or pop stuff into D'E' and if you need a count of stuff on the stack use B'C'

Forth-like is defo the way to go for a simple scripting language. I think Pascal p-code is basically Forth (or was in early implementations?). And I think Java uses a stack machine unlike .NET which uses a register based VM.

A forth interpreter is often the first thing you would do if you got a new processor and don't want to program too much in assembler.

Can be a good idea to write your first assembler for a new processor in Forth and then use that to write a new one in assembly language ;)

I think microcode on processors (i.e. complicated opcodes which don't map easily to hardware) often use forth like stuff as well.
User avatar
Seven.FFF
Manic Miner
Posts: 753
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: fprwards and backwards logic in IF statements (in assembly)

Post by Seven.FFF »

ParadigmShifter wrote: Tue Oct 17, 2023 12:42 pm So like a very primitive version of exception handling ;)
Yes, structured error handling is a common and great use of the technique. In my esXDOS dot commands errors can happen any time due to external causes (serial timeouts, external hardware misbehaving) and dozens of stack levels deep, so it ends up much more robust being able to jump out and rebalance the stack from any of those arbitary points, instead of having to back out from the error one level at a time.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Another thing which can make conditionals simpler is assume they will be true before the comparison (like what I was doing in several cases of my unescape routine).

So if you want to do

IF A == 1 THEN D = 5
ELSE IF A == 2 THEN D = 7

you can do this:

Code: Select all

    cp 1
    jr z, .ais1
    cp 2
    jr z, .ais2
    jr .dontdoanythingwithd

.ais1
    ld d, 5
    jr .donecheck
    
.ais2
    ld d, 7
    ; jr .donecheck ; not needed since .donecheck is coming next
.donecheck
    ; do stuff with d
.dontdoanythingwithd
or this, which is easier to grok I think

Code: Select all

    ld d, 5
    cp 1
    jr z, .donecheck
    ld d, 7
    cp 2
    jr z, .donecheck
    jr .aisnot1or2
    
.donecheck
    ; use d for whatever you wanted it for
    
.aisnot1or2
EDIT: Which only works since loading a register does not change the Z flag (even if you LD D, 0). (Exception: I or R registers apparently. I as in the interrupt register, nothing to do with IX or IY)

EDIT2: ARM and PowerPC let you choose (sometimes?) if you set flags or not which is a very nice feature :)
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

Seven.FFF wrote: Tue Oct 17, 2023 3:47 pm Yes, structured error handling is a common and great use of the technique. In my esXDOS dot commands errors can happen any time due to external causes (serial timeouts, external hardware misbehaving) and dozens of stack levels deep, so it ends up much more robust being able to jump out and rebalance the stack from any of those arbitary points, instead of having to back out from the error one level at a time.
My first published game (PS1) had to use structured exception handling, mainly because of my n00b design ;)

I was reading the joypad all over the place in the code (instead of just reading it once in the VBlank and remembering what was pressed - n00b mistake).

Then Sony announced that if you hold down Start and Select buttons for 2 seconds your game must return to the title menu or you would fail submission... oops.

So I basically did a GOTO MAINMENUINIT inside the pad reading routine if it detected that lol.

(But it was in C, so it was setjmp() and longjmp() which is how structured exception handling is done in C). C++ might do something similar at a very low level but it can't just set the stack pointer and jump to an arbitrary place in the code it has to make sure all destructors are called, so it has to do stack unwinding).

I agree structured exception handling is an excellent way to deal with errors (even in C++ if it's in a place where performance isn't that important).

Classic example is parsing a file, lots of errors can occur due to file read errors, parse errors, etc. Instead of putting error checks in everywhere it's far easier to do this:

Code: Select all

ParseFile()
{
    try
    {
         // do stuff to parse the file, assume everything is A-OK at all times
         // e.g.
         versionNum = ReadInt(); if it isn't an int, this will throw ParseError. If there's a file read error, it will throw FileSysError
    }
    catch(FileSysError fserr)
    {
         // deal with the file system error
    }
    catch(ParseError parserr)
    {
         // deal with the parse error
    }
}
Not the most efficient way probably but certainly the easiest. Linus probably wouldn't like it :)
sn3j
Manic Miner
Posts: 589
Joined: Mon Oct 31, 2022 12:29 am
Location: Germany

Re: fprwards and backwards logic in IF statements (in assembly)

Post by sn3j »

Wall_Axe wrote: Tue Oct 17, 2023 1:26 pm If you want pseudo code of what I'm talking about a good example is just imagine two else statements.

Code: Select all

If enemy dead
MakeExplosion()

Else
If enemy-hp>1
DamageEnemy()
Else
Killenemy()
Endif
Endif
I didn't read all of the thread in detail, but I'd go about that situation like so:

Code: Select all

  calculate_enemy_hp()   ; yields negative value if dead, 0 if no hp left
  push L_CarryOn
  jp m MakeExplosion
  jp nz DamageEnemy
  jp KillEnemy
L_CarryOn:
  ...
POKE 23614,10: STOP      1..0 hold, SS/m/n colors, b/spc toggle
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

So that's pushing a return address onto the stack so when you do a ret from any of the places you jump to, doing a ret then returns to L_carryon.

That will work but I think it would make stuff harder to follow myself. Maybe as an optimisation. But it is an option yeah.

Easily readable code with common idioms easy to see is better when starting out IMO.

Your method is better than reserving HL as the return address and using jp (hl) at the end though. (jp (hl) is very fast though. 4T IIRC)

Mostly when I am doing stuff like that (jumping instead of calling) I am in the middle of using the stack for something naughty and complicated so I can't PUSH, POP or CALL or RET :)

EDIT:

push label
jp func

is a less efficient way to do call func usually except you get to pick where you return to (i.e. not just the next instruction)

EDIT2: What's confusing about that method is examining the return address on the stack will not show you the instruction after the CALL so you have no idea where you came from (were "called" - actually jumped to not called - from). So you need to know what you are doing hence I wouldn't recommend it for beginners.
sn3j
Manic Miner
Posts: 589
Joined: Mon Oct 31, 2022 12:29 am
Location: Germany

Re: fprwards and backwards logic in IF statements (in assembly)

Post by sn3j »

When dealing with multiple conditions it is helpful to have the arbitrary condition results in the flags before jumping. This is mostly C/NC and Z/NZ (so 2 conditions actually). If you have more conditions, some value in A comes in handy that could be processed along the way, such as doing an RLCA or BIT x,A to get more checks done.

A more beginner friendly version could be this. But does beginner friendly assembler code even exist? Not sure.

Code: Select all

  calculate_enemy_hp() ; C if already dead, Z if no hp left
  jr c L_Explosion
  jr z L_KillEnemy
  call DamageEnemy
  jr L_CarryOn
L_Explostion:
  call Explosion
  jr L_CarryOn
L_KillEnemy:
  call KillEnemy
L_CarryOn:
  ...
This makes it not much different from what's already been posted, though. Just to pile on.

Or, to spin it further, imagine this:

Code: Select all

  calculate_enemy_state() ; yields C if dead, M if shield protected, Z if no hp left, else: 1..xx hp 
  jr c L_Explosion
  jr z L_KillEnemy
  jp m L_Protected
  jr L_DamageEnemy
L_Explosion:
  call Explosion
  jr L_CarryOn
L_KillEnemy:
  call KillEnemy
  jr L_CarryOn
L_Protected:
  bit 6,a ; check protection type in bit 6 to calculate effective damage (0 - weak, 1 - strong)
  jr z L_WeakShield
  half_damage()
L_WeakShield:
  half_damage() ; weak shield reduces dmg to 50% strong shield to 25%
L_DamageEnemy:
  call DamageEnemy
L_CarryOn:
  ...
Last edited by sn3j on Tue Oct 17, 2023 8:51 pm, edited 7 times in total.
POKE 23614,10: STOP      1..0 hold, SS/m/n colors, b/spc toggle
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

That's better than a non-local return though so easier to get your head around. I'd consider any non-local returns (i.e. not returning to place immediately after the call) much more advanced but if you get used to the pattern then why not. Definitely not beginner though :)
Wall_Axe
Manic Miner
Posts: 501
Joined: Mon Nov 13, 2017 11:13 pm

Re: fprwards and backwards logic in IF statements (in assembly)

Post by Wall_Axe »

Oh I see you're using a label and a call, to make it more 'forwards logic' like. That's good.
User avatar
ketmar
Manic Miner
Posts: 740
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ketmar »

ParadigmShifter wrote: Tue Oct 17, 2023 2:12 pm Forth-like is defo the way to go for a simple scripting language. I think Pascal p-code is basically Forth (or was in early implementations?). And I think Java uses a stack machine unlike .NET which uses a register based VM.
not any stack machine could be Forth. ;-) Forth has two separate stacks for data and return addresses, it is distinctive, and very important feature. it basically drives the design of everything else. and most stack VMs has either one stack, or return stack cannot be freely accessed from VM code.
ParadigmShifter wrote: Tue Oct 17, 2023 2:12 pm A forth interpreter is often the first thing you would do if you got a new processor and don't want to program too much in assembler.

Can be a good idea to write your first assembler for a new processor in Forth and then use that to write a new one in assembly language ;)
and then why rewrite it? ;-) written in Forth it will be actually smaller, and almost as fast.

i also love Oberon. now you can try to understand how very technically restricted strongly-typed language like Oberon, and anarchy in its purest form which is Forth, live together in my brain. if you'll do, please, explain it to me then, because i don't understand. ;-)
Last edited by ketmar on Wed Oct 18, 2023 2:18 am, edited 1 time in total.
User avatar
ketmar
Manic Miner
Posts: 740
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ketmar »

Wall_Axe wrote: Tue Oct 17, 2023 1:26 pm If you want pseudo code of what I'm talking about a good example is just imagine two else statements.

Code: Select all

If enemy dead
MakeExplosion()

Else
If enemy-hp>1
DamageEnemy()
Else
Killenemy()
Endif
Endif
tbh, it looks like a perfect fit to write your first compiler. no, really, you don't need hyperoptimised real-time code, and it the same time you have a real task at hand. a chance to learn compiler construction too!

(no irony here. the ability to write a compiler when you need it is of great value, and will help you many times in the future.)
User avatar
ParadigmShifter
Dynamite Dan
Posts: 1008
Joined: Sat Sep 09, 2023 4:55 am

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ParadigmShifter »

ketmar wrote: Wed Oct 18, 2023 2:10 am not any stack machine could be Forth. ;-) Forth has two separate stacks for data and return addresses, it is distinctive, and very important feature. it basically drives the design of everything else. and most stack VMs has either one stack, or return stack cannot be freely accessed from VM code.


and then why rewrite it? ;-) written in Forth it will be actually smaller, and almost as fast.

i also love Oberon. now you can try to understand how very technically restricted strongly-typed language like Oberon, and anarchy in its purest form which is Forth, live together in my brain. if you'll do, please, explain it to me then, because i don't understand. ;-)
Presumably you can use the machine stack (i.e. use SP) for return addresses and just have a separate stack for the data. When I mentioned call/gosub in a scripting language I did realise you'd need a separate stack for the return addresses :) Surely that alone will make Forth not as efficient as ASM (it's still very efficient though - on a Z80 at least which does not have autoincrement/decrement any register [i.e. can use any register as a stack pointer, and there is no push or pop instruction needed, 68000 is like that I believe] like more modern processors can do)? I agree about the code size probably being smaller though (which is why I think they use stuff like this for microcode on CPUs). When I say more modern I don't mean x86 and its descendants, they are not really modern design at all lol ;)

Ok maybe leave the assembler written in Forth until you have used said assembler to write a C compiler, then write your assembler (and a new version of the C compiler) in C :)

EDIT: Yup I see 68000 has pretty good autoincrement/decrement instructions AND it treats the SP(also known as A7) register differently in that it never increments/decrements it by 1.

Dunno why they didn't do that for INC SP on a Z80 would be a very useful instruction if it added 2 to SP instead of 1 as a special case for SP only... probably less mcgubbins needed in the instruction decoder/processor I guess.
User avatar
ketmar
Manic Miner
Posts: 740
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: fprwards and backwards logic in IF statements (in assembly)

Post by ketmar »

but why bothering writing C compiler, if there is already Forth compiler? yet if you need it… 'cmon, use Forth! writing compiler in Forth is faster, more fun, and the compiler will be smaller anyway. ;-)
Post Reply