; *********************************************************************** ; * * ; * Compare Two Numbers (Third Version in Assembly Language) * ; * * ; *********************************************************************** ; Authors: Saeid Nooshabadi and John Zaitseff ; Date: 5th May, 2003 ; Version: 1.5 ; This program compares two integer numbers using a function, larger. The ; main point to note about this version is that it uses stack frames to ; preserve the value of certain registers. Doing so helps meet the ; requirements of the ARM Thumb Procedure Call Standard (ATPCS). ; ; Please note that this version is not "optimised" for the ATPCS. That ; Standard does NOT require a stack frame for every function, merely that ; the registers R4-R11 and R13 have the same value on exit as on entry. ; See the file "larger-v4.s" for an optimised version. ; ; This program uses the ATPCS alias names for the registers. For example, ; A1-A4 are used instead of R0-R3. This version differs from larger-v2.s ; by using the "load multiple" and "store multiple" instructions. ; ----------------------------------------------------------------------- ; Assembly-language preamble for the main module .text ; Executable code follows _start: .global _start ; "_start" is required by the linker .global main ; "main" is our main program b main ; Start running the main program ; ----------------------------------------------------------------------- ; Function: main - Main program entry point ; Parameters: (none) - No parameters are passed ; Returns: int (in A1) - Return value: the value of "c" ; ; This function compares two integers stored in the variables "a" and "b". ; It uses the function "larger" to make the comparison. The larger of the ; two variables is stored in "c", which is returned to the operating ; system in register A1 (R0). ; ; This function conforms to the ATPCS; a full stack frame is generated. main: mov ip, sp ; Save the caller's stack pointer into IP stmfd sp!, {fp, ip, lr, pc} ; Save caller's FP, IP, LR and PC, ; modifying SP appropriately sub fp, ip, #4 ; Make FP point to one word (4 bytes) below the ; caller's SP (saved in IP). This marks the ; start of the stack frame (activation ; record) for the function main(). sub sp, sp, #8 ; Create room for two local variables on the ; stack---to show how it is done ldr a4, =a ; A4 = address of a ldr a1, [a4] ; A1 = 0xE0001234 ldr a2, [a4, #4] ; A2 = 0x00004567 (since A4+4 is address of b) str a1, [fp, #-16] ; Store value of A1 in first local variable str a2, [fp, #-20] ; Store value of A2 in second local variable ; (These local variables are not used any ; further in this program, but could be...) bl larger ; Call "larger"; this automatically saves ; return address in LR (R14). Result ; returned in A1 (R0). ldr a4, =c ; A4 = address of c str a1, [a4] ; Store result (0x00004567) into c exit: ldmea fp, {fp, sp, pc} ; Use the frame pointer to restore the ; caller's FP, SP and PC. This returns ; to the caller. ; ----------------------------------------------------------------------- ; Function: int larger (int first, int second) ; ; This function compares "first" (in register A1, ie, R0) with "second" ; (in A2, ie, R1) and returns the larger of these in A1. Registers are ; preserved/destroyed according to the ATPCS. Only A1 is modified by this ; function. ; ; This comment illustrates an alternative way of documenting functions; ; compare this to the comments for main(), above. You may use whichever ; you prefer. ; ; This function generates a complete stack frame for illustrative ; purposes. An optimised version would drop almost all of this code, ; since it is not strictly needed for the function to conform to the ; ATPCS. larger: mov ip, sp ; Save caller's (main's) stack pointer into IP stmfd sp!, {fp, ip, lr, pc} ; Save caller's FP, IP, LR and PC, ; modifying SP appropriately sub fp, ip, #4 ; Make FP point to one word (4 bytes) below the ; caller's SP (saved in IP). This marks the ; start of the stack frame (activation ; record) for the function larger(). ; No local variables; parameters in A1 and A2 ; (ie, R0 and R1 respectively) cmp a1, a2 ; Compare "first" (A1) and "second" (A2) movle a1, a2 ; Place A2 in A1 if and only if A1 <= A2 larger_exit: ; Result is now in A1 (R0) ldmea fp, {fp, sp, pc} ; Use the frame pointer to restore the ; caller's FP, SP and PC. This returns ; to the caller, main(). ; ----------------------------------------------------------------------- ; Program variables (stored together with the code) a: .word 0xE0001234 ; Variable "a" b: .word 0x00004567 ; Variable "b" c: .word 0 ; Variable "c" ; ----------------------------------------------------------------------- .end