Shop OBEX P1 Docs P2 Docs Learn Events
calling conventions / parameter passing in assembler? — Parallax Forums

calling conventions / parameter passing in assembler?

virtuPICvirtuPIC Posts: 193
edited 2009-02-04 08:41 in Propeller 1
Okay, the Propeller is even missing decent subroutine calls... However, assuming I am using call or jmpret instructions: are there any conventions
  • how to build a call stack that can even handle recursion,
  • how to pass parameters (i.e. at which addresses),
  • how to pass return values?
The documentation doesn't tell anything about all this. I've searched this forum and also couldn't find anything. However, calling conventions are extremely important! They are necessary for code sharing, to use software written by others, or to build or to use libraries.

If there are no such conventions yet I volunteer to define some. Either on my own or leading a working group. Might also be a program item for the Propeller West Coast Expo. I am competent for this since I have a strong history in compiler construction I know about programming languages, programming concepts and I am even a backend expert.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
«1

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2009-02-02 17:23
    Given the small size of a cog's memory (at most 496 instructions) and the need to use instruction modification for most pointer-based access, a formal subroutine call convention is not very appropriate. Typically, parameters and return values are simply stored in convenient variables. Recursion might be useful in a few special circumstances, but not a generally useful tool for Prop assembly code. Keep in mind that Spin is an entirely different story and supports value parameters, return values, and recursion. ImageCraft's LMM-based C implementation also supports value parameters, return values, and recursion.

    Code sharing isn't really done at the level of the Prop assembly code nor are libraries used (there's no "include" provision in the compiler). The basic unit of code sharing is the Spin object. More useful would be some guidelines for new objects. For example, there are a variety of display objects for different display devices (TV, VGA, LCD, serial, etc.) Some of them have a set of basic output editing routines (like for decimal, hexadecimal, and binary number formats and zero-terminated strings). Some of them don't have these or have a subset. A guideline document that summarizes what others have done and recommends a standard set of output editing routines would be useful for anyone implementing a new device driver. Others may bring the earlier I/O drivers up-to-date by adding any missing routines or making a modified version of the original that conforms to whatever common ground we agree on.

    A bit of a warning ... There's a natural flow to the creation of standards. If you attempt to create standards for something that's not mature enough, the standards will be ignored because they don't match what experience shows is a "best" way to do things or development will be arrested because you've codified something that doesn't really work well and developers may be locked into a standard that doesn't work. If you try to create a standard too late in the evolution of something, there will be too many ad-hoc solutions that are well established to make a meaningful standard (other than to codify what people actually do).
  • heaterheater Posts: 3,370
    edited 2009-02-02 17:29
    Of all the Prop code written so far, is there even one PASM program that uses or needs, a call stack or recursion etc.?

    This may be a problem that does not need solving.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • potatoheadpotatohead Posts: 10,261
    edited 2009-02-02 17:36
    Well, it's pretty easy to share larger scale things, like drivers. Typically, there is a block of memory defined for use by the driver. The rest runs on a cog and can just be called by your program, after populating the parameter block.

    Those share very easily.

    Smaller assembly language routines typically use a few COG longs, or a HUB memory location or two. Those are easily shared also. That's a straight forward cut 'n paste.

    Libraries in native PASM don't work like you would expect on other CPU's. I've seen people load up a COG with functions, then use a block of RAM to communicate with it. That COG is always running, ready to do stuff. I've also seen people fire off a COG to do something, then have it terminate. That has a COG startup cost though.

    There is also the C environment from Imagecraft. I remember a deal going on right now too. C + a demo board for a good price, or something!

    Richard can chime in [noparse]:)[/noparse]

    Anyway, since that's C, you can just do what you normally would!

    The mode of operation there is different still. Basically, a small software supervisor kernel runs on a COG. It fetches assembly language instructions from the HUB, one at a time, executes them, then continues on. Performance is about 1/5 of native PASM, but it's a more traditional environment / program work flow.

    Really, the design of the Propeller makes some new things possible that often marginalize the need for the things you are talking about in your post. Code sharing with SPIN and PASM is pretty easy. The structures are not all that complex, and driver type code is very atomic, as it's targeted for a COG. Mostly possible to just run it from SPIN, then do your thing in your program.

    Edit: Heater and Mike beat me to the punch!!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
    Safety Tip: Life is as good as YOU think it is!
  • heaterheater Posts: 3,370
    edited 2009-02-02 18:11
    mpark, What's that? [noparse]:)[/noparse]

    OK you got me.

    Edit: Could of sworn I was replying to mpark, or did I imaging his post?

    Edit again: So mpark, is it so that you did not get me, there is no recursion in the SPIN interpreter. Even if there is in SPIN itself. Rather like a CPU emulator where the emulated CPU supports a stack but the emulator need not have.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.

    Post Edited (heater) : 2/2/2009 6:25:45 PM GMT
  • mparkmpark Posts: 1,305
    edited 2009-02-02 20:08
    Sorry heater, I deleted my post because I realized I don't know enough about the inner workings of the Spin interpreter to say for sure one way or the other.

    Carl Jacobs (JDForth) has a recursive PASM Fibonacci program.
  • heaterheater Posts: 3,370
    edited 2009-02-02 20:18
    "Carl Jacobs (JDForth) has a recursive PASM Fibonacci program."

    Ha yes, now we are talking, those Forth guys can't do anything with out a stack.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Carl JacobsCarl Jacobs Posts: 41
    edited 2009-02-02 22:43
    JDForth has a recursive Fibonacci program in PASM, as mentioned by mpark. It uses a simulated stack (in HUB memory) to support the recursive nature of the algorithm.

    I believe that PASM is probably the first language that I've used that doesn't have any internal notion whatsoever of a stack. Spin, of course, has got a stack which allows the definition of recursive functions quite simply.

    heater is quite right in saying that us Forth guys can't live without a stack, but neither can Spin guys, C guys, Pascal Guys, most Assembly language guys, most Basic guys. In fact, finding a language that is *not* stack based is the real challenge. It's just that Forth is the one of the few languages where the stack is so explicitly exposed.

    I recall early last year stumbling over a bug in a AVR based C project that I was working on. The bug was caused by the fact that the floating point string printing routine was using a LOT more of the stack than what I was expecting (or had allocated)! The routine required something in the order of 100 bytes on the stack! I was shocked - to say the least.

    In 20 odd years of programming I think I've used a recursive algorithm to solve only ONE problem - directory tree navigation, using recusion to step down into the various sub-directories. I could imagine a memory allocation alorithm being recursive, or a database indexing algorithm. But, as mentioned by Mike and heater, this level of coding may well be outside the scope of programming on the Propeller.

    Regards,

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Carl Jacobs


    JDForth - Forth to Spin Compiler http://www.jacobsdesign.com.au/software/jdforth/jdforth.php
    Includes: FAT16 support for SD cards. Bit-bash Serial at 2M baud. 32-bit floating point maths.·Fib(28) in 0.86 seconds. ~3x faster than spin, ~40% larger than spin.
  • heaterheater Posts: 3,370
    edited 2009-02-02 23:36
    I have never had to use recursion during my career, which spans more decades than I'd like to say. In fact in many projects of a safety critical nature it was expressly forbidden. I used it for the first time last year only because I was writing a recursive decent parser for myself.

    Hmm...I now feel the urge to define a simple C or Pascal like language that has no need of a stack and generates PASM code.
    So:
    No recursion.
    No operator precedence or bracketed expressions.
    Operators evaluated in the order they appear.
    No local variables, at least not on a stack.

    What else do we have to ditch? We already don't have interrupts to worry about[noparse]:)[/noparse]

    I'd want a full set operators to cover all PASM operations, like SPIN does.

    Given that the call hierarchy would then be simple tree structure it must be possible for the compiler to pass parameters around through global variables and work out when they can be reused in different parts of the program. Same goes for local variables.

    As a start the compiler would know that if no one higher up the call tree than a given function uses a particular PASM register then it can be used in that function as a local or to pass a parameter. Even if some other function in another branch of the tree reuses that register.

    In this way quite compact and fast code could be generated.

    Would anyone have a use for such a thing? Or would it be just another fun toy for me?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Mike GreenMike Green Posts: 23,101
    edited 2009-02-03 00:06
    heater,
    PL360 is a high level assembler / low level compiler that was developed for the IBM360 long ago. It had a "full set" of operators much like Spin and evaluated them left to right without parentheses. It allowed subscript brackets, but these were for use with index registers. I'm not sure what should be done to handle self-modifying code for indexing. Some kind of local variable use could work like [noparse][[/noparse] ] with a number in the brackets could be a sort of local variable referring to a source or destination like "counter := counter + - " and somewhere else you'd have " := @table + 1". This 2nd statement would generate "MOVS local001,#table" then "ADD local001,#1". The 1st statement would generate "local001 ADD counter,0-0" and "local002 SUB counter,0-0". This notation wouldn't handle self-modification of immediate source values, but I'm sure someone could come up with something that makes sense.

    PL360 had nice flow of control statements like IF / THEN, GOTO, and WHILE / DO. It even had a FOR / DO statement which could be optimized when the start and end values are both constants (to use DJNZ). These mostly took care of generating labels and jumps. In this case, a Prop version might test the carry and zero flags and might test for zero or non-zero.
  • heaterheater Posts: 3,370
    edited 2009-02-03 04:10
    PL360 sounds like just the thing.

    Arrays? Who said anything about arrays? Let's just have pointers. After all arrays are just syntactic sugar for offsetting from a pointer.

    Either way in all instructions the src and dest fields are pointers (as long as there is no #) so all we have to do is jam the calculated index values into them with MOVS, MOVD. Tricky part might me optimizing that so that it does not happen too often and as you say for loops should add/subtract to the source and dest fields as they go around rather than calculating a new base + offset each time. That might be easier if the index variable in a for loop is only in scope during the loop, then you can:
    1. Calculate it's initial value at the start of the loop from base + offset and MOVS/MOVD that value into all instructions in the loop that use it.
    2. Calculate the for loop step size.
    3. After each iteration add/subtract that step size from all the instructions src/dest fields that use the index. There may be more than one.

    May help if it is not allowed to write to the index during the loop. If you allow it then there may be a whole bunch of instructions within the loop that need modifying accordingly, yuck.

    For random array accesses here and there in a program we need to MOVS/D the base address into an instruction and then add the index each time.

    Damn, now I'm going to be up all night thinking about this.

    Did I mention, the multiply and divide operators will only work for constant powers of 2 for efficiency sake[noparse]:)[/noparse]


    Edit: I just noticed that you didn't actually use the word "array" I just imagined it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.

    Post Edited (heater) : 2/3/2009 4:16:06 AM GMT
  • virtuPICvirtuPIC Posts: 193
    edited 2009-02-03 09:45
    Okay, let me get a clearer picture. I consider the propeller much more than a toy. This great chip deserves to be handled decently. We should build good software the great way using all our knowledge, professional technology, and good tools to keep it alive, finish its not-a-common-microcontroller status, and hopefully even make it a wide spread product.

    Mike, you are correct that currently program memory is very small. Half a KWords minus special registers minus data memory. That's even less than PIC12F508 has - and this one only has a two level stack. However, memory size might increase dramatically. The keyword here is virtual memory. We could see the cog memory as a first level cache. There is this other thread about connecting a large DRAM to the prop. I stopped following it as it went into philosophical discussion. However, I thought how to do it and I am pretty sure that you can connect a DRAM without additional hardware and access will be faster than to propeller main RAM.

    Yes, I started assembler programming (hobby and business) on the 6502 (Commodore C64). We didn't have calling conventions, parameters, or local variables on this machine. This caused a few tricky, time eating bugs since from time to time even a single programmer forget which addresses or symbols are already in use. This went different when I upgraded to the 68 000 (Atari ST). Here we had indirect addressing with displacement also on the stack pointer which allowed for simple implementation of parameters and local variables. And by the way, there have been C-compilers since the early 70s. A C compiler needs these features. C has been developed on PDP-11 which had 64 KB of memory. Consider a propeller a PDP-11 on a chip. cool.gif

    There is a duality between data structures and programming concepts.
    • Single data item vs. single instruction.
    • Set of data items vs. instruction sequence
    • Array of data items vs. loop
    • Tree or graph data structure vs. recursion
    Well, I can imagine that you don't handle trees or arrays in embedded programming that frequently. And if so, you can simulate recursion by programming a lopp and handling the stack explicitly. As a side note, there is also a relation to grammar levels. Parsing a context free grammar like that for an arithmetic expression results in a syntax tree which you can most easily traverse by recursion. And this concept is important for more than user interfaces. And a second side note: The data structure needs not to be in main memory completely. This makes the small memory argument less valid.

    I am still thinking that we need something like calling conventions. Maybe not really rules but recommendations. Kinda styleguide. Implementing quasi-local variables by prepending names with function names seems not enough and is also waste of precious memory.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Airspace V - international hangar flying!
    www.airspace-v.com/ggadgets for tools & toys
  • Paul BakerPaul Baker Posts: 6,351
    edited 2009-02-03 11:18
    Yes but there's a key difference between the PIC12F and the Propeller, the stack on the PIC is necessary in order to make subroutine calls and is part of the hardware, implement one to many calls and your program will not run under any circumstance. The Propeller was designed to make calls without the need of a stack. You can make 100 subroutne calls and as long as the calls are not re-entrant then you have absolutely no issue. And if you do want to make a stack you can, you have the assembly functions at your disposal to make one. There is a C compiler for the Propeller, it implements everything it needs using the Propeller instruction set and the LMM (large memory model). The Propeller is a different animal, just because it doesn't do things in ways that have always been done doesn't mean it's not possible. You know the old addage about skinning cats.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
  • virtuPICvirtuPIC Posts: 193
    edited 2009-02-03 11:33
    Sorry Paul, on PIC12F the stack is not necessary, too. In the PIC the PC is a regular register and can be read, write, modified by any data transfer or arithmetic instruction. This would allow for a software stack. I'm nitpicking, sorry.

    Thank you for the hint to Bill Henning's LMM. I'll have a look into that. Recently I found papers (and patents) on code compression. Might be interesting to combine these two.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Airspace V - international hangar flying!
    www.airspace-v.com/ggadgets for tools & toys
  • ErNaErNa Posts: 1,752
    edited 2009-02-03 12:55
    A stack is an instrument, intended for single processors and/or communication between two processes not running in parallel. Like an ISR for example. The Propeller with 8 cogs running in parallel needs a different mechanism. I one posted http://forums.parallax.com/showthread.php?p=725595 just as a quick and dirty solution. There is an array of addresses to variables and an initialization process. I didn't know how to call a method with pointer, therefor the code is not a subroutine. And I couldn't determine the offset (16) with the @@ operator, so this is also hard coded. But in the meantime a lot of people gained some experience and, maybe, there is an solution for these problems. In a next step, one of the cogs will be a communicator and than it will be possible to exchange informations between cogs placed in different chips transparently. ErNa
    PS: If there is a resonance, I intend to document the modules in a CMap and I also will try to implement the mechanism in the Hanno's communication process, as far as I know, the variable to communicate with ViewPort have to be consecutive and I can not arrange my variables in that way in my application

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
  • Mike GreenMike Green Posts: 23,101
    edited 2009-02-03 16:40
    On the PIC12F, the hardware stack is absolutely necessary for subroutine calls and interrupts (which are special subroutine calls). Read the datasheet. The upper bits of the program counter are write-only. It's not a "regular register".

    Cog memory size is not going to increase. The memory size is wired into the instructions (9-bit address fields). You cannot connect additional memory to the Propeller and have it function like the on-chip memory. The data paths do not exist. The Propeller is nothing like a PDP-11. For one, it's a RISC architecture. Self-modifying code has to be used for any kind of structure access to cog memory. Packing and unpacking of partial word data is expensive. Any kind of indirect reference to cog memory is expensive.
  • ErNaErNa Posts: 1,752
    edited 2009-02-03 17:25
    More COG memory would make sense: commonly one uses pointers to address memory. Addresses not immediately reachable can be accessed via pointers. So the program and pointers reside in the first 512 words, data can be placed in the available address space virtually without limit.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
  • virtuPICvirtuPIC Posts: 193
    edited 2009-02-03 17:32
    Okay, I give up. Seems that we are approaching the question from different directions. Seems that everyone of us is right.

    Just one remark regarding your last message, Mike: I've read a number of PIC datasheets. and haven't seen any interrupts for PIC10F / PIC12F. You don't need the hardware stack for subroutine calls. You can program your own call stack.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Airspace V - international hangar flying!
    www.airspace-v.com/ggadgets for tools & toys
  • kwinnkwinn Posts: 8,697
    edited 2009-02-03 17:47
    virtuPIC, I think what you are proposing is a bit like having a Ferrari towing a forty foot trailer. A misuse (even abuse) of a powerful and elegant design that was intended to be embedded in, and controling hardware. What heater is suggesting might have merit if it is what I think, basically an assembler with a few added statements for looping and branching, and possibly a simplified and reduced instruction syntax.
  • Andrew E MileskiAndrew E Mileski Posts: 77
    edited 2009-02-03 18:57
    virtuPIC said...
    Okay, the Propeller is even missing decent subroutine calls... However, assuming I am using call or jmpret instructions: are there any conventions
    • how to build a call stack that can even handle recursion,
    • how to pass parameters (i.e. at which addresses),
    • how to pass return values?
    The documentation doesn't tell anything about all this. I've searched this forum and also couldn't find anything. However, calling conventions are extremely important! They are necessary for code sharing, to use software written by others, or to build or to use libraries.

    If there are no such conventions yet I volunteer to define some. Either on my own or leading a working group. Might also be a program item for the Propeller West Coast Expo. I am competent for this since I have a strong history in compiler construction I know about programming languages, programming concepts and I am even a backend expert.
    Sort of sounds like you want a Propeller ABI (Application Binary interface) like there is for other CPU architectures. There isn't one for the Propeller, probably because there isn't a huge need for one with only 496 longs.

    The focus of the Propeller is on SPIN, and that is well defined. With the introduction of virtual machines like LMM, this may change; LMM already has small ABI itself. I suggest you look into LMM.

    Post Edited (Andrew E Mileski) : 2/3/2009 7:04:47 PM GMT
  • heaterheater Posts: 3,370
    edited 2009-02-03 19:52
    I seem to remember there were people here working on the problem of an LMM assembler with macros and such. Crtainly I have seen specifications written out about macros required for LMM, yes and calling conventions I believe. Don't remember who. Wonder how far they got with it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • ErNaErNa Posts: 1,752
    edited 2009-02-03 20:08
    My impression is, generally reading is more complicated than writing. I also don't always catch the idea behind a statement. But I'm not using my mother-tongue. From the beginning: There is a big difference between serial and parallel programming. Stacks can be used to transport information between processes. But in the case of 8 cogs present, you have to have a more sophisticated mechanism to exchange information and synchronize processes. Dykstra showed the way with semaphores. But we do not read old papers, even when their content is still valid and valuable.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
  • heaterheater Posts: 3,370
    edited 2009-02-03 20:46
    ErNa, you are right stacks are an excellent way of throwing data at procedures and getting results back. Calling conventions come about so that language designers can get their compilers to work and to specify how to interface assembler or other high languages together. If everyone works to the same calling convention then you can mix and match languages.

    There is not much demand for PASM calling conventions, I guess, because we don't have any high level languages generating raw PASM to mix and match together. Also as stated with the lack of a stack and the confined space it makes the overheads to burdensome.

    You are right about the equivalent parameter/result exchange amongst processes executing in parallel. As far as I can tell most Propeller driver objects, serial, TV, VGA, whatever come with a set of interface routines in SPIN. This is fine as it is really simple to use SPIN as glue to assemble a system out of those drivers.

    BUT what if you don't want SPIN? What if you want to go straight from the your PASM code in on COG to, say, the FullDuplexSerial object's PASM?. Or you want to go from ImageCraft C to a PASM driver from Obex? Then you find the interfaces are not defined. Its time to read the code and probably hack it around to fit. Not good.

    As far as I can tell there is a common pattern of sharing a data block containing a "command" and the parameters/results. I have not looked at so many objects.

    Perhaps there is scope to define a "convention" in that area.

    Don't worry, we read old papers from time to time , some times we even understand them!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • ErNaErNa Posts: 1,752
    edited 2009-02-03 22:18
    I don't! I myself have to read certain texts over and over and this keeps me from reading new stuff wink.gif So, if You look to my source code (apologize for comments in german language) You may see, what I mean: Instead of passing a bunch of pointers to the subroutine, I pass a pointer to an array of pointers to variables. The first variables informs the start method about the number of parameters, later on this variable is used to pass commands. The started process either is a spin or an assembler routine. And the start routine is equivalent for every started process. This is very comfortable, for you don't have to care for the address of the actual parameter. Maybe, this parameter is an array element itself. This is a kind of standard and hopefully soon, I shall develop a protocol to transparently mirror variables into distributed processors, that is, now a process doesn't have to no the cog-id, if only the address in the common memory is known. Later the variable can be located into a different propeller. I run out of cogs and have do distribute processes to chips in parallel.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
  • jazzedjazzed Posts: 11,803
    edited 2009-02-04 01:39
    The propeller provides the liberty to change the return instruction address. This allows methods other than stack for passing parameters, etc intra-pasm. The shared-memory approach between pasm and spin, c, or whatever is fine, but not easily maintained with changes. Copying a block of pointers for at pasm init is a reasonable idea.

    heater, I look forward to your pasm compiler implementation.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    --Steve
  • Carl HayesCarl Hayes Posts: 841
    edited 2009-02-04 03:52
    Carl Jacobs said...
    JDForth has a recursive Fibonacci program in PASM, as mentioned by mpark. It uses a simulated stack (in HUB memory) to support the recursive nature of the algorithm.

    I believe that PASM is probably the first language that I've used that doesn't have any internal notion whatsoever of a stack.

    ... us Forth guys can't live without a stack, but neither can Spin guys, C guys, Pascal Guys, most Assembly language guys, most Basic guys. In fact, finding a language that is *not* stack based is the real challenge.
    Interesting, Carl.· My experience, about 40 years of it, is the exact opposite.· I've used assembler on perhaps a score of architectures, from IBM 709 (a vacuum-tube machine!) through 7094 and·all of the 360/370/390 series; various DEC machines; several non-360-related IBM types (1130, 1800, System/7, etc.); various Control Data stuff.· That's all assembler, but I've also used many compiled languages starting with Fortran II, Fortran IV, PL/I, Lisp, APL (really strange!), SAS (strange at first), probably fifteen or twenty others, even a little abominable COBOL; but always concentrated most on assembler.· Stacks are quite foreign to all of these, although of course it's possible to make LIFO structures (stacks) in any of them.· The only one I ever used that had stacks inherent in the architecture·was PC (8088-80286-80386-Pentium etc.) assembler, which I found one of the most bizarre assembler languages ever (the assembler, not the hardware).· I like lots of general registers, as in 360-and-so-forth, and phooey on stacks.

    Interesting how one's experiences affect one's prejudices.· I wonder whether Crays have stacks?· Probably not, because Seymour Cray started out at Control Data.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net

    Post Edited (Carl Hayes) : 2/4/2009 4:31:34 AM GMT
  • Carl HayesCarl Hayes Posts: 841
    edited 2009-02-04 03:57
    jazzed said...
    The propeller provides the liberty to change the return instruction address.
    So does every other machine ever designed, and every language ever devised,·n'est-ce pas?· APL may be an exception. So, also, may languages I'e never used, or wanted to use, such as C and its derivatives.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net

    Post Edited (Carl Hayes) : 2/4/2009 4:03:28 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-02-04 04:37
    Carl Hayes said...
    jazzed said...
    The propeller provides the liberty to change the return instruction address.
    So does every other machine ever designed, and every language ever devised, n'est-ce pas?
    While this may be true of von Neumann machines, in which programs, data, and the return stack share the same address space, many Harvard architecture machines, such as the PIC and SX, provide no access to the return stack except by performing a call or return. So it's virtually (if not actually) impossible to effect a change in the return address.

    -Phil
  • jazzedjazzed Posts: 11,803
    edited 2009-02-04 04:51
    Hmm. If one digs deep into the implementation rather than just smirking about this that and the other thing, one may realize a better understanding of how it is done. I'm not some big propeller defender (there's enough of that around here). It's just another device, but it does have some nice attributes when you get past some of its silly limitations. Good luck.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    --Steve
  • ErNaErNa Posts: 1,752
    edited 2009-02-04 08:15
    There is no single truth. When I talk about the propeller, there is not "return". I start one of an infinite number of cogs (processes) and they communicate. In theory. In praxis, I don't care and call subroutines. So, there are different levels. I start a cog and pass a pointer to an array of data. The cogs process loops and tests a command, executes this command either once or in a loop (always testing for a "break"). A status variables shows the actual state to others. This is a very primitive version of a process management but it works quite well. For example: the start only returns, after the started program initialized and gave an acknowledge, so I never have a problem with a not-yet-running cog. The communication slows down the application a bit, but, that doesn't really matter. Who cares?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cmapspublic3.ihmc.us:80/servlet/SBReadResourceServlet?rid=1181572927203_421963583_5511&partName=htmltext
  • heaterheater Posts: 3,370
    edited 2009-02-04 08:41
    Jazzed: "heater, I look forward to your pasm compiler implementation."

    That sounds like a challenge!. Given that my compiler designing/writing skills are up to the level of Jack Crenshaws "Let's Build A Compiler" (just) and the language features proposed here are fairly minimal this might even happen.

    I do have a version of a Crenshaw TINY like language that compiles to LMM PASM so there is a little head start.

    Might take a while.....

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
Sign In or Register to comment.