Skip to main content
Engineering LibreTexts

13.4: Console Input

  • Page ID
    19942
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    The system service to read characters from the console is the system read (SYS_read). Like a high-level language, for the console, characters are read from standard input (STDIN). The STDIN is the default file descriptor for reading characters from the keyboard. The file descriptor is already opened and available for use in program (assembly and high-level languages).

    Reading characters interactively from the keyboard presents an additional complication. When using the system service to read from the keyboard, much like the write system service, the number of characters to read is required. Of course, we will need to declare an appropriate amount of space to store the characters being read. If we request 10 characters to read and the user types more than 10, the additional characters will be lost, which is not a significant problem. If the user types less than 10 characters, for example 5 characters, all five characters will be read plus the newline (LF) for a total of six characters.

    A problem arises if input is redirected from a file. If we request 10 characters, and there are 5 characters on the first line and more on the second line, we will get the six characters from the first line (5 characters plus the newline) and the first four characters from the next line for the total of 10. This is undesirable.

    To address this, for interactively reading input, we will read one character at a time until a LF (the Enter key) is read. Each character will be read and then stored, one at a time, in an appropriately sized array.

    The arguments for the read system service are as follows:

    Register

    SYS_read

    rax

    Call code = SYS_read (0)

    rdi

    Input location, STDIN (0)

    rsi

    Address of where to store characters read

    rdx

    Number of characters to read

    Assuming the following declarations:

        STDIN        equ    0                ; standard input
        SYS_read     equ    0                ; call code for read
        
        inChar       db     0
    

    For example, to read a single character from the keyboard, the system read (SYS_read) would be used. The code would be as follows:

        mov     rax, SYS_read 
        mov     rdi, STDIN 
        mov     rsi, inChar                         ; msg address
        mov     rdx, 1 syscall                      ; read count
    

    Refer to the next section for a complete program to read characters from the keyboard.

    Example, Console Input

    The example is a complete program to read a line of 50 characters from the keyboard. Since space for the newline (LF) along with a final NULL termination is included, an input array allowing 52 bytes would be required.

    This example will read up to 50 characters from the user and then echo the input back to the console to verify that the input was read correctly.

    ; Example program to demonstrate console output.
    ; This example will send some messages to the screen.
    ; **********************************************
    
    section .data 
    
    ; -----
    ;  Define standard constants.
    
    LF             equ    10             ; line feed
    NULL           equ    0              ; end of string 
    TRUE           equ    1
    FALSE          equ    0
    
    EXIT_SUCCESS   equ    0              ; success code
    
    STDIN          equ    0              ; standard input
    STDOUT         equ    1              ; standard output
    STDERR         equ    2              ; standard error
    
    SYS_read       equ    0              ; read
    SYS_write      equ    1              ; write
    SYS_open       equ    2              ; file open
    SYS_close      equ    3              ; file close
    SYS_fork       equ    57             ; fork
    SYS_exit       equ    60             ; terminate
    SYS_creat      equ    85             ; file open/create
    SYS_time       equ    201            ; get time
    
    ; -----
    ; Define some strings.
    
    STRLEN         equ    50
    
    pmpt           db     "Enter Text: ", NULL
    newLine        db     LF, NULL
    
    section    .bss
    chr            resb   1
    inLine         resb   STRLEN+2        ; total of 52
    
    ;------------------------------------------------------
    
    section     .text 
    global _start 
    _start:
    
    ; -----
    ;  Display prompt.
    
        mov     rdi, pmpt 
        call    printString
    
    ; -----
    ;  Read characters from user (one at a time)
        mov    rbx, inLine                ; inline addr
        mov    r12, 0                     ; char count
    readCharacters:
        mov    rax, SYS_read              ; system code for read
        mov    rdi, STDIN                 ; standard in
        lea    rsi, byte [chr]            ; address of chr
        mov    rdx, 1                     ; count (how many to read)
        syscall                           ; do syscall
        
        mov    a1, byte [chr]             ; get character just read
        cmp    a1, LF                     ; if linefeed, input done
        je     readDone
        
        inc    r12                        ; count++
        cmp    r12, STRLEN                ; if # chars >= STRLEN
        jae    readCharacters             ;   stop placing in buffer
        
        mov    byte [rbx], a1             ; inLine[i] = chr
        inc    rbx                        ; update tmpStr addr
        
        jmp    readCharacters
    readDone:
        mov    byte [rbx], NULL           ; add NULL termination
        
    ; -----
    ;  Output the line to verify successful read
    
        mov    rdi, inLine 
        call   printString
    
    ; -----
    ;  Example done.
    
    exampleDone:
        mov    rax, SYS_exit 
        mov    rdi, EXIT_SUCCESS 
        syscall
    
    ; ******************************************************
    ;  Generic procedure to display a string to the screen.
    ;  String must be NULL terminated.
    ;  Algorithm:
    ;     Count characters in string (excluding NULL)   
    ;  Use syscall to output characters
    ;  Arguments:
    ;  1) address, string 
    ;  Returns:
    ;  nothing
    
    global printString 
    printString:
        push     rbx
    
    ; -----
    ;  Count characters in string.
    
        mov     rbx, rdi 
        mov     rdx, 0  
    
    strCountLoop:
        cmp     byte [rbx], NULL
        je      strCountDone
        inc     rdx
        inc     rbx
        jmp     strCountLoop
    strCountDone:
    
        cmp     rdx, 0
        je      prtDone
        
    ; -----
    ; Call OS to output string.
    
        mov     rax, SYS_write     ; system code for write ()
        mov     rsi, rdi           ; address of char's to write
        mov     rdi, STDOUT        ; standard out
                                   ; RDX=count to write, set above
        syscall                    ; system call
        
    ; -----
    ;  String printed, return to calling routine.
    
    prtDone:
        pop     rbx
        ret                
    

    If we were to completely stop reading at 50 (STRLEN) characters and the user enters more characters, the characters might cause input errors for successive read operations. To address any extra characters the user might enter, the extra characters are read from the keyboard but not placed in the input buffer (inLine above). This ensures that the extra input is removed from the input steam and but does not overrun the array.

    The additional, unused constants are included for reference.


    This page titled 13.4: Console Input is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Ed Jorgensen.

    • Was this article helpful?