2

I have written an assembly code for calculating area mentioned in the following formula
enter image description here

I feel I have overcomplicated the code. Need suggestions if the same could be done in a simpler way. I am calculating sqrt of 5 than mul by 2. Each thing is done in a separate line.
Is there a way to do it one line or shorter way

INCLUDE Irvine32.inc


.data
testString BYTE "test",0

invalidValueString BYTE "invalid value entered for length of edge!",0
enterEdgeLength BYTE "Enter the length of the edge e : ",0
areaString BYTE "Area : ",0
volumeString BYTE "Volume : ",0
radiusString  BYTE "Midsphere Radius : ",0
edgeLength real4 ?
five real4 5.0
four real4 4.0
two real4 2.0
six real4 6.0
three real4 3.0
fortySeven real4 47.0
ninetyNine  real4 99.0
twelve real4 12.0


.code

call crlf

start:
mov edx, offset enterEdgeLength
call writestring
call readfloat            ; reads the edge length into ST(0)
fstp edgeLength           ; edgeLength variable will contain the length entered
cmp edgeLength, 0         ; comparing with 0 
jl negativeValue          ; if it's less than 0 print error msg and loop to start
cmp edgeLength, 0
je stop                   ; if length entered is 0 exit the program
jmp properValue

negativeValue: 
     mov edx, offset invalidValueString   
     call writestring
     call crlf
     jmp start
properValue:                   ; call each method one by one to calculate
    call area                  ; area, volume and radius
    call volume 
    call radius
    call crlf
    fstp ST(0)                 ; clear the stack before looping again
    jmp start
    stop:
    exit

area proc
finit                     
fld five                ; calculating the constant that is to be multiplied
fsqrt                   ; with edgelength squared
fmul two
fld five
fadd
fsqrt
fmul six
fld three
fsqrt
fadd
fmul five
                        ; the constant expression is in ST(0)
fmul edgeLength              
fmul edgeLength         ; multiply the edgelength squared to ST(0) to get area

call crlf
mov edx, offset areaString
call writestring
call writefloat
fstp ST(0)
area endp
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
rohit sharma
  • 171
  • 1
  • 9
  • What's *e* in your formulae? Surely not [Euler's number](https://en.wikipedia.org/wiki/E_(mathematical_constant)), the mathematical constant that's approximately 2.71828...? But if it's anything else, don't use *e* as a variable name! It would be like using pi for something other than 3.14159...! – Peter Cordes Apr 24 '21 at 09:07
  • You don't need to recompute the constants every time, do you? Just do that once, by hand, and include the decimal fraction in your source. (As a 10-byte `real10` if you want the same precision you could get from computing it on the fly). The assembler will convert it to the nearest representable FP bit-pattern. (like https://h-schmidt.net/FloatConverter/IEEE754.html / https://www.exploringbinary.com/floating-point-converter/ but for tbyte.) Unfortunately I don't think most assemblers support stuff like `real10 sqrt(5 + 2*sqrt(5))` :P – Peter Cordes Apr 24 '21 at 09:13
  • You don't need `fmul two`; use `fadd st(0), st(0)`. And it looks like you're never popping the FP stack so you'll use up all 8 registers and get NaNs. After `fld five`, use `faddp` instead of `fadd` unless you're going to use that `5` again later, like `fadd st(0), st(3)` or whatever. (One operand always has to be ST(0), but it can be first or 2nd with another register.) But if not, use `fadd five` – Peter Cordes Apr 24 '21 at 09:18
  • e is the length of edge. This is taken as input from user – rohit sharma Apr 24 '21 at 09:38
  • Is there any limit to how many numbers could be pushed into the fpu stack ? – rohit sharma Apr 24 '21 at 09:40
  • 1
    Yes, only 8, the number of x87 registers. http://www.ray.masmcode.com/tutorial/fpuchap1.htm. If you try to fld when st(7) is already in use, you get a NaN. – Peter Cordes Apr 24 '21 at 09:45
  • For subtraction assembly doesn't provide any simple thing like x = 2-3 right ? We have to mov 2 to a register and subtract 3 from it. That's weird why can't their be simpler instructions. Or perhaps that's how things closer to cpu works.. – rohit sharma Apr 24 '21 at 10:02
  • For integer that would be correct on x86, but for x87 there's `fsubr` (reverse-subtract): https://www.felixcloutier.com/x86/fsubr:fsubrp:fisubr. The same FPU tutorial I linked earlier (http://www.ray.masmcode.com/tutorial/index.html) has chapters on the available instructions, including that one: http://www.ray.masmcode.com/tutorial/fpuchap8.htm#fsubr. Fun fact: some other architectures *do* have integer reverse-subtract, e.g. ARM has `rsb r1, r2, #123` to do r1 = r2-123. Other than immediate, 3-operand ISAs like x86 with AVX can just swap the src operands: `vsubsd xmm0, xmm2, xmm1` – Peter Cordes Apr 24 '21 at 10:07
  • 2
    But yeah, x86 `sub dst, src` or (SSE2) `subsd dst, src` can only subtract *from* the destination, there's no reverse-subtract instruction for those. – Peter Cordes Apr 24 '21 at 10:12
  • I tried doing 'fld five' 9 time and then did 'call writefloat' it showed NaN as expected. But what's the reason for it. Normally if I push an element to a stack and there is no place in stack it should throw an error and the remaining elements should remain intact. So 'call writefloat' should have displayed the top element of the stack. Why does it print NaN – rohit sharma Apr 24 '21 at 14:39
  • It prints NaN because that's the current value of ST(0) after your code overflowed the x87 stack. Floating point has NaN as a way to flag problems without raising exceptions. If you unmasked FP-invalid exceptions (with the IM bit in [the x87 control word (`fldcw`)](http://www.ray.masmcode.com/tutorial/fpuchap1.htm#cword)), it would fault. But then so would divide-by-zero or sqrt of a negative number. The default FP environment has all FP exceptions masked, so you get a NAN instead of any actual CPU exception. – Peter Cordes Apr 25 '21 at 00:52
  • Having `fld` silently do nothing (except set the I bit in the [x87 status word](http://www.ray.masmcode.com/tutorial/fpuchap1.htm#sword)) if the x87 stack is full and that exception is masked seems even worse than getting a NaN. It would have been a reasonable design to give x87 stack over/underflow a different exception bit from FP-invalid so you could let that trap while still getting NaN from sqrt(-1). But the design they picked treats that like other FP things. – Peter Cordes Apr 25 '21 at 00:55
  • Your question would be excellent for reviewing on https://codereview.stackexchange.com/ – Sep Roland Apr 25 '21 at 21:28

0 Answers0