Morgan - Numerical Methods (523161), страница 44
Текст из файла (страница 44)
Used for binary-to-decimal conversions;multiplicand is a pointer to a double.multen368proc uses bx cx dx di si, multiplicand:wordmovmovmovsubdi,word ptr multiplicanddx,word ptr [di]cx,word ptr [di][2]ax,axshlrcldx,1cx, 1;multiply by twoFPMATH.ASMrclax, 1movmovmovword ptr [di],dxword ptr [di][2],cxword ptr [di][4],ax;save resultshlrclrcldx,lcx, 1ax,1;multiply by fourshlrclrcldx,lcx, 1ax,1;now make it eightaddadcadcdx,word ptr [di]cx,word ptr [di][2]ax,word ptr [di][4];add back the two to make tenmovmovretword ptr [di],dx;go homeword ptr [di][2],cxmultenendp; ******;div64;will divide a quadword operand by adivisor using linear interpolation.;dividend occupies upper three words of a 6-word array;divisor occupies lower three words of a 6-word array;used by floating-point division onlydiv64proc uses es ds,dvdnd:qword, dvsr:qword, qtnt:wordlocalresult:tbyte, tmp0:qword,tmp1:qword, opa:qword, opb:qwordpushfcldsubleamovax, axdi, word ptr resultcx, 4369NUMERICAL METHODSreprepstoswleamovstoswdi, word ptr tmp0;quotientcx, 4setup:movcontinue_setup:lealeasubbx, word ptr dvsr[3]movdivmovmovdivmovsubmovdivmovax, word ptr [si][3]bxword ptr [di][4], axax, word ptr [si][l]bxword ptr [di][2], axax, axah, byte ptr [si]bxword ptr [di][0], axchk_estimate:invoke;divisor no higher than;receives stuff for quotient;result goes into quotient;result goes into quotient;result goes into quotientmu164a, tmp0, dvsr, addr resultleamovcmpjledi, word ptr tmp0ax, word ptr result[7]ax, word ptr dvdnd[3]div_exitsubsubsbbsbbmovax, axword ptr [di], 1word ptr [di][2],axword ptr [di][4],axword ptr [di][6],axdiv_exit:movmovincincmov370si, word ptr dvdnddi, word ptr tmpodx, dxsi, didi, word ptr qtntdidicx, 4;don't need a remainder for;this divideFPMATH.ASMmovswpopfretdiv64 endprep; ******;*Mu164a -Multiplies two unsigned 5-byte integers.
The;* procedure allows for a product of twice the length of the multipliers,;* thus preventing overflows.mu164a proc uses ax dx,multiplicand:qword, multiplier:qword, result:wordmovsubdi,word ptr resultcx, cxmovmulmovax, word ptr multiplicand[4]word ptr multiplier[4]word ptr [dil[8], ax;multiply multiplicand MSW;by multiplier high wordmovmulmovaddax, wordword ptrword ptrword ptr;multiply multiplicand MSW;by second MSW;of multipliermovax, word ptr multiplicand[4]mulmovaddadcwordwordwordwordmovmuladdadcax, word ptr multiplicand[2]word ptr multiplier[4]word ptr [di][6], axword ptr [di][8], dxmovmuladdadcax, word ptr multiplicand[2] ;multiply second MSW of;multiplicand by second MSWword ptr multiplier[2];of multiplierword ptr [di][4], axword ptr [di][6], dx;ptr multiplicand[4]multiplier[2][di][6], ax[di][8], dxptr multiplier[0]ptr [di][4], axptr [di][6], dxptr [di][8], cx;multiply multiplicand high;word;by third MSW;of multiplier;propagate carry;;multiply second MSW;of multiplicand by MSW;of multiplier371NUMERICAL METHODSadcword ptr [di][8], cx;add any remnant carrymovmulmovaddadcadcax, word ptr multiplicand[2]word ptr multiplier[0]word ptr [di][2], axword ptr [di][4], dxword ptr [di][6], cxword ptr [di][8], cx;multiply second MSW;of multiplicand by LSW;of multipliermovmuladdadcadcax, word ptr multiplicand[0]word ptr multiplier[4]word ptr [di][4], axword ptr [di][6], dxword ptr [di][8], cx;multiply multiplicand LSW;by MSW of multipliermovmuladdadcadcadcax, word ptr multiplicand[0]word ptr multiplier[2]word ptr [di][2], axword ptr [di][4], dxword ptr [di][6], cxword ptr [di][8], cx;multiply multiplicand LSW;by second MSW;of multipliermovmulmovaddadcadcadcax, word ptr multiplicand[0]word ptr multiplier[0]word ptr [di][0], axword ptr [di][2], dxword ptr [di][4], cxword ptr [di][6], cxword ptr [di][8], cx;multiply multiplicand LSW;by multiplier low wordretmul64a endp372;add any remnant carry;add any remnant carry;add any remnant carry;add any remnant carry;add any remnant carry;add any remnant carry;add any remnant carryPrevious Home NextAPPENDIX EIO.ASM.dosseg.model small, c, os_dosinclude math.inc.data;infbytezrobytehundrediten wordpowers equmaxchar"infinite", 0"O.O",Obyte0ahoneequ64h8.code; ******;dectohex;pointer to a packed BCD is used to convert to binary;dectohex proc uses ax bx cx si di, dntgr:wordlocaldouble:dwordxormovmovsi,word ptr dntgrcx,4ax,axcnvt_int:movaamal,byte ptr [si];expand to unpacked form373NUMERICAL METHODSpushxchgsubaddaxah,alah,ahbx,axcallnear ptr mtenpopsubaddaxah,ahbx,axcallnear ptr mtenloopretcnvt_int;get high nibble;multiply by ten;multiply by tenmten:shlrclmovmovshlrclshlrcladdadcretndectohex; ******bx,1dx,1word ptr double,bxword ptr double[2],dxbx,ldx,lbx,ldx,lbx,word ptr doubledx,word ptr double[2]endp;converts single-precision floating point to an ASCII string; caller is responsible for array bounds of ASCII string; callable from Cftoasc proc uses si di, fp:dword, rptr:word374localflp:qwordcldxorax,axIO.ASMdi,word ptr flpcx,4repleamovstoswsi,word ptr fpdi,word ptr flp[2]cx,2replealeamovmovswinvokefta, flp, rptrretftoasc endp; ***; conversion of floating point to ASCII;ftaproc uses bx cx dx si di, fp:qword, sptr:wordlocalsinptr:byte, fixptr:qword, exponent:byte,leading_zeros:byte, ndg:bytepushfstdrepxorleamOVstoswmovmovmOVmovax,axdi,wordptr fixptr[6]cx,4byte ptr [sinptr],albyteptr [leading_zeros],albyte ptr [ndg],albyte ptr [exponent],al;clear the signtestjexornotword ptr fp[4],8000hgtr_0word ptr fp[4],8000hbyte ptr [sinptr]:get the signck_neg:;make positive;it is negative375NUMERICAL METHODS;***gtr_0:invokecmpjedeccmpjlinvokejmpless_than_teninvokecmpjeincflcomp, fp, oneax,1hless_than_tenbyte ptr [ndg]byte ptr [ndg],-37zero_resultflmul, fp, ten, addr fpshort gtr_0cmp53invokejmpflcomp, fp, tenax, -1norm_fixbyte ptr [ndg]byte ptr [ndg],37infinite_resultfldiv, fp, ten, addr fpshort less_than_teninvokeround, fp, addr fp;another kind of normalizationRnd:norm_fix:movmovmovshlax,word ptr fp[0]bx,word ptr fp[2]dx,word ptr fp[4]dx,lget_exp:movsubbyte ptr exponent, dhbyte ptr exponent, 7fhmovsubjsleado_shift:376cx,8hcl,byte ptr exponentinfinite_result;fixup for translation;this is for ASCII conversion;dump the sign bit;remove bias;could come out zero;but this is as far asdi,word ptr fixptr;can goIIO.ASMstcrcrsubjeshift_fraction:shrrcrrcrloopdl,1bx,1ax, 1shift_fractionput-upper:movmovmovmovxchgword ptr [di], axword ptr [di][2],bxal,dlbyte ptr fixptr[4],dlah,alsubmovcldincmovcmpjnemovput_sign:stosbleawrite_integer:xchgaamxchgorcallxchgorcall;restore hidden bitdl,1cx,1put_upper;shift significand into;fractional part;write integer portiondx,dxdi,word ptr sptr;reverse direction of writedxal,' 'byte ptr sinptr,0ffhput_signal,'-';is it a minus?si, byte ptr fixptr[3]ah,al;al contains integer;portional,ahal,'0'near ptr str_wrtal,ahal,'0'near ptr str_wrt377NUMERICAL METHODSincdecdo_decimal:movstosbdo_decimal1:invokeorcallincdxsi;max char countal,'.'cmpjejmpmulten, addr fixptral,'O'nearptr str_wrtdxdx,maxchardo_emshort do_decimal1subcmpjnejmpax,axal,byte ptr ndgwrite_exponentshort last_byte;convert binary fraction;to decimal fractiondo_exp:write_exponent:movstosbmovorjnsxchgmovstosbnegxchgsubfinish_exponent:cbwaamxchgorstosbxchg378al,'e'al,byte ptr ndgal,alfinish_exponental,ahal,'-'ahal,ahah,ah;cheap conversionah,alal,'O'ah,alIO.ASMorstosblast_byte:substosbpopffta_ex:retinfinite_result:movmovmovmovsbrepmovjmpzero_result:movmovmovmovsbrepmovjmpstrwrt:cmpjnetestjeputt:testjnenotpmt:stosbnope:retnftaendp;al,'O'al,aldi,word ptr sptrsi,offset infcx, 9ax, -1short fta_exdi,word ptr sptrsi,offset zrocx, 9ax,-1short fta_exal,'O'puttbyte ptr leading_zeros,-1nopebyte ptr leading_zeros,-1pmtleading_zeros379NUMERICAL METHODS;;******;Unsigned conversion from floating-point notation to integer (long).;This is in fixed-point format; the upper two words are the integer;and the lower two are the fraction.;ftofx proc uses si di, fp:dword, fixptr:wordlocalflp:qwordax,axdi,word ptr flpcx,4repcldxorleamovstoswsi,word ptr fpdi,word ptr flp[2]cx,2replealeamovmovswinvokeftfx, flp, fixptrretftofx endp;unsigned conversion from ascii string to short realproc uses si di, string:word, rptr:wordatf;one word for near pointerlocal exponent:byte, fp:qword, numsin:byte, expsin:byte,dp_flag:byte, digits:byte, dp:bytepushfstdxorlea380ax,axdi,word ptr fp[6];clear the floating;variableIO.ASMrepmovstoswcx,8word ptr [di]movsi,stringdo_numbers:movmovmovmovmovmovbytebytebytebytebytebyteptrptrptrptrptrptr[exponent],aldp_flag,alnumsin,alexpsin,aldp,aldigits,8h;count of total digits;;rounding digit is eight;;begin by checking for a sign or a number or a '.'do_num:movcmpjnenotincmovjmpbl, [si]bl,'-'not_minus[numsin]sibl,es:[si]not_signnot_minus:cmpjneincmovbl,'+'not_signsial, [si]not_sign:cmpjnetestjnenotincmovbl,'.'not_dotbyte ptr [dp],80hend_o_cnvtdp_flagsibl,[si];it is a negative number;check for decimal point381NUMERICAL METHODSnot_dot:cmpjbcmpjainvokemovsubsubshlshlshlinvoketestjedecno_dot_yet:incdecjcmovjmpnot_a_num:movorcmpbx,1bx,1fladd, fp, dgt[bx], addr fpbyte ptr [dp_flag],0ffhjmpend_o_cnvtjne;multiply floating point;accumulator by l0.0;clear upper byte;multiply index for proper;offset;have we encountered a;decimal point yet?sibyte ptr digitsnot_a_numbl,es:[si]not-signjecmp;get legitimate numberno_dot_yet[dp]bl, [si]bl,lower_casebl,'e'chk_expchk_exp:incmov382bl,'O'not_a_numbl,'9'not_a_numflmul, fp, ten, addr fpbl, [si]bl,30hbh,bhbx,lsibl, [si]bl,'-'chk_plus;check for decimal point;looks like we may have an;exponentIO.ASMnotjmpchk_plus:cmpjnechk_exp1:incmovchk_exp2:cmpjbcmpjasubmovmulmovmovsuborjmpend_o_cnvt:submovmovorjnssubjmppos_exp:add[expsin]short chk_explbl,'+'short chk_exp2sibl, [si]bl,'0'end_o_cnvtbl,'9'end_o_cnvtax,axal, byte ptr [exponent]itenbyte ptr [exponent],albl, [si]bl,30hbyte ptr [exponent],blshort chk_exp1cx,cxal,byte ptr [expsin]cl,byte ptr [dp]al,alpos_expcl,byte ptr [exponent]short chk_numsincl,byte ptr [exponent];exponentchk_numsin:cmpjneorchk_expsin:xororword ptr numsin,0ffhchk_expsinword ptr fp[4],8000h;if exponent negative,;so is numberax,axcl,cl383NUMERICAL METHODSjnsnegdo_negpow:orjeinctestjemovpushshlshlshlinvokepopdo_negpowa:shrjmpdo_pospow:orjeinctestjemovpushshlshlinvokepopdo_pospowa:shrjmpatf_ex:invokemovmov384do_pospowclcl,clatf_exaxcx,1hdo_negpowabx,axaxbx,1bx,1bx,1fldiv, fp, powers[bx], addr fpax;make exponent positive;is exponent zero yet?;check for one in lsb;divide by power of twocx,1short do_negpowcl,clatf_exaxcx,lhdo_pospowabx,axaxbx,1bx,1flmul, fp, powers[bx], addr fpaxcx,1shortdo_pospowround, fp, addr fpdi,word ptr rptrax,word ptr fp;is exponent zero yet?;check for one in lsb;multiply by power of twoIO.ASMatfmovmovmovmovpopfretendpbx,word ptr fp[2]dx,word ptr fp[4]word ptr [di],bxword ptr [di][2],dx; ******;Unsigned conversion from quadword fixed-point to short real.;The intention is to accommodate long and int conversions as well.;Binary is passed on the stack and rptr is a pointer;to the result.ftfproc uses si di, binary:qword, rptr:word;one word for near;pointerlocal exponent:byte, numsin:bytepushfxorax, ax;movaddleamov;do_numbers:mOVmovmov;do_num:movor;record signjnsnotnotdi, worddi,si,bx,ptr rptr6byte ptr binary[0]7;point at future float;point to quadword;indexbyte ptr [exponent], albyte ptr numsin, aldx, axal, byte ptr [si][bx]al, alfind_topbyte ptr numsinword ptr binary[6];this one is negative385NUMERICAL METHODSnotnotnegjcaddadcadcfind_top:cmpjemovorjnedecjmpword ptrword ptrword ptrfind_topword ptrword ptrword ptrbinary[4]binary[2]binary[0]binary[2], 1binary[4], 0binary[6], 0bl, dlmake_zeroal, byte ptr [si][bx]al,alfound_itbxshort find_top;we traversed the entire;number;move indexfound_it:movcmpcmpjedl, 80hbl, 4shift_rightfinal_right;test for MSBshift_leftstdmovsubshlshlshlnegmovcx, 4cx, bxcx, 1cx, 1cx, 1cxbyte ptr [exponent], cl;points to MSB;targetlealeaaddmovinc386di,si,si,cx,cxbyte ptr binary[4]byte ptr binarybxbx;times 8IO.ASMreprepmovsbmovsubsubstosbjmpshift_right:cldmovsubleamovsubcx, 4cx, bxax, axshort final_rightcx,cx,si,di,di,bx4byte ptr binary[4]sicxshlshlshlcl, 1cl, 1cl, 1movbyte ptr [exponent], clmovsubincmovsbsubmovsubsubleastosbcx, bxcx, 4cx;points to MSB;target;times 8reprepfinal_right:leafinal_right1:movtestjnedecbx,cx,cx,ax,di,44bxaxword ptr binarysi, byte ptr binary[4]al, byte ptr [si]al, dlalignedbyte ptr exponent387NUMERICAL METHODSshlrclrcljmpaligned:shlword ptr binary[0], 1word ptr binary[2], 1word ptr binary[4], 1short final_right1al, 1;clearbitmovaddcmpjestcjmppositive:clcget-ready_to_go:rcrah, 86hah, byte ptr exponentnumsin,dhpositiveshort get_ready_to_goax, 1movword ptr binary[4], axinvokeround, binary, rptr;put it all back the way it;should beftf_ex:exit:popfretmake_zero:stdsubmovstoswrepftf;; ***388jmpendpax, axcx, 4short exit;zero it all outIO.ASM;Conversion of floating point to fixed point;float enters as quadword;pointer, sptr, points to result;This could use an external routine as well.