vendredi 13 mai 2016

LESSON #2 : OS-Friendly Fibonacci routine


Overview


In the previous lesson, we learnt how to write the Fibonacci algorithm in ASM 68K. This is half the work because the program is not able - in current state - to outputs the value. The program calculates the correct numbers but the only way to see results is to use a Debugger - such as MonAm embedded in the Devpac IDE.

To outputs the values, our program needs to interact with his environment. There are some differents ways to do this. We could create a file and writes the results inside. It is a possibility. We could also outputs the results in the CLI window (Command Line Interface). We might eventually open a screen and print the values on it. Or why not outputs the value on a remote system using the Serial port (RS232).

Well. In all cases, we will need to use the underlying Operating System. Only exception is when you deliberately fully take over the machine and use directely the chipsets - we often call this "Bang" the hardware.

For our today lesson, we will use the Operating System, in a OS-Friendly way.


The plan


We will see how to add all the needed code to our Fibonacci program so that it becomes a dedicated AmigaOS binary, usable in the CLI/SHELL.

To accomplish that, here is what we need to do :
  • Use command line Arguments so that the user can interact with the program (INPUT).
  • Protect the program from Bad user inputs (PROCESS).
  • Compute the user inputs and calculates the corresponding Fibonacci numbers (PROCESS).
  • Print the computed Fibonacci numbers to the CLI (OUTPUT).
  • Return some Error Codes in case of something wrong (FEEDBACK).



Hello World


As a first OS program, we can try a simple 'Hello World' and explain it step by step.

What is important to keep in mind when programming the Operating System is to read the API carefully for each function we need to use. For the AmigaOS 3.x, best is to use the Amiga Developer Documentation.

I personally use the Online documentation available on this website :

http://amigadev.elowar.com

AmigaOS Includes and Autodocs


Or eventually, you could use the official documentation. But beware, it is AmigaOS 4 documentation, so there might be big differences with the old AmigaOS 3.x documentation. Anyway, this gives good overview of how to code the OS in C Language, with many nice examples.

Official AmigaOS.net Wiki

We will read the documentation for 3 functions used in the Hello World program. First step on AmigaOS is to use the EXEC library which is always open. This is a library similar to a DLL file on Windows. It is actually stored in the KickStart (ROM) so that it is available as soon as the computer boots. This is the entry that allows you to deal with all others libraries of the system. The EXEC library contains 2 importants functions in our case : OpenLibrary() and CloseLibrary() described here :

AmigaOS EXEC OpenLibrary()

AmigaOS EXEC CloseLibrary()

To output a string in the CLI, we need to open the DOS library. It contains many useful functions to print unformatted strings or formatted strings (similar to the C language printf). We will use the simplest one : PutStr(). It only needs the address of a NULL-terminated string and display it in the CLI window.

AmigaOS DOS PutStr()

Source code :

01:   IncDir   Work:Devpac/Include20/Include   
02:   Include  exec/exec_lib.i   
03:   Include  dos/dos_lib.i   
04: Main:   
05:   lea      DOSName,a1    ; A1 = DOS name.   
06:   moveq.l  #36,d0        ; D0 = DOS minimal version.   
07:   CALLEXEC OpenLibrary   ; D0 = OpenLibrary(A1, D0).   
08:   move.l   d0,_DOSBase   ; Store Result.   
09:   beq.b    .exit         ; Exit if D0 = 0.   
10:   move.l   #StrHello,d1  ; D1 = Message to print.   
11:   CALLDOS  PutStr        ; D0 = PutStr(D1).   
12:   move.l   _DOSBase,a1   ; A1 = DOS Base.   
13:   CALLEXEC CloseLibrary  ; CloseLibrary(A1).   
14: .exit                    ;   
15:   moveq.l  #0,d0         ; D0 = DOS Return Code.   
16:   rts                    ; Exit Program.   
17: _DOSBase   dc.l 0   
18: DOSName    dc.b "dos.library",0   
19: StrHello   dc.b "Hello World !",10,0  

