首页
社区
课程
招聘
一段将长10进制数转化为2进制数的代码
发表于: 2006-6-22 14:07 6492

一段将长10进制数转化为2进制数的代码

2006-6-22 14:07
6492

昨天跟个程序,跟了半天都没什么发现,结果迷迷糊糊跟进这个CALL里面来了。头都晕了才发现是在作数制转换。输入的是个很长的十进制字符串,大概有7,80位,然后返回对应2进制字符串。

废话的代码就不贴了,从这里开始处理:
004CF8B7     |.  >call dumped.00404A60                   ;  取得字符串长度
004CF8BC     |.  >mov ecx,9
004CF8C1     |.  >cdq
004CF8C2     |.  >idiv ecx                               ;  字符串长度/9,因为目前计算机字长一般32位,0xFFFFFFFF对10位的十进制数可能会溢出  
004CF8C4     |.  >mov dword ptr ss:[ebp-8],eax           ;  可以分割eax个9位长的10进制子字符串
004CF8C7     |.  >mov eax,dword ptr ss:[ebp-4]
004CF8CA     |.  >call dumped.00404A60                   ;  取得字符串长度
004CF8CF     |.  >mov ecx,9
004CF8D4     |.  >cdq
004CF8D5     |.  >idiv ecx
004CF8D7     |.  >test edx,edx                           ;比较余数,余数为几就还剩下一个几位的字符串
004CF8D9     |.  >je short dumped.004CF8DE
004CF8DB     |.  >inc dword ptr ss:[ebp-8]               ;有余数,子字符串个数+1
004CF8DE     |>  >mov eax,dword ptr ss:[ebp-8]
004CF8E1     |.  >inc eax
004CF8E2     |.  >push eax
004CF8E3     |.  >lea eax,dword ptr ds:[ebx+4]
004CF8E6     |.  >mov ecx,1
004CF8EB     |.  >mov edx,dword ptr ds:[4CF018]          ;  dumped.004CF01C
004CF8F1     |.  >call dumped.00405D74
004CF8F6     |.  >add esp,4
004CF8F9     |.  >mov eax,dword ptr ss:[ebp-8]
004CF8FC     |.  >cdq
004CF8FD     |.  >mov ecx,dword ptr ds:[ebx+4]
004CF900     |.  >mov dword ptr ds:[ecx],eax
004CF902     |.  >mov dword ptr ds:[ecx+4],edx
004CF905     |.  >mov esi,dword ptr ss:[ebp-8]
004CF908     |.  >dec esi
004CF909     |.  >test esi,esi
004CF90B     |.  >jle short dumped.004CF963
004CF90D     |.  >mov edi,1
004CF912     |>  >/lea eax,dword ptr ss:[ebp-24]         ;  这个循环开始把十进制字符串分成子字符串数组
004CF915     |.  >|push eax
004CF916     |.  >|mov eax,dword ptr ss:[ebp-4]
004CF919     |.  >|call dumped.00404A60                  ;  取得十进制字符长度
004CF91E     |.  >|mov edx,eax
004CF920     |.  >|sub edx,8
004CF923     |.  >|mov ecx,9
004CF928     |.  >|mov eax,dword ptr ss:[ebp-4]
004CF92B     |.  >|call dumped.00404CB8                  ;  得到字符串末尾9个字符
004CF930     |.  >|mov eax,dword ptr ss:[ebp-24]         ;  字符串末尾9个字符
004CF933     |.  >|call dumped.004090C4                  ;  eax返回9位字符表示的DEC数的HEX值
004CF938     |.  >|cdq                                   ;  edx=0
004CF939     |.  >|push edx
004CF93A     |.  >|push eax
004CF93B     |.  >|mov eax,dword ptr ds:[ebx+4]          ;  存储数据的基地址
004CF93E     |.  >|pop dword ptr ds:[eax+edi*8]          ;  a
004CF941     |.  >|pop dword ptr ds:[eax+edi*8+4]        ;  0
004CF945     |.  >|mov eax,dword ptr ss:[ebp-4]
004CF948     |.  >|call dumped.00404A60
004CF94D     |.  >|mov edx,eax                           ;  字符长度
004CF94F     |.  >|sub edx,8
004CF952     |.  >|lea eax,dword ptr ss:[ebp-4]          ;  字符地址
004CF955     |.  >|mov ecx,9
004CF95A     |.  >|call dumped.00404CF8                  ;  eax字符串砍去末尾9个字符
004CF95F     |.  >|inc edi
004CF960     |.  >|dec esi
004CF961     |.^ >\jnz short dumped.004CF912
004CF963     |>  >mov eax,dword ptr ss:[ebp-4]           ;  最后一个子字符
004CF966     |.  >call dumped.004090C4                   ;  转化为HEX
004CF96B     |.  >cdq
004CF96C     |.  >mov ecx,dword ptr ds:[ebx+4]
004CF96F     |.  >mov esi,dword ptr ss:[ebp-8]
004CF972     |.  >mov dword ptr ds:[ecx+esi*8],eax
004CF975     |.  >mov dword ptr ds:[ecx+esi*8+4],edx
004CF979     |.  >lea eax,dword ptr ss:[ebp-14]
004CF97C     |.  >call dumped.004047A8
004CF981     |.  >jmp short dumped.004CF9AD              
上面是准备工作,对10进制字符串进行分割.分割是从字符串末位开始的,每9个字符分割1次,剩余的不足9个字符的为一个子字符串具体点,如果是个"1234567
89987654321000"会被分成"654321000""456789987""123"三个子字符串,并转化为相应的HEX值,即是"27002568","1B3A0FE3","0000007B"
004CF983     |>  >/push 0                                ; /Arg2 = 00000000
004CF985     |.  >|push 2                                ; |Arg1 = 00000002
004CF987     |.  >|lea edx,dword ptr ss:[ebp-10]         ; |
004CF98A     |.  >|mov eax,ebx                           ; |
004CF98C     |.  >|call dumped.004CF6CC                  ; \对整个10进制数除以2!
004CF991     |.  >|push dword ptr ss:[ebp-C]             ; /Arg2 = 00000000
004CF994     |.  >|push dword ptr ss:[ebp-10]            ; |余数
004CF997     |.  >|lea eax,dword ptr ss:[ebp-28]         ; |
004CF99A     |.  >|call dumped.00409054                  ; \dumped.00409054
004CF99F     |.  >|mov edx,dword ptr ss:[ebp-28]
004CF9A2     |.  >|lea eax,dword ptr ss:[ebp-14]         ;  这里是保留最后结果2进制字符串的地址
004CF9A5     |.  >|mov ecx,dword ptr ss:[ebp-14]         ;  
004CF9A8     |.  >|call dumped.00404AAC                  ;  余数增加到2进制串的最前面(因为是要倒序排列)
004CF9AD     |>  > mov eax,dword ptr ds:[ebx+4]          ;  数据存储基地址
004CF9B0     |.  >|cmp dword ptr ds:[eax+4],0
004CF9B4     |.^ >|jnz short dumped.004CF983
004CF9B6     |.  >|cmp dword ptr ds:[eax],1              ;  比较子字符串数组是否只剩最后一个字符串?
004CF9B9     |.^ >|jnz short dumped.004CF983
004CF9BB     |.  >|mov eax,dword ptr ds:[ebx+4]          ;  数组地址
004CF9BE     |.  >|cmp dword ptr ds:[eax+C],0
004CF9C2     |.^ >|jnz short dumped.004CF983
004CF9C4     |.  >|cmp dword ptr ds:[eax+8],0            ;  比较是否除尽
004CF9C8     |.^ >\jnz short dumped.004CF983
004CF9CA     |.  >lea eax,dword ptr ss:[ebp-14]          ;  压入函数的DEC字符串的2进制
都知道,10进制转换2进制只需要不断除以2,一直除到0,将每次除法的余数倒序排列就可以了,这里也是这么做的.不同的是,这里将很长的字符串分成一些子字符
串,这样计算机才能计算.要注意的是,123-456789987-654321000和0000007B-1B3A0FE3-27002568的值是不等的,跟进除以2的这个CALL:
004CF6CC     /$  >push ebp
004CF6CD     |.  >mov ebp,esp
004CF6CF     |.  >add esp,-10
004CF6D2     |.  >push ebx
004CF6D3     |.  >push esi
004CF6D4     |.  >push edi
004CF6D5     |.  >mov esi,edx
004CF6D7     |.  >mov dword ptr ss:[ebp-4],eax
004CF6DA     |.  >mov eax,dword ptr ss:[ebp-4]
004CF6DD     |.  >mov eax,dword ptr ds:[eax+4]
004CF6E0     |.  >mov edi,dword ptr ds:[eax]             ;  子字符串数组基地址
004CF6E2     |.  >mov dword ptr ds:[esi],0               ;  [esi]和[esi+4]是2个循环变量,初始化为0
004CF6E8     |.  >mov dword ptr ds:[esi+4],0
004CF6EF     |.  >mov ebx,edi                            ;  字符串数组长度
004CF6F1     |.  >cmp ebx,1                              ;  是否小于1,小于1就直接出CALL
004CF6F4     |.  >jl short dumped.004CF76C
为方便表述,把子数值串记为N1,N2,N3...Nm.原来的长十进制数=Dec(Nm)|Dec(Nm-1)...|Dec(N1),这里Dec()表示转化为10进制,"|",表示连接字符串的作用
下面开始做除法,取子数值串的顺序为Nm,Nm-1...N2,N1,既是从最高位除起.
004CF6F6     |>  >/push 0
004CF6F8     |.  >|push 3B9ACA00                         ;  0x3B9ACA00=1000000000(DEC),9个"0"
004CF6FD     |.  >|mov eax,dword ptr ds:[esi]
004CF6FF     |.  >|mov edx,dword ptr ds:[esi+4]
004CF702     |.  >|call dumped.0040579C                  ;  [esi]和[esi+4]*=3B9ACA00,因为前面分子字符串是按9位分的,所以Nm中的1=Nm-1中的1*1000000000
004CF707     |.  >|mov dword ptr ds:[esi],eax            ;  [esi]=(Nm+1 mod 2)*1000000000(DEC)
004CF709     |.  >|mov dword ptr ds:[esi+4],edx          ;  [esi+4]指示[esi]和上一次数据相加是否产生进位
004CF70C     |.  >|mov eax,dword ptr ds:[esi]
004CF70E     |.  >|mov edx,dword ptr ds:[esi+4]
004CF711     |.  >|push edx
004CF712     |.  >|push eax
004CF713     |.  >|mov eax,dword ptr ss:[ebp-4]
004CF716     |.  >|mov eax,dword ptr ds:[eax+4]          ;  数组基地址
004CF719     |.  >|mov edx,dword ptr ds:[eax+ebx*8+4]
004CF71D     |.  >|mov eax,dword ptr ds:[eax+ebx*8]      ;  从数组末开始取一个数,最高位的子数值串先作除法
004CF720     |.  >|add eax,dword ptr ss:[esp]            ;  Nm+=[esi],即加上上一次除法的余数
004CF723     |.  >|adc edx,dword ptr ss:[esp+4]          ;  这里看出[esi+4]的作用,即表示Nm+(Nm+1 mod 2)是否>0xFFFFFFFF,产生进位
004CF727     |.  >|add esp,8                             ;  [esi].[esi+4]出栈,恢复指针
004CF72A     |.  >|mov dword ptr ss:[ebp-10],eax
004CF72D     |.  >|mov dword ptr ss:[ebp-C],edx
004CF730     |.  >|push dword ptr ss:[ebp+C]             ;  0
004CF733     |.  >|push dword ptr ss:[ebp+8]             ;  2
004CF736     |.  >|mov eax,dword ptr ss:[ebp-10]         ;  临时变量保存数组数据
004CF739     |.  >|mov edx,dword ptr ss:[ebp-C]          ;  [esi+4]
004CF73C     |.  >|call dumped.004057C0                  ;  eax是Nm/2的商,如果[esi+4]!=0,还要计算上[esi+4]
004CF741     |.  >|mov ecx,dword ptr ss:[ebp-4]
004CF744     |.  >|mov ecx,dword ptr ds:[ecx+4]          ;  子字符串数组基地址
004CF747     |.  >|mov dword ptr ds:[ecx+ebx*8],eax      ;  更新数据,即以Nm/2的商覆盖Nm
004CF74A     |.  >|mov dword ptr ds:[ecx+ebx*8+4],edx
004CF74E     |.  >|push dword ptr ss:[ebp+C]             ;  0
004CF751     |.  >|push dword ptr ss:[ebp+8]             ;  2
004CF754     |.  >|mov eax,dword ptr ss:[ebp-10]         ;  覆盖前的Nm
004CF757     |.  >|mov edx,dword ptr ss:[ebp-C]
004CF75A     |.  >|call dumped.00405888
004CF75F     |.  >|mov dword ptr ds:[esi],eax            ;  覆盖前的Nm mod 2
004CF761     |.  >|mov dword ptr ds:[esi+4],edx          ;  0
004CF764     |.  >|dec ebx
004CF765     |.  >|test ebx,ebx
004CF767     |.^ >\jnz short dumped.004CF6F6
004CF769     |.  >jmp short dumped.004CF76C
004CF76B     |>  >/dec edi
004CF76C     |>  > mov eax,dword ptr ss:[ebp-4]
004CF76F     |.  >|mov eax,dword ptr ds:[eax+4]          ;  数组首地址
004CF772     |.  >|cmp dword ptr ds:[eax+edi*8+4],0
004CF777     |.  >|jnz short dumped.004CF784
004CF779     |.  >|cmp dword ptr ds:[eax+edi*8],0
004CF77D     |.  >|jnz short dumped.004CF784
004CF77F     |.  >|cmp edi,1
004CF782     |.^ >\jg short dumped.004CF76B
004CF784     |>  >mov eax,edi
004CF786     |.  >cdq
004CF787     |.  >mov ecx,dword ptr ss:[ebp-4]
004CF78A     |.  >mov ecx,dword ptr ds:[ecx+4]
004CF78D     |.  >cmp edx,dword ptr ds:[ecx+4]
004CF790     |.  >jnz short dumped.004CF794
004CF792     |.  >cmp eax,dword ptr ds:[ecx]
004CF794     |>  >je short dumped.004CF7C1
004CF796     |.  >lea eax,dword ptr ds:[edi+1]
004CF799     |.  >push eax
004CF79A     |.  >mov eax,dword ptr ss:[ebp-4]
004CF79D     |.  >add eax,4
004CF7A0     |.  >mov ecx,1
004CF7A5     |.  >mov edx,dword ptr ds:[4CF018]          ;  dumped.004CF01C
004CF7AB     |.  >call dumped.00405D74
004CF7B0     |.  >add esp,4
004CF7B3     |.  >mov eax,edi
004CF7B5     |.  >cdq
004CF7B6     |.  >mov ecx,dword ptr ss:[ebp-4]
004CF7B9     |.  >mov ecx,dword ptr ds:[ecx+4]
004CF7BC     |.  >mov dword ptr ds:[ecx],eax
004CF7BE     |.  >mov dword ptr ds:[ecx+4],edx
004CF7C1     |>  >pop edi
004CF7C2     |.  >pop esi
004CF7C3     |.  >pop ebx
004CF7C4     |.  >mov esp,ebp
004CF7C6     |.  >pop ebp
004CF7C7     \.  >retn 8
上面可能说的不清楚,以前面的具体数来说,123-456789987-654321000被转为0000007B-1B3A0FE3-27002568.这里即是N3=0000007B,N2=1B3A0FE3,N1=27002568
先是N3=N3/2=3D,余数=1,继续N2=(N2+1*3B9ACA00)/2=2B6A6CF1,余=1,N3=(N3+1*3B9ACA00)/2=314D77B4,余数=0.看看结果,0x3D=61,0x2B6A6CF1=728394993,
0x314D77B4=827160500,连在一起就是61728394993827160500=123456789987654321000/2.
前面这个[esi+4]变量的作用是,在Nm+3B9ACA00时候可能会>0xFFFFFFFF.产生进位,那么在Nm+余数*3B9ACA00/2的时候要把进位考虑在内,这
是在004CF73C     |.  >|call dumped.004057C0里面处理的,这里就不说了.

所以这个CALL是对整个长十进制数/2,并把余数返回到外面,然后外面对余数倒序排列就OK。

哎,其他什么都没跟出来,懊恼,看能不能来骗篇精华,找点安慰。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//