/******************************************************************************/ /* Original Author: Jeffrey W. Minton */ /* Redesigned and Updated by Dr. Spiegel */ /* Filename: recordExFns.m */ /* Purpose: This program takes in up to 10 integers and stores them in an */ /* array. It then outputs the binary equivalent, its 2's */ /* complement in hexidecimal and the next higher power of 2 */ /* Functions with various parameter passing methods and venues */ /* are employed */ /******************************************************************************/ define(arrAdrs, %l0) !The address of the array define(numElts, %l1) !the number of elements in the array define(eltAdrs, %l2) !the address of the curent element define(iReg, %l3) !holds the current index define(eltOffset, %l4) !The offset to the next array element define(currentVal, %l5) !the current value being used .data .align 8 numPrompt: !entry prompt .asciz "Enter the next integer (^D quits) :" prompt: !entry prompt .asciz "Enter up to 10 integers (^D quits) \n" heading: !Table heading .asciz "\n Value Binary 2's Complement\n" frmtI: !decimal format specifier for input .asciz "%d" frmtDec: !decimal format specifier .asciz "%8d " frmtHex: !hex format specifier .asciz "%18x" frmtStr: !string format specifier .asciz "%s" endl: !end line string .asciz "\n" .align 4 .global main main: save %sp, (-108 - 44) & -8, %sp !call inputArray, passing it the address of the array by reference in !the stack and the number of elements by reference in a register (%o0) add %fp, -60, arrAdrs st arrAdrs, [%sp + 68] ! Pass array base address in 1st parameter call inputArray add %fp, -20, %o0 ! # elements address, passed by ref. in register !call the printTable function and pass it the array by reference in a !register and the number of elements by value on the stack ld [%fp - 20], numElts st numElts, [%sp + 72] call printTable add %fp, -60, %o0 call exit mov 0, %o0 /******************************************************************************/ /* Input Array */ /******************************************************************************/ .align 4 .global inputArray inputArray: !receive input and store numbers into the array save %sp, -108 & -8, %sp !load the base address of the array into arrAdrs ld [%fp + 68], arrAdrs !prompt for user input set prompt, %o0 call printf !reset the lcv mov 0, iReg loopIn: sll iReg, 2, eltOffset !shift the index by 2 to get offset add arrAdrs, eltOffset, eltAdrs !eltAdrs= base address + offset !input the value - pass eltAdrs to the function in a register; ! this passes the location for this element in main's frame to the function call readInt mov eltAdrs,%o3 !determine if user hit ^D; if so go to saveNumElts ! Check the bit in %sp+64 ldub [%sp+67], %l6 ! load the byte containing the info bit btst 0x00000001,%l6 ! Test if the info bit was set be saveNumElts ! If Z flag set (info bit was 0), done. nop !determine if array is full, if not loop for more input inc iReg !increment the index cmp iReg, 10 bl loopIn nop !save the number of elements in the array saveNumElts: ! Recall we passed in address for #elts in %o0 st iReg, [%i0] ! store the lcv (and counter) in numElts ret restore /******************************************************************************/ /* Read one value */ /******************************************************************************/ ! Reads one int into address passed in by register %i0 (caller's %o0). ! Returns whether an int was read via the lowest bit in the return ! address area. If set, item was read, otherwise, ^D was hit. .global readInt readInt: save %sp, -108 & -8, %sp ! Prompt the user set numPrompt, %o0 call printf nop ! Clear %l6. Will use it to report result (info bit 1=>value read 0=>^D) clr %l6 ! Read into address passed in in %i3 (caller's %o3) set frmtI, %o0 call scanf mov %i3,%o1 !determine if user hit ^D; cmp %o0, 1 bne noRead ! No value read (^D was hit) nop ! Value was read. Store lsb 1 into caller's return address area bset 0x00000001, %l6 stb %l6, [%fp+67] b endFn nop noRead: bset 0x00000000, %l6 ! No value was read stb %l6, [%fp+67] endFn: ret restore /******************************************************************************/ /* Print Table */ /******************************************************************************/ !print the table of data .global printTable printTable: save %sp, (-108 - 20) & -8, %sp ! 20 bytes for 16 char bit string + '\0' !put the address of the array in arrAdrs mov %i0, arrAdrs !put the number of elements into numElts ld [%fp + 72], numElts !reset the index mov 0, iReg !output the heading printHead: set heading, %o0 call printf nop tableLoop: sll iReg, 2, eltOffset !shift the index by 2 to find offset add arrAdrs, eltOffset, eltAdrs ! eltAdrs=arrAdrs+eltOffset ld [eltAdrs], currentVal !contents of adrs loaded into currentVal !output the decimal value set frmtDec, %o0 call printf, 0 mov currentVal, %o1 !retrieve the binary ibit string (a real string) and print it add %fp, -36, %l6 ! Location for the 1st char st %l6, [%sp + 68] ! Pass string's address to getBitString call getBitString ! Call getBitString to fill the binary string ld [eltAdrs], %o0 ! Pass the current value to getBitString set frmtStr, %o0 call printf ! Output the bnary string add %fp, -36, %o1 !output the value's 2's complement call twosComp st currentVal, [%sp + 72] ! Pass the curent value in 2nd parameter ! Result will be placed in return adrs area set frmtHex, %o0 call printf ! Output the 2's complement ld [%sp + 64], %o1 ! Get 2's complement from return adrs area !output newline set endl, %o0 call printf nop !determine if end of aray has been reached inc iReg ! Increment the lcv cmp iReg, numElts bl tableLoop nop ret restore /******************************************************************************/ /* printBits reworked: Function converts int to string of 0's and 1's */ /******************************************************************************/ ! Note that this function stores a binary string in the caller's frame .global getBitString getBitString: save %sp,-108 & -8, %sp mov %i0, currentVal ! Value was passed in in %o0 ld [%fp + 68], eltAdrs ! Address where string will be placed mov 0x00000001, %l1 ! modified code, puts one in mask sll %l1, 15, %l1 ! then shifts to 16th bit binaryLoop: btst %l1, currentVal ! %i0 still has the user inputed number bz zeroOut ! if the bit was 0, next char is '0' nop mov '1', %l6 ! Next bit was 1 stb %l6, [eltAdrs] ! Put a '1' into the string ba nextBit nop zeroOut: mov '0', %l6 stb %l6, [eltAdrs] ! Put a '0' into the string nextBit: inc eltAdrs ! Address for storing next char srl %l1,1,%l1 ! Move the testing bit over one position andcc %l1,0xffffffff,%g0 ! Did test bit fall off right end? If so, done bne binaryLoop ! Otherwise, haven't processed entire value. nop st %g0, [eltAdrs] ! Important! Store null terminator ret restore !============================= end of function ============================= /******************************************************************************/ /* 2's Complement */ /******************************************************************************/ .global twosComp twosComp: save %sp, -108 & -8, %sp ld [%fp + 72], currentVal !retrieve the current value xor currentVal, 0xffffffff, currentVal !invert the bits add currentVal, 1, currentVal !add 1 to the inverted bits !return the result to printTable's return address area (it's a value!) st currentVal, [%fp + 64] ret restore