The program begins by including some files from your disk. I use 'IncDir' to tell the compiler where to find the files on my disk. You have to modify it to use correct path. The directive 'IncDir' could be removed if you configure it globally in the Devpac settings : Menu / Settings / Assembler / Options... / Include field.

Then we include the 2 files that enable us to talk to the EXEC library and the DOS library, in a standard way. This two includes, you may want to look inside. You will see that they are quite simple. They defines the relative addresses of all the functions in the library. The values are relative to the Library Base. The Library Base is what you obtain in D0 each time you call OpenLibrary(). Also, at bottom of files, there is one useful MACRO.

01: CALLDOS MACRO  
02:   move.l _DOSBase,a6  
03:   jsr    _LVO\1(a6)  
04: ENDM  


This macro is important to understand. You can see that it use a '_DOSBase' which is pushed inside the Address Register 'A6'. This is how all OS functions works on AmigaOS. Before calling a function, we need to push the Library Base (could be DOS, Graphics, Intuition, ...) in A6 just before calling the function we want to use with the 'JSR' instruction. Every call to a OS function use 'JSR' instead of 'BSR'. Both are quite same, except that BSR is 16-bits so that if you want to jump in a sub-routine, this one must be not too far from current location in memory. When dealing with OS function, we use a 32-bits jump because the Library Bases locations are far in memory. About the '_DOSBase' in the macro, this means we need to declare it in our program. This is what we have at bottom of our Hello World program :

01: _DOSBase  dc.l 0  

This is a reserved space in our program. 'DC.L 0' means that we DeClare a LONG (4 bytes) and is initialized with 0. It is same as when declaring a variable in C Language 'int _DOSBase = 0;'. This area will be, then, filled by the 'move.l D0,_DOSBase' in our main program just after the OpenLibrary(). Doing this correctely allow us now to use the MACRO 'CALLDOS'.


The full program


Below is a complete program that use our Fibonacci routine, with extended features.



What the program does :

  • Use the AmigaOS EXEC library.
  • Open the AmigaOS DOS library.
  • Read 2 arguments from the command-line : FROM and TO.
  • Check the 2 arguments. Must be positive numbers (n >= 0).
  • Calculates all the Fibonacci numbers between FROM and TO.
  • Outputs the result in the command-line window.
  • Free the opened resources (library and arguments).
  • Returns an consistent error code, understandable by the user or a DOS Script.
  • Exit the program.

How is organized the code :

The source code shows how a ASM program 'could' or 'should' looks like. One proposal is :
  • Comment Block on top
  • CPU Target
  • Include files (AmigaOS3.x API)
  • Private definitions
  • Main program
  • Sub-Routines
  • Data Block at bottom

The full source code :

It introduces some other DOS functions such as ReadArgs() / FreeArgs() and another Print function that supports formatted strings : VPrintf() AmigaOS DOS ReadArgs() AmigaOS DOS FreeArgs() AmigaOS DOS VPrintf()

It also introduces some other new concepts such as the use of SECTIONs. These are blocks of memory that are relocated from DISK to MEMORY by the Operating System when executing the program. Generally, we place our code in a SECTION CODE and our data (defined with the DC.x / DS.x at bottom of file) in SECTION DATA. These directives allows the developer to choose in which memory type to program goes. It is useful in particular when core or data need to be located in the CHIP memory for use with the OCS/ECS/AGA chipsets.

At bottom of source, we use a 'MyLabel DS.L 2'. Do not mingle DC.L and DS.L. DC.L (DeClare) allocate 1 long, whereas DS.L (Declare Space) allocate 'n' longs.

