+1 (315) 557-6473 

Parse Floating Point and Integer Values from Text File in Assembly Language Using Nasm Assignment Solution.


Instructions

Objective
Write a assembly language assignment to parse floating point and integer values from text file using Nasm.

Requirements and Specifications

Parse floating point and integer values from text file in assembly language using Nasm

Screenshots of output

Parse floating point and integer values from text file in assembly language using Nasm 1

Source Code

section .data

noArgsStr:

            db "Usage:", 10

            db " %s ", 10, 0

intFilename:

            db "project4_int.out", 0

fltFilename:

            db "project4_float.out", 0

fileFmt:

            db "wt", 0

intFmt:

            db "%d", 10, 0

fltFmt:

            db "%.38f", 10, 0

openErrorStr:

            db "Error opening input file", 10, 0

openIntErrorStr:

            db "Error opening integer output file", 10, 0

openFltErrorStr:

            db "Error opening float output file", 10, 0

readErrorStr:

            db "Error reading input file", 10, 0

intErrorStr:

            db "Invalid number found in file", 10, 0

fltErrorStr:

            db "Invalid floating point found in file", 10, 0

numIntsStr:

            db "Number of integers: %d", 10, 0

numFltsStr:

            db "Number of floating point numbers: %d", 10, 0

maxFltStr:

            db "Largest floating point number: %f", 10, 0

minFltStr:

            db "Smallest floating point number: %f", 10, 0

sumIntsStr:

            db "Sum of all integers: %f", 10, 0

str:

            db "%s", 10, 0

fd:

            dd 0

intFile:

            dd 0

fltFile:

            dd 0

numInts:

            dd 0

numFlts:

            dd 0

maxFlt:

            dd -1.0e30

minFlt:

            dd 1.0e30

sumInts:

            dd 0

flt10:

            dd 10.0

section .bss

buffer:

            resb 100

number:

            resd 1

section .text

extern printf

extern fprintf

extern fopen

extern fclose

global main

;===============================================================================

; Main function for the program

;===============================================================================

main:

    push ebp ; save frame pointer

    mov ebp, esp ; create new frame

    finit ; initialize fpu

    mov eax, [ebp + 8] ; load argc

    mov edi, [ebp + 12] ; load argv pointer

    cmp eax, 1 ; compare argc with 1

    je noArgs ; if argc == 1, no arguments were given

    mov eax, 5 ; open file using syscall number 5

    mov ebx, [edi + 4] ; filename is second command line argument

    mov ecx, 0 ; open as read only

    int 80h ; call os to open file

    cmp eax, 0 ; check return value of syscall

    jl openError ; if <0, then there was an error

    mov [fd], eax ; save file descriptor

    mov eax, fileFmt ; load format for output file

    push eax ; pass as argument

    mov eax, intFilename ; load integer output filename

    push eax ; pass as argument

    call fopen ; open with C library

    add esp, 8 ; remove arguments from stack

    cmp eax, 0 ; check for errors

    jle openIntError ; if <=0, there was an error

    mov [intFile], eax ; save file pointer

    mov eax, fileFmt ; load format for output file

    push eax ; pass as argument

    mov eax, fltFilename ; load floating point output filename

    push eax ; pass as argument

    call fopen ; open with C library

    add esp, 8 ; remove arguments from stack

    cmp eax, 0 ; check for errors

    jle openFltError ; if <=0, there was an error

    mov [fltFile], eax ; save file pointer

    ; load number of entries in input file

    mov eax, 100 ; load max numbers to read

    push eax ; pass as 3rd argument to function

    mov eax, buffer ; load pointer to buffer

    push eax ; pass as second argument to function

    mov eax, [fd] ; load file descriptor

    push eax ; pass as argument to function

    call readLine ; read line from file

    add esp, 12 ; remove arguments from stack

    cmp eax, 0 ; check for errors in function

    jl readError ; if <0, there was an error

    ; convert to integer

    mov eax, number ; load pointer to number space

    push eax ; pass as second argument

    mov eax, buffer ; load pointer to buffer

    push eax ; pass as argument to function

    call stringToInt ; convert string to integer

    add esp, 8 ; remove arguments from stack

    cmp eax, 0 ; check for errors

    jl intError ; if not valid, error

    mov ecx, [number] ; load number of entries

