my assignment involves creating a grading program.
my program must accept a number from the user within the 0 - 100 range and
return the corresponding letter grade based on this rubric:

90 to 100 = A
80 to 89 = B
70 to 79 = C
60 to 69 = D
0 to 59 = F

as of now. my code is able to accept the user input and output it back to the console. now i would like to compare the input received form the user and return the
corresponding letter grade along with the number entered.

i have absolutely not a clue whether to use an array or other method, but my array
attempts have led to disaterous seg faults left and right.

here is the generated code thus far:

    sys_exit        equ     1
    sys_read        equ     3
    sys_write       equ     4
    stdin           equ     0
    stdout          equ     1
    stderr          equ     3

    SECTION     .data
    szName          db      "Enter your Score to Receive the Letter        Grade Equivalent: "
    Name_Len        equ     $-szName
    szHello         db      " ", 0
    Hello_Len       equ     $-szHello

    SECTION     .bss
    lpBuffer        resb    7
    Buf_Len         equ     $-lpBuffer

    Buf             resb    1

    SECTION     .text
    global      _start

    _start:

        nop

        mov     ecx, szName
        mov     edx, Name_Len
        call    DisplayText

        mov     ecx, lpBuffer
        mov     edx, Buf_Len
        call    ReadText
        push    eax

        cmp     eax, Buf_Len
        jl      Good

        cmp     byte [ecx + edx - 1], 10
        je      Good
        mov     byte [ecx + edx - 1], 10
        mov     ebp, 0
        call    ClearTerminal

    Good:
        mov     ecx, szHello
        mov     edx, Hello_Len
        call    DisplayText

        pop     edx
        mov     ecx, lpBuffer
        call    DisplayText

        jmp     Exit

    ClearTerminal: 

        inc     ebp

        mov     edx, 1
        mov     ecx, Buf
        mov     ebx, stdin
        mov     eax, sys_read
        int     80h    

        cmp     [Buf], 30h
        Jb ClearTerminal

        cmp [Buf], 39h
        Ja ClearTerminal

        cmp     byte [ecx + edx - 1], 10
        jne     ClearTerminal
        ret

    DisplayText:
        mov     eax, sys_write
        mov     ebx, stdout
        int     80H
        ret

    ReadText:
        mov     ebx, stdin
        mov     eax, sys_read
        int     80H
        ret

    GradeRubric:



    Exit: 
        mov     eax, sys_exit
        xor     ebx, ebx
        int     80H

        nop

You won't need an array. The simplest method to turn an integer into a grade from your table is to use a series of cmp and jg instructions. For example:

cmp score, 90
jg Grade_A
cmp score, 80
jg Grade_B
cmp score, 70
jg Grade_C
cmp score, 60
jg Grade_D
 - - and so on - -

I know you went to arrays for efficiency's sake, but try not to overthink these things. Keep it simple.

You'll need some way of converting the string you're getting from stdin into an integer (IIRC)

Edited 2 Years Ago by Assembly Guy

Comments
please take a look at my code below i would like your information

This is my code thus far, however i am stuck in an infinite loop and cannot identify the source, i have noticed this infinite loop takes place in "l1:"

section .bss

    myint resb 30
    intlen resd 1

section .data

    welcome_msg db "Welecome to Grade Calculator",13,10
    len1 equ $ - welcome_msg
    prompt_int db "Please enter your Score: ",0
    len2 equ $ - prompt_int

    gradeA db "A"
    gradeAlen equ $ - gradeA

    gradeB db "B"
    gradeBlen equ $ - gradeB

    gradeC db "C"
    gradeClen equ $ - gradeC

    gradeD db "D"
    gradeDlen equ $ - gradeD

    gradeF db "F"
    gradeFlen equ $ - gradeF

section .text

    global _start:

_start:

    nop

;print: welcome to grade calculator

    mov edx, len1
    mov ecx, welcome_msg
    mov ebx, 1
    mov eax, 4
    int 80h

;print: enter your score

    mov edx, len2
    mov ecx, prompt_int
    mov ebx, 1
    mov eax, 4
    int 80h

;read: int from user

    mov edx, 30
    mov ecx, myint
    mov ebx, 2
    mov eax, 3
    int 80h

;save size of string input

    dec eax
    mov dword [intlen], eax

