{"id":104147,"date":"2020-09-01T07:00:00","date_gmt":"2020-09-01T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104147"},"modified":"2020-09-09T06:09:30","modified_gmt":"2020-09-09T13:09:30","slug":"20200901-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200901-00\/?p=104147","title":{"rendered":"More on trivial functions like CopyRect and EqualRect"},"content":{"rendered":"<p>Some time ago, I discussed <a title=\"Why are there trivial functions like CopyRect and EqualRect?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200224-00\/?p=103472\"> trivial functions like <code>CopyRect<\/code> and <code>EqualRect<\/code><\/a> and why they even exist at all.<\/p>\n<p>Piotr Si\u00f3dmak wondered <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200224-00\/?p=103472#comment-136252\"> if you could just use <code>memcpy<\/code> to copy a rectangle<\/a>. &#8220;It&#8217;s already there and probably already used by other parts of code, so it&#8217;s 0 bytes of overhead.&#8221;<\/p>\n<p>One of the features of <code>CopyRect<\/code> and friends is that they all take far pointers to <code>RECT<\/code>. This means that you can use them to manipulate rectangles received from the operating system, even if your program uses <a title=\"A look back at memory models in 16-bit MS-DOS\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200728-00\/?p=104012\"> the small or medium memory model<\/a>.<\/p>\n<p>The <code>memcpy<\/code> version of <code>CopyRect<\/code> would actually be <code>_fmemcpy<\/code> in order to support far pointers. And since it&#8217;s a C runtime function, it would follow the <code>__cdecl<\/code> calling convention, which is caller-clean. And you would have to pass an extra parameter to represent the size of a rectangle.<\/p>\n<pre><span style=\"color: blue;\">b8 08 00        mov  ax, 8          ; sizeof(RECT)\u00b9\r\n50              push ax<\/span>\r\nc4 5e f0        les  bx, [bp-10]    ; es:bx -&gt; source rect\r\n53              push bx\r\n06              push es\r\nc4 5e ec        les  bx, [bp-14]    ; es:bx -&gt; destination rect\r\n53              push bx\r\n06              push es\r\n9a xx xx xx xx  call _fmemcpy\r\n<span style=\"color: blue;\">83 c4 0a        add  sp, 10         ; clean the stack<\/span>\r\n<\/pre>\n<p>This adds seven bytes to the code size.<\/p>\n<p>But it&#8217;s worse than that. You also have to <a title=\"I wrote FAT on an airplane, for heaven's sake\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20131008-00\/?p=3003\"> segment-tune<\/a> your <code>_fmemcpy<\/code> function: Which functions are you going to put into a single segment for code swapping purposes? Maybe copying rectangles is something your program does constantly, so you want to keep it in your &#8220;hot&#8221; segment. Or maybe it&#8217;s something you do only occasionally, in which case you would put it in one of the more rarely-used segments. It means that when you do get around to copying a rectangle, you may have to pause to load the <code>_fmemcpy<\/code> function off the floppy drive.<\/p>\n<p>And since the function is linked into your program, it means that if you are running five programs, each of them will have its own copy of <code>_fmemcpy<\/code>, with various other functions coming along for the ride in the same segments.<\/p>\n<p>Why not just use the copy that the window manager already has?<\/p>\n<p>The rectangle functions are in a &#8220;fixed&#8221; segment in the window manager, meaning that it is permanently loaded and cannot get swapped out. Calling it is basically free. You will never incur a segment swap by calling <code>CopyRect<\/code> or <code>EqualRect<\/code>. No need to create five private copies of a function and swap them in and out. Just use the one copy that the system already provides. That&#8217;ll help you fit your program into 256KB of memory.<\/p>\n<p><b>Bonus chatter<\/b>: The <code>Copy\u00adRect<\/code> function is also more efficient than a general-purpose <code>_fmemcpy<\/code> since it knows that it&#8217;s copying exactly eight bytes. The <code>_fmemcpy<\/code> function needs to support arbitrary-sized memory blocks, so it will spend extra time preparing for a block copy operation for maximum speed, even though that speed gain is not realized on such small copies.<\/p>\n<p>\u00b9 Why not use the two-byte <code>push 8<\/code> instruction? Because this is 8086 code, and the two-byte &#8220;push sign-extended 8-bit immediate&#8221; instruction didn&#8217;t exist. It was first available in the 80186 processor.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s go code golfing.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-104147","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Let&#8217;s go code golfing.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104147","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=104147"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104147\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=104147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}