www.retrosoftware.co.uk
http://www.retrosoftware.co.uk/forum/

PROCs vs GOSUBs
http://www.retrosoftware.co.uk/forum/viewtopic.php?f=73&t=631
Page 1 of 1

Author:  Samwise [ Thu Jun 16, 2011 8:35 pm ]
Post subject:  PROCs vs GOSUBs

In the interests of space saving in a BASIC program, am I correct in saying that it's better to use GOSUBs than PROCedures? Because you'll save memory both by not requiring a DEFPROC statement and also not needing to store the PROCedure name in memory?

I think I read somewhere that passing procedures variables is quicker than using global variables ... but in the case where I don't want to pass variables into a procedure, is there any reason to ever use PROCs over GOSUBs?

Sam.

Author:  tautology [ Thu Jun 16, 2011 9:33 pm ]
Post subject:  Re: PROCs vs GOSUBs

For space it all depends on what the procedure's being used for. Defining a procedure will take up 3 bytes for tokens (DEF, PROC and ENDPROC) plus however many bytes are taken up by the name and parameters plus 2 bytes for each colon (or 3 bytes if a separate line is used). So for a simple PROCA:
Code:
DEF PROCA:PRINT:ENDPROC
The overhead would be 3 bytes for tokens, 2 bytes for the colons and one byte for the name = 6 bytes.

Also each call of the procedure would take up 1 byte for token, plus the length of the name (so in the above case 2 bytes), a total of 3 bytes.

Using a GOSUB would take up 1 byte for tokens (RETURN), 3 bytes for a line and 1 byte for a colon, e.g.:
Code:
1000PRINT:RETURN
Which equals 5 bytes. Advantage GOSUB, by one byte.

Now to call a GOSUB, BBC BASIC actually hashes the number for its own internal reasons into 4 bytes no matter how long the number is (&8d to signify it's a line number and 3 bytes to describe the line number). So to call the GOSUB, at a minimum would take 1 byte token + 4 bytes line number which equals 5 bytes. Advantage procedure, by 2 bytes. (An ON GOSUB would take up an extra byte for the ON token and for each comma.)

So, the totals are:
PROC: 6 bytes + 3 bytes for each call
GOSUB: 5 bytes + 5 bytes for each call

Author:  Samwise [ Thu Jun 16, 2011 9:48 pm ]
Post subject:  Re: PROCs vs GOSUBs

Ahh, I hadn't considered the memory required to make the call ... schoolboy error.

Thanks for that, that was really helpful.

Sam.

Author:  JonW [ Thu Jun 16, 2011 10:10 pm ]
Post subject:  Re: PROCs vs GOSUBs

There is also a speed consideration as well.

A GOSUB will sequentially search the program every time to find the line number. If the subroutine is at the end of a long program, this will incur a time penalty. Putting the subroutines at the top of the program should speed things up a tad.

A PROC does it slightly differently. The first time a PROC is called, a sequential search is made then the memory address of the line number is stored in an internal data structure (like a hash table). On subsequent calls, the hash table is interrogated to find the address of the line to go to which makes things a lot quicker.

Jon.

Author:  Samwise [ Thu Jun 16, 2011 10:37 pm ]
Post subject:  Re: PROCs vs GOSUBs

Thanks, Jon. For the application I had in mind, memory was more of a concern than speed.

I had read in the User Guide that PROCs were faster, but it was the memory usage I was more interested in. Looks like PROCs are the better choice for that as well, though.

Sam.

Author:  tautology [ Thu Jun 16, 2011 10:43 pm ]
Post subject:  Re: PROCs vs GOSUBs

BTW does anybody know why BBC BASIC stores line numbers in a strange format? I'm guessing its used to speed up memory calculation later, but I'd've thought that it'd store it just as a 16 bit line number (as it does in the line header) to save a byte.

For those who don't know, the C code to convert a line number is below (which may be a bit clunky - I wrote it about 6 years ago, without digging into the whys and wherefores of it):
Code:
if (work == 0x8d && !quote)
{
   // It's a line number
   int num1=fgetc(infile), num2=fgetc(infile), num3=fgetc(infile);
   number=num2 - 0x40;
   switch(num1)
   {
      case 0x44: number += 0x40; break;
      case 0x54: break;
      case 0x64: number += 0xc0; break;
      case 0x74: number += 0x80; break;
   }
   number += (num3 - 0x40) * 256;
   printf("%d", number);
}

Author:  RichTW [ Thu Jun 16, 2011 10:54 pm ]
Post subject:  Re: PROCs vs GOSUBs

The reason it encodes them at all (rather than keeping them as ASCII text, like any other numeric literal) is so that the length of the line doesn't change during RENUMBER, and also for a bit of extra speed.

The reason it encodes them in the peculiar 8D+three bytes form, rather than as a 16 bit value, is to avoid extra checks when the interpreter is scanning through a line, looking for an ELSE token (which could otherwise manifest itself as either the LSB or MSB of a line number).

My friend Matt's blog goes into some more detail here:
http://xania.org/200711/bbc-basic-line-number-format

As for the reason for the format they chose - it just turns out that it's particularly easy to decode from that format into a 16 bit value in 6502 assembler:

http://xania.org/200711/bbc-basic-line- ... mat-part-2

Author:  tautology [ Fri Jun 17, 2011 12:15 am ]
Post subject:  Re: PROCs vs GOSUBs

RichTW wrote:
The reason it encodes them in the peculiar 8D+three bytes form, rather than as a 16 bit value, is to avoid extra checks when the interpreter is scanning through a line, looking for an ELSE token (which could otherwise manifest itself as either the LSB or MSB of a line number).


Wow base64/uuencoding techniques on the Beeb and makes total sense.

Thanks Rich, is there anything you don't know about out favourite machine?

Page 1 of 1 All times are UTC [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/