//---------------------------------------------------------------- // manydots.s // // Here is an example of "structured" programming, in which // the main routine is decomposed into three simpler steps. // In the first step the program's data is obtained through // an "interactive" dialogue between user and computer: two // standard functions from the C runtime library are called // to perform the asking of a question by the computer, via // the 'write()' function, and the listening for a response // from the user, via the 'read()' function. In the second // phase, an algorithm is employed to convert the string of // decimal numerals (ascii character-codes which were typed // in by the user) into a numerical value (called 'count'). // In the final step, the value of 'count' is used for loop // control to repeat the printing of a 'dot' character. // // NOTE: The programmer will need to be acquainted with the // prototypes for the two standard C library functions: // // int write( int fileno, void *buffer, int len ); // int read( int fileno, void *buffer, int len ); // // in order to properly transmit the function-arguments, in // the correct order, via the processor's stack. // // programmer: ALLAN CRUSE // written on: 09 SEP 2003 //---------------------------------------------------------------- # symbolic constants .equ STDIN, 0 # keyboard device-file ID .equ STDOUT, 1 # display device-file ID .equ MAXIN, 5 # maximum length of input #----------------------------------------------------------------- .section .data query: .ascii "How many dots do you want to see? " qsize: .long . - query # number of message-bytes reply: .space MAXIN # storage-space for input count: .long 0 # number of dots to print newln: .byte '\n' # ascii-code for new line dot: .byte '.' # ascii-code for a period #----------------------------------------------------------------- .section .text main: call obtain_input # dialogue with the user call process_data # turn string into count call print_output # show dot 'count' times ret # give control to system .globl main # make entry-point visible #----------------------------------------------------------------- #----------------------------------------------------------------- obtain_input: # # This subroutine uses standard C functions, write() and read(), # to implement a simple "interactive dialogue" by which the user # supplies the program-data to be used in the later steps. # # print a question for the user pushl qsize # push argument #3 pushl $query # push argument #2 pushl $STDOUT # push argument #1 call write # call runtime library addl $12, %esp # discard three arguments # obtain a reply from the user pushl $MAXIN # push argument #3 pushl $reply # push argument #2 pushl $STDIN # push argument #1 call read # call runtime library addl $12, %esp # discard three arguments ret # back to calling routine #----------------------------------------------------------------- process_data: # # This subroutine converts the user's input-string to an integer # which it stores in a global variable named 'count'. It scans # the array of character-codes which were typed in by the user, # stopping if it comes to one which does not represent a decimal # numeral. For each valid numeral, the previously accumulated # total is multiplied by ten (the number base) and then the new # digit's value is added. The processor's source-index register # (%esi) is used as a 'pointer' to the memory-location where the # the currently scanned character-code was stored. # # program loop, to process the array of input characters movl $reply, %esi # point ESI to input-buffer movl $0, count # initialize our accumulator movl $MAXIN, %ecx # setup our loop-counter nxnum: # load the current array-element into register DL movb (%esi), %dl # fetch next character-code incl %esi # then advance array-index # make sure this character-code represents a valid numeral cmpb $'0', %dl # character preceeds '0'? jl numxx # yes, it's not a numeral cmpb $'9', %dl # character follows '9'? jg numxx # yes, it's not a numeral # convert 8-bit character-code to its 32-bit integer-value subb $'0', %dl # convert: ascii to number movzx %dl, %edx # extend number to 32-bits # add the new integer-value to ten times the prior count imul $10, count, %eax # ten times prior count addl %edx, %eax # plus new numeral's value movl %eax, count # save the resulting total loop nxnum # check for further digits numxx: ret # back to calling routine #----------------------------------------------------------------- #----------------------------------------------------------------- print_output: # # The job of this subroutine is to print the number of dots which # are indicated by the value of the 'count' variable, and then to # advance the screen's cursor to a new line before exiting. Here # once again the standard C runtime library's 'write()' function # is called to product the desired output to the display screen. # cmp $0, count # check: count is zero? je fini # yes, no dots to print nxdot: pushl $1 # argument #3 pushl $dot # argument #2 pushl $STDOUT # argument #1 call write # call runtime library addl $12, %esp # discard these arguments decl count # decrement loop-counter jnz nxdot # nonzeo? show more dots fini: pushl $1 # argument #3 pushl $newln # argument #2 pushl $STDOUT # argument #1 call write # call runtime library addl $12, %esp # discard these argument ret # back to calling routine #-----------------------------------------------------------------