loadLoop:

    push ecx ; save loop counter

    ; load entry

    mov eax, 100 ; load max numbers to read

    push eax ; pass as 3rd argument to function

    mov eax, buffer ; load pointer to buffer

    push eax ; pass as second argument to function

    mov eax, [fd] ; load file descriptor

    push eax ; pass as argument to function

    call readLine ; read line from file

    add esp, 12 ; remove arguments from stack

    cmp eax, 0 ; check for errors in function

    jl readError ; if <0, there was an error

    ; convert to integer

    mov eax, number ; load pointer to number space

    push eax ; pass as second argument

    mov eax, buffer ; load pointer to buffer

    push eax ; pass as argument to function

    call stringToInt ; convert string to integer

    add esp, 8 ; remove arguments from stack

    cmp eax, 0 ; check for errors

    jge isInteger ; if valid, process as integer

flthere:

    ; convert to float

    mov eax, number ; load pointer to number space

    push eax ; pass as second argument

    mov eax, buffer ; load pointer to buffer

    push eax ; pass as argument to function

    call stringToFlt ; convert string to float

    add esp, 8 ; remove arguments from stack

    cmp eax, 0 ; check for errors

    jl fltError ; if not valid, error

    inc DWORD[numFlts] ; increment number of floating point numbers

    fld DWORD[number] ; load number

    fcom DWORD[maxFlt] ; compare with max

    fnstsw ax ; move status to ax

    sahf ; load flags

    jb updMin ; if

    fst DWORD[maxFlt] ; else, update max

updMin:

    fcom DWORD[minFlt] ; compare with min

    fnstsw ax ; move status to ax

    sahf ; load flags

    ja printFlt ; if >min, skip

    fst DWORD[minFlt] ; else, update min

printFlt:

    sub esp, 8 ; push qword

    fstp QWORD[esp] ; pass as argument

    mov eax, fltFmt ; load file output format

    push eax ; pass as argument

    mov eax, [fltFile] ; load file pointer

    push eax ; pass as argument

    call fprintf ; print to file with C library

    add esp, 16 ; remove arguments from stack

    jmp nextEntry

isInteger:

    inc DWORD[numInts] ; increment number of integers

    fild DWORD[number] ; load read number into fpu

    fiadd DWORD[sumInts] ; add to sum of integers

    fistp DWORD[sumInts] ; update sum

    mov eax, [number] ; load number

    push eax ; pass as argument

    mov eax, intFmt ; load file output format

    push eax ; pass as argument

    mov eax, [intFile] ; load file pointer

    push eax ; pass as argument

    call fprintf ; print to file with C library

    add esp, 12 ; remove arguments from stack

nextEntry:

    pop ecx ; load loop counter

    dec ecx

    je endLoop

    jmp loadLoop ; repeat for the number of entries

endLoop:

    mov eax, [intFile] ; load file pointer

    push eax ; pass as argument

    call fclose ; close with C library

    add esp, 4 ; remove arguments from stack

    mov eax, [fltFile] ; load file pointer

    push eax ; pass as argument

    call fclose ; close with C library

    add esp, 4 ; remove arguments from stack

    mov eax, 6 ; syscall to close file

    mov ebx, [fd] ; load file descriptor

    int 80h ; call os to close the file

    ; print results

    mov eax, [numInts] ; load number of integers

    push eax ; pass as argument

    mov eax, numIntsStr ; load message string format

    push eax ; pass as argument

    call printf ; print number of ints

    add esp, 8 ; remove arguments from stack

    mov eax, [numFlts] ; load number of floats

    push eax ; pass as argument

    mov eax, numFltsStr ; load message string format

    push eax ; pass as argument

    call printf ; print number of ints

    add esp, 8 ; remove arguments from stack

    sub esp, 8 ; allocate space for float

    fldz ; load zero

    cmp DWORD[numFlts], 0 ; check if there are floats

    je noflt1 ; if no floats, skip

    fld DWORD[maxFlt] ; load largest float

noflt1:

    fstp QWORD[esp] ; push to stack argument

    mov eax, maxFltStr ; load message string format

    push eax ; pass as argument

    call printf ; print number of ints

    add esp, 12 ; remove arguments from stack

    sub esp, 8 ; allocate space for float

    fldz ; load zero

    cmp DWORD[numFlts], 0 ; check if there are floats

    je noflt2 ; if no floats, skip

    fld DWORD[minFlt] ; load smallest float

noflt2:

    fstp QWORD[esp] ; push to stack argument

    mov eax, minFltStr ; load message string format

    push eax ; pass as argument

    call printf ; print number of ints

    add esp, 12 ; remove arguments from stack

    sub esp, 8 ; allocate space for float

    fild DWORD[sumInts] ; load sum of integers

    fstp QWORD[esp] ; push to stack argument

    mov eax, sumIntsStr ; load message string format

    push eax ; pass as argument

    call printf ; print number of ints

    add esp, 12 ; remove arguments from stack

    jmp progEnd ; jump to program end