There are some new instructions used in code such as LEA (Load an address in a Address Register), BTST (Test a given Bit), BMI (Branch if Minus)... I advise you to read the documentation on the official Motorola PDF or on the http://68k.hax.com website.
 ***********************************************************  
 **  
 ** Program   : Fibonacci  
 ** Version   : 1.01  
 ** Descr.    : Output Fibonacci 32bits numbers.  
 ** Author    : Flype  
 ** Copyright : Free to use.  
 **   
 ***********************************************************  
 **   
 ** Arguments:  
 **   
 ** FROM/N/A : Mandatory, First Number to compute.  
 ** TO /N/A  : Mandatory, Last Number to compute.  
 **   
 ***********************************************************  
 **   
 ** Usage:  
 **   
 ** >Fibonacci ?  
 ** >Fibonacci 1 47  
 ** >Fibonacci FROM=1 TO=47  
 **  
 ** >Version Fibonacci FULL  
 **  
 ** >Echo $RC   
 ** OK    ( 0) => No error occured.  
 ** WARN  ( 5) => An overflow occured.  
 ** ERROR (10) => One or more bad arguments.  
 ** FAIL  (20) => Failed to open DOS V36+ library.  
 **   
 ***********************************************************  
 **   
 ** Limitation:  
 **   
 ** Range of valid numbers is FROM=1 TO=47.  
 ** Starting from Fibonacci(48), the result is incorrect  
 ** due to the 32bits limitation which produces overflows.  
 **   
 ***********************************************************  
 **   
 ** History:  
 **   
 ** 1.01 - Initial release.  
 **   
 ***********************************************************  
   
   MACHINE MC68000  
   
 ***********************************************************  
 ** INCLUDES  
 ***********************************************************  
   
   IncDir Work:Devpac/Include20/Include  
   Include exec/exec_lib.i  
   Include dos/dos.i  
   Include dos/dos_lib.i  
     
 ***********************************************************  
 ** PRIVATES  
 ***********************************************************  
 
 RDARG_FROM EQU 0 ; FROM argument.  
 RDARG_TO   EQU 4 ; TO  argument.  
 
 ***********************************************************  
 ** MAIN PROGRAM  
 ** D6 = DOS Return Code.  
 ***********************************************************  
 
   SECTION .fast,CODE  
 
 Main:
 
 .openDOS
   lea      _DOSName,a1      ; A1 = DOS name.  
   moveq.l  #36,d0           ; D0 = DOS minimal version.  
   CALLEXEC OpenLibrary      ; D0 = OpenLibrary(A1, D0).  
   move.l   d0,_DOSBase      ; Store Result.  
   beq.b    .exitNoDos       ; Exit if D0 = 0.  
   
 ;==========================================================  
   
 .readArgs
   move.l  #ArgsTmplt,d1     ; D1 = Arguments Template.  
   move.l  #ArgsArray,d2     ; D2 = Arguments Array.  
   moveq.l #0,d3             ; D3 = Optional RDArgs struct.  
   CALLDOS ReadArgs          ; D0 = ReadArgs(D1, D2, D3).  
   move.l  d0,_RDArgs        ; Store Result.  
   beq.b   .exitBadArgs      ; Exit if D0 = 0.  
   lea     ArgsArray,a1      ; A1 = Arguments array.  
   move.l  RDARG_FROM(a1),a0 ; A0 = FROM argument.  
   move.l  (a0),d0           ; D0 = FROM number.  
   btst.l  #31,d0            ; D0 < 0 ?  
   bne.b   .exitBadArgs      ; Exit if D0 < 0.  
   move.l  RDARG_TO(a1),a0   ; A0 = TO argument.  
   move.l  (a0),d2           ; D2 = TO number.  
   btst.l  #31,d2            ; D2 < 0 ?  
   bne.b   .exitBadArgs      ; Exit if D2 < 0.  
   
 ;==========================================================  
   
 .loop
   cmp.l   d0,d2             ; While (D0 < D2)  
   bmi.b   .closeArgs        ; (  
   bsr     Fibonacci         ;   D1 = Fibonacci(D0)  
   bsr     PrintResult       ;   PrintResult(D0, D1)  
   add.l   #1,d0             ;   D0 + 1  
   bra.b   .loop             ; )  
   
 ;==========================================================  
   
 .exitNoDos
   moveq.l  #RETURN_FAIL,d6  ; D6 = DOS Return Code.  
   bra.b    .exit            ; Branch to Exit.  
   
 .exitBadArgs
   moveq.l  #RETURN_ERROR,d6 ; D6 = DOS Return Code.  
   move.l   #StrBadArgs,d1   ; D1 = String.  
   moveq.l  #0,d2            ; D2 = NULL.  
   CALLDOS  VPrintf          ; D0 = VPrintf(D1, D2).    
   bra.b    .closeDOS        ; Branch to CloseDOS.  
   
 .closeArgs
   move.l   _RDArgs,d1       ; D1 = Struct RDargs.  
   CALLDOS  FreeArgs         ; FreeArgs(D1).  
   
 .closeDOS
   move.l   _DOSBase,a1      ; A1 = DOS Base.  
   CALLEXEC CloseLibrary     ; CloseLibrary(A1).  
   
 .exit
   move.l   d6,d0            ; D0 = DOS Return Code.  
   rts                       ; Exit Program.  
   
 ***********************************************************  
 ** Fibonacci()  
 ** INPUT: D0 = Number to compute.  
 ** OUTPUT: D1 = Fibonacci Number.  
 ***********************************************************  
   
 Fibonacci:
   movem.l  d0/d2/d3,-(sp)   ; Store registers.  
   moveq.l  #RETURN_OK,d6    ; D6 = DOS Return Code.  
   clr.l    d1               ; D1 = 0  
   tst.l    d0               ; D0 = 0 ?  
   beq.b    .exit            ; Exit if D0 = 0.  
   moveq.l  #1,d1            ; D1 = 1  
   moveq.l  #0,d2            ; D2 = 0  
   moveq.l  #1,d3            ; D3 = 1  
 .loop
   cmp.l    #1,d0            ; While (1 < D0)  
   ble.b    .exit            ; (  
   move.l   d2,d1            ;   D1 = D2  
   add.l    d3,d1            ;   D1 + D3  
   bvs      .overflow        ;   Branch if Overflow detected  
 .continue
   move.l   d3,d2            ;   D2 = D3  
   move.l   d1,d3            ;   D3 = D1  
   sub.l    #1,d0            ;   D0 - 1  
   bra.b    .loop            ; )  
 .overflow
   moveq.l  #RETURN_WARN,d6  ; D6 = DOS Return Code.  
   bra.b    .continue        ; Come back to the loop.  
 .exit
   movem.l  (sp)+,d0/d2/d3   ; Restore registers.  
   rts                       ; Exit Sub-Routine.  
   
 ***********************************************************  
 ** PrintResult()  
 ** INPUT: D0 = Number to compute.  
 ** INPUT: D1 = Fibonacci Number.  
 ***********************************************************  
   
 PrintResult:
   movem.l  d0-d2/a0,-(sp)   ; Store registers.  
   lea      ResArg1,a0       ; A0 = 1st arg address.  
   move.l   d0,(a0)          ; (A0) = 1st arg value.  
   lea      ResArg2,a0       ; A0 = 2nd arg address.  
   move.l   d1,(a0)          ; (A0) = 2nd arg value.  
   move.l   #StrResult,d1    ; D1 = Result String.  
   move.l   ResArgV,d2       ; D2 = Result Array.  
   CALLDOS  VPrintf          ; D0 = VPrintf(D1, D2).  
   movem.l  (sp)+,d0-d2/a0   ; Restore registers.  
   rts                       ; Exit Sub-Routine.  
   
 ***********************************************************  
 ** DATA SECTION  
 ***********************************************************  
   
   SECTION .fast,DATA  
   
 _RDArgs    dc.l 0  
 _DOSBase   dc.l 0  
 _DOSName   DOSNAME  
   
   EVEN  
   
 ResArg1    dc.l 0  
 ResArg2    dc.l 0  
 ResArgV    dc.l ResArg1,ResArg2  
 
 ArgsArray  ds.l 2  
 ArgsTmplt  dc.b "FROM/N/A,TO/N/A",0  
   
 StrResult  dc.b "Fibonacci(%lu) = %lu",10,0  
 StrBadArgs dc.b "Invalid Arguments.",10,0   
 StrVersion dc.b "$VER: Fibonacci 1.01 (10.5.2016) Flype",10,0,0  
   
 ***********************************************************  
 ** END OF FILE  
 ***********************************************************  
   

