Home > Palm > Samples > Combination > Assembly
 
  Palm sample in Assembly

 Purpose

This is the 68K assembly language version of our combination application. It's one of the Palm Samples.

 Requirements

You need PilA (see tools section).

 Source code

Below is the .asm file.

For .inc, .rcp, .bmp, make-prc and .prc, please download the ZIP file.

; Combination.asm
; Palm
; Assembly language

; Special thanks to Darrin Massena, who provides great samples 
; in assembly language for Palm
; His site is a MUST if you're interested in this language
; For more information see http://www.massena.com/darrin/pilot


; **************************************************************************
; APPLICATION section
; **************************************************************************

        appl    "Comb-Asm", 'CoAs'  ;Application name and ID

        include "Pilot.inc"         ;System incs
        include "Startup.inc"
        include "combination.inc"   ;Application incs


; **************************************************************************
; DATA section
; **************************************************************************

        data                        ;(globals are a5-relative)
global gpfldN.l                     ;pointer to the n field
global gpfldP.l                     ;pointer to the p field
global gpfldFactorialN.l            ;pointer to the n! field
global gpfldFactorialP.l            ;pointer to the p! field
global gpfldFactorialNP.l           ;pointer to the (n-p)! field
global gpfldCombination.l           ;pointer to the combination(n,p) field


; **************************************************************************
; CODE section
; **************************************************************************
        code

