LCF-AT Posted December 4, 2015 Posted December 4, 2015 Hi guys, sorry to create a new topic but I got a little stupid problem with some calculation and I don't get it work. Problem: I have created a slidebar and did set the maximum range to 100 (dec) = used as 0-100 %.The problem now are the calculations.So I remember I have done this in the past with a progressbar & filesize (downloader) and there is was working but now I don't get it work anymore. <0100739D> MOV EDI,0x60 ; full lenght NOP @L00000001: MOV EAX,EDI MOV EDX,0x0 MOV ECX,0x64 ; 100 dec DIV ECX CMP EDX,0x0 JE SHORT @L00000002 DEC EDI JMP SHORT @L00000001 @L00000002: MOV EDI,EAX MOV ESI,0x30 ; is lenght NOP @L00000003: MOV EAX,ESI MOV EDX,0x0 DIV ECX CMP EDX,0x0 JE SHORT @L00000004 DEC ESI JMP SHORT @L00000003 @L00000004: MOV ESI,EAX IMUL ESI,ESI,0x64 ; 100 dec MOV EAX,ESI MOV ECX,EDI MOV EDX,0x0 DIV ECX NOP NOP Normaly I should get 96 % from that calculation to use this value to set the position of slidebar but I get 0.So I do anything wrong so maybe you can help how to make it correctly and easy too if possible. Thank you 1
Kurapica Posted December 4, 2015 Posted December 4, 2015 Maybe because you are doing integer divisions ? The progress is less than 100 and when you divide the current progress on 100 it will return 0. maybe you should use a different approach or try with floating points instructions. http://stackoverflow.com/questions/8804770/how-to-divide-floating-point-number-in-x86-assembly
CodeExplorer Posted December 4, 2015 Posted December 4, 2015 0x60 = full lenght = 100% 0x30 = 50% 0x60 ... 100 % current progress ... ??? % (X) X = (current_progress * 100) / 0x060 So for example: if progress = 0x30 the result should be 50: so we do: x = (0x30 * 100) / 0x060 x = (48 dec * 100) / 96 x = 4800 / 96 = 50 % So do: multiply current lenght with 100 (64h) and divide the result with full lenght "Normaly I should get 96 % from that calculation to use this value to set the position of slidebar but I get 0" if full lenght = 0x60 and you are position 0x30 you should get 50% from where 96 % ??? 1
CodeExplorer Posted December 4, 2015 Posted December 4, 2015 From Kurapica post: "The progress is less than 100 and when you divide the current progress on 100 it will return 0. " Whell you supose to multiply by 100 not divide!
LCF-AT Posted December 4, 2015 Author Posted December 4, 2015 Hi guys and thanks for the answers. Ok now I wrote this.... mov eax, 30 ; current mov ecx, 64 ; 100 mov edx, 0 mul ecx mov ecx, 60 ; full length mov edx, 0 div ecx .....and I got 50 & in dec.Oh my so simple and I did spend yesterday few hours and didn't got it work.Now it works and slider does move correctly so far.Thanks again very much and sorry for asking about it. greetz
LCF-AT Posted December 6, 2015 Author Posted December 6, 2015 Hi again, have another small question.Can anyone tell me how to calc size bytes to QWORD = int64?Lets say I do alloc any section with a size of 30000 hex bytes so how I have to calc to get this size into QWORD = int64 pushed to stack? greetz
CodeExplorer Posted December 6, 2015 Posted December 6, 2015 So you need the size in qword (int 64) of 30000 hex bytes; An qword = 8 bytes (from what I know) So we do 30000 hex bytes / 8 bytes, so we do 30000 / 8 probable the result value needs to be runded so if reminder of divide operation (30000 / 8) is not 0 increment the result with 1
LCF-AT Posted December 6, 2015 Author Posted December 6, 2015 Hi again and thanks so far. So have I to work with any QWORD commands maybe?FISTP or so?Problem is I wanna use a API and there I have to use QWORD into stack. datalength : QWORD DataLength [in] Length of that file There is also a other API... function BassVideo_GetLength(handle: DWORD): Double; stdcall; If successful, then the channel's length in seconds is returned, else -1 is returned ...so here I can see Double = also QWORD (2 DWORDs ) right?Now I did debug a file what used this API and right after this API call I see that operation commands... sub esp,8 FISTP QWORD PTR SS:[ESP] ...also I am not sure whether it wants the filesize as lenght or seconds. function BassVideo_StreamCreateFileMem(data :Pointer; datalength : QWORD; MediaType, Flags, BassFlags : DWORD; CallBackProc : VIDEOPROC; user : Pointer): DWORD; stdcall; Unfortunately there is no example file using this API above which I could check. greetz
LCF-AT Posted January 4, 2016 Author Posted January 4, 2016 Hi guys, I have again another questions about calculations with values getting higher than -1h.All in all I have really trouble to work with float and not float together and now I thought there would be any other easier solution which I could maybe use to prevent massiv calculation etc.My question is: Are there maybe some API of any module out there which I could use to handle math operations (+/-/*/div/percent) only by strings?Lets say I have 2 ASCII strings and wanna add them and as results I will get also a ASCII string back. 1234567890 ; String 1 445454 ; String 2 1234567890+445454=1235013344 Invoke CalcAPIxy,String1,String2,addition,Buffer = Buffer "1235013344" Maybe you know any helpfully APIs which I could use if there some who can do such string operations etc maybe any msvcrt API or so.Would be nice. greetz
T-rad Posted January 5, 2016 Posted January 5, 2016 I don't know of any API the will do math directly on / using ASCII string but you could do something like this... invoke sscanf, addr String1, chr$("%d"), addr buf1 ;"1234567890" invoke sscanf, addr String2, chr$("%d"), addr buf2 ;"445454" mov eax, buf1 mov edx, buf2 add eax, edx invoke sprintf, Buffer, chr$("%d"), eax ; "1235013344"
LCF-AT Posted January 5, 2016 Author Posted January 5, 2016 Hi, no it dosen't work like I expected.You only can handle values till max -1h on that way like you did post above.I also don't whether there are any API which I could use to do calc operations only with dez ASCII strings. But thanks for trying to help T-rad greetz
T-rad Posted January 5, 2016 Posted January 5, 2016 no problem. Just a note. When using chr$("%d") you are limited to the max value of an integer so you would change it according to your variable chr$("%d") signed decimal or integer chr$("%i") signed decimal or integer chr$("%u") unsigned decimal or integer chr$("%ld") signed long decimal or integer chr$("%lu") unsigned long decimal or integer chr$("%hd") short chr$("%l") long chr$("%f") float chr$("%lf") double chr$("%Lf") long double chr$("%lld") signed long long decimal or integer chr$("%I64d") signed long long decimal or integer chr$("%llu") unsigned long long decimal or integer chr$("%I64u") unsigned long long decimal or integer chr$("%llx") long long decimal or integer in hex format chr$("%I64x") long long decimal or integer in hex format for example... if you were to do something using a long double like this String1 db "12345678909876", 0 String2 db "445454.123", 0 invoke sscanf, addr String1, chr$("%Lf"), addr buf1 invoke sscanf, addr String2, chr$("%Lf"), addr buf2 fld [buf1] fld [buf2] fadd fstp [buf1] invoke sprintf, serial, chr$("%Lf"), buf1 the result would yield "12345679355330.123000" or an unsigned 64 bit integer String1 db "1234567890987654", 0 String2 db "445454", 0 invoke sscanf, addr String1, chr$("%llu"), addr buf1 invoke sscanf, addr String2, chr$("%llu"), addr buf2 fld [buf1] fld [buf2] fadd fst [buf1] invoke sprintf, serial, chr$("%llu"), buf1 the result would yield "1234567891433108" 1
LCF-AT Posted January 6, 2016 Author Posted January 6, 2016 Hi and thanks for the infos so far.The example for unsigned 64 bit integer does not work for me.Maybe I wrote anything wrong. 00401C60 PUSH 0x40A960 00401C65 PUSH 0x4054DD ; ASCII "%llu" 00401C6A PUSH 0x4054C5 ; ASCII "1234567890987654" 00401C6F CALL DWORD PTR DS:[0x404058] ; msvcrt.sscanf 00401C75 ADD ESP,0xC 00401C78 PUSH 0x40A964 00401C7D PUSH 0x4054E4 ; ASCII "%llu" 00401C82 PUSH 0x4054D6 ; ASCII "445454" 00401C87 CALL DWORD PTR DS:[0x404058] ; msvcrt.sscanf 00401C8D ADD ESP,0xC 00401C90 FLD DWORD PTR DS:[0x40A960] 00401C96 FLD DWORD PTR DS:[0x40A964] 00401C9C FADDP ST(1),ST 00401C9E FST DWORD PTR DS:[0x40A960] 00401CA4 PUSH DWORD PTR DS:[0x40A960] 00401CAA PUSH 0x4054EC ; ASCII "%llu" 00401CAF PUSH 0x40C978 ; ASCII "1016588934" 00401CB4 CALL DWORD PTR DS:[0x40405C] ; msvcrt.sprintf 00401CBA ADD ESP,0xC 1016588934 1016588934 is the results I get. .data String1 db "1234567890987654", 0 String2 db "445454", 0 .data? buf1 dd ? buf2 dd ? serial dd 256 dup (?) invoke crt_sscanf, addr String1, chr$("%llu"), addr buf1 invoke crt_sscanf, addr String2, chr$("%llu"), addr buf2 fld [buf1] fld [buf2] fadd fst [buf1] invoke crt_sprintf, addr serial, chr$("%llu"), buf1 greetz
T-rad Posted January 6, 2016 Posted January 6, 2016 (edited) dd is a dword (4 bytes) and not big enough to hold the the size of the int64. you should declare it as dq or qword (8 bytes) Like this .data? buf1 dq ? buf2 dq ? Edited January 6, 2016 by T-rad
LCF-AT Posted January 6, 2016 Author Posted January 6, 2016 Ok I did but still get not the right result back. 00401C60 PUSH 0x40A968 00401C65 PUSH 0x4054DD ; ASCII "%llu" 00401C6A PUSH 0x4054C5 ; ASCII "1234567890987654" 00401C6F CALL DWORD PTR DS:[0x404058] ; msvcrt.sscanf 00401C75 ADD ESP,0xC 00401C78 PUSH 0x40A970 00401C7D PUSH 0x4054E4 ; ASCII "%llu" 00401C82 PUSH 0x4054D6 ; ASCII "445454" 00401C87 CALL DWORD PTR DS:[0x404058] ; msvcrt.sscanf 00401C8D ADD ESP,0xC 00401C90 FLD QWORD PTR DS:[0x40A968] 00401C96 FLD QWORD PTR DS:[0x40A970] 00401C9C FADDP ST(1),ST 00401C9E FST QWORD PTR DS:[0x40A968] 00401CA4 PUSH DWORD PTR DS:[0x40A96C] 00401CAA PUSH DWORD PTR DS:[0x40A968] 00401CB0 PUSH 0x4054EC ; ASCII "%llu" 00401CB5 PUSH 0x40C988 ; ASCII "1017034388" 00401CBA CALL DWORD PTR DS:[0x40405C] ; msvcrt.sprintf 00401CC0 ADD ESP,0x10 1017034388 0040A968 3C9EB694 0040A96C 00000000 0040A970 0006CC0E 0040A974 00000000 greetz
kao Posted January 6, 2016 Posted January 6, 2016 For some reason, you have all zeroes at 0040A96C. It's incorrect, it should have value "000462d5". Quick look at the disassembly doesn't show anything particularly wrong, so I can only suggest that you debug it instruction-by-instruction. For reference, here's the code produced by VS2010. I can see 2 main differences. First, it uses FADD QWORD PTR instead of FLD/FADDP. Second, it uses FLD/FSTP to prepare arguments for sprintf. sscanf("1234567890987654", "%llu", &a); 00D61269 68 30 62 D6 00 push offset a (0D66230h) 00D6126E 68 58 47 D6 00 push offset string "%llu" (0D64758h) 00D61273 68 44 47 D6 00 push offset string "1234567890987654" (0D64744h) 00D61278 FF 15 3C 72 D6 00 call dword ptr [__imp__sscanf (0D6723Ch)] 00D6127E 83 C4 0C add esp,0Ch sscanf("445454", "%llu", &b); 00D61281 68 20 62 D6 00 push offset b (0D66220h) 00D61286 68 58 47 D6 00 push offset string "%llu" (0D64758h) 00D6128B 68 3C 47 D6 00 push offset string "445454" (0D6473Ch) 00D61290 FF 15 3C 72 D6 00 call dword ptr [__imp__sscanf (0D6723Ch)] 00D61296 83 C4 0C add esp,0Ch c = a + b; 00D61299 DD 05 30 62 D6 00 fld qword ptr [a (0D66230h)] 00D6129F DC 05 20 62 D6 00 fadd qword ptr [b (0D66220h)] 00D612A5 DD 1D 28 62 D6 00 fstp qword ptr [c (0D66228h)] sprintf((char *)&result, "%llu", c); 00D612AB 83 EC 08 sub esp,8 00D612AE DD 05 28 62 D6 00 fld qword ptr [c (0D66228h)] 00D612B4 DD 1C 24 fstp qword ptr [esp] 00D612B7 68 58 47 D6 00 push offset string "%llu" (0D64758h) 00D612BC 68 20 61 D6 00 push offset result (0D66120h) 00D612C1 FF 15 40 72 D6 00 call dword ptr [__imp__sprintf (0D67240h)] 00D612C7 83 C4 10 add esp,10h
T-rad Posted January 6, 2016 Posted January 6, 2016 my rip looks the same but everything is working here. I have attached my src so you can have a look. sscanf app.rar 0040102A PUSH Keygen.00403034 0040102F PUSH Keygen.00403018 ; |format = "%llu" 00401034 PUSH Keygen.00403000 ; |s = "1234567890987654" 00401039 CALL DWORD PTR DS:[<&msvcrt.sscanf>] ; \sscanf 0040103F ADD ESP,0C 00401042 PUSH Keygen.0040303C 00401047 PUSH Keygen.0040301D ; |format = "%llu" 0040104C PUSH Keygen.00403011 ; |s = "445454" 00401051 CALL DWORD PTR DS:[<&msvcrt.sscanf>] ; \sscanf 00401057 ADD ESP,0C 0040105A FLD QWORD PTR DS:[403034] 00401060 FLD QWORD PTR DS:[40303C] 00401066 FADDP ST(1),ST 00401068 FST QWORD PTR DS:[403034] 0040106E PUSH DWORD PTR DS:[403038] 00401074 PUSH DWORD PTR DS:[403034] ; | 0040107A PUSH Keygen.00403022 ; |format = "%llu" 0040107F PUSH Keygen.00403044 ; |s = Keygen.00403044 00401084 CALL DWORD PTR DS:[<&msvcrt.sprintf>] ; \sprintf 0040108A ADD ESP,10
LCF-AT Posted January 6, 2016 Author Posted January 6, 2016 Hhmm.Thanks for the file / source but I get same as before too.See pic.
simple Posted January 6, 2016 Posted January 6, 2016 None of the sample codes here have error checking. The return value of sscanf will indicate success/failure. Besides, strtol(), strtoul(), etc (family of functions) are specifically designed for string/numerical conversions & probably the cleanest way. Assuming you are using a MS compiler, atoi(), atof(), atoi64() etc are probably the easiest but they aren't cross platform. Personally, sscanf() would be my last choice for this, it has many odd things about it.
kao Posted January 6, 2016 Posted January 6, 2016 2 hours ago, ragdog said: Fpu for a simply Qword Addition? Crazy coding That's LCF-AT, always having "unconventional" ideas. I'm already used to it.. 1
ragdog Posted January 6, 2016 Posted January 6, 2016 Quote That's LCF-AT, always having "unconventional" ideas. I'm already used to it.. Hehe but with Fpu is a really bad solution No error checking no Overflow check. And is not Optimized
simple Posted January 6, 2016 Posted January 6, 2016 (edited) LCF, I had exact same problem as u w/Trad code, big number was getting cut off. For me, problem was %llu wasn't introduced till C99 or later and ur msvcrt is still running on C89. To fix this problem change the format string for arguments to sscanf & sprintf from "%llu" to C89 standard "%I64d" and it should work fine. When using masm w/libc functions probably best to use only C89. I still prefer other functions for this though. edit - also to add 445454 all u have to do is use add instruction Edited January 6, 2016 by simple add 3
LCF-AT Posted January 7, 2016 Author Posted January 7, 2016 Hi guys, yes maybe I am the one who has unconventional ideas and also looking for unconventional solutions too. All in all I wanna find special solutions (simple of course if possible) to prevent unnecessary headache.Ok it works now with the hint of simple to change the format.Thanks again so far guys. greetz
T-rad Posted January 7, 2016 Posted January 7, 2016 question... whats so wrong with FPU for the addition i can use 3-ish lines of code with FPU fld [buf1] fadd [buf2] fst [buf1] or 6 lines without it. MOV EAX,DWORD PTR DS:[buf1] MOV EDX,DWORD PTR DS:[buf1+4] ADD EAX,DWORD PTR DS:[buf2] ADC EDX,DWORD PTR DS:[buf2+4] MOV DWORD PTR DS:[buf1],EAX MOV DWORD PTR DS:[buf1+4],EDX Please note that this is a genuine question. I normally code in C/C++ so i don't code in ASM much and would like to learn the proper do's and dont's.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now