End notes

As we can see, making a program in a OS-Friendly way requires many new code around our primary Fibonacci routine. That's a fact ! On the other hand, with the corresponding documentation, it is not so difficult. AmigaOS provide a clean and easy way to 'talk' to the system in assembly language.




mercredi 11 mai 2016

LESSON #1 : Fibonacci routine in ASM Motorola 68000.



Overview


For the first lesson, i will show you how to code the famous Fibonacci routine in ASM.





This algorithm is often used as an example / snippet to learn a new programming language syntax.

http://www.scriptol.com/programming/fibonacci.php

So, why not do it also for the Motorola 68000 processor ?

The Fibonacci formula calculates a sequence of integer numbers, well-known in mathematics and computer science.

The sequence is always the same :

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, [...]

fibonacci(0) ==> 0
fibonacci(1) ==> 1
fibonacci(2) ==> 1
fibonacci(3) ==> 2
fibonacci(4) ==> 3
fibonacci(5) ==> 5
fibonacci(6) ==> 8
fibonacci(7) ==> 13
fibonacci(8) ==> 21
[...]




More informations about the Fibonacci number can be found here :

https://en.wikipedia.org/wiki/Fibonacci_number



Begin the lesson with a Javascript implementation of the Fibonacci formula


Why Javascript ? Well, because it is simple and available for all of us. Just open your modern favorite web-browser in your main home computer, type the F12 key, and you have a ready-to-use tool that can execute code.

