鱼C论坛

 找回密码
 立即注册
查看: 1712|回复: 0

[技术交流] [算法实战002]高精度正负浮点数四则运算

[复制链接]
发表于 2019-2-24 09:31:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
几年之前,论坛正搞笔记征集活动,才写了几篇,这个区就突然没了 ,就没怎么上论坛了
今天偶然看到汇编区回来了 ,发个帖子,
账号可能被注销了 ,emmm只能新搞一个了

                               
登录/注册后可看大图


                               
登录/注册后可看大图

  1. ;高精度正负浮点数四则运算 Algo
  2. ;Code By 老刘
  3. ;编译环境:MASM32 SDK
  4. ;编译指令:ml /coff 高精度正负浮点数四则运算.ASM /link /subsystem:console
  5. ;调用方法:
  6. ;        传参,参数1为数1对数2进行的运算(+、-、*、/),
  7. ;        参数2、3为分别为数1,数2参数。
  8. ;合规数字:1 01 1.0 00.100 -01.1234        (不和规数字:.1 3.)
  9. ;其他:
  10. ;        两个数字的最大长度为124位(包含负号、小数点、0)。
  11. ;        受MASM32 SDK中老旧的ArgClC函数限制,两个数字的总长度和应不超过188。
  12. ;        应尽量避免多余0的出现(如0100中开头的0、0.0010中最后的0),会削减除法运算的精度。
  13. ;参考:MHL批处理标准教程之高精度系列代码。


  14. Include masm32rt.inc
  15. Main Proto        ;主函数
  16. _Addition Proto        ;加(减)法函数
  17. _ArraySubtraction Proto        lpMinuend:dword,lpSubtrahend:dword,bArrayLength:byte        ;数组减法函数
  18. _ArrayCompare Proto lpArray1:dword,lpArray2:dword,bArrayLength:byte        ;数组(表示的数字的)大小比较函数
  19. _Multiplication Proto        ;乘法函数
  20. _Division Proto        ;除法函数

  21. .Data?
  22.         szNum1 DB 128 Dup (?)
  23.         szNum2 DB 128 Dup (?)
  24.         bNum1Symbol DB ?
  25.         bNum2Symbol DB ?
  26.         bNum1Length DB ?
  27.         bNum2Length DB ?
  28.         bNum1IntegralPartLength DB ?
  29.         bNum1DecimalPartLength DB ?
  30.         bNum2IntegralPartLength DB ?
  31.         bNum2DecimalPartLength DB ?
  32.         bNum1LengthPlusNum2Length DB ?
  33.         bNum1IntegralPartLengthPlusNum2IntegralPartLength DB ?
  34.         bNum1DecimalPartLengthPlusNum2DecimalPartLength DB ?
  35.         bNum1LengthPlusNum2DecimalPartLength DB ?
  36.         bNum2LengthPlusNum1DecimalPartLength DB ?
  37.         lpNum1IntegralPart DD ?
  38.         lpNum1DecimalPart DD ?
  39.         lpNum2IntegralPart DD ?
  40.         lpNum2DecimalPart DD ?
  41. ;End Data?

  42. .Code
  43.         Main Proc
  44.                 Local @szOperation:word        ;运算符+null的长度
  45.                
  46.                 ;获得参数并赋值变量
  47.                 Invoke ArgClC,1,Addr @szOperation
  48.                 Invoke ArgClC,2,Addr szNum1
  49.                 Invoke ArgClC,3,Addr szNum2
  50.                
  51.                 Lea Eax,szNum2
  52.                 Mov lpNum2IntegralPart,Eax        ;初步确定指针
  53.                 Lea Esi,szNum1
  54.                 Mov lpNum1IntegralPart,Esi
  55.                
  56.                 ;正负号判断(0正1负)
  57.                 LodSB        ;Esi=lpNum1IntegralPart
  58.                 .If Al == '-'
  59.                         Mov bNum1Symbol,1
  60.                         Inc lpNum1IntegralPart        ;指针修正,使其指向数字
  61.                 .Else
  62.                         Mov bNum1Symbol,0
  63.                 .EndIf
  64.                 Mov Ax,@szOperation
  65.                 Mov Ah,Al
  66.                 Mov Esi,lpNum2IntegralPart
  67.                 LodSB
  68.                 .If Ah == '-'        ;负负得正的处理
  69.                         .If Al == '-'
  70.                                 Mov bNum2Symbol,0
  71.                                 Inc lpNum2IntegralPart
  72.                         .Else
  73.                                 Mov bNum2Symbol,1
  74.                         .EndIf
  75.                 .Else
  76.                         .If Al == '-'
  77.                                 Mov bNum2Symbol,1
  78.                                 Inc lpNum2IntegralPart
  79.                         .Else
  80.                                 Mov bNum2Symbol,0
  81.                         .EndIf
  82.                 .EndIf
  83.                
  84.                 ;获得两数的小数、整数部分长度;
  85.                 ;获得两数的小数部分的内存地址;
  86.                 ;去掉小数点;将数字从Ascii转为Byte。
  87.                 Mov bNum1IntegralPartLength,0
  88.                 Mov bNum1DecimalPartLength,0
  89.                 Mov bNum2IntegralPartLength,0
  90.                 Mov bNum2DecimalPartLength,0
  91.                 Mov Esi,lpNum1IntegralPart
  92.                 Mov Edi,Esi        ;同时操作一个字符串
  93.                 Lea Ebx,bNum1IntegralPartLength
  94.                 Lea Ecx,bNum1DecimalPartLength
  95.                 Xor Edx,Edx        ;作为循环flag
  96.                 @@:
  97.                 LodSB
  98.                 .While Al != '.' && Al != NULL
  99.                         Inc Byte Ptr [Ebx]
  100.                         Sub Al,30H        ;将数字从Ascii转为Byte
  101.                         StoSB        ;重新写回去
  102.                         LodSB
  103.                 .EndW
  104.                 Push Esi
  105.                 .If Al != NULL
  106.                         LodSB
  107.                         .While Al != NULL
  108.                                 Inc Byte Ptr [Ecx]
  109.                                 Sub Al,30H
  110.                                 StoSB
  111.                                 LodSB
  112.                         .EndW
  113.                 .EndIf
  114.                 .If Edx == 0
  115.                         Pop lpNum1DecimalPart
  116.                         Mov Esi,lpNum2IntegralPart
  117.                         Mov Edi,Esi
  118.                         Lea Ebx,bNum2IntegralPartLength
  119.                         Lea Ecx,bNum2DecimalPartLength
  120.                         Inc Edx
  121.                         Jmp @B
  122.                 .EndIf
  123.                 Pop lpNum2DecimalPart
  124.                 Dec lpNum1DecimalPart        ;去掉了小数点后的指针修正
  125.                 Dec lpNum2DecimalPart
  126.                
  127.                 ;计算各种长度。
  128.                 Mov Al,bNum1IntegralPartLength
  129.                 Add Al,bNum1DecimalPartLength
  130.                 Mov bNum1Length,Al
  131.                 Add Al,bNum2DecimalPartLength
  132.                 Mov bNum1LengthPlusNum2DecimalPartLength,Al
  133.                 Add Al,bNum2IntegralPartLength
  134.                 Mov bNum1LengthPlusNum2Length,Al
  135.                 Sub Al,bNum1IntegralPartLength
  136.                 Mov bNum2LengthPlusNum1DecimalPartLength,Al
  137.                 Sub Al,bNum1DecimalPartLength
  138.                 Mov bNum2Length,Al
  139.                 Sub Al,bNum2DecimalPartLength
  140.                 Add Al,bNum1IntegralPartLength
  141.                 Mov bNum1IntegralPartLengthPlusNum2IntegralPartLength,Al
  142.                 Sub Al,bNum1LengthPlusNum2Length
  143.                 Mov Al,bNum1LengthPlusNum2Length
  144.                 Sub Al,bNum1IntegralPartLengthPlusNum2IntegralPartLength
  145.                 Mov bNum1DecimalPartLengthPlusNum2DecimalPartLength,Al
  146.                
  147.                 ;调用相应的计算函数。
  148.                 Mov Ax,@szOperation
  149.                 .If Al == '+' || Al == '-'
  150.                         Call _Addition
  151.                 .ElseIf Al == '*'
  152.                         Call _Multiplication
  153.                 .ElseIf Al == '/'
  154.                         Call _Division
  155.                 .EndIf
  156.                
  157.                 Ret
  158.         Main EndP
  159.        
  160.         _Addition Proc
  161.                 Local @bNum1Array[256]:byte,@bNum2Array[256]:byte        ;其中之一同时作为结果数组
  162.                 Local @bDestSymbol:byte,@lpDestArray
  163.                 Local @bDestEqualZeroSign:byte,@bDestDecimalPartEqualZeroSign:byte
  164.                 Local @bDestDecimalPartLength:byte,@szDest[128]:byte
  165.                 Mov Al,bNum1DecimalPartLengthPlusNum2DecimalPartLength        ;初步确定结果小数部分长度
  166.                 Mov @bDestDecimalPartLength,Al
  167.                
  168.                 ;数组清0。
  169.                 Xor Eax,Eax
  170.                 Mov Ecx,SizeOf @bNum1Array
  171.                 Lea Edi,@bNum1Array
  172.                 Rep StoSB
  173.                 Mov Ecx,SizeOf @bNum2Array
  174.                 Lea Edi,@bNum2Array
  175.                 Rep StoSB
  176.                
  177.                 ;数1存入数组。
  178.                 Mov Esi,lpNum1IntegralPart
  179.                 Lea Edi,@bNum1Array
  180.                 Movzx Eax,bNum1LengthPlusNum2DecimalPartLength
  181.                 Add Edi,Eax
  182.                 Dec Edi ;数组从0开始
  183.                 Movzx Ecx,bNum1Length
  184.                 .Repeat
  185.                         MovSB
  186.                         Dec Edi        ;倒序装入数组
  187.                         Dec Edi
  188.                 .UntilCxZ
  189.                
  190.                 ;数2存入数组。
  191.                 Mov Esi,lpNum2IntegralPart
  192.                 Lea Edi,@bNum2Array
  193.                 Movzx Eax,bNum2LengthPlusNum1DecimalPartLength
  194.                 Add Edi,Eax
  195.                 Dec Edi
  196.                 Movzx Ecx,bNum2Length
  197.                 .Repeat
  198.                         MovSB
  199.                         Dec Edi
  200.                         Dec Edi
  201.                 .UntilCxZ
  202.                
  203.                 ;判断同异号并计算结果。
  204.                 Mov @bDestEqualZeroSign,0FFH
  205.                 Mov Al,bNum1Symbol
  206.                 Xor Al,bNum2Symbol
  207.                 .If Al == 0        ;同号
  208.                         ;获取结果符号。
  209.                         Mov Al,bNum1Symbol
  210.                         Mov @bDestSymbol,Al
  211.                        
  212.                         ;计算结果。
  213.                         Xor Eax,Eax        ;Ah进位清0
  214.                         Lea Esi,@bNum2Array
  215.                         Lea Edi,@bNum1Array        ;作为结果数组
  216.                         Mov @lpDestArray,Edi
  217.                         Movzx Ecx,bNum1LengthPlusNum2Length        ;计数器
  218.                         Mov Bl,10        ;十进制
  219.                         .Repeat
  220.                                 LodSB
  221.                                 Add Al,[Edi]
  222.                                 Add Al,Ah
  223.                                 Cbw
  224.                                 Div Bl
  225.                                 Xchg Al,Ah
  226.                                 StoSB
  227.                         .UntilCxZ
  228.                 .Else        ;异号
  229.                         ;比较两数大小并获取结果符号。
  230.                         Invoke _ArrayCompare,Addr @bNum1Array,Addr @bNum2Array,bNum1LengthPlusNum2Length
  231.                         .If Eax == 1        ;(绝对值)数1>数2
  232.                                 Mov Al,bNum1Symbol
  233.                                 Mov @bDestSymbol,Al
  234.                                 Lea Edi,@bNum1Array        ;作为结果数组
  235.                                 Mov @lpDestArray,Edi
  236.                                 Invoke _ArraySubtraction,Edi,Addr @bNum2Array,bNum1LengthPlusNum2Length
  237.                         .ElseIf Eax == 2
  238.                                 Mov Al,bNum2Symbol
  239.                                 Mov @bDestSymbol,Al
  240.                                 Lea Edi,@bNum2Array
  241.                                 Mov @lpDestArray,Edi
  242.                                 Invoke _ArraySubtraction,Edi,Addr @bNum1Array,bNum1LengthPlusNum2Length
  243.                         .Else        ;两数相等
  244.                                 Inc @bDestEqualZeroSign        ;=0
  245.                         .EndIf
  246.                 .EndIf
  247.                
  248.                 ;验证加法结果是否为0。
  249.                 ;(其实就是应对0+0或-0-0这样的情况)
  250.                 Mov Al,@bDestEqualZeroSign
  251.                 .If Al == 0FFH
  252.                         Mov Esi,@lpDestArray
  253.                         Movzx Ecx,bNum1LengthPlusNum2Length
  254.                         .Repeat
  255.                                 LodSB
  256.                         .UntilCxZ Al != 0
  257.                         .If Al == 0        ;全部跑完,且值为0
  258.                                 Inc @bDestEqualZeroSign
  259.                         .EndIf
  260.                 .EndIf
  261.                
  262.                 ;结果转为字符串。
  263.                 Mov Al,@bDestEqualZeroSign
  264.                 .If Al == 0FFH        ;值为FF在此表示值不为0
  265.                         Mov Al,@bDestDecimalPartLength
  266.                         .If Al != 0        ;两整数相加时小数部分肯定为0
  267.                                 ;修正结果小数部分长度。
  268.                                 Mov Esi,@lpDestArray
  269.                                 Movzx Ecx,@bDestDecimalPartLength
  270.                                 .Repeat
  271.                                         LodSB
  272.                                 .UntilCxZ Al != 0
  273.                                 .If Al != 0        ;小数部分不为0
  274.                                         Inc Cl        ;长度从1开始
  275.                                         Mov @bDestDecimalPartLength,Cl
  276.                                 .Else
  277.                                         Mov @bDestDecimalPartLength,Al        ;=0
  278.                                 .EndIf
  279.                         .EndIf
  280.                        
  281.                         ;结果字符串写入。
  282.                         Lea Edi,@szDest
  283.                         ;结果符号判断&写入。
  284.                         Mov Al,@bDestSymbol
  285.                         .If Al == 1        ;结果为负
  286.                                 Mov Al,'-'
  287.                                 StoSB
  288.                         .EndIf
  289.                         ;结果的整数部分转为字符串。
  290.                         Movzx Esi,bNum1LengthPlusNum2Length
  291.                         Add Esi,@lpDestArray
  292.                         Dec Esi
  293.                         Movzx Ecx,bNum1IntegralPartLengthPlusNum2IntegralPartLength
  294.                         .Repeat        ;去除先导0
  295.                                 LodSB
  296.                                 Dec Esi
  297.                                 Dec Esi
  298.                         .UntilCxZ Al !=0
  299.                         Add Al,30H        ;Byte转Ascii
  300.                         StoSB        ;整数部分的最高位或0写入
  301.                         .While Ecx != 0        ;剩余整数部分写入
  302.                                 LodSB
  303.                                 Dec Esi
  304.                                 Dec Esi
  305.                                 Add Al,30H
  306.                                 StoSB
  307.                                 Dec Ecx
  308.                         .EndW
  309.                         ;结果小数点及小数部分转为字符串。
  310.                         Movzx Ecx,@bDestDecimalPartLength        ;计数器
  311.                         .If Cl != 0
  312.                                 Mov Al,'.'
  313.                                 StoSB        ;小数点写入
  314.                                 .Repeat
  315.                                         LodSB
  316.                                         Dec Esi
  317.                                         Dec Esi
  318.                                         Add Al,30H
  319.                                         StoSB
  320.                                 .UntilCxZ
  321.                         .EndIf
  322.                         Mov DWord Ptr [Edi],000A0DH        ;字符串结尾
  323.                 .Else
  324.                         ;结果字符串写入
  325.                         Lea Edi,@szDest
  326.                         Mov DWord Ptr [Edi],000A0D30H        ;"0\r\n"+null
  327.                 .EndIf
  328.                
  329.                 ;输出结果。
  330.                 Invoke StdOut,Addr @szDest
  331.                
  332.                 Xor Eax,Eax
  333.                 Ret
  334.         _Addition EndP
  335.        
  336.         _ArraySubtraction Proc Uses Eax Ebx Ecx Esi Edi lpMinuend:dword,lpSubtrahend:dword,bArrayLength:byte
  337.                 ;参数:被减数数组指针、减数数组指针、两个数组的共同长度。
  338.                 ;要求:被减数大于减数。
  339.                
  340.                 Mov Edi,lpMinuend
  341.                 Mov Esi,lpSubtrahend
  342.                 Movzx Ecx,bArrayLength
  343.                 Xor Ebx,Ebx        ;Bl借位清0
  344.                 .Repeat
  345.                         Mov Al,[Edi]
  346.                         Sub Al,Bl
  347.                         Sub Al,[Esi]
  348.                         .If Sign?        ;结果为负
  349.                                 Add Al,10
  350.                                 Mov Bl,1
  351.                         .Else
  352.                                 Xor Ebx,Ebx
  353.                         .EndIf
  354.                         StoSB
  355.                         Inc Esi
  356.                 .UntilCxZ
  357.                
  358.                 Ret
  359.         _ArraySubtraction EndP
  360.        
  361.         _ArrayCompare Proc Uses Edi Esi Ecx lpArray1:dword,lpArray2:dword,bArrayLength:byte
  362.                 ;参数:数组1、数组2、两个数组的共同长度。
  363.                 ;返回值(存于Eax中):0-两数(组)相等;1-数1大于数2;2-数2大于数1。
  364.                
  365.                 Mov Edi,lpArray1
  366.                 Mov Esi,lpArray2
  367.                 Movzx Ecx,bArrayLength        ;计数器
  368.                 Add Esi,Ecx
  369.                 Dec Esi        ;指向数组最后一个元素
  370.                 Add Edi,Ecx
  371.                 Dec Edi
  372.                
  373.                 .Repeat
  374.                         Xchg Esi,Edi
  375.                         LodSB        ;数1
  376.                         Dec Esi
  377.                         Dec Esi
  378.                         Mov Ah,Al
  379.                         Xchg Esi,Edi
  380.                         LodSB        ;数2
  381.                         Dec Esi
  382.                         Dec Esi
  383.                         .If Ah > Al        ;(绝对值)数1>数2
  384.                                 Mov Eax,1
  385.                                 Ret
  386.                         .ElseIf Ah < Al
  387.                                 Mov Eax,2
  388.                                 Ret
  389.                         .EndIf
  390.                 .UntilCxZ
  391.                 Xor Eax,Eax        ;能运行到这里,说明两数相等。
  392.                
  393.                 Ret
  394.         _ArrayCompare EndP
  395.        
  396.         _Multiplication Proc
  397.                 Local @bDestArray[256]:byte,@bDestDecimalPartLength:byte,@szDest[256]:byte
  398.                 Local @bDestEqualZeroSign:byte,@bDestSymbol:byte
  399.                
  400.                 ;结果数组清0。
  401.                 Xor Eax,Eax
  402.                 Mov Ecx,SizeOf @bDestArray
  403.                 Lea Edi,@bDestArray
  404.                 Rep StoSB
  405.                
  406.                 ;数1、数2从低到高按位相乘并放入结果数组。
  407.                 Lea Edi,@bDestArray
  408.                 Mov Ebx,lpNum1IntegralPart
  409.                 Movzx Edx,bNum1Length
  410.                 Add Ebx,Edx
  411.                 Dec Ebx        ;指针修正
  412.                 Xchg Dh,Dl        ;Dh做计数器
  413.                 ;使用数1的每一位乘数2的全部位。
  414.                 .While Dh != 0
  415.                         Mov Dl,[Ebx]        ;Dl做因数
  416.                         Push Edi
  417.                        
  418.                         ;数2初始化。
  419.                         Mov Esi,lpNum2IntegralPart
  420.                         Movzx Ecx,bNum2Length        ;Ecx做计数器
  421.                         Add Esi,Ecx
  422.                         Dec Esi
  423.                         .Repeat
  424.                                 LodSB
  425.                                 Dec Esi        ;逆读取指针修正;数2换高一位
  426.                                 Dec Esi
  427.                                 Mul Dl
  428.                                 Add [Edi],Al
  429.                                 Inc Edi
  430.                         .UntilCxZ
  431.                        
  432.                         ;进位处理,避免溢出。
  433.                         Movzx Ecx,bNum2Length        ;要处理进位的长度=数2的长度
  434.                         Mov Edi,[Esp]        ;使Edi指向需进位处理的首个数字
  435.                         Mov Dl,10
  436.                         .Repeat
  437.                                 Movzx Ax,Byte Ptr [Edi]
  438.                                 Div Dl
  439.                                 Mov [Edi],Ah
  440.                                 Add [Edi+1],Al
  441.                                 Inc Edi
  442.                         .UntilCxZ
  443.                        
  444.                         ;根据乘法法则,数1换高一位,结果也换高一位。
  445.                         Pop Edi
  446.                         Dec Ebx
  447.                         Inc Edi
  448.                        
  449.                         Dec Dh
  450.                 .EndW
  451.                
  452.                 ;判断结果是否为0;
  453.                 ;获得结果符号。
  454.                 Movzx Ecx,bNum1DecimalPartLength
  455.                 Add Cl,bNum2DecimalPartLength
  456.                 Mov @bDestEqualZeroSign,0
  457.                 Lea Esi,@bDestArray
  458.                 .If Cl > 0
  459.                         .Repeat
  460.                                 LodSB
  461.                         .UntilCxZ Al != 0
  462.                         .If Al != 0        ;小数部分非0
  463.                                 ;小数部分非0说明乘积不为0,获得结果符号。
  464.                                 Mov Al,bNum1Symbol
  465.                                 Xor Al,bNum2Symbol
  466.                                 Mov @bDestSymbol,Al
  467.                                
  468.                                 Inc Ecx
  469.                                 Mov @bDestDecimalPartLength,Cl
  470.                         .Else
  471.                                 Mov @bDestDecimalPartLength,0
  472.                                 ;判断整数部分是否为0。
  473.                                 Movzx Ecx,bNum1IntegralPartLength
  474.                                 Add Cl,bNum2IntegralPartLength
  475.                                 .Repeat
  476.                                         LodSB
  477.                                 .UntilCxZ Al != 0
  478.                                 .If Al == 0        ;乘积为0,不管正负,使结果为正(避免输出-0)
  479.                                         Mov @bDestSymbol,0
  480.                                         Inc @bDestEqualZeroSign        ;=1
  481.                                 .EndIf
  482.                         .EndIf
  483.                 .Else        ;结果不存在小数部分
  484.                         Mov @bDestDecimalPartLength,0
  485.                 .EndIf
  486.                
  487.                 ;生成结果字符串。
  488.                 Lea Esi,@bDestArray
  489.                 Movzx Ecx,bNum1Length
  490.                 Add Cl,bNum2Length
  491.                 Add Esi,Ecx        ;使得Esi指向数组末尾
  492.                 Lea Edi,@szDest
  493.                 .If @bDestEqualZeroSign == 1
  494.                         Mov DWord Ptr [Edi],000A0D30H        ;"0\r\n"+null
  495.                 .Else
  496.                         ;获得整数部分长度。
  497.                         Movzx Ecx,bNum1IntegralPartLength
  498.                         Add Cl,bNum2IntegralPartLength
  499.                        
  500.                         ;写入符号。
  501.                         .If @bDestSymbol == 1
  502.                                 Mov Al,'-'
  503.                                 StoSB
  504.                         .EndIf
  505.                        
  506.                         ;略过整数部分开头的0。
  507.                         .Repeat
  508.                                 Dec Esi
  509.                                 LodSB
  510.                                 Dec Esi
  511.                         .UntilCxZ Al != 0
  512.                         Inc Ecx
  513.                        
  514.                         ;写入整数部分。
  515.                         .Repeat
  516.                                 LodSB
  517.                                 Dec Esi
  518.                                 Dec Esi
  519.                                 Add Al,30H        ;Byte转Ascii
  520.                                 StoSB
  521.                         .UntilCxZ
  522.                        
  523.                         ;写入小数部分(如果有)。
  524.                         Movzx Ecx,@bDestDecimalPartLength
  525.                         .If Cl > 0
  526.                                 ;写入小数点。
  527.                                 Mov Al,'.'
  528.                                 StoSB
  529.                                 ;写入小数部分。
  530.                                 .Repeat
  531.                                         LodSB
  532.                                         Dec Esi
  533.                                         Dec Esi
  534.                                         Add Al,30H
  535.                                         StoSB
  536.                                 .UntilCxZ
  537.                         .EndIf
  538.                        
  539.                         ;字符串结尾。
  540.                         Mov DWord Ptr [Edi],000A0DH
  541.                 .EndIf
  542.                
  543.                 ;输出结果。
  544.                 Invoke StdOut,Addr @szDest
  545.                
  546.                 Xor Eax,Eax
  547.                 Ret
  548.         _Multiplication EndP
  549.        
  550.         _Division Proc
  551.                 Local @szDest[256]:byte,@bDividendArray[256]:byte,@bDivisorArray[128]:byte,@lpDest
  552.                 Local @bDestDecimalPointPos:byte,@bDivisorArrayLength:byte
  553.                 Local @bDestEqualZeroSign:byte,@bDestIntegralPartEqualZeroSign:byte,@bDecimalPointWriteInSign:byte
  554.                
  555.                 ;将除数的有效数字存入除数数组。
  556.                 Mov Esi,lpNum2IntegralPart
  557.                 Movzx Ecx,bNum2IntegralPartLength
  558.                 .Repeat        ;去除整数部分多余的0
  559.                         LodSB
  560.                 .UntilCxZ Al != 0
  561.                 .If Al != 0
  562.                         Inc Ecx
  563.                         Mov bNum2IntegralPartLength,Cl
  564.                         Dec Esi        ;指向有效数字
  565.                         Add Cl,bNum2DecimalPartLength
  566.                 .Else        ;整数部分均为0,继续去0直到遇到有效数字
  567.                         Mov bNum2IntegralPartLength,0
  568.                         Movzx Ecx,bNum2DecimalPartLength
  569.                         .If Ecx != 0        ;除数存在小数部分
  570.                                 .Repeat
  571.                                         LodSB
  572.                                 .UntilCxZ Al != 0
  573.                                 .If Al != 0
  574.                                         Inc Ecx
  575.                                         Dec Esi        ;指向有效数字
  576.                                 .Else        ;除数为0
  577.                                         Mov Eax,1
  578.                                         Ret
  579.                                 .EndIf
  580.                         .Else        ;不存在小数部分,除数为0
  581.                                 Mov Eax,1
  582.                                 Ret
  583.                         .EndIf
  584.                 .EndIf
  585.                 ;按位(倒序)存入除数数组。
  586.                 Mov @bDivisorArrayLength,Cl        ;有效数字到除数末尾的长度
  587.                 Lea Edi,@bDivisorArray
  588.                 Add Edi,Ecx
  589.                 Dec Edi        ;指向数组最后一个元素
  590.                 .Repeat
  591.                         LodSB
  592.                         StoSB
  593.                         Dec Edi
  594.                         Dec Edi
  595.                 .UntilCxZ
  596.                 ;为配合运算,将除数数组增加一个元素;
  597.                 ;不影响除数数组代表的除数的大小。
  598.                 Movzx Ecx,@bDivisorArrayLength
  599.                 Inc @bDivisorArrayLength
  600.                 Lea Eax,@bDivisorArray        ;此时Eax+Ecx指向新增的元素
  601.                 Mov Byte Ptr [Eax][Ecx],0        ;清0
  602.                
  603.                 ;计算结果小数点的位置。
  604.                 Mov Al,bNum1IntegralPartLength
  605.                 Add Al,bNum2DecimalPartLength
  606.                 Mov @bDestDecimalPointPos,Al
  607.                
  608.                 ;判断被除数是否为0;
  609.                 ;判断结果符号并写入。
  610.                 Mov Esi,lpNum1IntegralPart
  611.                 Movzx Ecx,bNum1Length
  612.                 .Repeat
  613.                         LodSB
  614.                 .UntilCxZ Al != 0
  615.                 .If Al == 0
  616.                         Mov @bDestEqualZeroSign,1
  617.                         Lea Eax,@szDest
  618.                         Mov DWord Ptr [Eax],000A0D30H        ;"0\r\n"+null
  619.                 .Else
  620.                         Mov @bDestEqualZeroSign,0
  621.                         Mov Al,bNum1Symbol
  622.                         Xor Al,bNum2Symbol
  623.                         .If Al == 0        ;结果为正
  624.                                 Lea Eax,@szDest
  625.                                 Mov @lpDest,Eax
  626.                         .Else        ;结果为负
  627.                                 Lea Eax,@szDest
  628.                                 Mov Byte Ptr [Eax],'-'
  629.                                 Inc Eax
  630.                                 Mov @lpDest,Eax
  631.                         .EndIf
  632.                 .EndIf
  633.                
  634.                 ;被除数数组清空。
  635.                 Xor Eax,Eax
  636.                 Mov Ecx,SizeOf @bDividendArray
  637.                 Lea Edi,@bDividendArray
  638.                 Rep StoSB
  639.                
  640.                 ;进行除法运算并生成最终字符串。
  641.                 .If @bDestEqualZeroSign != 1
  642.                         ;获得被除数数组起始元素地址;
  643.                         Lea Esi,@bDividendArray
  644.                         Mov Ebx,SizeOf @bDividendArray
  645.                         Dec Ebx        ;此时Esi+Ebx指向被除数数组末尾
  646.                         Sub Bl,@bDivisorArrayLength        ;作为计算终止的标识之一
  647.                         Add Esi,Ebx        ;此时Esi指向(当前的)被除数数组起始元素地址
  648.                         Mov Bh,bNum1Length
  649.                         Mov Ecx,lpNum1IntegralPart        ;作为被除数的读取指针
  650.                         Sub Bl,4        ;减小精度,为字符串中数字以外的其它字符保留空间
  651.                         Mov Edi,@lpDest        ;Edi作为字符串指针
  652.                         Mov Dh,@bDestDecimalPointPos        ;Dh作为小数点写入的标识
  653.                         Mov @bDestIntegralPartEqualZeroSign,0
  654.                        
  655.                         ;开始除法(减法模拟)运算。
  656.                         .While Bl > 0
  657.                                 Invoke _ArrayCompare,Esi,Addr @bDivisorArray,@bDivisorArrayLength
  658.                                 Dec Bl
  659.                                 .If Eax <= 1        ;被除数数组>=除数数组,做减法
  660.                                         Xor Dl,Dl        ;Dl作为商
  661.                                         .While Eax != 2
  662.                                                 Invoke _ArraySubtraction,Esi,Addr @bDivisorArray,@bDivisorArrayLength
  663.                                                 Invoke _ArrayCompare,Esi,Addr @bDivisorArray,@bDivisorArrayLength
  664.                                                 Inc Dl
  665.                                         .EndW
  666.                                         Mov Al,Dl
  667.                                         Add Al,30H
  668.                                         StoSB
  669.                                         Mov @bDestIntegralPartEqualZeroSign,1
  670.                                 .Else        ;被除数数组已经(被减到)小于除数数组
  671.                                         ;用被除数将被除数数组添加一位。
  672.                                         Dec Esi
  673.                                         .If Bh > 0        ;被除数未全部放入数组
  674.                                                 Mov Al,Byte Ptr [Ecx]
  675.                                                 Mov Byte Ptr [Esi],Al
  676.                                                 Inc Ecx
  677.                                                 Dec Bh
  678.                                         .EndIf
  679.                                         ;若被除数全部放入数组,则只需添0,由于数组已经清空,无需处理。
  680.                                        
  681.                                         ;判断是否需要向字符串中写入小数点。
  682.                                         .If Dh == 0 && @bDecimalPointWriteInSign == 0
  683.                                                 Mov @bDecimalPointWriteInSign,1
  684.                                                 .If @bDestIntegralPartEqualZeroSign == 0
  685.                                                         Mov @bDestIntegralPartEqualZeroSign,1
  686.                                                         Mov Al,'0'
  687.                                                         StoSB
  688.                                                 .EndIf
  689.                                                 Mov Al,'.'
  690.                                                 StoSB
  691.                                         .EndIf
  692.                                         Dec Dh
  693.                                        
  694.                                         ;判断是否处理完成;
  695.                                         ;写入0。
  696.                                         Invoke _ArrayCompare,Esi,Addr @bDivisorArray,@bDivisorArrayLength
  697.                                         .If Eax == 2
  698.                                                 .If Bh == 0 && @bDecimalPointWriteInSign == 1        ;被除数非零数全部放入数组且被除数整数部分除完
  699.                                                         Movzx Ecx,@bDivisorArrayLength        ;判断被除数数组是否除完(全空)
  700.                                                         .Repeat
  701.                                                                 Lea Eax,[Ecx-1]
  702.                                                                 Mov Al,Byte Ptr [Esi][Eax]
  703.                                                         .UntilCxZ Al != 0
  704.                                                         .If Al == 0
  705.                                                                 .If Dh == 0FFH        ;小数点刚写入,已经计算完成
  706.                                                                         Dec Edi        ;去掉小数点
  707.                                                                 .EndIf
  708.                                                                 .Break
  709.                                                         .EndIf
  710.                                                 .EndIf
  711.                                                 .If @bDestIntegralPartEqualZeroSign == 1
  712.                                                         Mov Al,'0'
  713.                                                         StoSB
  714.                                                 .EndIf
  715.                                         .EndIf
  716.                                 .EndIf
  717.                         .EndW
  718.                 .EndIf
  719.                 Mov DWord Ptr [Edi],00000A0DH        ;字符串结尾
  720.                
  721.                 ;输出结果。
  722.                 Invoke StdOut,Addr @szDest
  723.                
  724.                 Xor Eax,Eax
  725.                 Ret
  726.         _Division EndP
  727.        
  728.         Start:
  729.                 Call Main
  730.                 Invoke ExitProcess,Eax
  731.         End Start
  732. End
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-1 10:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表