noArgs:

    push DWORD[edi] ; pass first command line argument

    mov eax, noArgsStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 8 ; remove arguments from stack

    jmp progEnd ; jump to program end

openError:

    mov eax, openErrorStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 4 ; remove arguments from stack

    jmp progEnd ; jump to program end

openIntError:

    mov eax, openIntErrorStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 4 ; remove arguments from stack

    jmp progEnd ; jump to program end

openFltError:

    mov eax, openFltErrorStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 4 ; remove arguments from stack

    jmp progEnd ; jump to program end

readError:

    mov eax, readErrorStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 4 ; remove arguments from stack

    jmp progEnd ; jump to program end

intError:

    mov eax, intErrorStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 4 ; remove arguments from stack

    jmp progEnd ; jump to program end

fltError:

    mov eax, fltErrorStr ; load address of error string

    push eax ; pass as argument to printf

    call printf ; print error message on screen

    add esp, 4 ; remove arguments from stack

    jmp progEnd ; jump to program end

progEnd:

    xor eax, eax ; return 0

    pop ebp ; restore frame pointer

    ret ; return to os

;===============================================================================

; Reads a line from the file to a buffer

; Receives file descriptor, pointer to buffer and max number of chars to read

; returns eax <0 if there was no error, number of read chars if there was no

; error

;===============================================================================

readLine:

    push ebp ; save frame pointer

    mov ebp, esp ; create new frame

    mov edi, [ebp + 12] ; buffer pointer is the second argument

    mov esi, 0 ; initialize number of read chars to zero

rdLoop:

    mov eax, 3 ; read file using syscall number 3

    mov ebx, [ebp + 8] ; take filename descriptor from first argument

    mov ecx, edi ; pass current buffer pointer

    mov edx, 1 ; read only 1 character

    int 80h ; call os to open file

    cmp eax, 0 ; check return value

    jl rdError ; if <0 return read error

    je rdEnd ; if we reached end of file, end

    cmp BYTE[edi],13 ; if we reached cr (windows file)

    je rdLoop ; continue to read newline

    cmp BYTE[edi],10 ; if we reached newline

    je rdEnd ; end reading file

    inc edi ; increment buffer position

    inc esi ; increment number of read chars

    cmp esi, [ebp + 16] ; compare with max number of chars

    jl rdLoop ; read another character if we didn't reach max

rdEnd:

    mov BYTE[edi], 0 ; save string end

    mov eax, esi ; return number of read chars

rdError:

    pop ebp ; restore frame pointer

    ret ; return to calling function

;===============================================================================

; Converts an input string to an integer

; Receives a string pointer and a pointer to an int variable

; Returns eax < 0 if error

;===============================================================================

stringToInt:

    push ebp ; save frame pointer

    mov ebp, esp ; create new frame

    push ebx ; save ebx

    mov ecx, 1 ; positive sign by default

    mov ebx, 0 ; start with converted number in zero

    mov esi, [ebp + 8] ; load string pointer

    mov edi, [ebp + 12] ; load pointer to number

    mov al, [esi] ; load character

    cmp al, 0 ; if end of string

    je stoiErr ; is an error

    cmp BYTE[esi], '-' ; check if the number is negative

    jne stoiLoop ; if not, start loop

    mov ecx, -1 ; else, set negative sign

    inc esi ; advance to next char

    mov al, [esi] ; load character

    cmp al, 0 ; if end of string

    je stoiErr ; is an error

stoiLoop:

    mov al, [esi] ; load digit

    cmp al, 0 ; if end of string

    je stoiEnd ; end loop

    cmp al, '0' ; see if digit is valid

    jl stoiErr ; if not, error

    cmp al, '9' ; see if digit is valid

    jg stoiErr ; if not, error

    sub al, '0' ; convert digit to integer

    imul ebx, 10 ; multiply old number by 10

    movzx eax, al ; convert to dword

    add ebx, eax ; add digit to number

    inc esi ; increment pointer

    jmp stoiLoop ; convert another char

stoiErr:

    mov eax, -1 ; return -1 to indicate error

    jmp stoiRet ; go to return

stoiEnd:

    imul ebx, ecx ; multiply by sign

    mov [edi], ebx ; save in output

    mov eax, 0 ; return no error

stoiRet:

    pop ebx ; restore ebx

    pop ebp ; restore frame pointer

    ret ; return to calling function

;===============================================================================

; Converts an input string to a float

; Receives a string pointer and a pointer to a float variable