A typical Javascript Fibonacci program could be written like this :

function fibonacci(n) {
  return (n <= 2) ? 1 : fibonacci(n - 1) + fibonacci(n - 2);
}

But this is a recursive function - a function that calls itself - and i do not want this as a first ASM lesson.

So, better use such procedural approach :

function fibonacci(n) {
  var result = 1, a = 0, b = 1;
  while (n > 1) {
    result = a + b;
    a = b;
    b = result;
    n--;
  }
  return result;
}


Translating this function in ASM


In the 68000 CPU, the developer can use Data Registers to store any 32bits integer values. There is 8 Data Registers (D0 to D7). The CPU also have 8 Address Registers (A0 to A7) that can store any 32bits integer values just like the Data Registers does - but this time they should store a 32bits Address (pointer to a memory area) rather than a random value. In other words a Address Register should contains a Valid Address whereas a Data Register can contains any value. For our example, we only need to use Data Registers ; which is better for this first ASM lesson.

Now, let's replace the Javascript variables by some Data Registers ASM syntax. This will help us to understand better the logic when we will translate the code to ASM :

function fibonacci(d0) {
  var d1 = 1, d2 = 0, d3 = 1;
  while (d0 > 1) {
    d1 = d2 + d3;
    d2 = d3;
    d3 = d1;
    d0--;
  }
  return d1;
}

Once this is done, we will again make some changes to the Javascript code to avoid such mathematical expressions : d1 = d2 + d3;

We can't do such complex operations in ASM. We need to simplify it a little.

d1 = d2 + d3;

This is equal to :

d1  = d2;
d1 += d3;

According to this simple rule, we now rewrite the our function like this :

function fibonacci(d0) {
  var d1 = 1;
  var d2 = 0;
  var d3 = 1;
  while (d0 > 1) {
    d1  = d2;
    d1 += d3;
    d2  = d3;
    d3  = d1;
    d0 -= 1;
  }
  return d1;
}



Create our own ASM Sub-Routine


That is good enough now. We have a simple Fibonacci function, easy to convert in ASM. Only thing remaining is the While loop. In assembly language, you have no choice, all loops are done using the good old LABELS / GOTO, just like it is/was with old BASIC language. 

Let's see how this looks like :

