I have to make a program that calculates the volume of a cone which is 22/21*(r^2)*h for purposes of this program.
So this code I developed works for me for any variables that don't cause the EDX register to become populated after multiplying the variables together. I can't shift registers or "OR" them together, nor can I use jumps or cmp statements. I also must use 8 bit registers for the height and width variables, 16 bit for the radius^2 and radius^2*height calculations, and then finish it off with 32 bit for the final division calculation. Take a look. I don't know why it is overflowing into EDX and I don't know how to correct it...
.data
radius WORD ? ;var for radius
height WORD ? ;var for height
numerator WORD 22 ;Making a variable for numerator
denominator DWORD 21 ;Making a variable for denominator
volume DWORD ? ;Making a variable to store volume main
decimal DWORD ? ;Making a variable to store volume remainder
prompt BYTE "Enter the radius: ",0 ;val for radius prompt
promp2 BYTE "Enter the height: ",0 ;val for height prompt
result BYTE "The volume of the cone is: ", 0 ;val for printing volume
decim BYTE ".", 0 ;val for decimal place
;volume of cone is 1/3(pi(r^2)h) or 22/21(r^2)h
.code
main PROC
mov edx,OFFSET promp2 ;move prompt into edx for printing
call WriteString ;ask user for height
mov eax,0
mov edx,0
mov ecx,0
mov ebx,0 ;move zero into all main registers
call ReadDec ;reading the height
mov bl,al ;move height into storage
mov edx,OFFSET prompt ;move promp2 into edx for printing
mov eax,0 ;re-zero eax
call WriteString ;ask user for radius
call ReadDec
mul al ;obtain r^2
mul bl ;multiply r^2 by height
mov edx,0 ;zero out edx
mov dx,numerator ;move numerator into dx
mul dx ;multiply r^2*h by 22
mov ebx,denominator ;move 21 into ebx to divide
div ebx ;divide by 21 to get total volume
mov volume,eax ;move volume into volume variable
mov decimal,edx ;move decimal remainder into decimal variable
mov edx,OFFSET result ;prepare string result for printing
call WriteString ;print result string
mov eax,volume ;move volume into eax to print
call WriteDec ;print volume
mov edx,OFFSET decim ;move dec into print register
call WriteString ;print decimal
mov eax,decimal ;move decimal remainder into eax to print
call WriteDec ;print decimal value
call CRLF ;carriage return and new line
call WaitMsg ;pause output
exit
main ENDP
Maybe I could do different registers for the intermediate arithmetic, but I have no idea how to accomplish that given the current 8-8-16-16-32 requirements. If anyone could help me with a working solution and explain why it works, maybe step through it so I can understand why mine doesn't work for larger integers (most over 20 don't work) that would be amazing. Thank you ahead of time for any help you can give me!
Let's walk through the whole calculation:
mul al ;obtain r^2
This mul al
leaves a result in the AX
register. So you must use a word multiply in the next line or else you loose a part of the value of r^2.
mov bh, 0
mul bx ;multiply r^2 by height
Now the result is in DX:AX
. To multiply it by 22 you can move it to the 32 bit register EAX
by means of the stack.
push dx
push ax
pop eax
movzx edx, numerator ;Why is this defined a word?
mul edx
This time the result is in EDX:EAX
, ready for the final division.
div denominator
Finally move quotient in EAX
and remainder in EDX
to their respective variables.
mov volume, eax ;move volume into volume variable
mov decimal, edx