0

I am trying to create a function which returns a character value based on a floating-point value such as:

|Percentage | Letter Grade | | 90.0 - 100.0 A | | 80.0 - 89.9 B | | 70.0 - 79.9 C | | 60.0 - 69.9 D | | Below 59.9 F |

Here what I have so far:

program grade
#include("stdlib.hhf");
static
percentage: real32 :=0;

// Function grader //
procedure grader(percentage:real32); @nodisplay; @noframe;
static
returnAddress: dword;
cA : byte := $41; // A = hex 41
cB : byte := $42; // B = hex 42
cC : byte := $43; // C = hex 43
cD : byte := $44; // D = hex 44
cF : byte := $46; // F = hex 46
aGrade : real32 := 90.0;
bGrade : real32 := 80.0;
cGrade : real32 := 70.0;
dGrade : real32 := 60.0;
fGrade : real32 := 50.0;

begin grader;
pop(returnAddress);
pop(percentage);
push(returnAddress); 

// Score for grade A
finit();
fld(percentage);
fld(st0); 
fld(aGrade); 
fld(st1);  
fcomp();
fstsw(AX);  
sahf();
setb(AL);
cmp(AL,0);
je gradeA;

// grade B score
fld(percentage);
fld(st0); 
fld(bGrade); 
fld(st1);
fcomp();
fstsw(AX);
sahf();
setb(AL);
cmp(AL,0);
je gradeB;

// grade C score
fld(percentage); 
fld(st0);
fld(cGrade); 
fld(st1);
fcomp();
fstsw(AX);
sahf();
setb(AL);
cmp(AL,0);
je gradeC;

// grade D score
fld(percentage); // st0
fld(st0);
fld(dGrade); // st4
fld(st1);
fcomp();
fstsw(AX);
sahf();
setbe(AL);
cmp(AL,0);
je gradeD;

// grade F score
fld(percentage); // st0
fld(st0);
fld(fGrade); // st5
fld(st1);
fcomp();
fstsw(AX);
sahf();
setbe(AL);
cmp(AL,0);
jne gradeF;

jmp finalGrade;

gradeA:
stdout.put("that's the grade: ");
stdout.putc(cA); 
jmp finalGrade; 

gradeB:
stdout.put("that's the grade: ");
stdout.putc(cB); 
jmp finalGrade;

gradeC:
stdout.put("that's the grade: ");
stdout.putc(cC); 
jmp finalGrade;

gradeD:
stdout.put("that's the grade: ");
stdout.putc(cD); 
jmp finalGrade;

gradeF:
stdout.put("that's the grade: ");
stdout.putc(cF); 
jmp finalGrade;

finalGrade:  

ret();
end grader;

// Main //
begin grade;
stdout.put("Feed Me: ");
stdin.get(percentage);
push(percentage);

call grader;

stdout.newln();
end grade; 

This is what I got for output here:

Feed Me: 90.0
that's the grade: A

Feed Me: 80.0
that's the grade: B

Feed Me: 70.0
(Exit Program)

Feed Me: 60.0
(Exit Program)

The first 2, A and B grades I was able to get it to work, but with anything below 80, I can't get the right correct letter and it keeps terminate the program. What is the issue behind this? Thanks.

  • For anyone considering answering this question, this user vandalized [their previous question](https://stackoverflow.com/questions/68522250/pop-push-instruction), so anything you write here might have less than normal future value. – Peter Cordes Aug 07 '21 at 07:30
  • 1
    Did you single-step your code in a debugger? You do a lot of `fld` and not much popping of the x87 register stack (http://www.ray.masmcode.com/tutorial/fpuchap1.htm), so it probably fills up, making future `fld` operations produce NaN. Using a debugger is essential, if you're not doing that, you could be saving yourself (and everyone else) a lot of time compared to asking on SO. e.g. [`fcomip`](https://www.felixcloutier.com/x86/fcomi:fcomip:fucomi:fucomip) with a memory operand can compare directly into EFLAGS and pop the previous fld. – Peter Cordes Aug 07 '21 at 07:32
  • 1
    Also, there's no need to materialize a boolean 0/1 in AL, just `jae` or `jnb gradeB` based on flags set from `sahf`. (Or like I said, from `fcomi`, new instruction available since P6 that avoids all that.) Or do math to map to an integer from 0..10, and use that as a table lookup, no branching. – Peter Cordes Aug 07 '21 at 07:37
  • @PeterCordes , sorry, I just want it's deleted, but now I understand why it's wrong to do that. I won't do that again. I just put back the question. – retrofusion Aug 07 '21 at 07:53
  • 1
    Thank you @PeterCordes, the tutorial website really help me understanding the stack so thank you for that. I won't modify this question. – retrofusion Aug 07 '21 at 08:51

0 Answers0