{"id":100835,"date":"2019-01-30T23:00:00","date_gmt":"2019-01-31T14:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100835"},"modified":"2019-03-18T11:13:23","modified_gmt":"2019-03-18T18:13:23","slug":"20190131-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190130-00\/?p=100835","title":{"rendered":"The Intel 80386, part 9: Stack frame instructions"},"content":{"rendered":"<p>There are a pair of specialized instructions for creating and tearing down stack frames. <\/p>\n<pre>\n    ENTER   i16, 0      ; push ebp\n                        ; mov ebp, esp\n                        ; sub esp, (uint16_t)i16\n<\/pre>\n<p>The <code>ENTER<\/code> instruction sets up a stack frame for a new subroutine. It combines three instructions into one, so that what used to be encoded in eight bytes (1 + 2 + 5) is now encoded in four. However, even on the 80386, the combination instruction executes more slowly than the three component instructions, so this was always a size optimization, not a speed optimization. <\/p>\n<pre>\n    LEAVE               ; mov esp, ebp\n                        ; pop ebp\n<\/pre>\n<p>The <code>LEAVE<\/code> instruction tears down the stack frame by reversing the effects of the <code>ENTER<\/code> instruction. This is a one-byte instruction that replaces two instructions that together require three bytes (2 + 1), so it is a size optimization. But it also executes faster than the two instructions it replaces, so it is also a speed optimization. <\/p>\n<p>Modern compilers avoid the <code>ENTER<\/code> instruction but keep the <code>LEAVE<\/code> instruction. <\/p>\n<p><b>Bonus chatter<\/b>: What&#8217;s with the second operand of the <code>ENTER<\/code> instruction? <\/p>\n<p>In C code, the second operand is always zero because C doesn&#8217;t support lexically-nested procedures with inherited stack frames. So in practice, you will always see zero as the second parameter. <\/p>\n<p>The second parameter can go up to 15, and it represents the number of additional values pushed onto the stack after pushing <var>ebp<\/var>. <\/p>\n<pre>\n    ENTER   i16, n      ; push ebp\n                        ;<span STYLE=\"border: solid 1px black;border-bottom: none\"> sub ebp, 4 <\/span> &#x23b1; <span>n times<\/span>\n                        ;<span STYLE=\"border: solid 1px black;border-top: none\"> push [ebp] <\/span> &#x23b0;\n                        ; mov ebp, esp\n                        ; sub esp, (uint16_t)i16\n<\/pre>\n<p>This means that the <code>ENTER<\/code> instruction can read as many as fifteen 32-bit values from memory and can write as many as sixteen 32-bit values to memory. That&#8217;s a lot of memory access for a single instruction. <\/p>\n<p><a HREF=\"http:\/\/devblogs.microsoft.com\/oldnewthing\/20190201-00\/?p=100845\">Next time<\/a>, we&#8217;ll look at atomic operations and memory alignment. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>For creating and tearing down stack frames.<\/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-100835","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>For creating and tearing down stack frames.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100835","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=100835"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100835\/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=100835"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100835"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100835"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}