Shop OBEX P1 Docs P2 Docs Learn Events
Assembly Language Question — Parallax Forums

Assembly Language Question

I have been trying to find free courses on learning Assembly language and so far have not come across any.

Does anyone know where I can find such courses and any backup software that may be require?
«13

Comments

  • Hello!
    And welcome to the Forum as they say.
    Now as to your question, which dialect are you thinking of? For your PC? For a target? We'd need to know which of course to help you. For all of the machines I've written for, I found I needed to read the books on them, for the PC there are plenty, for the target? It depends.



    ----
    This message is sponsored by Wookiees for a freer world.
  • JonnyMacJonnyMac Posts: 8,912
    edited 2018-09-15 19:15
    A colleague in the Cyber-Security world recommends "Programming From the Ground Up" to learn Assembly coding.
    -- https://www.amazon.com/gp/product/1540831825

    I bought a copy, but I'm told you can find it a PDF on the Internet.
  • tonyp12tonyp12 Posts: 1,950
    edited 2018-09-15 02:54
    recommend going with older 16bit risc type mcu like a msp430
    http://robotics.hobbizine.com/asmlau.html

    Arm Cortex are simple load-and-store (accumulator) but makes up for it by merging shift or multiple registers in same instruction,
    that makes your head spin, so program them in C.
  • An older intel 8085 trainer is a good learning tool. You'll learn the 8085 instruction set and. It will take you from bit loading a monitor program from switches so you can load programs from a keypad.
    Building your own processor from TTL logic gates will give you a ground up approach. This way you'll build The ALU, registers, counters, clock, control logic and write your own instruction set.
    if that's to much you can always download one of the emulators.
  • I want to learn Assembly not only because of the Propeller but also for some coding on other stuff.
  • Heater.Heater. Posts: 21,230
    Personally now a days I would stay away from learning assembler starting with 8 or 16 bit instructions sets. Things like 8085 assembler are not pleasant to deal with compared to a 32 bit instruction set like the Propeller, ARM, MIPS, RISC V etc. Simply adding numbers that are bigger than 255 is multi-instruction pain.

    I'd also avoid the complex mess that is the Intel x86 instruction set unless you really need to use that for some odd reason.

    The Propeller instructions set and assembly language is about one of the simplest and nicest I have ever seen. Especially as PASM is nice integrated into the Spin language and the whole thing is so easy to use from the Propeller tool. It's about the easiest way to start with assembler whilst programming an actual machine.

    Surely there is some nice course material out there for learning PASM. I have never checked as I quickly picked up what I needed from the Propeller manual.

    I don't know if they still do it but universities and colleges used to introduce assembler programming using the MIPS instruction set. That is nice and simple to get started with. They would often do the teaching using a simulator so no messing about with hardware was required. For example: https://chortle.ccsu.edu/AssemblyTutorial/index.html

    MIPS is not such a common machine to find now a days, except your home network router probably runs a MIPS processor. But learning assembler with it is very relevant as it is a RISC machine similar to ARM, as in your phone, or the up and coming RISC V architecture and others.

  • potatoheadpotatohead Posts: 10,253
    edited 2018-09-17 18:45
    The single most important thing to internalize is assembly language is operating the computer directly.

    It takes a mental shift away from higher level programming where operating the computer is indirect most of the time.

    Take a print statement. You write it, and all sorts of code happens, and you see what you asked for rendered on what you asked for.

    In assembly, there is a loop somewhere taking the print characters say it is "hello world", from where they may be in RAM, and copying them to the device memory, port or register, one at a time.

    That same kind of loop may point at something entirely different, say adding numbers together, to a different outcome.

    At the most basic level, computers do only three things:

    Add numbers together.

    Operate on them, AND, OR, NOT, XOR, etc...

    Copy numbers from one address, into another address or register.

    That's it!

    Storing a number somewhere can mean very different things! There may be one move or store operator. What the number is, and where it goes determines what happens. You have an impact on that, due to what you want the numbers to mean, and the computer does, based on how it was made and what it may contain, how it was connected, addressed.

    Store a number in a screen memory range and it may be dots, or a character, or a color.

    Store it in a memory location you intend to hold a counter, and that is what it is, because you say it is and your code is written based on that being what it is, or means.

    Store it in a hardware register, and a light may come on, or some action may happen.

    Think of the computer not as a unit. It has many parts. They almost all matter to an assembly language programmer.

    You need the schematics, or at the least, functional description of it's parts, what is connected to what, where, and how it is addressed.

    https://www.nand2tetris.org/book

    I would start somewhere like that book to get the right frame of mind.

    I would also get a commented assembly listing from one or more of your intended targets, along with the CPU reference cards that detail the instruction set.


    Here is one that makes a beep on the old Apple 2. This is one of the very first things I did way back when.
        LDA #DURATION
    outer:
        LDX #FREQ ; The lower the value, the faster the clicks and the higher the pitch of the tone
    inner:
        DEX       ; decrease inner counter
        BNE inner ; loop inner counter until zero
        STA $C030 ; click the speaker
        DEC       ; decrease outer counter
        BNE outer ; loop outer counter until zero
        RTS
    

    A, X, Y are CPU registers. Those are the working parts of the CPU. The memory holds data, or some memory addresses are actually wired to hardware! Every type of CPU is different. This one is very simple, also very limited.

    That program sits in the memory, and the CPU fetches it a byte at a time, does the operations with its registers, or by working with memory, and that is it! Anything else that happens is all about what hardware is in the computer. Important to understand.

    In this case, address $C030 is wired to the speaker. When it is accessed, the speaker clicks. Access it a lot of times and you get a buzz. Access it fast, and you get a tone. On that computer, it is just the address access that makes the click. Other computers may want a specific number too. This can be true even though they have the same CPU, and thus, same assembly language!

    This program is just two nested FOR loops. Outer, and inner. The only thing in this whole program that makes sound is the store instruction. The rest is what makes the loop happen.

    In a higher level language, this might be something like BEEP(frequency, duration)

    Now, here is a key insight: what frequency numbers make what sounds? Secondly, what duration numbers equal what times?

    To answer these, you have to go look at how the computer was made. That computer ran at 1mhz. Sloooow. That gives you one clue. The clock and that CPU getting things one byte each clock.

    Look at the data sheet for the 6502 CPU, and each line of that program, an instruction, takes X number of cycles. Clocks.

    With that, you can add all the cycles up, figure out how long a loop takes, and understand what duration and time mean. Clicks per second = pitch.

    Those things all are an artifact of the hardware, and the code. They are not predetermined for you like they would be for something like a BEEP statement that can be written for many different computers.

    I will stop there. Pick a target machine. Get some really simple code, ideally with comments. Get the hardware description, the CPU, and begin to work through the program. Comment it yourself. Then change it, etc...

    Use the book, or similar, for background.

    Start asking questions. It may take a lot of them. That is OK, usually does.




  • Heater.Heater. Posts: 21,230
    edited 2018-09-17 17:29
    potatohead,
    At the most basic level, computers do only three things:
    Add numbers together.
    Operate on them, AND, OR, NOT, XOR, etc...
    Copy numbers from one address, into another address or register.
    That's it!
    Wait a minute. We need more than that. We need less than that...

    Sure we need arithmetic, logical operators etc. They are all variants of the same thing. They take a couple of operands from memory somewhere and produce a result somewhere else. But we need more than memory in which to store operands and results and operators like that.

    To make a computer that runs programs we need to be able to do many such operations one after the other, sequentially.

    But we need more, we need the machine to be able to make decisions depending on some condition or other. That is to say, select one sequence of instructions to follow next or some other.

    From a program building point of view we also need a way to do iteration. Repeating some sequence of instructions many times.

    There we have all of programming: Sequence, Selection, Iteration.

    (Arguably "iteration" is redundant as it can be built from "selection")

    Now, we can achieve all of that with a single instruction, SUBLEQ. That is "Subtract something from something then jump somewhere else in the code if the result is negative else continue with the next sequential instruction"

    SUBLEQ A, B, C

    Of course if you only have one instruction you don't need to say what it is so we have

    A, B, C

    https://esolangs.org/wiki/Subleq

    On the other hand if you are programming an Intel x86 processor you only need the move instruction (MOV):
    https://github.com/xoreaxeaxeax/movfuscator

    :)

  • Assuming the target is a Propeller1:

    Get Spin2Cpp (including FastSpin) and translate whatever you are interested in from C or Spin (BASIC is work in progress) to PASM (cog mode) with them and compare the PASM output to your high level language source.

    This method may work with other systems/compilers too but it was an opportunity to mention FastSpin which currently is the coolest kid on the block... ;-D
  • potatoheadpotatohead Posts: 10,253
    edited 2018-09-17 17:41
    @Heater, one instruction capable of all three things is still doing all three things. Baby steps here. Lol We should not throw our friend into the deep pool just yet.

    Bonus: anyone questioning the three things has the important mindset to advance mastery of ASM.

  • Heater.Heater. Posts: 21,230
    Ah, sorry potatohead, I went of the deep end a bit there. My, possibly, useful contribution to the question was in a post before that.

    What I started out trying to say is that we need something more than just operators like ADD, SUB, AND, OR, XOR, MOV etc. Conceptually we need more, we also need flow control, JMP, CALL, RET, and critically we need decision making BEQ, BLE, etc.

    Without those we cannot express algorithms.
  • potatoheadpotatohead Posts: 10,253
    edited 2018-09-17 18:33
    Indeed we do.

    Add does all math. Bit ops handles bits and can help make conditionals easier. Moving numbers handles, call, jump, and friends.

    I find thinking right here somewhere super useful for that mindset. The times I have taught ASM lead rapidly to your observations.

    What is JMP? Put a number in the program counter and find out!

    Going lower, we only need NAND. Going a bit higher, may not convey what assembly, and or machine language is as it begins to look higher level.

  • Heater.Heater. Posts: 21,230
    potatohead,

    OK. If we are prepared to accept the program counter as just another number that we can operate on (Not true in many machines) we don't need jump and branch instructions. Just move stuff into it or add to it etc.

    Yes, with only NAND or NOR we can make any other gate, and registers, memory, adders, multipliers etc, etc.

    Hmmm... Foregt the SUBLEQ we have to build a NAND only instruction set and assembly language.

    But, at risk of being annoying, riddle me this:

    Given nothing but a huge supply of perfect NAND or NOR gates is it possible to build a computer? When I say perfect I imply zero propagation delay.

    Seems to me that one needs a clock. That is going to require a capacitor or other time delay in the circuit somewhere.

    That is not one of our NAND or NOR building blocks.

    The clock is what gives us the "sequential" part of computing. It's what ensures steps get done in the right order.
  • Heater.Heater. Posts: 21,230
    Oh, Smile, potatohead, you got me thinking....

    I'm sure you are familiar with Conway' Game of Life.

    In the Game of life there are no logic gates. There are cells. Their inputs are the state (live or dead) of their neighbors. Their output is their own state (live or dead).

    Arguably cells can all be implemented without NAND or NOR. An analogue comparator would do.

    But, I'm told the game of life is Turing complete. It can do anything a computer can do. Which includes computing NAND or NOR.

    Seems NAND and NOR are not the fundamental building blocks after all.

    It does have a clock mind...
  • Heater. wrote: »
    Seems NAND and NOR are not the fundamental building blocks after all.

    I'm pretty sure there's no single "fundamental building block", there are a number of alternate approaches that can be equally "fundamental" in that sense that any one of them can be built from the others. That's kind of what Church's thesis is. (For example, the lambda calculus, which has no comparators, NAND, or NOR at all, is Turing complete.)

    Getting back from the realms of abstract computing to the original thread... :)

    @yeti's suggestion to look at assembly output from a compiler is a good one. Not only fastspin, but also PropBasic and PropGCC can produce assembly language, as can gcc or clang for any platform. Try writing simple functions and run them through the compiler, and see what kinds of output it produces. This won't replace an assembly language tutorial, but it may supplement it and help you to see how to do specific things. As a for-instance, if you want to know how to add numbers you can create a function like:
      PUB addit(x, y)
        return x+y
    
    or in C
      int addit(int x, int y) { return x + y; }
    
    then compile it with "spin2cpp --asm foo.spin" or "propeller-elf-gcc -S -Os foo.c" to get something like:

    spin2cpp output:
    PUB main
      coginit(0, @entry, 0)
    DAT
            org     0
    entry
    
    _addit
            add     arg1, arg2
            mov     result1, arg1
    _addit_ret
            ret
    
    result1
            long    0
    COG_BSS_START
            fit     496
            org     COG_BSS_START
    arg1
            res     1
    arg2
            res     1
            fit     496
    

    PropGCC output:
            .text
            .balign 4
            .global _addit
    _addit
            add     r0, r1
            jmp     lr
    

    These are a little different (different compilers enforce different ways of calling functions and storing variables in memory) but the basic iinformation is the same -- to add two integers x and y, use the "add" instruction.
  • Heater.Heater. Posts: 21,230
    ersmith,

    Hmm... I have no idea about Church's thesis or lambda calculus. I have never seen even a description of them that is written in any kind of language I understand.

    If there are no comparators, NAND, or NOR at all then how are we ever going to build an actual computing machine out of it? Don't we need a fundamental building block somewhere? A simple conceptual thing we can make in hardware.

    I have often looked at the assembler generator by compilers to see what is going on. Especially when I want to link my own assembler functions with a high level language or vice versa and want to be sure how parameter passing and such goes on.

    I'm not sure it's the best way to start learning assembler from scratch though.














  • ersmithersmith Posts: 5,900
    edited 2018-09-17 23:57
    Heater. wrote: »
    Hmm... I have no idea about Church's thesis or lambda calculus. I have never seen even a description of them that is written in any kind of language I understand.
    Lambda calculus is really simple -- all it consists of is functions and variables. "lambda" (in text represented by a backslash) binds a variable in a function. For example, \x.x is the identity function; \y(\x.y) is a function which itself returns a function that always returns its argument. Evaluation consists of variable substituion ((\y(\x.y))z)w => (\x.z)w => z. Anything computable can be defined in terms of these things. Note that lambda calculus doesn't even have integers as builtin concepts (they can be defined as lambda expressions). There's a proof that Turing machines and lambda calculus are equivalent (can calculate the same functions). Church's thesis is that these capture the "intuitive" idea of a computable function, i.e. a function that you can describe how to compute.
    I have often looked at the assembler generator by compilers to see what is going on. Especially when I want to link my own assembler functions with a high level language or vice versa and want to be sure how parameter passing and such goes on.

    I'm not sure it's the best way to start learning assembler from scratch though.

    Agreed, it's not enough on its own. Reading manuals is good; so is reading good examples (like from the obex).


  • jmgjmg Posts: 15,140
    AIman wrote: »
    I have been trying to find free courses on learning Assembly language and so far have not come across any.
    Does anyone know where I can find such courses and any backup software that may be require?

    Which Microcontroller or processor ?
    A good way to learn both the Assembler Code and what the assembler actually does, as it runs, is on a Chip Simulator (or good debugger)

    Google finds a few useful looking simulators, & do not be averse to trying more than one... or more than one core..

    8 Bit Simulators are well tested and well supported with examples

    https://sourceforge.net/projects/mcu8051ide/
    https://www.edsim51.com/
    http://www.oshonsoft.com/avr.html#screenshot
    http://starlo.org/blake/boardmicro/


    Or, if you want to learn, and also run some real code in a HW project, look at the low cost eval boards, with USB-Debug-Bridges included.
    SiLabs toolsticks (eg TOOLSTICK850-B-SK) and Atmel Xplained minis for example.
    Those Debug IDEs tend to be rather larger, but they are actively supported.
  • AleAle Posts: 2,363
    edited 2018-09-18 19:17
    Personally now a days I would stay away from learning assembler starting with 8 or 16 bit instructions sets. Things like 8085 assembler are not pleasant to deal with compared to a 32 bit instruction set like the Propeller, ARM, MIPS, RISC V etc. Simply adding numbers that are bigger than 255 is multi-instruction pain.

    I think the same, but: I changed jobs recently and had to learn 8051 assembly. Yes, we program in C but I may be custom to the good code produced by gcc (loosely use of "good", if you want) and sometimes choke at the code produced by certain commercial compiler. The compiler doesn't let you do much, not that much is possible but I have a couple wishes for the writers. I may not have wanted to learn yet another assembly dialect but I really enjoy programming again, even... that :smile: . We develop and fab integrated circuits, what else can I want ? :smile:
  • My recommendations:

    8-bit: Z8
    16-bit: MSP430
    32-bit: Propeller!

    Avoid the AVR. The instruction set is optimized for C, not for native assembly programming.

    -Phil
  • My recommendations:

    8-bit: Z8
    16-bit: MSP430
    32-bit: Propeller!

    Avoid the AVR. The instruction set is optimized for C, not for native assembly programming.

    -Phil
    Why would the fact that the instruction set is optimized for C mean you couldn't do assembly language programming in it?
  • David Betz wrote:
    Why would the fact that the instruction set is optimized for C mean you couldn't do assembly language programming in it?
    If you actually read my post, you would realize that I did not say that you couldn't. (In fact, I have programmed it in assembly on multiple occasions.) It's just that the instruction set, being optimized for C, is highly non-orthogonal, which means that there are exceptions (traps) around every corner. So it's not a good assembly language to cut your teeth on.

    -Phil
  • David Betz wrote:
    Why would the fact that the instruction set is optimized for C mean you couldn't do assembly language programming in it?
    If you actually read my post, you would realize that I did not say that you couldn't. (In fact, I have programmed it in assembly on multiple occasions.) It's just that the instruction set, being optimized for C, is highly non-orthogonal, which means that there are exceptions (traps) around every corner. So it's not a good assembly language to cut your teeth on.

    -Phil
    That's kind of odd. I would think a C compiler would do better with an orthogonal instruction set. It's usually the oddball instructions in a CISC architecture that are never used by the C compiler. I guess I should take a look at the AVR architecture.
  • Heater.Heater. Posts: 21,230
    Do you have some examples of that AVR non-orthogonality Phil? I don'y know so much about the AVR instruction set so that would be interesting.

    In terms of staying away from non-orthogonality I would suggest staying away from the 8080 and 8086 machines.

    Is it so that we don't have a super simple beginners tutorial for Propeller assembler that we can link people to?
  • heater wrote:
    Do you have some examples of that AVR non-orthogonality Phil?
    It's been awhile, but what I most remember is that some registers could not be used in certain instructions with certain addressing modes. I think that the (then) Atmel engineers ran a bunch of simulations with various C programs, and culled the instruction/addressing-mode combinations that appeared least frequently in order to shoehorn their most-frequent combinations into an 8-bit instruction set.

    -Phil
  • jmgjmg Posts: 15,140
    Wiki claims this
    "Program execution
    Atmel's AVRs have a two-stage, single-level pipeline design. This means the next machine instruction is fetched as the current one is executing.
    Most instructions take just one or two clock cycles, making AVRs relatively fast among eight-bit microcontrollers.

    The AVR processors were designed with the efficient execution of compiled C code in mind and have several built-in pointers for the task.

    Instruction set
    Main article: Atmel AVR instruction set
    The AVR instruction set is more orthogonal than those of most eight-bit microcontrollers, in particular the 8051 clones and PIC microcontrollers with which AVR competes today. However, it is not completely regular:

    Pointer registers X, Y, and Z have addressing capabilities that are different from each other.
    Register locations R0 to R15 have more limited addressing capabilities than register locations R16 to R31.
    I/O ports 0 to 31 can be bit addressed, unlike I/O ports 32 to 63.
    CLR (clear all bits to zero) affects flags, while SER (set all bits to one) does not, even though they are complementary instructions. (CLR is pseudo-op for EOR R, R; while SER is short for LDI R,$FF. Arithmetic operations such as EOR modify flags, while moves/loads/stores/branches such as LDI do not.)
    Accessing read-only data stored in the program memory (flash) requires special LPM instructions; the flash bus is otherwise reserved for instruction memory.
    Additionally, some chip-specific differences affect code generation.
    Code pointers (including return addresses on the stack) are two bytes long on chips with up to 128 KB of flash memory, but three bytes long on larger chips;
    not all chips have hardware multipliers;
    chips with over 8 KB of flash have branch and call instructions with longer ranges; and so forth.

    The mostly regular instruction set makes programming it using C (or even Ada) compilers fairly straightforward. GCC has included AVR support for quite some time, and that support is widely used.
    In fact, Atmel solicited input from major developers of compilers for small microcontrollers, to determine the instruction set features that were most useful in a compiler for high-level languages."
  • Heater.Heater. Posts: 21,230
    Thanks for that comprehensive summary jmg.

    So all in all more orthogonal that something like Intel 8080/8086. Not bad at all.

    If you want orthogonal you have to go RISC V or Propeller!

  • The_MasterThe_Master Posts: 199
    edited 2018-09-19 06:10
    AIman wrote: »
    I have been trying to find free courses on learning Assembly language and so far have not come across any.

    Does anyone know where I can find such courses and any backup software that may be require?

    This is really good question. I have seen a number of times where no documentation on assembly was available at all. Just a C compiler.

    I can recommend books, depending on the processor.

    I have this fantasy that now that Microchip bought Atmel, they slowly phase out all the PIC crp and start ramping up AVR and 8051. Of course the OPPOSITE could happen too. And that would really really suck.
  • My favorite 8-bit CPU to code in assembly is still the 6502 variants. For 16-bits the MSP430 is very nice and of course for 32-bits there can be no other but Prop although I used to program 32-bit ARM and they were quite nice to program in assembler before they went to their C optimized 16-bit crippled Thumb instruction Cortex M series. Something to do with running out of memory and not fast enough IIRC :)
  • jmgjmg Posts: 15,140
    The_Master wrote: »
    I have this fantasy that now that Microchip bought Atmel, they slowly phase out all the PIC crp and start ramping up AVR and 8051. Of course the OPPOSITE could happen too. And that would really really suck.
    If you look at the new products from Microchip, the lowest cost recent additions were all AVR tiny's so it looks like the bottom-end PICs are already being de-emphasized.
    In the sub 35c MCU space, Microchip have some Tiny's but they have less code:ram than the STM8 and EFM8 alternatives from ST & Silabs.

Sign In or Register to comment.