Mahdi Safsafi
Members-
Content Count
383 -
Joined
-
Last visited
-
Days Won
10
Everything posted by Mahdi Safsafi
-
GExperts supports even more laziness
Mahdi Safsafi replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Happy for you ! In the attached file, you will find a small tool that automatically extracts offset for you (this should help you to validate all older versions). The tool is written using C as it uses my AMED decoder. I attached a source an a binary. Use it as follow: OffsetDumper win32debugide260.bpl @Win32debug@TNativeDebugger@DoShowException$qqrv Good luck. OffsetDumper.rar -
GExperts supports even more laziness
Mahdi Safsafi replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Very sorry man I thought that you relied on some tools ... shame one me. -
GExperts supports even more laziness
Mahdi Safsafi replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
@Kas Ob. Never rely on "on fly tools" ... from my experience they can give wrong information. Better is to use your hand with your mind. BTW, what's your debugger ? Its interface looks familiar for me. Is it IDA ? -
GExperts supports even more laziness
Mahdi Safsafi replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
@dummzeuch Ok, I downloaded and installed D2007. On Win10 its mostly unusable for me (a lot of exceptions). But I could disasm DoShowException. Here is what I find : As you can see, unlike Rio, the field offset is 0x99 and not 0xA1. Try change the offset for D2007 and let me know if that works for you. If it does, you may need to check all other old Delphi version too ! -
GExperts supports even more laziness
Mahdi Safsafi replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
@dummzeuch Go to DoShowException entry point and then go to the end of that function(on the right panel, I made some pseudo pascal code for clarification) : https://i.ibb.co/zZd5spY/Dbg.png Can you give a simple DUnit test ? Basically when an exception occurs and you click continue, the RTL tries to find a handler for that exception and executes it. So stopping at the end of procedure is weird! I'm not very familiar with D2007 but was DUnit shipped with Delphi 2007 at that time ? I guess, either DUnit is doing something behind the scene ! Otherwise why under D2007, it worked with a simple test project and failed on DUnit project . Why it just worked fine under 10.2 for both project ? Or there is something with D2007 RTL. Can you confirm if the same behavior occurs without hooking (disabling GExpert) ? Also, I suggest that you disable GExpert for DUnit on D2007(make sure there is no hook is installed as well), put a break point on DoShowException, run a dummy project that raise exception and try to follow until the function returns. See whether a call to PostDebugMessage was made or not. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yeah Stefan, I clearly understand you. But the same thing you described can be achieved by branch prediction. So compiler should not generate such code unless you are targeting an old cpu. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Moreover saying that "Fewer instructions / uops inside the loop = better" is somehow wrong. I can certainly prove that its wrong. using SIMD instructions where using n instruction to reduce loop count is better than having a single/few instruction inside that loop. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Today no high end compiler is doing that because it affects an important optimization part OoOE. Delphi uses a very old code generator that is not up to date. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
@Stefan Glienke As I said before, MSVC is somehow far behind gcc and clang. In fact, it used 8-bit registers heavily which are known to be slow as they require internal manipulation by the CPU: 00241000 8A 0D 10 21 24 00 mov cl,byte ptr [string "test" (0242110h)] 00241006 B8 10 21 24 00 mov eax,offset string "test" (0242110h) 0024100B 0F 1F 44 00 00 nop dword ptr [eax+eax] 00241010 40 inc eax 00241011 80 F9 30 cmp cl,30h 00241014 74 09 je test1+1Fh (024101Fh) 00241016 8A 08 mov cl,byte ptr [eax] 00241018 84 C9 test cl,cl 0024101A 75 F4 jne test1+10h (0241010h) 0024101C 32 C0 xor al,al 0024101E C3 ret 0024101F B0 01 mov al,1 00241021 C3 ret For Delphi, output of Test1 and Test2 is very close. In fact if you change to PChar, you may find that unlike Test1, Test2 is using add reg, imm instruction. No its not a good pattern : 0041BD92 EB09 jmp $0041bd9d // unecessary relative branch. 0041BD94 80F930 cmp cl,$30 // suppose this was a load op => bad for OoOE. 0041BD97 7503 jnz $0041bd9c 0041BD99 B001 mov al,$01 0041BD9B C3 ret Just hope for better. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Keep some faith Stefan ... remember a tortoise wins a hare once. -
Yeah it makes very sense.
-
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
No mov cl,byte ptr [eax] At CPU level indexed addressing = indirect addressing. The only difference is that an indexed addressing can have an expression inside []. Sometime this could be just good for alignment purpose. [eax] = [eax+0x00]. But Stefan was referring to something else : register usage for each load instruction. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
It even depends on your compiler. If your compiler is smart enough, it will generate better code sometime better than using pointer because compiler can understand better integer behavior than pointer. Using MSVC (which is not really smart enough) to compile those two function, generates EXACTLY the SAME opcodes for both ! __declspec(noinline) bool test1(const char* str) { int i = 0; while (str[i]) if ('0' == str[i++]) return true; return false; } __declspec(noinline) bool test2(const char* str) { char* p = (char*)&str[0]; while (*p) if ('0' == *p++ ) return true; return false; } -
Yes I understand that but would we be able to assume that the future for that language is good ?
-
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yes, you're absolutely right. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
On x86, sizeof(pointer) = sizeof(integer) so its much likely you are going to have the same performance. On x64, sizeof(pointer) = sizeof(int64) so using integer could be some how better. This was just a general rule, but does not apply always as it depends on the way you're using your code. -
Exactly, you hit the nail on the head.
-
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
@Stefan Glienke For some time it was totally out of my control Now its getting better but yet I still fight my self some time. -
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
@Kas Ob. I noticed that you take optimization very seriously. That's really good but just as an advice from someone that did, don't be driven too much. Behind that optimization door resides the evil ! In fact, I spent much time reading Intel doc/books, comparing different compilers (gcc, clang, ...). At the end I become more obsessional and less productive as I started paying much attention to my codes than what is required like taking some time to decide whether I should write if a = b or if a <> b. -
Nothing last for ever. its just a question of time. COBOL developers are old by now and the time they go for retiring, No one would be there to fill that gap as the language is unable to attract young developers. A programming language that is unable to attract young people would likely to have no future. Its hard to me to declare the above statements but that's the reality -whether we liked or not-.
-
Soon or later current COBOL developers are going to retire. So if its not died ... its dying.
-
Help with string extraction function
Mahdi Safsafi replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
AFAIK it gets a little bit better on modern CPU. However it's getting abandoned on favor of SIMD instructions. IMO, I think that the RTL Move routine should be implemented as an intrinsic (not a function) in that way the compiler can generate a much better code. -
Its much complex than offering a community edition and an academy. In the last decade the market was bload up with new programming languages(thanks to LLVM). Those languages are very easy and very attractive for young people. Moreover they're free and have a wide community support(thanks to the big tech behind them). Delphi on the other hand is an old language and is no longer considered as the easiest language. Today developers are not like old developers. Today developers tend to seek for easy and fast solution without much complexity(i.e : GC). A language is considered dead when its no longer able to attract young people. Delphi can't compete with those languages. Not because its bad ... but because is not able to satisfy a particular range of new developers. I believe EMB understood clearly this. that's why it focuses on old developers, on compatibility and does not spend much on resources.
-
For me I'd go with AddObject as its better than using Pair<Name, Value>. However you can either set CheckListBox1.Style to lbVirtual and then handle all data event. Or simply set Style to lbOwnerDrawFixed and owner draw your control: // CheckListBox1.Style := lbOwnerDrawFixed; procedure TMain.CheckListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var Flags: Longint; Data: String; FCanvas: TCanvas; CheckListBox: TCheckListBox; begin CheckListBox := TCheckListBox(Control); FCanvas := CheckListBox.Canvas; FCanvas.FillRect(Rect); if Index < CheckListBox.Count then begin Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX); if not UseRightToLeftAlignment then Inc(Rect.Left, 2) else Dec(Rect.Right, 2); Data := CheckListBox.Items.Names[Index]; DrawText(FCanvas.Handle, Data, Length(Data), Rect, Flags); end; end; EDIT: Removed ExtractName function.
-
That reminded me about a nice quote :