Shop OBEX P1 Docs P2 Docs Learn Events
PASM is universal? — Parallax Forums

PASM is universal?

lardomlardom Posts: 1,659
edited 2011-12-10 10:00 in Propeller 1
After a partially browsing a tutorial on PASM a couple thoughts occurred to me: If assembly is one level above machine language, and I assume machine language is the starting point for all computer languages, then the only difference between PASM and any other assembly language is mnemonics. BIOS must be assembly. C/C++ is probably a high level language like "Spin" which became a standard programming language. I don't yet understand the significance of 'object oriented'. Am I still pretty far off?

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-12-10 07:31
    Assembly language is a notation (a way of writing) for the machine language which is a sequence of (in this case) 32-bit words or groups of 8-bit bytes. Spin is indeed a programming language very similar to C. "object oriented" is a feature of some programming languages where names (of variables, subroutines, etc.) are grouped into named "objects". Sometimes these objects are grouped into hierarchies (not in Spin) where, at any level, these names can be inherited from lower in the hierarchy or overridden by supplying a new definition of the name. In some languages (not Spin), the "primitives" of the language are defined in this way so they can be modified / overridden by the user. Smalltalk and C++ are examples of this sort of thing where you can define something like large integers (say a 256-bit integer) and define the basic arithmetic operators (like +, -, *, /, etc.) in terms of the built-in 32-bit operators.

    Have a look at the Wikipedia's article on "object oriented" for more detail.
  • ersmithersmith Posts: 6,099
    edited 2011-12-10 07:47
    lardom wrote: »
    After a partially browsing a tutorial on PASM a couple thoughts occurred to me: If assembly is one level above machine language, and I assume machine language is the starting point for all computer languages, then the only difference between PASM and any other assembly language is mnemonics.
    Well, not quite -- assembly language (and PASM) is pretty much equivalent to machine language in the sense that a given assembly language program maps directly to a unique set of machine instructions. Assembly language is at its heart just putting human-readable strings to the numbers of the machine language, e.g. the PASM code:
    add 0,1
    ret
    
    produces the machine language instructions (written in hexadecimal for convenience):
    01 00 BC 80 00 00 7C 5C
    

    Note that the machine instructions available, and their encoding, differ from chip to chip, so you can't use 80386 assembly language for a Propeller, and vice versa! It's not just that the mnemonics are different, but the instructions that the machine understands are different.

    Typically assembly language adds a bit of convenience (e.g. you can use labels instead of numbers to refer to memory locations, and the assembler does some calculations for you), so in a sense it's higher level than machine language, but only just.
    BIOS must be assembly. C/C++ is probably a high level language like "Spin" which became a standard programming language. I don't yet understand the significance of 'object oriented'. Am I still pretty far off?

    C is slightly higher level still, because there's now a compiler that translates your C statements into machine language, and the mapping from C to machine language depends on the compiler -- a good compiler will produce very compact, "natural" code, but a weaker compiler will produce more inefficent code. The code above might be written in C something like:
    int foo(int a, int b) { 
      return a+b;
    }
    
    A compiler might turn it into PASM code that looks like:
    _foo
        sub    sp, #4
        wrlong    r14, sp
        mov    r14, sp
        add    r0, r1
        mov    sp, r14
        rdlong    r14, sp
        add    sp, #4
        'native return
    _foo_ret
        ret
    
    for a not so great compiler, and
    _foo
        add    r0, r1
        'native return
    _foo_ret
        ret
    
    for a better one. (Actually I used GCC for both of these examples, but just improved the optimization level for the second one.)

    Spin is a bit of a special case because AFAIK there is no compiler to translate Spin to PASM; rather the procedure is to translate Spin to "bytecodes" which are then interpreted by a program that runs in a COG. These bytecodes are designed to minimize the size of the program. The COG program reads the spin byte codes out of hub memory and then performs actions based on them. If it sees one number it will add some COG registers together, if it sees another it will subtract, and so on. This is very much like what the Propeller hardware does for machine instructions, but instead of each instruction taking 4 bytes of memory the Spin bytecodes can be variable sized in length (many of them just 1 byte) and can do more complicated things than the Propeller machine instructions. So the Spin bytecode program takes up much less memory than an equivalent machine language (or PASM) program. The Spin bytecodes can also be placed in hub memory (of which there is 32K) instead of COG memory (of which there is only 2K).

    And on the Propeller the small size of the internal COG memory has led to a kind of hybrid called LMM PASM (LMM stands for "Large Memory Model") where there is a very simple "bytecode" interpreter that reads machine instructions from hub ram and then executes them in COG memory. This is much faster than the Spin interpreter, since there is virtually no decoding of the instructions necessary, but the tradeoff is that the code is much bigger. Many high level languages for the Propeller actually use this mode of operation (including most C compilers).

    Eric
  • potatoheadpotatohead Posts: 10,261
    edited 2011-12-10 08:20
    Assembly language is somewhat universal in that how one approaches building programs in it doesn't vary much. The CPUs can differ considerably in how they do things, but the basic operations of computing; namely add, operate (and, or, not, xor) and move are the same.

    Some CPUs use a load operate store model that contains registers that are addressed as such apart from memory locations. Others use a memory to memory design. That is probably the biggest variance I've seen.

    If you've done assembly language on one CPU, mapping what you do to another one is a matter of understanding the model, load store vs memory direct, as much as it is understanding the various operations provided.

    So it's not really universal, in that programs generally must be rewritten, but it is in terms of the overall approach, IMHO.
  • lardomlardom Posts: 1,659
    edited 2011-12-10 08:52
    ersmith said:
    Note that the machine instructions available, and their encoding, differ from chip to chip, so you can't use 80386 assembly language for a Propeller, and vice versa! It's not just that the mnemonics are different, but the instructions that the machine understands are different.
    And I'm guessing this may have something to do with the 'architecture' of the processor. This is such a deep subject. It makes you appreciate all that had to happen to make "Spin" possible.
    @Mike Green, I bookmarked the article.
    @Potato head, you authored the tutorial I referred to. I have a lot of studying to do.
  • potatoheadpotatohead Posts: 10,261
    edited 2011-12-10 09:14
    Yes. It has everything to do with the architecture of the processor. IMHO, that is where the fun is in assembly language land. We get to deal very directly and quickly with the device we are authoring programs for.

    On a Prop, the core CPU design is a memory to memory design. It doesn't make use of registers addressed apart from memory. It also has conditional execution and flags to determine whether or not a given operation changes memory or the flags: zero and carry.

    On other CPUs, there are often registers, which are addressable apart from memory! They may or may not be conditionally executed too.

    eg:

    mov destination, source -- moves a number contained in the storage at the source address to the destination storage address (prop)

    vs

    ld r2, source -- moves a number contained in storage at the source address to the register addressed as "r2"

    LDA source -- moves a number contained in storage at the source address to register "A".

    All three of those move a number from one addressable place to another. That's a universal operation in assembly language. The actual places one would move the number, do vary according to how that processor works.

    On load store processors, one needs to pick the number up, put it into a working register, then put it down in to storage RAM again, to accomplish what a memory to memory design does with one instruction. So then, after performing the loads above, the load store designs would require this:

    mv destination, r2 -- moves the number contained in register "r2" to the storage addressed at destination

    STA destination -- moves the number in register A to the storage addressed at destination

    This is probably the most important bit of understanding of assembly language. One must understand the hardware in high detail to write effective programs. A higher level language like C doesn't have that same requirement. It can be done in C, but one doesn't have to do it, and in fact, not doing that is desirable because it then makes it considerably easier to use the same program on different CPUs.

    **I made up basic mnemonics to highlight differences in CPUs and the implications of those differences on what their assembly language might look like.

    The first thing one does when considering an assembly language program on a given CPU, is look at the programming model and hardware data sheet(s). All computers really only do a few things! They add numbers, operate on them, and move them around.

    What those numbers do is largely dependent on the hardware features of the CPU and connected devices. Storing a number into RAM is just storing a number. Store that same number in some address being watched by an additional device, and that same number might put a character on the screen, emit a sound or trigger current to flow to an LED.

    Re: Tutorial. Well cool! Let's hope it gets you over the hump! :) That one is very basic, and it does contain some of the core things important to me when I got my head wrapped around the basic assembly language concepts. Ask lots of questions, keep your goals very simple, like blinking that light, or making some sound (rapidly blinking light can be clicks on a speaker), and don't stop asking them. When it clicks, you will know, and you are off to doing greater things.
  • lardomlardom Posts: 1,659
    edited 2011-12-10 10:00
    Potatohead, thanks for writing the tutorial. Your writing style is compelling. The more I learn about spin the more I want to look through the microscope. It is an amazing field of study.
Sign In or Register to comment.