;convert string to int

    mov edi, 10
    mov ecx, [intlen]
    mov esi, myint
    xor eax, eax
    xor ebx, ebx

    mov bl, [esi]
    cmp bl, '-'
    jne next_check
    inc eax
    inc esi
    dec ecx
    jmp done_sign

    next_check:

    cmp bl, '+'
    jne done_sign
    inc esi
    dec ecx

    done_sign:

    push eax

    l1:
    mov bl, [esi]
    ;cmp bl, 30h
    ;jb error
    ;cmp bl, 39h
    ;ja error

    sub bl, 30h
    mul edi; eax=eax*10
    mov bh, 0
    add eax, ebx
    inc esi
    loop l1

    pop ebx
    cmp ebx, 1
    jne rubric
    neg eax

    rubric:

    cmp eax, 90
    jg Grade_A

    cmp eax, 80
    jg Grade_B

    cmp eax, 70
    jg Grade_C

    cmp eax, 60
    jg Grade_D

    cmp eax, 59
    jle Grade_F

    Grade_A:

    mov edx, gradeAlen
    mov ecx, gradeA
    mov ebx, 1
    mov eax, 4
    int 80h

    jmp exit

    Grade_B:

    mov edx, gradeBlen
    mov ecx, gradeB
    mov ebx, 1
    mov eax, 4
    int 80h

    jmp exit

    Grade_C:

    mov edx, gradeClen
    mov ecx, gradeC 
    mov ebx, 1
    mov eax, 4
    int 80h

    jmp exit

    Grade_D:

    mov edx, gradeDlen
    mov ecx, gradeD
    mov ebx, 1
    mov eax, 4
    int 80h

    jmp exit    

    Grade_F:

    mov edx, gradeFlen
    mov ecx, gradeF
    mov ebx, 1
    mov eax, 4
    int 80h

    jmp exit

    nop

    exit:

    mov eax, 1
    mov ebx, 0
    int 80h

I'm not getting the infinite loop locally. What input were you using when the infinite loop happened? Also, my initial comment was wrong, we should be using jge. It's also considered bad practice to not have your last condition a simple fallthrough too.

it continues looping here:
i am not sure where i should do to break it and move on to the next function.

l1:
    mov bl, [esi]
    ;cmp bl, 30h
    ;jb error
    ;cmp bl, 39h
    ;ja error
    sub bl, 30h
    mul edi; eax=eax*10
    mov bh, 0
    add eax, ebx
    inc esi
    loop l1

Roger,

Several things. First, why is the range check for input digits valid commented out? I also will point out that the first compare (cmp bl, 30h) is redundant. Just subtract '0' right away - it also sets the sign flag and saves some work. Then compare the result to 9 (not the character '9') for the second test.

Now as for the infinite looping - are you sure that ECX is still valid? It appears as if entering a grade without a sign will cause an "infinite" loop in the sense that ECX will be decremented 0 while looking for a sign that it never finds and then, when entering the I1 loop, you will run for 2^32 loops (close to infinite;-). I'm surprised that this doesn't cause a segfault when [ESI] falls off the end of the segment. My suggestion would be to make sure that there is a null byte at the end of the input string, even if you need to put it there yourself. Then you can test each char for null and exit the loop, maybe even using loopne.

Finally, read about the string instructions. Knowing about them will improve your coding skills. For example, you could look for '-' with SCANSB then use LODSB to fetch the following characters, simply ignoring anything that's not a digit. YOu could even terminate the loop on anything that's not a digit.

Edited 2 Years Ago by sbesch: Spelling

I have a few more thoughts on the problem of deciding on how to map scores to grades. If you have a fixed paradigm as specified so far, then consider what happens when you integer divide the grade by 10 and subtract the result from 10, then decrement if >0 and add 'A'. Then you get A, B, C, D, ... directly. Anything greater than D would be an F. While this is compact and efficient, it depends too much on the grading paradigm and really is a bit arcane.

The Jump on compare chain is probably best for any simple paradigm based on fixed grading breakpoints.

Now, the array solution. At first it was not clear what you meant to put in the array, but I suspect that it is the set of grading characters. This makes no sense because if you go to the trouble to generate an index into the array, you may as well just add the character 'A' to the index as given above in the first example.

However, what about making a char array 100 elements long and using it to map the grade directly - for example by setting the first 59 elements to 'F', etc. This is by far the most speedy method and it does take a bit more space. You also need to qualify the index to make sure some humorous type does not enter a grade of 120. It also has some other advantages. First, it allows for more complex grading schemes, such as +/- Grading (using for example an array 200 characters long), Grading based on statistics (mean+standard deviation), in which the table could be loaded dynamically based on a paradigm of your choice.

The bottom line - it really doesn't matter how you do the algorithm, as long as it works and you actually do the programming yourself.

Edited 1 Year Ago by sbesch: Spelling

This article has been dead for over six months. Start a new discussion instead.