01 Fibonacci:          ; function fibonacci(d0) {
02   move.l  #1,d1     ;   d1 = 1
03   move.l  #0,d2     ;   d2 = 0
04   move.l  #1,d3     ;   d3 = 1
05 .loop               ; 
06   cmp.l   #1,d0     ;   while (d0 > 1)
07   ble     .exit     ;   {
08   move.l  d2,d1     ;     d1  = d2
09   add.l   d3,d1     ;     d1 += d3
10   move.l  d3,d2     ;     d2  = d3
11   move.l  d1,d3     ;     d3  = d1
12   sub.l   #1,d0     ;     d0 -= 1
13   bra     .loop     ;   }
14 .exit               ; 
15   rts               ; }

Ok, it is done ! This 68K ASM Fibonacci routine works :) It is not optimized but it works as expected.

As you can see in this ASM code there is some stuff that needs to be explained. Let's try to do so line after line.

Line 1 : We declare the name of the function. It is a simple Label. In assembly language we call such Labels a "Sub-Routine" label.

Line 2 to 4 : We initialize our 3 variables, just like in the Javascript function.

Line 5 : We declare a sub-label. This label is in the scope of our Sub-Routine label. This means this label is not usable "outside" of the sub-routine. This label is used to "emulate" our "While" Javascript keyword.

Line 6 : Here we process the boolean expression of our "While". We wants to compare the Data Register "d0" and the numerical value "1". Such numerical values are called "Immediates values" in assembly language.

Line 7 : Once we asked the CPU to compare "d0" and "1", we wants now to compute our ">" operator (Greater Than).  CMP must have the numerical value as Left Operator. So we need to reverse our comparison. This becomes "Lower or Equal" which is "BLE". BLE means Branch to the given Label (.exit) if Right Operand (d0) is Lower or Equal to the Left Operand (1).

Line 8 to 12 : Easy to understand. Look at the comments and keep in mind that the Right operator is the destination whereas the Left operator is the source.

Line 13 : We branch to the .loop Label. This is same as the closing bracket of the Javascript While.

Line 14 : This is our Exit label, used by our comparison at line 6.

Line 15 : This RTS keyword tells the CPU to Return Sub-Routine. This means the program will come back to the main program. This is equivalent to the closing bracket of our Javascript function.



Call our Sub-Routine in a ASM program


Ok ok, we have a sub-routine that computes Fibonacci values. But how to make a full program with this ?

Well, this is not complicated. Just a matter of some lines in a so called "Main" program.

Here it is :

Main:              ; Main program          
move.l  #8,d0     ; d0 = 8
bsr     Fibonacci ; Fibonacci(8)
rts               ; Stop the main program

Fibonacci:         ; Sub-routine           
move.l  #1,d1     ; d1 = 1
move.l  #0,d2     ; d2 = 0
move.l  #1,d3     ; d3 = 1
.loop              ; 
cmp.l   #1,d0     ; while (d0 > 1)
ble     .exit     ; {
stop    #-1       ; 
move.l  d2,d1     ;   d1  = d2
add.l   d3,d1     ;   d1 += d3
move.l  d3,d2     ;   d2  = d3
move.l  d1,d3     ;   d3  = d1
sub.l   #1,d0     ;   d0 -= 1
bra     .loop     ; }
.exit              ; 
rts               ; Exit the Sub-Routine 

What to learn here ?

We have a "Main" label which is the Main program, just as a main() in a C source code.
Difference is you can call it as you want. Main: or Program: or MyProgram: or anything you prefers.

The "BSR". The BSR means "Branch to Sub-Routine" and will move the program to the given label - to our Fibonacci sub-routine.

The "RTS". The RTS in the main program will exit the program and return to the Operating System whereas a RTS in a sub-routine only exit from the sub-routine.

Ok, seems we understand little more how works a ASM program now. But there is something that is bad in our program (actually there is more than one but it is enough for the first lesson).



Protect the registers used in our Sub-Routine


As you can see our sub-routine use some Data Registers. We use D0, D1, D2 and D3. This 4 registers are used and overwritten by such instructions : MOVE Something into Dx.

Well, and ? Is it a problem ? Yes it could be. Our Data-Registers needs to be "protected" in the Sub-Routine so that the main program will not be impacted by the sub-routine execution. Just like a Javascript (or any language) function has his own scope inside the brackets { }. Remark : This is not mandatory, you could deliberately not wants to protect your routine to saves some execution cycles but then you need to perfectely know what you do - but this is another story. Let's focus on our 'protection'.

