; Assessment, Excersise 2
;
; Program to sort the contents of a file
; and store it on disk
;
; By Andy Bennett (andyjpb@ashurst.eu.org), 2002
;
; we use the insertion sort because it is more efficient than a bubble sort: An insertion
; sort is often twice as fast as an equivalent bubble sort whilst being only mildly more
; complex.

                AREA    sortFile, CODE, READONLY                ; declare code area
SWI_Exit        EQU     0x11    ; finish program
SWI_Open        EQU     0x66    ; open a file or device
SWI_Close       EQU     0x68    ; close an open file or device
SWI_Read        EQU     0x6a    ; read from an open file or device
SWI_Flen        EQU     0x6c    ; returns the current length of an open file or device
SWI_Write       EQU     0x69    ; write to an open file or device
readonly        EQU     0       ; open a file or device for reading
writeonly       EQU     4       ; open a file or device for writing
                ENTRY           ; code entry point

START           ADR     r0, INFILE      ; set r0 to point to INFILE
                MOV     r1, #readonly   ; set access mode to file as readonly
                SWI     SWI_Open        ; open the file pointed at by r0
                CMP     r0, #0          ; check for success on opening file
                SWIEQ   SWI_Exit        ; if file could not be opened then exit now
                MOV     r5, r0          ; save the file handle in r5 for later
                SWI     SWI_Flen        ; store the length of the file in r0
                CMP     r0, #-1         ; check that the call was successful
                SWIEQ   SWI_Exit        ; if the call failed then exit now
                MOV     r2, r0          ; move the length of the file into r2
                MOV     r9, r0          ;move the length of the file into r9 as well
                MOV     r0, r5          ; move the file handle back into r0
                ADR     r1, FILECONTENTS        ; point r1 at a place for the contents of the file
                SWI     SWI_Read        ; read the data from the file
                CMP     r0, #0          ; check that the call was successful
                SWIEQ   SWI_Exit        ; if anything was left unread from the file then exit now
                MOV     r0, r5          ; move the file handle back into r0
                SWI     SWI_Close       ; close the file


                ADD     r2, r1, r2      ; r2 = r1 + r2. r2 points to the end of the file
                MOV     r3, r1          ; start sorting near the top of the file
                ADD     r3, r3, #1      ; start with the second byte

SORT            CMP     r3, r2
                BEQ     ENDSORT         ; if we are at the end of the file, goto ENDSORT
                LDRB    r5, [r3]        ; get the first byte
                MOV     r4, r3          ; start comparisons at the bottom of the sorted bytes
LOOP            CMP     r4, r1          ; see if we are at the top of the file again
                BEQ     NEXT            ; if we are, go to the next byte
                SUB     r8, r4, #1
                LDRB    r6, [r8]        ; get the next byte up
                CMP     r6, r5
                BLE     NEXT            ; if the next byte up is less than or equal then our byte is in the correct place: goto next byte
                STRB    r6, [r4]        ; move the next byte up into this position then move to the next byte up
                SUB     r4, r4, #1
                B       LOOP
NEXT            STRB    r5, [r4]        ; put the byte we are sorting into the current position
                ADD     r3, r3, #1      ; move onto the next byte
                B       SORT            ; resume processing with the next byte

ENDSORT         MOV     r6, r1          ; set r6 to point at the top of the file
                MOV     r7, r2          ; set r7 to point at the bottom of the file
                ADR     r0, OUTFILE     ; set r0 to point to OUTFILE
                MOV     r1, #writeonly  ; set access mode to file as writeonly
                SWI     SWI_Open        ; open the file pointed to by r0
                CMP     r0, #0          ; check for success on opening file
                SWIEQ   SWI_Exit        ; if file could not be opened then exit now
                MOV     r5, r0          ; save the file handle in r5 for later

WRITEF          MOV     r0, r5          ; put the file handle into r0
                MOV     r1, r6          ; put the current position in the file into r6
                ADD     r6, r6, #1      ; increment the position in the file
                CMP     r6, r7          ; check to see if we are past the end of the file
                BGT     ENDWRITEF       ; if we are, stop writing bytes
                MOV     r2, #1          ; otherwise we want to write one byte

                LDRB    r8, [r1]        ; load the value pointed at by r1 into r8
                CMP     r8, #33         ; non white space occurs between ASCII 33 and 126 inclusive
                BLT     WRITEF          ; if we have white space, resume processing with the next byte
                CMP     r8, #127
                BEQ     WRITEF          ; or if we have a DEL character
                CMP     r8, #255
                BEQ     WRITEF          ; or if we have character 255

                SWI     SWI_Write       ; write byte to the file
                B       WRITEF          ; resume processing with the next byte
ENDWRITEF       SWI     SWI_Close       ; close the file


                SWI     SWI_Exit        ; end of execution

INFILE = "turing.txt", 0        ; input filename + null
OUTFILE = "out.txt", 0          ; output filename + null
FILECONTENTS = ""               ; arbitrary amount of memory for contents of file
                END