Skocz do zawartości

Konwersja czasu pliku na czas systemowy


Trix

Recommended Posts

Witam
Moj problem polega na tym ze, gdy po odczycie daty ostatniego wpisu w pliku i jej konwersji na czas systemowy konwertuje ja na ciag znakow funkcja wsprintf to niestety wynikiem sa jakies liczby ktore z pewnoscia nie sa data ani czasem. Oto fragment kodu:

invoke FileTimeToSystemTime, ADDR FoundData.ftLastWriteTime, ADDR STime                    
                    .if eax == 0
                        invoke MessageBox, NULL, SADD("Blad przy konwersji daty"), SADD("Konwersja daty"), MB_OK
                    .endif
                    invoke wsprintf, ADDR fsBuf, ADDR templateData, STime.wHour, STime.wMinute, STime.wDay, STime.wMonth, STime.wYear

Ponizej zmienne wykorzystywane we fragmencie:

LOCAL FoundData:    WIN32_FIND_DATA
LOCAL STime:        SYSTEMTIME
LOCAL fsBuf[MAX_PATH]: BYTE             ; pomocniczy bufor
templateData db "%u:%u %u-%u-%u",0  ciag formatujacy

Wczesniej w programie struktura FoundData jest oczywiscie wypelniana przez funkcje FindNextFile. W czym moze byc problem?

Link do komentarza
Udostępnij na innych stronach

Witam
Zdaje sie, ze juz mniej wiecej wiem gdzie siedzi problem - prawdopodobnie jest nim funkcja wsprintf! Po deasemblacji programu zauwazylem ze na stos wrzucany jest tylko pierwszy parametr, a nastepne nie sa juz wrzucane parametry tylko zamiast nich sa instrukcje

push 0

. Nie wiem dokladnie co tam sie dzieje bo nie mam czasu tego analizowac ale z ta funkcja wsprintf sa same problemy...Moj problem rozwiazalem srednio fajnie ale wazne ze dziala - zamiast wrzucac wszystko do wsprintf dopisuje poprostu do bufora kolejne przekonwertowane liczby. Wyglada to tak:

     invoke FileTimeToLocalFileTime, ADDR FoundData.ftLastWriteTime, 
ADDR FTime
     invoke FileTimeToSystemTime, ADDR FTime, ADDR STime                    
     invoke wsprintf, ADDR fsBuf, SADD("%u:"),  STime.wHour
     invoke wsprintf, ADDR temp, SADD("%02u "), STime.wMinute
     invoke lstrcat, ADDR fsBuf, ADDR temp
     invoke wsprintf, ADDR temp, SADD("%u-"), STime.wDay
     invoke lstrcat, ADDR fsBuf, ADDR temp
     invoke wsprintf, ADDR temp, SADD("%02u-"), STime.wMonth
     invoke lstrcat, ADDR fsBuf, ADDR temp
     invoke wsprintf, ADDR temp, SADD("%u"), STime.wYear
     invoke lstrcat, ADDR fsBuf, ADDR temp

Byc moze zle tez tworzylem ciag formatujacy ale probowalem z wieloma typami i nic to nie dawalo wiec watpie. Oczywiscie wsprintf z jednym paramterem dziala poprawnie.
pozdrawiam

Link do komentarza
Udostępnij na innych stronach

Witam
Problem nie tkwi w samej funkcji wsprintf a w sposobie przekazywania parametrów. Kompilator spodziewa się argumentu 32 bitowego (dword) a otrzymuje 16 bitowy (word). Dlatego uzupełnia to sobie w niezbyt mądry sposób przez dodanie push 0 pomiędzy argumentami. Aby pozbyć się prolemu można napisać tak:

            sub eax, eax ;lepiej  wyzerować rejestr
            mov ax, STime.wYear ;zapisz word do rejeestru ax
            push eax    ;teraz idzie dword na stos jak oczekuje kompilator    
            mov ax, STime.wMonth
            push eax        
            mov ax, STime.wDay
            push eax
            mov ax, STime.wMinute
            push eax                
            mov ax, STime.wHour
            push eax        
            lea eax, templateData
            push eax        
            lea eax, fsBuf
            push eax
            call wsprintf

Myślę ,że to lepsze od Twojego obejścia problemu a taksamo działa :P
Pozdro

Link do komentarza
Udostępnij na innych stronach

Faktycznie! Teraz kiedy to wyjasiles wydaje sie to prawie oczywiste:). Dzieki wielkie! Troche bez sensu jest to ze kompilator wlasnie tak rozwija invoke'a...Z tego co wycztalem z dokumentacji funkcji to proces wywolujacy jest odpowiedzialny za oczyszczenie stosu - zatem trzeba po instrukcji call dodac jeszcze add ESP, 28...
Zastanawia mnie tylko jeszcze jedna rzecz: gdy program wrzuca na stos zmienna typu np. WORD to i tak na stos wrzucana jest warotsc DWORD ( ponoc wynika to z tego ze jest to szybsze) - czyli jest jakby wyrownanie do DWORD. Dlaczego wiec nie wrzuca poprawnie tego? Czy moze sie myle?

ps. Fajnie ze piszesz w asmie bo ciezko jest sie kogos poradzic, gdy kroluje c++:)

Link do komentarza
Udostępnij na innych stronach

Witam
Cieszę się, że się przydało :D
Niestety nie wiem, dlaczego źle interpretuje akurat to. Zrobiłem nawet sobie z ciekawości przykładową funkcję gdzie parametrami były kolejno 2 byte, 2 word, 2 dword i wszystko Ok (na stos rzeczywiście jest wrzucony dword przynajmniej tak pokazuje dissasembler). Być może wina leży w tym, że wsprintf ma nie określoną liczbę argumentów.
Pozdro

Link do komentarza
Udostępnij na innych stronach

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...