9.7 SORTINT: Sorting Integers from a File

As a second example of working with files, we present a companion to the SORTSTR program, which performed a bubble sort on strings entered interactively. The SORTINT program (Figure 9-6) reads integer quantities from an ASCII text file into internal binary storage as quad words, sorts them using the bubble sort algorithm, and writes the ordered list of signed integers to a new text file, one per line. This program utilizes I/O features of the SCANFILE program to implement the bubble algorithm of the SORTSTR program.

Figure 9-6 SORTINT: Bubble sort for integer quantities
 // SORTINT       Bubble sort integers from a file // This program will read 100 or fewer integers from a // text file, sort them using the bubble sort algorithm, // and write the sorted list into a text file.         FLEN     = 40             // File name allowance         CASES    = 100            // Array length         NUML     = 8              // Integer size         .global  gets, perror, printf         .global  fopen, fclose, fscanf, fprintf         .data                     // Declare storage         .align   8                // Desired alignment ARRAY:  .skip    CASES*NUML       // Room for integers IFILE:  .skip    FLEN             // Input file name OFILE:  .skip    FLEN             // Output file name IPRMT:  stringz  "Input from? " OPRMT:  stringz  "Output to? " IMODE:  stringz  "r"              // Read from input file OMODE:  stringz  "w"              // Create output file TELL:   stringz  "The program has processed %d numbers.\n" PFORM:  stringz  "%s"             // Prompts are strings IFORM:  stringz  "%lld"           // Scan for a "word" OFORM:  stringz  "%18lld\n"       // Print number & newline ERROR:  stringz  "Error"         .text                     // Section for code         .align   32               // Desired alignment         .global  main             // These three lines         .proc    main             //  mark the mandatory main:                             //   'main' program entry         .prologue 12,r32          // Mask for rp, ar.pfs only         alloc    loc0 = ar.pfs,0,8,3,0  // ins, locals, outs         .save    rp,loc1          // Must save return address         mov      loc1 = b0;;      //  to our caller         .body first:  add      out0 = @gprel(IPRMT),gp  // out0 -> format         mov      loc2 = gp        // Save gp         br.call.sptk.many b0 = printf  // Ask about input         mov      gp = loc2        // Restore gp         cmp4.lt  p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop0;;  //  go to handler (null)         add      out0 = @gprel(IFILE),gp  // out0 -> filename         br.call.sptk.many b0 = gets  // Unformatted input         mov      gp = loc2        // Restore gp         cmp.eq   p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop1;;  //  go to handler (null)         add      out0 = @gprel(IFILE),gp // out0 -> filename         add      out1 = @gprel(IMODE),gp // out1 -> mode         br.call.sptk.many b0 = fopen  // Find input file         mov      gp = loc2        // Restore gp         cmp.eq   p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop2;;  //  go to handler (null)         mov      loc3 = r8        // loc3 = file pointer         add      out0 = @gprel(OPRMT),gp  // out0 -> format         br.call.sptk.many b0 = printf  // Ask about input         mov      gp = loc2        // Restore gp         cmp4.lt  p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop0;;  //  go to handler (null)         add      out0 = @gprel(OFILE),gp  // out0 -> filename         br.call.sptk.many b0 = gets  // Unformatted input         mov      gp = loc2        // Restore gp         cmp.eq   p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop1;;  //  go to handler (null)         add      out0 = @gprel(OFILE),gp // out0 -> filename         add      out1 = @gprel(OMODE),gp // out1 -> mode         br.call.sptk.many b0 = fopen  // Find output file         mov      gp = loc2        // Restore gp         cmp.eq   p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop4;;  //  go to handler (null)         mov      loc4 = ret0      // loc4 = file pointer         mov      loc5 = 0         // loc5 counts numbers         add      loc6 = @gprel(ARRAY),gp;; // loc6 -> buffer loop:   mov      out0 = loc3      // out0 = IPTR         add      out1 = @gprel(IFORM),gp // out1 -> format         mov      out2 = loc6      // out2 -> ARRAY         br.call.sptk.many b0 = fscanf // Read a number         mov      gp = loc2        // Restore gp         cmp4.ne  p6,p0 = 1,ret0   // Expect one %d item    (p6) br.cond.sptk.few eof;;    // No - maybe it's EOF         add      loc6 = NUML,loc6 // Bump storage pointer         add      loc5 = 1,loc5;;  // Count one number         cmp.gt   p6,p0 = CASES,loc5 // If storage is ok,    (p6) br.cond.sptk.few loop;;   //  go back for more eof:    cmp4.ne  p6,p0 = -1,ret0  // If not EOF,    (p6) br.cond.sptk.few stop6;;  //  then exit         mov      out0 = loc3      // out0 = input pointer         br.call.sptk.many b0 = fclose // Close input         mov      gp = loc2        // Restore gp         cmp4.ne  p6,p0 = 0,ret0   // If not successful,    (p6) br.cond.sptk.few stop3;;  //  then exit sort:   add      r20 = -1,loc5;;  // r20 = outer count-down o_loop: mov      r21 = r20        // r21 = inner count-down         add      r20 = -1,r20     // Count down for o_loop         add      r22 = @gprel(ARRAY),gp;; // r22 -> 1st         add      r23 = NUML,r22;; // r23 -> 2nd number i_loop: mov      r2 = r22         // r2 -> 1st number (temp)         mov      r3 = r23;;       // r3 -> 2nd number (temp)         add      r21 = -1,r21;;   // Count down for i_loop look:   ld8      r24 = [r2]       // r24 = 1st number         ld8      r25 = [r3];;     // r25 = 2nd number why:    cmp.le p6,p0 = r24,r25    // If 1,2 order is ok,    (p6) br.cond.spnt.many adjust;; //  go on to next numbers swap:   st8      [r2] = r25       // Swap the data         st8      [r3] = r24       //  between the locations adjust: add      r22 = NUML,r22   // Advance to next 1st         add      r23 = NUML,r23   // Advance to next 2nd         cmp.gt   p6,p0 = r21,r0   // Still more work    (p6) br.cond.sptk.many i_loop;; // for inner loop to do?         cmp.gt   p6,p0 = r20,r0   // Still more work    (p6) br.cond.sptk.many o_loop  //  for outer loop to do?         add      loc6 = @gprel(ARRAY),gp // loc6 -> ARRAY         mov      loc7 = loc5;;    // Copy of the count p_loop: mov      out0 = loc4      // out0 = output pointer         add      out1 = @gprel(OFORM),gp // out1 -> format         ld8      out2 = [loc6],NUML // out2 = what to print         add      loc7 = -1,loc7   // Count down for p_loop         br.call.sptk.many b0 = fprintf // C print function         mov      gp = loc2        // Restore gp         cmp4.lt  p6,p0 = ret0,r0  // If any error,    (p6) br.cond.sptk.few stop7;;  //  go to handler (null)         cmp.gt   p6,p0 = loc7,r0  // Still more work    (p6) br.cond.sptk.few p_loop   //  for print loop to do?         mov      out0 = loc4      // out0 = OPTR         br.call.sptk.many b0 = fclose // Close output         mov      gp = loc2        // Restore gp         cmp4.ne  p6,p0 = 0,ret0   // If not successful,    (p6) br.cond.sptk.few stop5;;  //  then exit         add      out0 = @gprel(TELL),gp // out0 -> format         mov      out1 = loc5      // out1 = number of words         br.call.sptk.many b0 = printf  // C print function         mov      gp = loc2        // Restore gp         cmp4.lt  p6,p0 = r8,r0    // If any error,    (p6) br.cond.sptk.few stop0;;  //  go to handler (null)         br.cond.sptk.many done    // That is all stop0:                            // Terminal output error stop1:                            // Terminal input error stop2:                            // Problem opening IFILE stop3:                            // Problem closing IFILE stop4:                            // Problem opening OFILE stop5:                            // Problem closing OFILE stop6:                            // Problem getting input stop7:                            // Problem doing output         add      out0 = @gprel(ERROR),gp // out0 -> format         br.call.sptk.many b0 = perror // C error function         mov      gp = loc2        // Restore gp done:   mov      ret0 = 0         // Signal all is normal         mov      b0 = loc1        // Restore return address         mov      ar.pfs = loc0    // Restore caller's ar.pfs         br.ret.sptk.many b0;;     // Back to command line         .endp    main             // Mark end of procedure 

