Skip to main content

My first assembly program dating from 1991 (Motorola 68000 for the Amiga 500)

While resurrecting my old Amiga I found and salvaged some of my first programs from the ailing floppy discs.

A program written in 1991 for the Amiga 500.

I wrote my first hello world program in 1983, but really learnt how to program in 1984. But this was my first assembly language program. It took me about 2 weeks to learn Motorola 68000 Assembly and the tools needed to develop it. I wrote it for a friend who was designing, building and selling hardware for the Amiga at the time. It was a memory expansion cartridge that upgraded to 1MB CHIP internally (and perhaps also extra fast memory, can't recall). The program tested and reported any defective memory chips.

A photo of it (still) running:


And here is the source code... don't judge too harshly!


       
        opt     c+,d+

        incdir  "df0:include/"

        include exec/exec.i
        include exec/exec_lib.i
        include libraries/dos.i
        include libraries/dos_lib.i



        lea     dos_name(pc),a1
        CALLEXEC OpenLibrary
        tst.l   d0
        beq     exit
        move.l  d0,_DOSBase

        lea.l   window_console(pc),a1
        move.l  a1,d1
        move.l  #MODE_NEWFILE,d2
        CALLDOS Open
        tst.l   d0
        beq     exit_closedos
        move.l  d0,filehandle

*****************************************************************

        lea     hello_message(pc),a0
        jsr     print
        
setupbuffer
        move.l  #2048,Bufsize                   Size of Buffermem(Freeing memory)
        move.l  Bufsize,d0
        move.l  #MEMF_CHIP,d1
        CALLEXEC        AllocMem
        tst.l   d0
        beq     nomem   
        move.l  d0,Bufstart                     Start of buffer
        move.l  #0,Offset                       Current offset

getmem  move.l  #MEMF_PUBLIC!MEMF_LARGEST,d1
        CALLEXEC        AvailMem
        cmp.l   #1024,d0  
        blt     freemem
        move.l  d0,Memsize
        lea     alloc_mem(pc),a0
        jsr     print
        move.l  Memsize,d0
        move.l  #MEMF_PUBLIC,d1
        CALLEXEC        AllocMem
testalloc
        tst.l   d0
        bne     test
        lea.l   failed(pc),a0
        jsr     print
        bra     getmem
test    move.l  d0,Memstart
        lea.l   passed(pc),a0
        jsr     print
        lea.l   allocated(pc),a0
        jsr     print
        move.l  Memstart,a1
        CALLEXEC        TypeOfMem
        cmp.l   #MEMF_CHIP!MEMF_PUBLIC,d0
        beq     chipmem
        lea.l   fast(pc),a0
        jsr     print
        bra     endtype
chipmem lea.l   chip(pc),a0
        jsr     print
endtype lea.l   memory(pc),a0
        jsr     print
        move.l  Memstart,d6
        jsr     printhex
        lea.l   to(pc),a0
        jsr     print
        move.l  Memstart,d6
        add.l   Memsize,d6
        jsr     printhex
        jsr     cr
        move.l  Bufstart,a1
        add.l   Offset,a1
        move.l  Memstart,(a1)
        add.l   #4,a1
        move.l  Memsize,(a1)
        add.l   #8,Offset
        move.l  Memstart,d0
        add.l   Memsize,d0
        move.l  D0,Memend

        lea.l   pattern(pc),a0
        move.l  a0,PatternCount

NextPattern
        move.l  PatternCount,a0
        move.w  (a0),d5
        jsr     startloop
        add.l   #2,PatternCount
        cmp.w   #%1010101010101010,d5
        bne     NextPattern

        jsr     cr
        move.l  Offset,d0
        cmp.l   Bufsize,d0
        beq     fragment
        bra     getmem

startloop
        move.l  Memend,a2
        move.l  #0,d4
        move.l  Memstart,a1
loopw   cmp.l   #0,d4
        bne     nowri
        jsr     wri
nowri   sub.l   #1,d4
        move.w  d5,(a1)
        add.l   #2,a1
        cmp.l   a2,a1
        blt     loopw

        move.l  #0,d4
        move.l  Memstart,a1
loopr   cmp.l   #0,d4
        bne     noveri
        jsr     veri
noveri  sub.l   #1,d4
        cmp.w   (a1),d5
        
        
        cmp.l   #$80000,a1              take these out
        bne     noerror
        jsr     seterror
        bra     noerror


        beq     noerror
        jsr     seterror
noerror add.l   #2,a1
        cmp.l   a2,a1
        blt     loopr
        rts

seterror

        move.w  #1,(a1)                 take this out
        
        move.l  a1,temp
        lea.l   founderror(pc),a0
        jsr     print
        move.l  temp,d6
        jsr     printhex
        lea.l   is(pc),a0
        jsr     print
        move.l  temp,a0
        move.w  (a0),d6
        jsr     printbin
        jsr     cr

        cmp.l   #$080000,temp
        blt     enderror
        move.l  temp,a0
        move.w  (a0),d6
        eor.w   d5,d6
        cmp.l   #$0fffff,temp
        bgt     next1
        move.l  #0,d2
        jsr     getbits         
        bra     enderror
next1   cmp.l   #$c00000,temp
        blt     enderror
        cmp.l   #$c7ffff,temp
        bgt     next2
        move.l  #4,d2
        jsr     getbits         
        bra     enderror
next2   cmp.l   #$cfffff,temp
        bgt     next3   
        move.l  #8,d2
        jsr     getbits         
        bra     enderror
next3   cmp.l   #$d7ffff,temp
        bgt     enderror
        move.l  #12,d2
        jsr     getbits 
enderror                
        move.l  Memend,a2
        move.l  temp,a1
        move.l  #$10707,d4
        rts
        
getbits 
        move.l  #16,d0
bitloop sub.l   #1,d0
        btst    d0,d6
        bne     nosetbit
        move.l  d0,d1
        divs    #4,d1
        add.l   d2,d1
        bset    d1,RamChips

nosetbit
        cmp.l   #0,d0
        bne     bitloop
        rts     

wri     move.l  a1,temp
        lea.l   writing(pc),a0
        jsr     print
        move.l  temp,d6
        jsr     printhex
        lea.l   pat(pc),a0
        jsr     print
        move.w  d5,d6
        jsr     printbin
        move.l  Memend,a2
        move.l  temp,a1
        move.l  #$10707,d4
        rts

veri    move.l  a1,temp 
        lea.l   verifying(pc),a0
        jsr     print
        move.l  temp,d6
        jsr     printhex
        lea.l   pat(pc),a0
        jsr     print
        move.l  d5,d6
        jsr     printbin
        move.l  Memend,a2
        move.l  temp,a1
        move.l  #$10707,d4
        rts
        

print   move.l  a0,a1
loop2   cmp.b   #0,(a1)
        beq     printit
        add.l   #1,a1
        bra     loop2
printit sub.l   a0,a1
        move.l  a1,d3
        move.l  a0,d2   
        move.l  filehandle,d1
        CALLDOS Write                           print something
        rts

printhex
        lea.l   hexstart(pc),a0                 d6-num to print
        lea.l   quickprint(pc),a4
        move.b  (a0),(a4)+
        lea.l   hex(pc),a0
        move.l  a0,hexnum       
        move.l  #8,digit
loophex move.l  d6,d1
        move.l  digit,d2
        jsr     shiftrighth
        move.l  d1,a0
        add.l   hexnum,a0
        move.b  (a0),(a4)+
        move.l  d6,d1
        move.l  digit,d2
        jsr     shiftrighth
        move.l  digit,d2
        jsr     shiftlefth
        sub.l   d1,d6
        move.l  digit,d2
        sub.l   #1,d2
        move.l  d2,digit
        cmp.l   #0,d2
        bne     loophex
        move.b  #0,(a4)
        lea.l   quickprint(pc),a0
        jsr     print
        rts
shiftrighth
        sub     #1,d2
        cmp     #0,d2
        beq     ret
        lsr.l   d1
        lsr.l   d1
        lsr.l   d1
        lsr.l   d1
        bra     shiftrighth
shiftlefth
        sub     #1,d2
        cmp     #0,d2
        beq     ret
        lsl.l   d1
        lsl.l   d1
        lsl.l   d1
        lsl.l   d1
        bra     shiftlefth

printbin
        lea.l   binstart(pc),a0                 d6-num to print
        lea.l   quickprint(pc),a4
        move.b  (a0),(a4)+
        lea.l   hex(pc),a0
        move.l  a0,hexnum       
        move.l  #16,digit
loopbin move.l  d6,d1
        move.l  digit,d2
        jsr     shiftrightb
        move.l  d1,a0
        add.l   hexnum,a0
        move.b  (a0),(a4)+
        move.l  d6,d1
        move.l  digit,d2
        jsr     shiftrightb
        move.l  digit,d2
        jsr     shiftleftb
        sub.l   d1,d6
        move.l  digit,d2
        sub.l   #1,d2
        move.l  d2,digit
        cmp.l   #0,d2
        bne     loopbin
        move.b  #0,(a4)
        lea.l   quickprint(pc),a0
        jsr     print
        rts
shiftrightb
        sub     #1,d2
        cmp     #0,d2
        beq     ret     
        lsr.w   d1
        bra     shiftrightb
shiftleftb
        sub     #1,d2
        cmp     #0,d2
        beq     ret
        lsl.w   d1
        bra     shiftleftb

bk      lea     back(pc),a0
        move.l  #1,d3
        move.l  a0,d2   
        move.l  filehandle,d1
        CALLDOS Write                           go to start of line
        rts

cr      lea     return(pc),a0
        move.l  #2,d3
        move.l  a0,d2   
        move.l  filehandle,d1
        CALLDOS Write                           print carige return
        rts

ret     rts


fragment
        lea     fragment_message(pc),a0
        jsr     print
        bra     freemem

freemem cmp.l   #0,Offset
        beq     cheers
        add.l   #-8,Offset
        move.l  Offset,a0
        add.l   Bufstart,a0
        move.l  (a0),a1
        add.l   #4,a0
        move.l  (a0),d0
        CALLEXEC        FreeMem
        bra freemem     

nomem   lea     nomem_message(pc),a0
        jsr     print
        bra     exit_closewindow

cheers  move.l  Bufstart,a1                             Free buffer memory
        move.l  Bufsize,d0
        CALLEXEC        FreeMem
        lea     finished_message(pc),a0
        jsr     print
        cmp.l   #0,RamChips
        beq     noerrors        
        lea     memerror_message(pc),a0
        jsr     print
        move.l  #0,count
endloop move.l  count,d0
        btst    d0,RamChips
        beq     noset
        lea     chipnames(pc),a0
        muls    #5,d0
        add.l   d0,a0
        jsr     print
noset   add.l   #1,count
        cmp.l   #16,count
        bne     endloop 
        bra     quit
noerrors
        lea     nomemerror_message(pc),a0
        jsr     print
quit    move.l  #$FF,d1
        CALLDOS Delay
        move.l  filehandle,d1
exit_closewindow
        CALLDOS Close
        bra     exit_closedos


*****************************************************************

exit_closedos
        move.l  _DOSBase(pc),a1
        CALLEXEC CloseLibrary
exit    rts

_DOSBase        dc.l    0
dos_name        DOSNAME

hello_message   dc.b    'Innovative Designs',$d,$a
                dc.b    '(c)1991 E&T Systems Development',$D,$A
                dc.b    'Memory Test for 1MB CHIP RAM Expansion',$D,$A
                dc.b    'Written by Marius van Wyk',$D,$A,0
alloc_mem       dc.b    $A,'Trying to allocate memory... ',0
passed          dc.b    'done.',$0D,$0A,0
failed          dc.b    'failed.',$0D,$0A,$0a,0

allocated       dc.b    'Allocated ',0
chip            dc.b    'CHIP',0
fast            dc.b    'FAST',0
memory          dc.b    ' memory from ',0
to              dc.b    ' to ',0 

founderror              dc.b    $d,$a,'Error found at address ',0
is                      dc.b    ' : Pat. is ',0

nomem_message           dc.b    'There is no memory available for Buffer!!!',$0D,$0A,0
memerror_message        dc.b    'Errors found on RAM Chip(s): ',0
nomemerror_message      dc.b    'No Errors found.',$0D,$0A,0
fragment_message        dc.b    'Too many fragments: Buffer ovfl.',$0D,$0A,0
finished_message        dc.b    $A,'Memory test finished.',$0D,$0A,0
return                  dc.b    $d,$a
back                    dc.b    $d
writing                 dc.b    $d,'Writing   memory location ',0
verifying               dc.b    $d,'Verifying memory location ',0
pat                     dc.b    ' ; Pattern ',0

RamChips        dc.l    0
Memstart        dc.l    0
Memsize         dc.l    0
Memend          dc.l    0
Bufstart        dc.l    0
Bufsize         dc.l    0
Offset          dc.l    0
temp            dc.l    0
count           dc.l    0

PatternCount    dc.l    0
ValueCount      dc.l    0

hexnum          dc.l    0
binnum          dc.l    0
digit           dc.l    0

pattern dc.w    00000000000000
        dc.w    %1111111111111111
        dc.w    00000011111111
        dc.w    %1111111100000000
        dc.w    00111100001111
        dc.w    %1111000011110000
        dc.w    11001100110011
        dc.w    %1100110011001100
        dc.w    %0101010101010101
        dc.w    %1010101010101010

chipnames       dc.b    'U11 ',0
                dc.b    'U12 ',0
                dc.b    'U13 ',0
                dc.b    'U14 ',0
                dc.b    'U15 ',0
                dc.b    'U16 ',0
                dc.b    'U17 ',0
                dc.b    'U18 ',0
                dc.b    'U19 ',0
                dc.b    'U20 ',0
                dc.b    'U21 ',0
                dc.b    'U22 ',0
                dc.b    'U23 ',0
                dc.b    'U24 ',0
                dc.b    'U25 ',0
                dc.b    'U28 ',0
                
binstart        dc.b    '%',0   
hexstart        dc.b    '$',0
hex     dc.b    '0123456789ABCDEF',0

window_console  dc.b    'CON:0/0/640/200/Memory Tester',0
filehandle      dc.l    0

quickprint      dc.b    '%1234567890123456',0
       
 

Comments

Popular posts from this blog

My Custom Mechanical 60% Keyboard Build

My Custom Mechanical 60% Keyboard Build All the parts   1x GH60 (Satan) board - $35 61x Cherry Clear switches  - $35 2x Cherry Blue switches - $3 10x Cherry Red switches - $10 1x PCB Stabilizer set (6.25 space) - $6 1x Royal Oak Glam 60% case (Black Walnut) - $78 1x Aluminium 60% plate - $19 1x SA profile Choclatier keycaps - $102 ( base, modifiers, and novelties ) 1x Braided Nylon USB cable - $15 Solder, Tools, Risers, Labor, etc. Total: ± $300 (Other single switch types added as needed) Testing the board I had my helper do the work here. We needed to test the board before applying any solder. Assembling Add the stabilizers first Add the plate (using a few switches as spacers) Then add the rest Solder solder solder... And test again: The casing The casing I received did to have built-in risers: So I added my own: Then Assemble (using temporary spare GMK Carbon Cherry-profile k...

Compacting internal memory of SAP tables in ABAP.

How to force-free memory from deleted entries in internal tables in SAP ABAP, since the garbage collector won't touch these. This is only needed in rare occasions and/or when memory fragmentation needs to be avoided. This method will do it fast, and correctly: CLASS cl_demo DEFINITION . PUBLIC SECTION . CLASS - METHODS compact CHANGING ct_tab TYPE ANY TABLE . ENDCLASS . CLASS cl_demo IMPLEMENTATION . METHOD compact . FIELD-SYMBOLS : <lt_buffer> TYPE ANY TABLE , <lt_buffer_std> TYPE STANDARD TABLE , <ls_buffer> TYPE any , <ls_buffer_prev> TYPE any . DATA : ltr_buffer TYPE REF TO data , lsr_buffer TYPE REF TO data , l_kind TYPE c LENGTH 1 . " simple case: IF ct_tab IS INITIAL . FREE ct_tab . RETURN . ENDIF . CREATE DATA ltr_buffer LIKE ct_tab . DESCRIBE TABLE...

Lock Screen on Mac OS X using keyboard shortcut.

1. Download "Global Hotkey" 2. Create a folder "Global Hotkey" and copy contents of downloaded DMG to that. 3. In a terminal do: cd "/Applications/Global Hotkey" ln -s /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app "command f10" 4. Make sure Screensaver is set to prompt for password (you may need to relog for this to take effect) 5. Preferences -> Accounts -> -> Login Items : Add "Global Hotkey.app" 6. Launch the app as well