WinAPI - examples - post 2 lazarus / 67-Windows ---------------------------------------------------------------------- 440bx · 2021-01-17 07:38 Hello, The examples will be presented roughly in order of complexity, that is, from simplest to more complex.  The simplest are by far those APIs which should NOT be used since no example will be provided for those. Amond the APIs that should be avoided and preferably never used are : GlobalCompact GlobalFix    GlobalFlags  GlobalHandle GlobalLock  GlobalReAlloc GlobalSize  GlobalUnfix  GlobalUnlock GlobalUnWire GlobalWire  LocalAlloc  LocalCompact LocalFlags  LocalFree    LocalHandle  LocalLock    LocalReAlloc LocalShrink  LocalSize    LocalUnlock  All of the above are Windows 16 bit memory management functions which are _not_ well suited for a 32 bit O/S.  Use the 32 bit memory management functions instead. As mentioned previously, no example for any of the above APIs will be given. GlobalAlloc GlobalFree These two (2) APIs are still commonly found in C programs but, are not as flexible as HeapAlloc() and HeapFree() which should be preferred. No example of GlobalAlloc and GlobalFree will be given.  An example of HeapAlloc and HeapFree will be given in the future. GlobalMemoryStatus GlobalMemoryStatus returns incorrect information on systems with more than 4GB of memory. Use GlobalMemoryStatusEx instead. An example for both will be given in the future. GetTextExtentPoint Use GetTextExtentPoint32 instead which, according to MS, is more accurate. This post is for examples of API used in the great majority of the examples. Examples attached to this post are : WinAPI - GetTextExtentPoint      (gdi) WinAPI - GetTextExtentPoint32  (gdi) Both of these APIs return the width and height in pixels of a specified string WinAPI - SetBkMode                    (gdi) Sets the background color to opaque or transparent.  When the background is opaque then whatever color was chosen as background will be visible. WinAPI - SetTextAlign                 (gdi) Sets the text alignment.  This example visually demonstrates the effects of some of the SetTextAlign options. See MSDN for all available options. WinAPI - TextOut                        (gdi) Outputs a string at the specified location, using the currently selected font, background color, and text color. WinAPI - GetClientRect               (user) Retrieves the coordinates of the client area.  This example draws a frame around the client area.  It also serves as an example of CreatePen, SetCapture, ReleaseCapture, InvalidateRect, SelectObject, Rectangle, lstrcpy, lstrlen and DeleteObject. NOTE: this example does not include code to eliminate or minimize flicker,which would not be hard to implement (left for future example.) WinAPI - Windows Bitness       (technique) This version includes minor editing of the comments and loads csrss.exe as an image resource instead of a data file.  Since Windows uses the low bits of the load address to indicate the mode the file was loaded in, this version aligns the load address instead of simply subtracting one (1) which is valid only when the module is loaded as a data file.  Using alignment works regardless of the way the module is loaded. recommendation : replace the previous version with this version. What follows is the code for the GetClientRect example (the source for the remaining examples is present in the zip file attached to this post.) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$APPTYPE      GUI} {$LONGSTRINGS    OFF}{$WRITEABLECONST ON}{$DESCRIPTION    'Win32 API function - GetClientRect example'} {$R GetClientRect.Res} program _GetClientRect;  { Win32 API function - GetClientRect example                                } uses Windows, Messages, Resource, SysUtils; const  AppNameBase  = 'GetClientRect Example';   {$ifdef WIN64}    Bitness64  = ' - 64bit';    AppName    = AppNameBase + Bitness64;  {$else}    Bitness32  = ' - 32bit';    AppName    = AppNameBase + Bitness32;  {$endif}   AboutBox     = 'AboutBox';  APPICON      = 'APPICON';  APPMENU      = 'APPMENU'; {--- ---------------------------------------------------------------------- ----} {$ifdef VER90} { Delphi 2.0 }type  ptrint  = longint;  ptruint = dword;{$endif} {------------------------------------------------------ -----------------------} function About(DlgWnd : hWnd; Msg : UINT; wParam, lParam : ptrint)         : ptrint; stdcall;begin  About := ord(TRUE);   case msg of     WM_INITDIALOG: exit;     WM_COMMAND:    begin      if (LOWORD(wParam) = IDOK) or (LOWORD(wParam) = IDCANCEL) then      begin        EndDialog(DlgWnd, ord(TRUE));         exit;    end;    end;  end;   About := ord(FALSE);end; {---------------------- -------------------------------------------------------} function WndProc (Wnd : hWnd; Msg : UINT; wParam, lParam : ptrint)         : ptrint; stdcall;  { main application/window handler function                                }const  GetClientRect_Call = 'GetClientRect (Wnd : HWND; var Rect : TRECT) : BOOL;';   Pen                : HPEN = 0;      { deleted when the window is destroyed  }   Hint = 'Press the Left mouse button anywhere in the client area';   Tracking           : BOOL = FALSE; var  ps                 : TPAINTSTRUCT;   ClientRect       : TRECT;   Buf                : packed array[0..255] of char;   TextSize           : TSIZE;  OldPen             : HPEN; begin  WndProc := 0;   case Msg of    WM_CREATE:    begin      {--------------------- --------------------------------------------------}      { Using "not GetSysColor(COLOR_WINDOW)" guarantees that the pen will    }      { be created using a color that will always be visible.  Note that      }    { for this to be true, the value passed to GetSysColor must be the    }      { same as the one passed when the class was registered.               }       { We AND with $00FFFFFF to make sure that the high byte is zero.        }      { Windows uses this byte to select a palette which is not something     }      { we want it to do in this occasion.                                    }       Pen := CreatePen(PS_INSIDEFRAME,                       3,                     not GetSysColor(COLOR_WINDOW) and $00FFFFFF);      exit;    end;   WM_LBUTTONDOWN:    begin      {--------------------------------------- --------------------------------}      { capture the mouse to make sure we always get the button up which      }      { is the signal to refresh the client area.                             }       SetCapture(Wnd);      Tracking := TRUE;      InvalidateRect(Wnd, nil, TRUE);       exit;    end;     WM_LBUTTONUP:    begin      {---------- -------------------------------------------------------------}      { if the mouse was not captured then we don't have anything to do       }       if Tracking then      begin        ReleaseCapture;                 { let the cat play with it          }         Tracking := FALSE;        InvalidateRect(Wnd, nil, TRUE);   { redraw the client area            }      end;       exit;    end;     WM_PAINT:    begin      BeginPaint(Wnd, ps);       { set up the dc                                                       }       SetBkMode(ps.hdc, TRANSPARENT);      SetTextAlign(ps.hdc, TA_CENTER);       GetClientRect(Wnd, ClientRect);       { we'll use this quite often    }       if Tracking then      begin        {------------------------- --------------------------------------------}        { we have the mouse captured. we draw a frame around the client       }        { rectangle and display its size.                                     }         OldPen := SelectObject(ps.hdc, Pen);        SelectObject(ps.hdc, GetStockObject(NULL_BRUSH));         {----------- ----------------------------------------------------------}        { draw a frame around the client area. This could be done using       }        { the FrameRect API instead of Rectangle.                           }         with ClientRect do        begin          Rectangle(ps.hdc, Left, Top, Right, Bottom);        end;         {---- -----------------------------------------------------------------}      { draw the size of the client area                                  }         SelectObject(ps.hdc, OldPen);         with ClientRect do      begin          StrFmt(Buf,                 '(Left, Top) (%d, %d) - (Right, Bottom) (%d, %d)',                 [Left, Top, Right, Bottom]);        end;         { the code outside the if statement will output the buffer            }      end      else      begin        {- --------------------------------------------------------------------}        { we don't have the mouse captured.  we draw a string giving        }        { the user a hint about what to do next.                            }         lstrcpy(Buf, Hint);      end;       {---------- -------------------------------------------------------------}      { calculate the size of the output string currently in Buf              }       GetTextExtentPoint32(ps.hdc,                           Buf,                         lstrlen(Buf), TextSize);      TextOut(ps.hdc,              ClientRect.Right  div 2,              ClientRect.Bottom div 2 - TextSize.cy,              Buf,              lstrlen(Buf));     {------------------------------------------------------------------- ----}      { draw the function call                                              }       SelectObject(ps.hdc, GetStockObject(DEFAULT_GUI_FONT));      SetTextAlign(ps.hdc, TA_CENTER or TA_BOTTOM);       lstrcpy(Buf, GetClientRect_Call);       { calculate the size of the output string                               }       GetTextExtentPoint32(ps.hdc,                           Buf,                         lstrlen(Buf), TextSize);      TextOut(ps.hdc,            ClientRect.Right div 2,              ClientRect.Bottom - TextSize.cy,              Buf,              lstrlen(Buf));       {---- -------------------------------------------------------------------}    { we're done painting                                                 }       EndPaint(Wnd, ps);       exit;    end;     WM_COMMAND:    begin      case LOWORD(wParam) of        IDM_ABOUT:        begin        DialogBox(hInstance, ABOUTBOX, Wnd, @About);           exit;      end; { IDM_ABOUT }         IDM_EXIT:        begin          DestroyWindow(Wnd);           exit;        end; { IDM_EXIT }      end; { case LOWORD(wParam) }    end; { WM_COMMAND }     WM_DESTROY:    begin      if Pen <> 0 then DeleteObject(Pen);        PostQuitMessage(0);       exit;    end; { WM_DESTROY }  end; { case msg }   WndProc := DefWindowProc (Wnd, Msg, wParam, lParam);end; {---- ---------------------------------------------------------------------- ---} function InitAppClass : WordBool;  { registers the application's window classes                                }var  cls : TWndClassEx; begin  cls.cbSize          := sizeof(TWndClassEx);       { must be initialized   }   if not GetClassInfoEx (hInstance, AppName, cls) then  begin    with cls do begin      { cbSize has already been initialized as required above                 }       style           := CS_BYTEALIGNCLIENT;      lpfnWndProc     := @WndProc;                    { window class handler  }      cbClsExtra      := 0;      cbWndExtra      := 0;      hInstance       := system.hInstance;            { qualify instance!     }      hIcon         := LoadIcon (hInstance, APPICON);      hCursor         := LoadCursor(0, idc_arrow);      hbrBackground   := GetSysColorBrush(COLOR_WINDOW);      lpszMenuName    := APPMENU;                   { Menu name             }      lpszClassName   := AppName;                     { Window Class name     }      hIconSm       := LoadImage(hInstance,                                   APPICON,                                   IMAGE_ICON,                                 16,                                   16,                                 LR_DEFAULTCOLOR);    end; { with }     InitAppClass := WordBool(RegisterClassEx(cls));  end  else InitAppClass := true;end; {------------------------------------------- ----------------------------------} function WinMain : integer;  { application entry point                                                 }var  Wnd : hWnd;  Msg : TMsg; begin  if not InitAppClass then Halt (255);  { register application's class        }   { Create the main application window                                        }   Wnd := CreateWindowEx(WS_EX_CLIENTEDGE,                        AppName,              { class name                  }                        AppName,                { window caption text         }                      ws_Overlapped       or  { window style                }                      ws_SysMenu          or                        ws_MinimizeBox      or                        ws_ClipSiblings     or                      ws_ClipChildren     or  { don't affect children     }                        ws_visible,             { make showwindow unnecessary }                        50,                     { x pos on screen             }                        50,                   { y pos on screen             }                        400,                  { window width                }                        300,                  { window height               }                      0,                      { parent window handle        }                      0,                      { menu handle 0 = use class   }                      hInstance,              { instance handle             }                        Nil);                   { parameter sent to WM_CREATE }   if Wnd = 0 then Halt;                         { could not create the window }   while GetMessage (Msg, 0, 0, 0) do          { wait for message            }  begin    TranslateMessage (Msg);                   { key conversions             }    DispatchMessage  (Msg);                     { send to window procedure    }  end;   WinMain := Msg.wParam;                        { terminate with return code  }end; begin  WinMain;end. This example also shows how and when to capture the mouse to cause it to update the client area when necessary.  It also serves as an example for CreatePen, SelectObject, Rectangle and DeleteObject. ---------------------------------------------------------------------- FlierMate · 2021-01-21 11:09 Please allow me to ask two general questions here: 1. Can we say Windows API is a "framework"? 2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call? ---------------------------------------------------------------------- 440bx · 2021-01-21 11:57 Quote from: FlierMate on January 21, 2021, 12:09:54 pmPlease allow me to ask two general questions here: 1. Can we say Windows API is a "framework"? 2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call? All questions are welcome. To the first question, I don't consider the Windows API a framework because, unlike in a framework, a great number of APIs are completely independent of each other.  A framework usually incorporates a significant number of dependencies among the facilities it provides, e.g, .net. To the second question, a lot of people know _exactly_ how Windows executes its API functions.  A lot of API functions can be traced through using an application debugger.  APIs that cause a ring transition, that is from ring-3 to ring-0, can be traced through using a system debugger.  Another way to see exactly what an API does and, how it does it, is to disassemble the DLL that contains it. In summary, except for ring transition code and code that executes in ring 0, there is nothing particularly different between Windows API functions and run of the mill code that can be found in application code.  For instance, an API such as DebugBreak() can be written as a Pascal assembler routine in just two lines of assembly code.  Other APIs would require more code and yet other APIs would require calling functions present in Ntdll to trigger execution of ring-0 code (though, even those could be coded in Pascal but, why re-invent the wheel.) ---------------------------------------------------------------------- PascalDragon · 2021-01-21 12:57 Quote from: FlierMate on January 21, 2021, 12:09:54 pm2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call? In addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented (I've done that in the past a few times to find out how some API functions work). ---------------------------------------------------------------------- FlierMate · 2021-01-21 13:32 Quote from: PascalDragon on January 21, 2021, 01:57:29 pmIn addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented Whoa, I completely forgot an operating system is written NOT in Assembly language. ReactOS was written in C... Quote from: 440bx on January 21, 2021, 12:57:45 pmAll questions are welcome. Thank you for the assurance. Quote from: 440bx on January 21, 2021, 12:57:45 pm Another way to see exactly what an API does and, how it does it, is to disassemble the DLL that contains it. Never thought of that. I am delighted to know this. Quote from: 440bx on January 21, 2021, 12:57:45 pm For instance, an API such as DebugBreak() can be written as a Pascal assembler routine in just two lines of assembly code.  This makes sense to me. Quote from: PascalDragon on January 21, 2021, 01:57:29 pm(I've done that in the past a few times to find out how some API functions work). This means an operating system is not a secret. (I am new to the design of OS and just at very beginning level of design of compiler.) Besides CPU itself, an operating system is such a massive and intelligent work by men. As an off-topic question: I often saw someone comes up with real-time operating system on freelancer hiring website, is it a hoax?  It was thrilling to discover ReactOS open-source page. All contributors deserve respect! ---------------------------------------------------------------------- lucamar · 2021-01-21 15:27 Quote from: FlierMate on January 21, 2021, 02:32:42 pmAs an off-topic question: I often saw someone comes up with real-time operating system on freelancer hiring website, is it a hoax? Why would it be? Lots of people and business need real time OSs and there is not always one readily available for download/purchase; the obvious solution then is to contract some freelancer and pay them (oftentimes through the nose ) to build one, more or so as they usually have a very specific scope and need not be what we might term a "general purpose" OS. In fact, OS and application are frequently so interwoven that it's not very clear where one ends and the other starts. ---------------------------------------------------------------------- FlierMate · 2021-01-21 16:29 Quote from: lucamar on January 21, 2021, 04:27:21 pmWhy would it be? Lots of people and business need real time OSs and there is not always one readily available for download/purchase; the obvious solution then is to contract some freelancer and pay them (oftentimes through the nose ) to build one, more or so as they usually have a very specific scope and need not be what we might term a "general purpose" OS. In fact, OS and application are frequently so interwoven that it's not very clear where one ends and the other starts. I have better understanding now. Thanks lucamar. ---------------------------------------------------------------------- PascalDragon · 2021-01-22 08:09 Quote from: FlierMate on January 21, 2021, 02:32:42 pmQuote from: PascalDragon on January 21, 2021, 01:57:29 pmIn addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented Whoa, I completely forgot an operating system is written NOT in Assembly language. ReactOS was written in C... Windows itself is written in C as well. As is Linux. There are also OSes written in Pascal. Or essentially any language that can compile binary code. And yes, there are also examples in assembly language. Quote from: FlierMate on January 21, 2021, 02:32:42 pmAs an off-topic question: I often saw someone comes up with real-time operating system on freelancer hiring website, is it a hoax? Depends on whether the developers know what they're doing. At work we have a custom realtime, microkernel operating system as well. ---------------------------------------------------------------------- FlierMate · 2021-03-01 13:40 Quote from: PascalDragon on January 21, 2021, 01:57:29 pmQuote from: FlierMate on January 21, 2021, 12:09:54 pm2. Windows API is at the lowest level. Does that mean literally nobody knows how Windows execute the API call? In addition to what 440bx said: if you're really curious you can look around in ReactOS' source code and find out how some calls are implemented (I've done that in the past a few times to find out how some API functions work). Hi PascalDragon and 440bx. I took about an hour to search and try to gain preliminary understanding about ReactOS in particular WriteConsoleA. I noticed that it uses RtlCopyMemory() function and I was not able to locate this function anywhere in the ReactOS kernel. Can you please help to locate which .c file contains this RtlCopyMemory function? I found some soundalike and lookalike functions but none are exactly spelled as RtlCopyMemory. Does that mean Windows (or React OS) has direct screen buffer access (WriteConsoleA in this case) and that the OS prohibits end -user from accessing the video memory? Unlike back in DOS era, programmers can read from and write to B800:0 (80x25 x 2) and A000:0 (graphics memory). ---------------------------------------------------------------------- lucamar · 2021-03-01 14:21 Quote from: FlierMate on March 01, 2021, 02:40:30 pmDoes that mean Windows (or React OS) has direct screen buffer access (WriteConsoleA in this case) and that the OS prohibits end -user from accessing the video memory? Unlike back in DOS era, programmers can read from and write to B800:0 (80x25 x 2) and A000:0 (graphics memory). I don't know about more modern Windows but we have a program running on Windows 2K and XP which does exactly that for console output (through B800). Only, IIRC (I'm not the responsible for that program anymore), the program has to be run under very specific conditions: full screen, un-windowed, with a special info file (.PIF), ... and don't remember what else we had to do (something about the video mode, I think). But that is for somewhat special "industrial PCs" resembling thickly rugerized tablets more than anything else, and they might have special hardware or drivers or whatnots, so YMMV! ---------------------------------------------------------------------- 440bx · 2021-03-01 15:57 Quote from: FlierMate on March 01, 2021, 02:40:30 pmI noticed that it uses RtlCopyMemory() function and I was not able to locate this function anywhere in the ReactOS kernel. RtlCopyMemory is found in the 64bit version of NTDLL and _not_ found in the 32bit version.  Also, in 64bit just FYI, RtlCopyMemory, RtlMoveMemory, memcpy and memmov are the same function (the export entries all point to the same routine.)  In 32bit, every one of those functions (those that exist) have their own implementation.  Quote from: FlierMate on March 01, 2021, 02:40:30 pmCan you please help to locate which .c file contains this RtlCopyMemory function? I found some soundalike and lookalike functions but none are exactly spelled as RtlCopyMemory. It's quite possible that RtlCopyMemory is not present in ReactOS since it is _not_ present in the 32bit version of NTDLL in Windows.  You can use RtlMoveMemory instead which effectively makes a copy of whatever is moved (it doesn't clear the source buffer, thus the target of the move is a copy.) Quote from: FlierMate on March 01, 2021, 02:40:30 pmDoes that mean Windows (or React OS) has direct screen buffer access (WriteConsoleA in this case) and that the OS prohibits end -user from accessing the video memory? Unlike back in DOS era, programmers can read from and write to B800:0 (80x25 x 2) and A000:0 (graphics memory). The answer to that is yes and no.  If the application is a dos application then it is run in a dos VM in full screen.  Since the program is running in a VM its video memory is virtualized and pretty much works just as it would under dos.  The "No" part comes when dealing with a 32bit or 64bit console application.  Those are _not_ virtualized instead they are clients of the facility Windows provides to emulate a character subsystem (conhost.exe in Win7+ and a different thing I don't remember at this time in WinXP.)  The application has access to the video buffer but in a different way than it is done under dos.  Specifically, the video buffer could be anywhere in memory and the character emulator has to be "informed" that it should display on screen whatever is in the buffer by means of console functions. HTH. In case you are interested, what follows is the 64bit implementation of RtlCopyMemory (and its synonyms, of course) : Code: ASM  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ; Exported entry 685. RtlCopyMemory; Exported entry 1041. RtlMoveMemory; Exported entry 1926. memcpy; Exported entry 1928. memmove ; =============== S U B R O U T I N E =======================================  ; void *__cdecl memmove(void *, const void *, size_t)                public memmovememmove         proc near               ; CODE XREF: RtlpEnsureBufferSize+6Fp                                        ; RtlpQueryInformationActivationContextDetailedInformation+1F9p ...              mov     r11, rcx        ; RtlCopyMemory                                      ; RtlMoveMemory                                      ; memcpy                sub     rdx, rcx                jb      loc_78E9E89A                cmp     r8, 8                jb      short loc_78E9E764                test    cl, 7                jz      short loc_78E9E73E                test    cl, 1                jz      short loc_78E9E718                mov     al, [rdx+rcx]                dec   r8                mov     [rcx], al                add     rcx, 1 loc_78E9E718:                           ; CODE XREF: memmove+1Aj              test    cl, 2                jz      short loc_78E9E72C              mov     ax, [rdx+rcx]                sub     r8, 2              mov     [rcx], ax                add     rcx, 2 loc_78E9E72C:                         ; CODE XREF: memmove+2Bj                test    cl, 4                jz      short loc_78E9E73E                mov   eax, [rcx+rdx]                sub     r8, 4                mov     [rcx], eax                add     rcx, 4 loc_78E9E73E:                         ; CODE XREF: memmove+15j memmove+3Fj ...                mov     r9, r8                shr     r9, 5                jnz     short loc_78E9E797 loc_78E9E747:                           ; CODE XREF: memmove+E0j                mov     r9, r8                shr   r9, 3                jz      short loc_78E9E764 loc_78E9E750:                         ; CODE XREF: memmove+6Ej                mov     rax, [rdx+rcx]                mov     [rcx], rax                add   rcx, 8                dec     r9                jnz     short loc_78E9E750                and     r8, 7 loc_78E9E764:                         ; CODE XREF: memmove+10j memmove+5Ej                test    r8, r8                jnz     short loc_78E9E770                mov   rax, r11                retn; ------------------------------------- --------------------------------------                align 10h loc_78E9E770:                           ; CODE XREF: memmove+77j memmove+8Bj                mov     al, [rdx+rcx]                mov   [rcx], al                inc     rcx                dec     r8              jnz     short loc_78E9E770                mov     rax, r11              retn; ---------------------------------------------------- -----------------------                db 7 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)                db 3 dup(66h), 90h                db 2 dup(66h), 90h; ----------------------------------------------------------------- ---------- loc_78E9E797:                           ; CODE XREF: memmove+55j                cmp     r9, 2000h                jnb     short loc_78E9E7E2 loc_78E9E7A0:                           ; CODE XREF: memmove+DAj memmove+F9j                mov     rax, [rdx+rcx]                mov     r10, [rdx+rcx+8]                add     rcx, 20h                mov     [rcx-20h], rax                mov     [rcx-18h], r10                mov     rax, [rdx+rcx-10h]              mov     r10, [rdx+rcx-8]                dec     r9                mov     [rcx-10h], rax                mov     [rcx-8], r10                jnz     short loc_78E9E7A0                and     r8, 1Fh              jmp     loc_78E9E747; ---------------------------------------------- -----------------------------                db 3 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)                db 66h, 90h; ---------------------------- ----------------------------------------------- loc_78E9E7E2:                         ; CODE XREF: memmove+AEj                cmp     rdx, 1000h                jb      short loc_78E9E7A0 loc_78E9E7EB:                         ; CODE XREF: memmove+184j                mov     eax, 20h loc_78E9E7F0:                           ; CODE XREF: memmove+112j                prefetchnta byte ptr [rdx+rcx]              prefetchnta byte ptr [rdx+rcx+40h]                add     rcx, 80h                dec     eax                jnz     short loc_78E9E7F0                sub     rcx, 1000h                mov     eax, 40h loc_78E9E810:                           ; CODE XREF: memmove+174j                mov     r9, [rdx+rcx]                mov   r10, [rdx+rcx+8]                movnti  qword ptr [rcx], r9              movnti  qword ptr [rcx+8], r10                mov     r9, [rdx+rcx+10h]                mov     r10, [rdx+rcx+18h]              movnti  qword ptr [rcx+10h], r9                movnti  qword ptr [rcx+18h], r10                mov     r9, [rdx+rcx+20h]              mov     r10, [rdx+rcx+28h]                add     rcx, 40h              movnti  qword ptr [rcx-20h], r9                movnti  qword ptr [rcx-18h], r10                mov     r9, [rdx+rcx-10h]              mov     r10, [rdx+rcx-8]                dec     eax                movnti  qword ptr [rcx-10h], r9                movnti  qword ptr [rcx-8], r10                jnz     short loc_78E9E810                sub     r8, 1000h                cmp     r8, 1000h                jnb   loc_78E9E7EB                lock or byte ptr [rsp+0], 0              jmp     loc_78E9E73E; --------------------------------------------- ------------------------------                db 4 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)                db 3 dup(66h), 90h                db 3 dup(66h), 90h                db 66h, 90h; ---------------------------- ----------------------------------------------- loc_78E9E89A:                         ; CODE XREF: memmove+6j                add     rcx, r8                cmp     r8, 8                jb      short loc_78E9E904                test    cl, 7                jz      short loc_78E9E8DE                test    cl, 1                jz      short loc_78E9E8B8                dec     rcx                mov     al, [rdx+rcx]                dec     r8                mov     [rcx], al loc_78E9E8B8:                           ; CODE XREF: memmove+1BBj                test    cl, 2                jz      short loc_78E9E8CC                sub     rcx, 2                mov     ax, [rdx+rcx]              sub     r8, 2                mov     [rcx], ax loc_78E9E8CC:                           ; CODE XREF: memmove+1CBj                test    cl, 4                jz      short loc_78E9E8DE              sub     rcx, 4                mov     eax, [rcx+rdx]                sub     r8, 4                mov     [rcx], eax loc_78E9E8DE:                         ; CODE XREF: memmove+1B6j memmove+1DFj ...              mov     r9, r8                shr     r9, 5                jnz   short loc_78E9E937 loc_78E9E8E7:                           ; CODE XREF: memmove+27Fj                mov     r9, r8                shr   r9, 3                jz      short loc_78E9E904 loc_78E9E8F0:                         ; CODE XREF: memmove+20Ej                sub     rcx, 8                mov     rax, [rdx+rcx]                dec     r9                mov     [rcx], rax                jnz     short loc_78E9E8F0                and     r8, 7 loc_78E9E904:                         ; CODE XREF: memmove+1B1j memmove+1FEj                test    r8, r8                jnz     short loc_78E9E910              mov     rax, r11                retn; ------------------------------- --------------------------------------------                align 10h loc_78E9E910:                           ; CODE XREF: memmove+217j memmove+22Bj                dec     rcx                mov     al, [rdx+rcx]                dec     r8                mov     [rcx], al              jnz     short loc_78E9E910                mov     rax, r11                retn; --------------------------------------------- ------------------------------                db 7 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)                db 3 dup(66h), 90h                db 2 dup(66h), 90h; ------------------------------------------------------- -------------------- loc_78E9E937:                           ; CODE XREF: memmove+1F5j                cmp     r9, 2000h                jnb     short loc_78E9E982 loc_78E9E940:                           ; CODE XREF: memmove+279j memmove+299j                mov     rax, [rdx+rcx-8]                mov     r10, [rdx+rcx-10h]                sub     rcx, 20h                mov     [rcx+18h], rax                mov     [rcx+10h], r10                mov     rax, [rdx+rcx+8]              mov     r10, [rdx+rcx]                dec     r9              mov     [rcx+8], rax                mov     [rcx], r10                jnz     short loc_78E9E940                and     r8, 1Fh              jmp     loc_78E9E8E7; ---------------------------------------------- -----------------------------                db 4 dup(66h), 0Fh, 1Fh, 84h, 5 dup(0)                db 66h, 90h; ---------------------------- ----------------------------------------------- loc_78E9E982:                         ; CODE XREF: memmove+24Ej                cmp     rdx, 0FFFFFFFFFFFFF000h                ja      short loc_78E9E940 loc_78E9E98B:                           ; CODE XREF: memmove+324j                mov     eax, 20h loc_78E9E990:                         ; CODE XREF: memmove+2B2j                sub     rcx, 80h                prefetchnta byte ptr [rdx+rcx]                prefetchnta byte ptr [rdx+rcx+40h]                dec     eax              jnz     short loc_78E9E990                add     rcx, 1000h              mov     eax, 40h loc_78E9E9B0:                           ; CODE XREF: memmove+314j                mov     r9, [rdx+rcx-8]              mov     r10, [rdx+rcx-10h]                movnti  qword ptr [rcx-8], r9                movnti  qword ptr [rcx-10h], r10              mov     r9, [rdx+rcx-18h]                mov     r10, [rdx+rcx-20h]                movnti  qword ptr [rcx-18h], r9              movnti  qword ptr [rcx-20h], r10                mov     r9, [rdx+rcx-28h]                mov     r10, [rdx+rcx-30h]              sub     rcx, 40h                movnti  qword ptr [rcx+18h], r9              movnti  qword ptr [rcx+10h], r10                mov     r9, [rdx+rcx+8]                mov     r10, [rdx+rcx]                dec   eax                movnti  qword ptr [rcx+8], r9                movnti  qword ptr [rcx], r10                jnz     short loc_78E9E9B0                sub     r8, 1000h                cmp     r8, 1000h                jnb     loc_78E9E98B                lock or byte ptr [rsp+0], 0                jmp     loc_78E9E8DEmemmove       endp ---------------------------------------------------------------------- FlierMate · 2021-03-02 13:55 Thanks @lucamar for your additional information. 32-bit Windows still allows 16-bit DOS programs to run. I do not know about Windows 2000 and XP, but Windows 10 32-bit needs NTVDM (Virtual DOS Machine) feature turned on to run legacy apps. Thanks @440bx for the lengthy information. No wonder I could not find the function in ReactOS since it is not available in 32-bit. The ASM dump is interesting, I thought I would expect CPU instruction like: Code: ASM  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i rep stosbBut I did not notice any of this. My old DOS program actually use the code above to copy image data to A000:0 video memory. You are more competent (in study of operating system and portable executable) than what I initially thought. ---------------------------------------------------------------------- PascalDragon · 2021-03-03 08:04 Quote from: FlierMate on March 02, 2021, 02:55:34 pmThe ASM dump is interesting, I thought I would expect CPU instruction like: Code: ASM  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i rep stosbBut I did not notice any of this. My old DOS program actually use the code above to copy image data to A000:0 video memory. That's because rep stosb is slow (at least compared with other instructions). There might not be much difference with small amount of data, but for large sizes it's noticeable. Also it does not handle the case of overlapping source and target areas. Take a look for example at FPC's Move implementation (you can find them in the CPU specific directories of the RTL, e.g. for x86_64 it would be $fpcdir\rtl\x86_64\x86_64.inc). ---------------------------------------------------------------------- FlierMate · 2021-03-04 12:16 Quote from: PascalDragon on March 03, 2021, 09:04:09 amTake a look for example at FPC's Move implementation (you can find them in the CPU specific directories of the RTL, e.g. for x86_64 it would be $fpcdir\rtl\x86_64\x86_64.inc). I am still downloading it, it is quite thrilling knowing I would be looking at source of my favorite compiler. Quote from: PascalDragon on March 03, 2021, 09:04:09 amThat's because rep stosb is slow (at least compared with other instructions). There might not be much difference with small amount of data, but for large sizes it's noticeable. Also it does not handle the case of overlapping source and target areas. Do they still use "CPU cycles" per instruction to find out the speed?