The protection is quite easy to add to our sub-routine. This is done like this :

Main:                      ; Main program
move.l  #8,d0             ; d0 = 8
bsr     Fibonacci         ; Fibonacci(8)
; d0 = $15 = 21
 rts                       ; Stop the main program

Fibonacci:                 ; Sub-Routine
movem.l d1-d3,-(sp)       ; Store used registers
move.l  #1,d1             ; d1 = 1
move.l  #0,d2             ; d2 = 0
move.l  #1,d3             ; d3 = 1
.loop                      ; 
cmp.l   #1,d0             ; while (d0 > 1)
ble     .exit             ; {
stop    #-1               ; 
move.l  d2,d1             ;   d1  = d2
add.l   d3,d1             ;   d1 += d3
move.l  d3,d2             ;   d2  = d3
move.l  d1,d3             ;   d3  = d1
sub.l   #1,d0             ;   d0 -= 1
bra     .loop             ; }
.exit                      ; 
 move.l  d1,d0             ; Put the result in d0
movem.l (sp)+,d1-d3       ; Restore used registers
rts                       ; Exit from the Sub-Routine 


The MOVEM instruction is like the MOVE instruction but it can move the contents of one or more registers into the STACK of the program, in one ASM instruction. The stack is a memory area that is pre-allocated by the Operating System when it executes a new task. Typically, the stack is 4096 bytes, but it can be much more. We are speaking of the same stack as the one we use in the AmigaOS CLI / SHELL when we do >SetStack 10000 for example. This memory area is very useful to store temporary our CPU Registers contents or any other datas. By convention, a sub-routine store and restore the registers in this dedicated memory area.

The SP is a special register. It is a ALIAS of the A7 Address Register that represents the stack of our program. This can be replace by A7 but it is more readable to use SP (Stack Pointer). We will studied it later, so i will not develop more this right now.



End-notes


Ok, we are now done for this first lesson. I hope this was interesting for ASM 68K beginners. As you can see, this lesson requires some general programming skills such as some Maths, Javascript and General Programming vocabulary and concepts.

Don't forget to refers to official Motorola documentation and to some useful existing websites :

http://68k.hax.com/

https://www.nxp.com/files/archives/doc/ref_manual/M68000PRM.pdf


See you for the next lesson.

Welcome to this new blog dedicated to the learning of the Motorola 68000 Assembly language.



Overview



In this blog i will try to show you some simple ASM coding under the AmigaOS 3.x environment and mainly using the Amiga Devpac 3.18 assembly editor.

This blog will **NOT** explain you all the instructions of the M68K CPU. No need for this. Always prefers the officials documentations. On my side, I prefer to show you how to code routines in practice - rather than explains you the theory. Some others books and websites will do this much better than this blog. My point is a more practical approach where we will see things as long as we need them.




Environment


The environment setup for the next lessons is quite basic. For what we will need to do, a basic AmigaOS 3.1 (or even 2.x) without any third-party apps is enough.

My choice of using Devpac instead of any other ASM programming editor is only because i find the Devpac editor very OS friendly, easy to use and it have a handy Debugger (Monam) that i know how to use. But PhxAss or ASM Pro are also very good alternatives.

As a easy start, you could use a real Amiga, WinUAE, or FS-UAE in addition to ClassicWB for example.

http://www.winuae.net/

https://fs-uae.net/

http://classicwb.abime.net/


 



Resources



- Documentation of Devpac :

 Devpac 3.x Manual (PDF)

- Officials Motorola MC680x0 manuals :

 MC68000 - User Manual (PDF)
 MC68000 - Programmer Manual (PDF)

- Online quick MC680x0 reference manual :

 http://68k.hax.com/

- Local MC680x0 reference manual (for use with Multiview) :

 http://aminet.net/package/dev/asm/mc680x0

- Online AmigaOS 3.x API documentation :

 http://amigadev.elowar.com/

- Some cool and helpy Blogs :

 http://assembly68k.blogspot.fr/