Morgan - Numerical Methods (523161), страница 30
Текст из файла (страница 30)
Test CL to see whether its LSB has azero.If so, multiply the value of the loop counter by eight to point to theproper power of 10. Divide the floating-point accumulator by that powerof 10 and shift CL right once. Continue with the beginning of step 9.(These powers of 10 are located in a table labeled 10. For this schemeto work, these powers of 10 follow the binary order 1, 2, 4, 8, as shownin the table immediately preceding the code.)If not, shift CL right once for next power of two and continue at thebeginning of step 9.10. Test CL for zero.If it's zero, go to step 11.If not, increment a loop counter and test CL to see whether its LSB isa zero.If so, multiply the value of the loop counter by eight to point to theproperpower of 10.
Multiply the floating-point accumulator by that powerof 10, shift CL right once, and continue with the beginning of step 10.(These powers of 10 are located in a table labeled '10'. Again, for thisscheme to work, these powers of 10 must follow the binary order 1, 2,4, 8, as shown in the table immediately preceding the code.)If not, shift CL to the right once and continue with the beginning ofstep 10.11.
Round the new float, write it to the output, and leave.atf: Listing;*****dst.dataqwordonetenqwordqword000000000000h,408000000000h,410000000000h,3f8000000000h412000000000h,3f8000000000h, 400000000000h, 404000000000h,40a000000000h, 40c000000000h, 40e000000000h,411000000000h42c800000000h,195NUMERICAL METHODS461c40000000h,4cbebc200000h, 5a0elbc9bf00h, 749dc5ada82bh.code;unsigned conversion from ASCII string to short realproc uses si di, string:word, rptr:word ;one word for near pointeratflocal exponent:byte, fp:qword, numsin:byte, expsin:byte.dp_flag:byte, digits:byte, dp:bytereppushfstdxorleaax,axdi,word ptr fp[6]movstoswcx,8word ptr [di]movsi,stringdo_numbers:movmovmovmovmovmovbytebytebytebytebytebyteptrptrptrptrptrptr;clear the floating;variable;pointer to string[exponent],aldp_flag,alnumsin,alexpsin,aldp,aldigits,8h;initialize variables;count of total digits rounding;digit is eight;begin by checking for a;sign, a number, or a;period;do_num:movcmpjnenotincmovjmpnot_minus:cmp196bl, [si]bl,'-'not minus[numsin]sibl,es:[si]not sign;get next charbl,'+';is it plus?;it is a negative number;set negative flag;get next charINPUT, OUTPUT, AND CONVERSIONjneincmovnot_signsial, [si];get next charnot_sign:cmpjnetestjnenotincmovbl,'.'not_dotbyte ptr [dp],80hend_o_cnvtdp_flagsibl, [si];check for decimal pointnot_dot:cmpjbcmpjainvokemovsubsubshlbl,'0'not_a_numbl,'9'not_a_numflmul, fp, ten, addr fpbl, [si]bl,30hbh,bhbx,1;get legitimate numbershlshlinvoketestjedecno_dot_yet:incdecjcmovjmpnot_a_num:movorcmpje;negative?;end of conversion;set decimal point flag;get next char;multiply floating-point;accumulator by 10.0;make it hex;clear upper byte;multiply index for;proper offsetbx,1bx,1fladd, fp, dgt[bx], addr fp ;add to floating-point;accumulatorbyte ptr [dp_flag],0ffh;have we encountered a;decimal point yet?no_dot_yet;count fractional digits[dp]sibyte ptr digitsnot_a_numbl,es:[si]not_sign;increment pointer;one less digit;at our limit?;next charbl, [si]bl,lower_casebl,'e'chk_exp;next char;check for exponent;looks like we may have;an exponent197NUMERICAL METHODSjmpchk_exp:incmovcmpjnenotjmpchk_plus:cmpjnechk_expl:incmovchk_exp2:cmpjbcmpjasubmovmulend_o_cnvtsibl, [si]bl,'-'chk_plus[expsin]short chk_explbl,'+'short chk_exp2sibl, [si]bl,'0'end_o_cnvtbl,'9'end_o_cnvtax, axal, byte ptr [exponent]itenmovbyte ptr [exponent],almovsuborjmpbl, [si]bl,30hbyte ptr [exponent],blshort chk_explend_o_cnvt:submovmovorjnssubcx, cxal,byte ptr [expsin]cl,byte ptr [dp]al,alPos_expcl,byte ptr [exponent];set exponent sign;maybe a plus?;next char;do conversion of;exponent as in;integer conversion;by multiplication;next char;make hex;or into accumulator;calculate exponent;is exponent negative?; subtract exponent from;fractional countshort chk_numsinjmppas_exp:addcl,byte ptr [exponent]chk_numsin:cmpword ptr numsin,0ffh198;next char;negative exponent*exponent to fractional;count;test signINPUT, OUTPUT, AND CONVERSIONjneorchk_expsin:xororjnsnegdo_negpow:orjeinctestjemovpushshlshlshlinvokepopdo_negpowa:shrjmpdo_pospow:orjeinctestjemovpushshlshlshlinvokepopdo_pospowa:shrjmpatf_ex:invokechk_expsinword ptr fp[4],8000hax,axcl,cldo_pospowcl;if exponent negative,;so is number;make exponent positivecl,cl;is exponent zero yet?atf_exax;check for one in LSBcx,1hdo_negpowabx,axaxbx,1;make pointerbx,1bx,1fldiv, fp, powers[bx], addr fp;divide by power of 10axcx, 1short do_negpowcl,cl;is exponent zero yet?atf exaxcx,lh;check for one in LSBdo_pospowabx,axaxbx,lbx,lbx,l;make pointerflmul, fp, powers[bx], addr fp;multiply by power oftenaxcx,1short do_pospowround, fp, addr fp;round the new float199NUMERICAL METHODSatfmovmovmovmovmovmovpopfretendpdi,word ptr rptrax,word ptr fpbx,word ptr fp[2]dx,word ptr fp[4]word ptr [di],bxword ptr [di][2],dx;write it outSingle-Precision Float to ASCIIThis function is usually handled in C with fcvt() plus some ancillary routines thatformat the resulting string.
The function presented here goes a bit further; its purposeis to convert the float from binary to an ASCII string expressed in decimal scientificformat.Scientific notation requires its own form of normalization: a single leadinginteger digit between 1.0 and 10.0. The float is compared to 1.0 and 10.0 upon entryto the routine and successively multiplied by 10.0 or divided by 10.0 to bring it intothe proper range.
Each time it is multiplied or divided, the exponent is adjusted toreflect the correct value.When this normalization is complete, the float is disassembled and converted tofixed point. The sign, which was determined earlier in the algorithm, is positionedas the first character in the string and is either a hyphen or a space. Each byte of thefixed-point number is then converted to an ASCII character and placed in the string.After converting the significand, the routine writes the value of the exponent to thestring.In pseudocode, the procedure might look like this.fta: Algorithm1.Clear a variable, fixptr, large enough to hold the fixed-pointconversion.
Allocate and clear a sign flag, sinptr. Do the same for aflag to suppress leading zeros (leading zeros), a byte to hold theexponent, and a byte to count the number of multiplies or divides it takesto normalize the number, ndg.2.Test the sign bit of the input float. If it's negative, set sinptr andmake the float positive.200INPUT, OUTPUT, AND CONVERSION3.Compare the input float to 1.0.If it's greater, go to step 4.If it's less, multiply it by 10.0.
Decrement ndg and check for underflow.If underflow occurred, go to step 18.If not, return to the beginning of step 3.4. Compare the float resulting from step 3 to 10.0.If it's less, go to step 5.If it's greater, divide by 10.0. Increment ndg and check for overflow.If overflow occurred, go to step 17.If not, return to the beginning of step 4.5.Round the result.6.Extract the exponent, subtract the bias, and check for zero. If weunderflow here, we have an infinite result; go to step 17.7.Restore the hidden bit. Using the value resulting from step 6, align thesignificand and store it in the fixed-point field pointed to by fixptr.We should now have a fixed-point value with the radix point alignedcorrectly for scientific notation.8.Start the process of writing out the ASCII string by checking the signand printing hyphen if sinptr is -1 and a space otherwise.9.Convert the fixed-point value to ASCII with the help of AAM and call step19 to write out the integer.10.Write the radix point.11.
Write each decimal digit as it's converted from the binary fractionalportion of the fixed-point number until eight characters have beenprinted.12. Check ndg to see whether any multiplications or divisions were necessaryto force the number into scientific format.If ndg is zero, we're done; terminate the string and exit through step16.If ndg is not zero, continue with step 13.13. Print the "e."14. Examine the exponent for the appropriate sign. If it's negative, printhyphen and two's-complement ndg.201NUMERICAL METHODS15.
Convert the exponent to ASCII format, writing each digit to the output.16. Put a NULL at the end of the string and exit.17. Print "infinite" to the string and return with failure, AX = -1.18. Print "zero" to the string and return with failure, AX = -1.19. Test to see whether or not any zero is leading.If so, don't print-just return.If not, write it to the string.Fta: Listing; *****; conversion of floating point to ASCIIftaproc uses bx cx dx si di, fp:qword, sptr:wordlocalsinptr:byte, fixptr:qword, exponent:byte.leading_zeros:byte, ndg:bytepushfstdrepxorax,axleamovstoswmovmovmovmovdi,word ptr fixptr[6]cx,4testjexornotword ptr fp[4],8000hgtr_0word ptr fp[4],8000hbyte ptr [sinptr]invokeflcomp, fp, onebytebytebytebyte;clear fixed-point;variableptrptrptrptr[sinptr],al[leadin_zeros],al[ndg],al[exponent],al;clear the sign;and other variablesck_neg:;; ***gtr_0:202;get the sign;make float positive;set sign;negative;compare input with 1.0;still another kind ofINPUT, OUTPUT, AND CONVERSIONcmpjedeccmpax,1hless_than_tenbyte ptr [ndg]byte ptr [ndg],-37jlinvokejmpzero_resultflmul, fp, ten, addr fpshort gtr_0less_than_ten:invokecmpjeinccmp;normalization;argument reduction;decimal counter;range of single;precision float;multiply by 10.0;compare with 10.0flcomp, fp, tenax,-1norm fixbyte ptr [ndg]byte ptr [ndg],37;decimal counter;orange of single;precision floatjginvokejmpinfinite resultfldiv, fp, ten, addr fpshort less_than_ten;divide by 10.0invokeround, fp, addr fp;fixup for translationRnd:norm_fix:movmovmovshlget_exp:movsubmovsubjsleado_shift:stcrcrsubax,word ptr fp[0]bx,word ptr fp[2]dx,word ptr fp[4]dx, 1byte ptr exponent, dhbyte ptr exponent, 7fhcx,shcl,byte ptr exponentinfinite_resultdi,word ptr fixptr;this is for ASCII;conversion;dump the sign bit;remove bias;could come out zero;but this is as far as I;can go;restore hidden bitdl,1cx, 1203NUMERICAL METHODSjeshift_fraction:shrrcrrcrloopput_upper:movdl,1bx,1ax,1shift fraction;shift significand into;fractional partword ptr [di], ax;write to fixed-point;variablemovmovmovxchgword ptr [di][2],bxal,dlbyte ptr fixptr[4],dlah,alsubmovclddx,dxdi,word ptr sptrincmovcmpjnemovput_sign:stosbleawrite_integer:xchg;write integer portion;reverse direction of;writedxal,' 'byte ptr sinptr,0ffhput_signal,'-';is it a minus?si, byte ptr fixptr[3]ah,al;AL contains integer;portionaamxchgal,ahorcallxchgorcallincdecal,'0'near ptr str wrtal,ahal,'0'near ptr str_wrtdxsi;use AAM to convert to;decimal;then ASCII;then write to string;and repeatdo_decimal:204put_upper;max char countINPUT, OUTPUT, AND CONVERSIONmovstosbdo_decimall:invokeorcallinccmpal,'.';decimal pointmulten, addr fixptral,'0'near ptr str wrtdxdx,maxchar;convert binary fraction;to decimal fraction;write to stringjejwdo_expshort do_decimal1subcmpjnejmpax,axal,byte ptr ndgwrite exponentshort last_byte;have we written our;maximum?do_exp:write_exponent:movstosbmovorjnsxchgmostosbnegxchgsubf inish exponentcbwaamxchgorstosbxchgorstosblast_byte:sub;is there an exponent?al,'e';put the 'e'al,byte ptr ndgal,alfinish_exponental,ahval,'-';with ndg calculate;exponent*negative exponentahal,ahah,ah;sign extension;cheap conversionah,alal,'0'ah,alal,'0'al,al;make ASCII;write NULL to the end;of the stringstosbpopffta_ex:205NUMERICAL METHODSretinfinite_result:movmovmovmovsbmovjmprepzero_result:movmovmovmovsbrepmovjmpdi,word ptr sptr;actually writes;'infinite'si,offset infcx, 9ax,-1short fta_exdi,word ptr sptrsi,offset zrocx, 9;actually writes 'zero'ax,-1short fta_exstr_wrt:cmpjneal,'0'putttestbyte ptr leading_zeros,-1jenopetestjnenotbyte ptr leading_zeros,-1prntleading_zeros;subroutine for writing;characters to output;string;check whether leading;zero or not;don't want any leading;zerosputt:prnt:stosbnope:ftaretnendpFixed Point to Single-Precision Floating PointFor this conversion, assume a fixed-point format with a 32-bit integer and a 32-206INPUT, OUTPUT, AND CONVERSIONbit fraction.