The fscanf function (using %lld as the format string) in the data input loop (starting at loop) expects an address for the location where the interpreted binary value is to be stored. In contrast, the fprintf function in the data output loop (starting at p_loop) expects an actual value as an argument in a stacked register or in a special area on the stack.

The behavior of this program on a Linux system can be explored with both invalid and valid input, as follows:

 L> bin/sortint Input from? sortint.txt Output to? /abc.txt Error: Permission denied L> Input from? sortint.txt Output to? sorted.txt The program has processed 5 numbers. L> cat sorted.txt                -20                  2                 24                123                200 L> cat sortint.txt 2 200 -20 123 24 L> 

Assuming that there is a file named sortint.txt in the current directory, the first error is a result of the user not having permission to create files in the root directory.

On systems where native integers are 64 bits in width, ll can be used with numeric indicators (like %d) in format strings for I/O routines like fscanf and fprintf in the C support library when the quantities are anticipated to be negative ( 20 here) or positive but spilling beyond 32 bits in width.

We have again suggested where some of the conditional tests for errors should be positioned. Just above done we have also shown how to use the perror function to display the error text, which may vary with the programming environment or default language on a particular system.



ItaniumR Architecture for Programmers. Understanding 64-Bit Processors and EPIC Principles
ItaniumR Architecture for Programmers. Understanding 64-Bit Processors and EPIC Principles
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net