; ---------------------------------------------------------------------------
; DWord PilotMain(Word cmd, void *cmdPBP, Word launchflags)
; PilotMain is called by the startup code and implements a simple event handling loop.
; ---------------------------------------------------------------------------
proc PilotMain(cmd.w, cmdPBP.l, launchFlags.w)
local   err.w
local   evt.EventType
beginproc
        tst.w   cmd(a6)                 ;sysAppLaunchCmdNormalLaunch is 0
        bne     PmReturn                ;not a normal launch, bag out

        systrap FrmGotoForm(#MainForm.w)

PmEventLoop
; Doze until an event arrives
        systrap EvtGetEvent(&evt(a6), #evtWaitForever.w)

; System gets first chance to handle the event
        systrap SysHandleEvent(&evt(a6))
        tst.b   d0                      ;handled?
        bne.s   PmEventDone             ;yep

; Menu handler gets second chance to handle the event
        systrap MenuHandleEvent(&0, &evt(a6), &err(a6))
        tst.b   d0                      ;handled?
        bne.s   PmEventDone             ;yep

; Application handler gets third chance to handle the event
        call    ApplicationHandleEvent(&evt(a6))
        tst.b   d0                      ;handled?
        bne.s   PmEventDone             ;yep

; Form handler gets fourth chance to handle the event
        call    MainFormHandleEvent(&evt(a6))
        tst.b   d0                      ;handled?
        bne.s   PmEventDone             ;yep

; Still not handled. We're not interested in it anymore so let the
; default form handler take it.
        systrap FrmGetActiveForm()
        systrap FrmHandleEvent(a0.l, &evt(a6))

; Return from PilotMain when an appStopEvent is received
PmEventDone
        cmpi.w  #appStopEvent,evt+EventType.eType(a6) ;time to stop?
        bne.s   PmEventLoop             ;nope, loop until it is

        systrap FrmCloseAllForms()      ;to avoid memory leaks

PmReturn
        moveq   #0,d0
endproc


; ---------------------------------------------------------------------------
; Boolean ApplicationHandleEvent(EventType *pevt)
; ---------------------------------------------------------------------------
proc ApplicationHandleEvent(pevt.l)
beginproc
        movem.l a3,-(a7)                ;save registers we're going to trash

        movea.l pevt(a6),a0             ;a0 = pevt

; Handle frmLoadEvent
        cmpi.w  #frmLoadEvent,EventType.eType(a0) ;frmLoadEvent?
        bne     AHENotHandled           ;no

; Initialize the form and make it active
        systrap FrmInitForm(EventType.data+frmLoad.formID(a0).w)
        move.l  a0,a3                   ;save a copy of FormPtr for later
        systrap FrmSetActiveForm(a0.l)

; Get pointers to the form fields and store'em into globals
        systrap FrmGetObjectIndex(a3.l, #MainN.w)
        systrap FrmGetObjectPtr(a3.l,d0.w)
        move.l  a0,gpfldN(a5)

        systrap FrmGetObjectIndex(a3.l, #MainP.w)
        systrap FrmGetObjectPtr(a3.l,d0.w)
        move.l  a0,gpfldP(a5)

        systrap FrmGetObjectIndex(a3.l, #MainFactorialN.w)
        systrap FrmGetObjectPtr(a3.l,d0.w)
        move.l  a0,gpfldFactorialN(a5)

        systrap FrmGetObjectIndex(a3.l, #MainFactorialP.w)
        systrap FrmGetObjectPtr(a3.l,d0.w)
        move.l  a0,gpfldFactorialP(a5)

        systrap FrmGetObjectIndex(a3.l, #MainFactorialNP.w)
        systrap FrmGetObjectPtr(a3.l,d0.w)
        move.l  a0,gpfldFactorialNP(a5)

        systrap FrmGetObjectIndex(a3.l, #MainCombination.w)
        systrap FrmGetObjectPtr(a3.l,d0.w)
        move.l  a0,gpfldCombination(a5)

        moveq.l #1,d0                   ;event handled
        bra.s   AHEReturn

AHENotHandled
        clr.b   d0

AHEReturn
        movem.l (a7)+,a3
endproc


; ---------------------------------------------------------------------------
; Boolean MainFormHandleEvent(EventType *pevt)
; ---------------------------------------------------------------------------

proc MainFormHandleEvent(pevt.l)
beginproc
        movea.l pevt(a6),a0             ;a0 = pevt
        move.w  EventType.eType(a0),d0

; Handle frmOpenEvent
        cmp.w   #frmOpenEvent,d0
        bne     MFH1

; Draw the form
        systrap FrmGetActiveForm()
        systrap FrmDrawForm(a0.l)
        moveq.l #1,d0
        bra     MFHReturn

; Handle frmMenuEvent
MFH1
        cmp.w   #menuEvent,d0
        bne     MFH2
        cmp.w   #MainOptionsHelpCmd,EventType.data+menu.itemID(a0)
        bne     MFHTestAbout

; Handle HelpCmd
        systrap FrmAlert(#HelpAlert.w)
        bra     MFHMenuDone

MFHTestAbout
        cmp.w   #MainOptionsAboutCmd,EventType.data+menu.itemID(a0)
        bne     MFHNotHandled

; Handle HelpCmd
        systrap FrmAlert(#AboutAlert.w)

MFHMenuDone
        moveq.l #1,d0
        bra     MFHReturn

; Handle ctlSelectEvent
MFH2
        cmp.w   #ctlSelectEvent,d0
        bne     MFHNotHandled

; Compute button clicked?
        cmp.w   #MainCompute,EventType.data+ctlEnter.controlID(a0)
        bne     MFHNotHandled

        jsr     Go(pc)             ;yes, call our main function
        bra     MFHReturn

MFHNotHandled
        clr.b   d0

MFHReturn
endproc


; ---------------------------------------------------------------------------
; DWord Factorial(Word n)
; ---------------------------------------------------------------------------
proc Factorial(n.w)
beginproc
        movem.l d1,-(a7)        ;save registers that we'll overwrite locally

        move.w  n(a6),d1        ;we'll use d1 to decrement
        move.w  #1,d0       
        cmp.w   #1,d1           ;if n <= 1, we've already got the result in d0!
        blt     FCTReturn
        
FCTLoop
        mulu    d1,d0           ;multiply
        subi    #1,d1           ;decrement
        bne     FCTLoop         ;check > 0
        
FCTReturn
        movem.l  (a7)+,d1       ;restore registers
endproc


; ---------------------------------------------------------------------------
; DWord Combination(Word n, Word p)
; ---------------------------------------------------------------------------

proc Combination(n.w,p.w)
beginproc
        movem.l d1-d3,-(a7)         ;save registers that we'll overwrite locally
        
        call    Factorial(n.w(a6))
        move.w  d0,d1               ;d1 = n!
        
        call    Factorial(p.w(a6))
        move.w  d0,d2               ;d2 = p!
        
        move    n.w(a6),d0
        sub.w   p.w(a6),d0
        call    Factorial(d0.w)
        move.w  d0,d3               ;d3 = (n-p)!
        
        move.w  d2,d0               ;d0 = p!
        mulu    d3,d0               ;d0 = (n-p)! * p!
        divu    d0,d1               ;d1 = result
        
        move.w  d1,d0               ;return result in d0

        movem.l  (a7)+,d1-d3        ;restore registers
endproc

; ---------------------------------------------------------------------------
; void Go(void)
; ---------------------------------------------------------------------------

proc Go()
local n.w
local p.w
beginproc
        call    GetField(gpfldN.l(a5))
        move.w  d0,n(a6)                                ;save N

        call    GetField(gpfldP.l(a5))
        move.w  d0,p(a6)                                ;save P
        
        call    Factorial(n.w(a6))                      ;compute n!
        call    SetField(d0.l,gpfldFactorialN.l(a5))    ;display result

        call    Factorial(p.w(a6))                      ;compute p!
        call    SetField(d0.l,gpfldFactorialP.l(a5))    ;display result

        move.w  n(a6),d0
        sub.w   p(a6),d0
        call    Factorial(d0.w)                         ;compute (n-p)!
        call    SetField(d0.l,gpfldFactorialNP.l(a5))   ;display result

        call    Combination(n.w(a6),p.w(a6))            ;compute combination(n,p)
        call    SetField(d0.l,gpfldCombination.l(a5))   ;display result

        systrap FrmGetActiveForm()
        systrap FrmDrawForm(a0.l)                       ;Redraw form
endproc

; ---------------------------------------------------------------------------
; void GetField(Word field)
; ---------------------------------------------------------------------------

proc GetField(field.l)
beginproc
        move.l  field.l(a6),a0                          ;load adr of our field
        systrap FldGetTextPtr(a0.l)                     ;get ptr to field
        systrap StrAToI(a0.l)                           ;convert field to number
endproc

; ---------------------------------------------------------------------------
; void SetField(Word value, Word field)
; ---------------------------------------------------------------------------

proc SetField(value.l,field.l)
local   szBuffer.8
beginproc
        movem.l a3,-(a7)                    ;save registers that we'll overwrite locally

        move.l  value.l(a6),-(a7)           ;push integer
        pea.l   szBuffer(a6)                ;push pointer to string buffer

        trap    #15
        dc.w    sysTrapStrIToA
        addq.l  #8,a7                       ;pop the args off the stack

        move.l  field.l(a6),a3
        systrap FldFreeMemory(a3.l)         ;free field memory

        systrap StrLen(&szBuffer(a6))       ;calculate buffer length
        lea.l   szBuffer(a6),a0             ;load buffer address
        systrap FldInsert(a3.l,a0.l,d0.w)   ;insert buffer into field

        movem.l  (a7)+,a3                   ;restore registers
endproc


; **************************************************************************
; RESOURCE section
; **************************************************************************

; Version resource
        res 'tver', AppVersion, "tver0001.bin"

; Icon and SmallIcon resources
        res 'tAIB', AppIcon, "taib03e8.bin"
        res 'tAIB', AppSmallIcon, "taib03e9.bin"

; 'pref' resource. Defines app launch flags, stack and heap size
        res 'pref', AppPref
        dc.w    sysAppLaunchFlagNewStack|sysAppLaunchFlagNewGlobals|sysAppLaunchFlagUIApp|sysAppLaunchFlagSubCall
        dc.l    $1000                           ; stack size
        dc.l    $1000                           ; heap size

; Form resources
        res 'tFRM', MainForm, "tfrm03e8.bin"

; Menu resources
        res 'MBAR', MainMenu, "mbar03e8.bin"

; Alert resources
        res 'Talt', HelpAlert, "talt03e8.bin"
        res 'Talt', AboutAlert, "talt03e9.bin"

 Comments

See how big the source code is? Rite, there's a lot of overhead! But actually, the executable is pretty small. It weighs 2424 bytes versus 3101 bytes for the C version of the very same app, which means... 25% smaller, not to mention that this 68K version is quicker than any of our samples in the combination category!

If you take a closer look at the source code, you'll see that Palm API's are directly invokable thru wrappers, as system traps. Like:

systrap FrmDrawForm(a0.l)      ;Redraw form 

Also, PilA provides you with an easy way of making your application modular. You may define a function that takes arguments, like this: proc Combination(n.w,p.w) and invoke it like that: call Combination(n.w(a6),p.w(a6)).

Again, the core functions are : Factorial, Combination and Go.

Next sample

 
[ Copyright © 2000- Eric Poncet - All rights reserved ]

[ Stage de musique classique | Stage de musique baroque | Stage de musique de chambre | Stage de musique latine ]
[ Stage de jazz | Stage de musiques actuelles | Stage de funk | Stage de metal | Stage de pop | Stage de reggae | Stage de rock ]
[ Stage d'improvisation | Colonie musicale ]