{"id":101028,"date":"2019-02-03T23:00:00","date_gmt":"2019-02-04T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=101028"},"modified":"2019-03-18T11:15:27","modified_gmt":"2019-03-18T18:15:27","slug":"20190204-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190203-00\/?p=101028","title":{"rendered":"The Intel 80386, part 11: The TEB"},"content":{"rendered":"<p>The 80386 does not have a lot of registers. But there needs to be a place to record per-thread information. For performance reasons, this should be something available in user mode, to avoid a kernel transition. But where do we keep it? We don&#8217;t want to burn a precious general-purpose register to hold this value. <\/p>\n<p>Ah, but there are some available registers: The segment registers! There are six segment registers on the 80386: <\/p>\n<table BORDER=\"1\" CLASS=\"cp3\" CELLPADDING=\"3\" STYLE=\"border-collapse: collapse\">\n<tr>\n<th>Segment<\/th>\n<th>Mnemonic<\/th>\n<\/tr>\n<tr>\n<td><var>ss<\/var><\/td>\n<td>stack segment<\/td>\n<\/tr>\n<tr>\n<td><var>cs<\/var><\/td>\n<td>code segment<\/td>\n<\/tr>\n<tr>\n<td><var>ds<\/var><\/td>\n<td>data segment<\/td>\n<\/tr>\n<tr>\n<td><var>es<\/var><\/td>\n<td>extra segment<\/td>\n<\/tr>\n<tr>\n<td><var>fs<\/var><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><var>gs<\/var><\/td>\n<td><\/td>\n<\/tr>\n<\/table>\n<p>The previous versions of the processor had only <var>ss<\/var>, <var>cs<\/var>, <var>ds<\/var>, and <var>es<\/var>. The 80386 added two new segment registers, which were named <var>fs<\/var> and <var>gs<\/var> to continue the alphabetic pattern, but the letters <i>f<\/i> and <i>g<\/i> don&#8217;t have any mnemonic significance. <\/p>\n<p>The first four segments have architectural meaning. The stack segment is used by instructions that access the stack, either implicitly via instructions like <code>PUSH<\/code>, or explicitly by accessing memory with the <var>esp<\/var> or <var>ebp<\/var> registers. The code segment specifies which segment the instruction pointer is reading from. The data segment is used by most memory-access instructions, and the extra segment is used by the block operation instructions. <\/p>\n<p>But the two bonus segment registers aren&#8217;t architecturally significant. We can use them for anything! <\/p>\n<p>On the 80386, Windows uses the <var>fs<\/var> segment register to access a small block of memory that is associated with each thread, known as the Thread Environment Block, or TEB. <\/p>\n<p>To access memory relative to a specific segment register, you prefix the segment register and a colon to the memory reference. <\/p>\n<pre>\n    MOV     eax, fs:[0]        ; eax = memory at offset 0 in segment fs\n<\/pre>\n<p>The part of the TEB you&#8217;re going to see most often is the memory at offset 0, which is the head of a linked list of structured exception handling records threaded through the stack. The 80386 is unusual in that it&#8217;s the only architecture which executes instructions at runtime to manage exception handling state. All the other architectures use tables generated at compile time, so that there is no runtime penalty. <\/p>\n<p>Windows on the 80386 does not use the <var>gs<\/var> register for anything as far as I can tell. <\/p>\n<p><a HREF=\"http:\/\/devblogs.microsoft.com\/oldnewthing\/20190205-00\/?p=101030\">Next time<\/a>, I&#8217;m going to break my promise and cover the instructions that you will never see. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I need another register, let&#8217;s see what scraps I can find.<\/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-101028","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>I need another register, let&#8217;s see what scraps I can find.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/101028","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=101028"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/101028\/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=101028"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=101028"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=101028"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}