//---------------------------------------------------------------- // gpacalc.s // // This procedure shows a way of generating the string of // ascii characters which expresses a grade-point average // to the nearest hundredth. // // programmer: ALLAN CRUSE // written on: 15 OCT 2003 // revised on: 08 APR 2009 -- for a Linux x86_64 platform //---------------------------------------------------------------- .section .data .extern credits:quad # total number of units taken .extern qpoints:quad # total quality-points earned .extern gpabuff:char # buffer for the digit-string .section .text gpacalc: # compute (100 * qpoints)/credits to the nearest integer mov $100, %rax # setup the multiplicand in RAX mulq qpoints # multiply it by quality-points divq credits # then divide it by the credits # rounding rule: if ( 2*remainder >= divisor ) ++quoient; add %rdx, %rdx # now double the remainder-value cmpq credits, %rdx # examine: 2*remainder - divisor cmc # reverse CF (the 'borrow' flag) adc $0, %rax # use add-with-carry for roundup # convert the resulting quotient in RAX (as adjusted) to # a 3-digit string of decimal numerals, with a null-byte # appended (for printf), and with a decimal-point before # the leading digit. Here we generate these ascii-codes # in backward order, for convenience in coding the loop. mov $4, %rdi # setup the maximum array-index movb $0, gpabuff(%rdi) # and store a null-byte mov $3, %rcx # now RCX with count of digits mov $10, %rbx # setup RBX with decimal-radix nxdgt: xor %rdx, %rdx # extend numerator for division div %rbx # divide by the decimal radix add $'0', %dl # convert remainder to numeral dec %rdi # then back up the array-index mov %dl, gpabuff(%rdi) # and store the numeral loop nxdgt # generate any remaining digits mov $'.', %dl # setup decimal-point character xchg %dl, gpabuff(%rdi) # swap w/ leading digit dec %rdi # back up the array-index again mov %dl, gpabuff(%rdi) # then store that digit ret # return control to the caller .global gpacalc # so linker can find the symbol