subj процедура dwtoa из библиотеки MASM32 (без нового SP, сейчас не знаю) by Tim Roberts/Alexander Yackubtchik слетает на некоторых числах. Пример: -1501748189 (0A67D2423h).
Она не слетает, просто неверный результат выдаёт. По причине отсутствия обработки знака. Пользуйся atol
какого знака? она переваривает числа меньше 0 (со знаком), там в начале проверка стоит. Я на скорую руку написал такую: Код (Text): pecreg10 proc chislo:DWORD, mem:DWORD pushad mov edi, [mem] mov eax, [chislo] mov PW [edi], "0" test eax,eax jz @@kon jns @@pos mov PW [edi],'-' neg eax inc edi @@pos: xor ecx, ecx mov ebx, 10 @@1: inc ecx xor edx, edx div ebx push edx CP eax, 0, NZ, @@1 @@2: pop eax add eax, "0" mov [edi], al inc edi dnz ecx, @@2 dec edi @@kon: inc edi mov [pecreg_kon], edi mov PB [edi], 0 stc popad ret pecreg10 endp
Как она его переваривает? Код (Text): num_string db '-1501748189',0 ;твоя строка invoke atodw, addr num_string PrintDec eax ;[b]eax = 1766010845[/b] PrintHex eax ;[b]eax = 69432FDD[/b] А говоришь знак переваривает Может она его в прямом смысле слова переваривает?
Вот на медленную руку: Код (Text): r_divisor dd -858993459 cr_dwtostr proc dwDword:DWORD, lpOutString:DWORD option prologue : none option epilogue : none push esi push edi mov edi,[esp+16] ;lpOutString mov esi,[esp+12] ;dwDword cmp esi,0 jg _loop jz _zero neg esi mov byte ptr[edi],2Dh inc edi inc dword ptr[esp+16] ;lpOutString align 16 _loop: mov eax,esi mul r_divisor shr edx,3 mov ecx,edx lea ecx,[ecx*4+ecx] add ecx,ecx neg ecx add ecx,esi mov byte ptr[edi],30h or [edi],cl mov esi,edx test edx,edx lea edi,[edi+1] jnz _loop @@: mov byte ptr[edi],0 mov esi,[esp+16] align 16 @@: dec edi mov al,[esi] mov dl,[edi] mov [edi],al mov [esi],dl inc esi cmp esi,edi jl @B pop edi pop esi retn 8 _zero: mov word ptr[edi],30h pop edi pop esi retn 8 option prologue : prologuedef option epilogue : epiloguedef cr_dwtostr endp
У меня нормально сконвертировало. Уже тучу лет назад этот баг был выловлен, исправленая версия послана куда только можно. Стив просто тупит каждый раз и не меняет версию. Вот тестовая программа Вот код нормальной atodw (от кода Тима там только ножки да рожки честно говоря) (PS для новых процов начало лучше бы другое) Код (Text): ;##################################################################### #### ; ----------------------------------------- ; This procedure was written by Tim Roberts and Svin ; ----------------------------------------- .386 .model flat, stdcall ; 32 bit memory model option casemap :none ; case sensitive .code ; ###################################################################### ### OPTION PROLOGUE:NONE OPTION EPILOGUE:NONE atodw proc FORCENOFRAME ;uses edi esi String:PTR BYTE ;---------------------------------------- ; Convert decimal string into dword value ; return value in eax ;---------------------------------------- ;String equ [esp+4] push esi mov esi,[esp+8] sub ecx,ecx cmp byte ptr [esi],2Eh ;"-"+1 sbb edx,edx mov eax,ecx adc esi,ecx jmp @F again: lea eax,[eax+4*eax] inc esi lea eax,[ecx+2*eax] @@: mov cl,[esi] sub cl,30h jns again add eax,edx pop esi xor eax,edx retn 4 atodw endp ; ###################################################################### ### end 2138736227__testdwta.rar
The Svin Вы привели код atodw, а аттач хоть и называется dwtoa но вызывает atodw. Ошибочна процедура dwtoa (печати числа). Это которая Код (Text): dwtoa proc dwValue:DWORD, lpBuffer:DWORD ; ------------------------------------------------------------- push ebx push esi push edi mov eax, dwValue mov edi, [lpBuffer] or eax,eax jnz sign zero: mov word ptr [edi],30h jmp dw2asc sign: jns pos mov byte ptr [edi],'-' neg eax inc edi pos: mov ecx,429496730 mov esi, edi .while (eax > 0) mov ebx,eax mul ecx mov eax,edx lea edx,[edx*4+edx] add edx,edx sub ebx,edx add bl,'0' mov [edi],bl inc edi .endw mov byte ptr [edi], 0 ; terminate the string ; We now have all the digits, but in reverse order. .while (esi < edi) dec edi mov al, [esi] mov ah, [edi] mov [edi], al mov [esi], ah inc esi .endw dw2asc: pop edi pop esi pop ebx ret dwtoa endp
yureckor Кстати, о птицах: попробовал dwtoa из masmlib - работает, ничего не вылетает, возвращает строку нормально. Может в чём другом проблема?
yureckor Про это тоже известно, опять же проблемы со Стивом по замене на правильную написанную тучу лет назад: Код (Text): OPTION PROLOGUE:NONE OPTION EPILOGUE:NONE dwtoa proc arg1, arg2 dwValue equ [esp+16] lpBuffer equ [esp+20] push esi push edi push ebx mov eax, dwValue mov edi,lpBuffer test eax,eax ;it'll set both sf and zf jnz sign zero: mov word ptr [edi],30h pop ebx pop edi pop esi retn 8 sign: jns pos ;sf already set by or eax,eax we don't need cmp it again mov byte ptr [edi],'-' neg eax inc edi pos: mov ecx,429496730 mov byte ptr [edi][10],0 lea esi, [edi][9] cmp eax,10 jl less10 @@: mov ebx,eax mul ecx mov eax,edx ;edx == reminder of division eax by 10 lea edx,[edx+edx*4] add edx,edx .IF edx > ebx ;check for exeption array sub edx,10 ;correct result dec eax .ENDIF sub ebx,edx add bl,30h mov [esi],bl dec esi cmp eax,9 ;don't do last iteration if it's already figure ja @B less10: or al,30h ;just convert it to simbol mov edx,[esi+8] ;shift to the beginning of the buffer mov [esi],al mov ecx,[esi+4] mov eax,[esi] mov [edi][4],ecx mov [edi],eax mov [edi][8],edx pop ebx pop edi pop esi retn 8 dwtoa endp ; ###################################################################### ### end
yureckor equ человек-макрос dnz ecx, @@2 это видимо dec ecx jnz @@2 CP eax, 0, NZ, @@1 похоже на cmp eax,0 jnz @@1
dnz - это от Спековской привычки CP - чтоб короче было Код (Text): ;- dnz MACRO QAX,M dec QAX jnz M ENDM ;- CP MACRO QAX,QBX,J1,M IF ((@SizeStr(<QBX>) GT 1) AND (@InStr(1,<QBX>,<0>) EQ 1)) OR (@InStr(1,<QBX>,<FALSE>) EQ 1) OR (@InStr(1,<QBX>,<NULL>) EQ 1) IF $x_reg(QAX) AND ( (@InStr(1,<QBX>,<Z>) EQ 1)OR(@InStr(1,<QBX>,<z>) EQ 1)OR(@InStr(1,<QBX>,<NZ>) EQ 1)OR(@InStr(1,<QBX>,<nz>) EQ 1) ) test QAX, QAX J&J1 M ELSE cmp QAX,QBX J&J1 M ENDIF ELSE cmp QAX,QBX J&J1 M ENDIF ENDM ;- $x_reg MACRO x:REQ IF (OPATTR (x)) AND 00010000y EXITM <-1> ;TRUE ELSE EXITM <0> ;FALSE ENDIF ENDM