; Returns eax < 0 if error

;===============================================================================

stringToFlt:

    push ebp ; save frame pointer

    mov ebp, esp ; create new frame

    push ebx ; save ebx

    mov ecx, 0 ; positive sign by default

    mov ebx, 0 ; start with converted number in zero

    mov esi, [ebp + 8] ; load string pointer

    mov al, [esi] ; load character

    cmp al, 0 ; if end of string

    je stofErr ; is an error

    cmp BYTE[esi], '-' ; check if the number is negative

    jne stofLoop ; if not, start loop

    mov ecx, 1 ; else, set negative sign

    inc esi ; advance to next char

stofLoop:

    mov al, [esi] ; load digit

    cmp al, 0 ; if end of string

    je stofErr ; is an error

    cmp al, '.' ; if dot

    je stofFrac ; go to fraction

    cmp al, '0' ; see if digit is valid

    jl stofErr ; if not, error

    cmp al, '9' ; see if digit is valid

    jg stofErr ; if not, error

    sub al, '0' ; convert digit to integer

    movzx eax, al ; convert to dword

    imul ebx, 10 ; multiply old number by 10

    add ebx, eax ; add digit to number

    inc esi ; increment pointer

    jmp stofLoop ; convert another char

stofFrac:

    inc esi ; skip dot

    push ebx ; save whole part

    fild DWORD[esp] ; load in fpu

    add esp, 4 ; restore stack pointer

    fld1 ; initialize divisor to 1

    mov ebx, 0 ; start with converted number in zero

stofFracLoop:

    mov al, [esi] ; load digit

    cmp al, 'E' ; if dot

    je stofExp ; go to exponent

    cmp al, '0' ; see if digit is valid

    jl stofErr ; if not, error

    cmp al, '9' ; see if digit is valid

    jg stofErr ; if not, error

    sub al, '0' ; convert digit to integer

    movzx eax, al ; convert to dword

    imul ebx, 10 ; multiply old number by 10

    add ebx, eax ; add digit to number

    fmul DWORD[flt10] ; multiply divisor by 10

    inc esi ; increment pointer

    jmp stofFracLoop ; convert another char

stofExp:

    inc esi ; skip E

    push ebx ; save fraction part

    fild DWORD[esp] ; load in fpu

    add esp,4 ; restore stack pointer

    fdivr ; divide fraction by power of 10

    fadd ; add to whole part

    mov ebx, 0 ; start with converted exp in zero

    mov edx, 0 ; initialize sign to positive

    cmp BYTE[esi], '-' ; check if the exponent is negative

    jne chkPos ; if not, check positive

    mov edx, 1 ; else, set negative sign

    jmp stofExp1

chkPos:

    cmp BYTE[esi], '+' ; check if the exponent is positive

    jne stofErr ; if not, error

stofExp1:

    inc esi ; advance to next char to skip sign

    cmp BYTE[esi + 2], 0 ; check valid exponent

    jne stofErr ; if not, error

    mov al, [esi] ; load digit

    cmp al, '0' ; see if digit is valid

    jl stofErr ; if not, error

    cmp al, '9' ; see if digit is valid

    jg stofErr ; if not, error

    sub al, '0' ; convert digit to integer

    movzx ebx, al ; convert to dword

    mov al, [esi+1] ; load digit

    cmp al, '0' ; see if digit is valid

    jl stofErr ; if not, error

    cmp al, '9' ; see if digit is valid

    jg stofErr ; if not, error

    sub al, '0' ; convert digit to integer

    movzx eax, al ; convert to dword

    imul ebx, 10 ; multiply old number by 10

    add ebx, eax ; add digit to number

    fld1 ; load 1 to fpu

expMul:

    cmp ebx, 0 ; if exponent is zero

    je stofEnd ; go to next step

    fmul DWORD[flt10] ; multiply by 10

    dec ebx ; decrement exponent

    jmp expMul ; repeat loop

stofErr:

    mov eax, -1 ; return -1 to indicate error

    jmp stofRet ; go to return

stofEnd:

    cmp edx, 0 ; if exponent is negative

    jne expDiv ; then use divisions

    fmulp ; multiply number by exponent

    jmp last

expDiv:

    fdivp ; divide number by exponent

last:

    cmp ecx, 0 ; if sign is positive

    je saveNum ; skip

    fchs ; else change sign

saveNum:

    mov edi, [ebp + 12] ; load pointer to number

    fstp DWORD[edi] ; save in output

    mov eax, 0 ; return no error

stofRet:

    pop ebx ; restore ebx

    pop ebp ; restore frame pointer

    ret ; return to calling function