about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--subx/011run.cc139
-rw-r--r--subx/013direct_addressing.cc84
-rw-r--r--subx/014indirect_addressing.cc142
-rw-r--r--subx/015immediate_addressing.cc124
-rw-r--r--subx/016index_addressing.cc20
-rw-r--r--subx/017jump_disp8.cc28
-rw-r--r--subx/018jump_disp32.cc28
-rw-r--r--subx/019functions.cc12
-rw-r--r--subx/021byte_addressing.cc14
-rw-r--r--subx/022div.cc4
-rw-r--r--subx/028translate.cc9
-rw-r--r--subx/030---operands.cc18
-rw-r--r--subx/031check_operands.cc38
-rw-r--r--subx/032check_operand_bounds.cc18
-rw-r--r--subx/034compute_segment_address.cc125
-rw-r--r--subx/035labels.cc28
-rw-r--r--subx/036global_variables.cc72
-rw-r--r--subx/038---literal_strings.cc15
-rw-r--r--subx/040---tests.cc4
-rw-r--r--subx/049memory_layout.subx8
-rw-r--r--subx/Readme.md7
-rw-r--r--subx/examples/ex1.subx2
-rw-r--r--subx/examples/ex10.subx2
-rw-r--r--subx/examples/ex11.subx4
-rw-r--r--subx/examples/ex12.subx4
-rw-r--r--subx/examples/ex2.subx2
-rw-r--r--subx/examples/ex3.subx2
-rwxr-xr-xsubx/examples/ex4bin171 -> 171 bytes
-rw-r--r--subx/examples/ex4.subx13
-rw-r--r--subx/examples/ex5.subx2
-rw-r--r--subx/examples/ex6.subx4
-rw-r--r--subx/examples/ex7.subx4
-rw-r--r--subx/examples/ex8.subx2
-rw-r--r--subx/examples/ex9.subx2
-rwxr-xr-xsubx/test_apps14
-rwxr-xr-xsubx/test_layers1
36 files changed, 481 insertions, 514 deletions
diff --git a/subx/011run.cc b/subx/011run.cc
index 236401b8..319cbfb3 100644
--- a/subx/011run.cc
+++ b/subx/011run.cc
@@ -13,15 +13,15 @@ put_new(Help, "syntax",
   "(start of line, or following a space).\n"
   "\n"
   "Each segment starts with a header line: a '==' delimiter followed by the name of\n"
-  "the segment.\n"
+  "the segment and a (sometimes approximate) starting address in memory.\n"
+  "The name 'code' is special; instructions to execute should always go here.\n"
   "\n"
-  "The first segment contains code and should be called 'code'.\n"
-  "The second segment should be called 'data'.\n"
-  "The resulting binary starts running from the start of the code segment by default.\n"
+  "The resulting binary starts running from the start of the segment by default.\n"
   "To start elsewhere in the code segment, define a special label called 'Entry'.\n"
   "\n"
   "Segments with the same name get merged together. This rule helps keep functions and\n"
   "their data close together in .subx files.\n"
+  "You don't have to specify the starting address after the first time.\n"
   "\n"
   "Lines consist of a series of words. Words can contain arbitrary metadata\n"
   "after a '/', but they can never contain whitespace. Metadata has no effect\n"
@@ -35,16 +35,16 @@ put_new(Help, "syntax",
 cerr << "  syntax\n";
 
 :(code)
-void test_add_imm32_to_EAX() {
+void test_copy_imm32_to_EAX() {
   // At the lowest level, SubX programs are a series of hex bytes, each
   // (variable-length) instruction on one line.
   run(
       // Comments start with '#' and are ignored.
       "# comment\n"
-      // Segment headers start with '==' and a name or starting hex address.
+      // Segment headers start with '==', a name and a starting hex address.
       // There's usually one code and one data segment. The code segment
       // always comes first.
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
 
       // After the header, each segment consists of lines, and each line
       // consists of words separated by whitespace.
@@ -107,6 +107,7 @@ struct program {
 };
 :(before "struct program")
 struct segment {
+  string name;
   uint32_t start;
   vector<line> lines;
   // End segment Fields
@@ -132,6 +133,7 @@ struct word {
 
 :(code)
 void parse(istream& fin, program& out) {
+  segment* curr_segment = NULL;
   vector<line> l;
   while (has_data(fin)) {
     string line_data;
@@ -148,19 +150,25 @@ void parse(istream& fin, program& out) {
       if (word_data[0] == '#') break;  // comment
       if (word_data == ".") continue;  // comment token
       if (word_data == "==") {
-        flush(out, l);
-        string segment_title;
-        lin >> segment_title;
-        if (starts_with(segment_title, "0x")) {
-          segment s;
-          s.start = parse_int(segment_title);
-          sanity_check_program_segment(out, s.start);
+        flush(curr_segment, l);
+        string segment_name;
+        lin >> segment_name;
+        curr_segment = find(out, segment_name);
+        if (curr_segment != NULL) {
+          trace(3, "parse") << "appending to segment '" << segment_name << "'" << end();
+        }
+        else {
+          trace(3, "parse") << "new segment '" << segment_name << "'" << end();
+          uint32_t seg_start = 0;
+          lin >> std::hex >> seg_start;
+          sanity_check_program_segment(out, seg_start);
+          out.segments.push_back(segment());
+          curr_segment = &out.segments.back();
+          curr_segment->name = segment_name;
+          curr_segment->start = seg_start;
           if (trace_contains_errors()) continue;
-          trace(3, "parse") << "new segment from 0x" << HEXWORD << s.start << end();
-          out.segments.push_back(s);
+          trace(3, "parse") << "starts at address 0x" << HEXWORD << curr_segment->start << end();
         }
-        // End Segment Parsing Special-cases(segment_title)
-        // todo: segment segment metadata
         break;  // skip rest of line
       }
       if (word_data[0] == ':') {
@@ -174,19 +182,27 @@ void parse(istream& fin, program& out) {
     if (!curr.words.empty())
       l.push_back(curr);
   }
-  flush(out, l);
+  flush(curr_segment, l);
   trace(99, "parse") << "done" << end();
 }
 
-void flush(program& p, vector<line>& lines) {
+segment* find(program& p, const string& segment_name) {
+  for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    if (p.segments.at(i).name == segment_name)
+      return &p.segments.at(i);
+  }
+  return NULL;
+}
+
+void flush(segment* s, vector<line>& lines) {
   if (lines.empty()) return;
-  if (p.segments.empty()) {
+  if (s == NULL) {
     raise << "input does not start with a '==' section header\n" << end();
     return;
   }
-  // End flush(p, lines) Special-cases
-  trace(99, "parse") << "flushing segment" << end();
-  p.segments.back().lines.swap(lines);
+  trace(3, "parse") << "flushing segment" << end();
+  s->lines.insert(s->lines.end(), lines.begin(), lines.end());
+  lines.clear();
 }
 
 void parse_word(const string& data, word& out) {
@@ -216,9 +232,9 @@ void parse(const string& text_bytes) {
 void test_detect_duplicate_segments() {
   Hide_errors = true;
   parse(
-      "== 0xee\n"
+      "== segment1 0xee\n"
       "ab\n"
-      "== 0xee\n"
+      "== segment2 0xee\n"
       "cd\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -242,7 +258,7 @@ void transform(program& p) {
 //:: load
 
 void load(const program& p) {
-  if (p.segments.empty()) {
+  if (find(p, "code") == NULL) {
     raise << "no code to run\n" << end();
     return;
   }
@@ -267,10 +283,20 @@ void load(const program& p) {
         ++addr;
       }
     }
-    if (i == 0) End_of_program = addr;
+    if (seg.name == "code") {
+      End_of_program = addr;
+      EIP = seg.start;
+      // End Initialize EIP
+    }
   }
-  EIP = p.segments.at(0).start;
-  // End Initialize EIP
+}
+
+const segment* find(const program& p, const string& segment_name) {
+  for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    if (p.segments.at(i).name == segment_name)
+      return &p.segments.at(i);
+  }
+  return NULL;
 }
 
 uint8_t hex_byte(const string& s) {
@@ -291,8 +317,8 @@ uint8_t hex_byte(const string& s) {
 void test_number_too_large() {
   Hide_errors = true;
   parse_and_load(
-      "== 0x1\n"
-      "05 cab\n"
+      "== code 0x1\n"
+      "01 cab\n"
   );
   CHECK_TRACE_CONTENTS(
       "error: token 'cab' is not a hex byte\n"
@@ -302,8 +328,8 @@ void test_number_too_large() {
 void test_invalid_hex() {
   Hide_errors = true;
   parse_and_load(
-      "== 0x1\n"
-      "05 cx\n"
+      "== code 0x1\n"
+      "01 cx\n"
   );
   CHECK_TRACE_CONTENTS(
       "error: token 'cx' is not a hex byte\n"
@@ -312,8 +338,8 @@ void test_invalid_hex() {
 
 void test_negative_number() {
   parse_and_load(
-      "== 0x1\n"
-      "05 -12\n"
+      "== code 0x1\n"
+      "01 -02\n"
   );
   CHECK_TRACE_COUNT("error", 0);
 }
@@ -321,8 +347,8 @@ void test_negative_number() {
 void test_negative_number_too_small() {
   Hide_errors = true;
   parse_and_load(
-      "== 0x1\n"
-      "05 -12345\n"
+      "== code 0x1\n"
+      "01 -12345\n"
   );
   CHECK_TRACE_CONTENTS(
       "error: token '-12345' is not a hex byte\n"
@@ -331,12 +357,41 @@ void test_negative_number_too_small() {
 
 void test_hex_prefix() {
   parse_and_load(
-      "== 0x1\n"
-      "0x05 -0x12\n"
+      "== code 0x1\n"
+      "0x01 -0x02\n"
   );
   CHECK_TRACE_COUNT("error", 0);
 }
 
+void test_repeated_segment_merges_data() {
+  parse_and_load(
+      "== code 0x1\n"
+      "11 22\n"
+      "== code\n"  // again
+      "33 44\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "parse: new segment 'code'\n"
+      "parse: appending to segment 'code'\n"
+      // first segment
+      "load: 0x00000001 -> 11\n"
+      "load: 0x00000002 -> 22\n"
+      // second segment
+      "load: 0x00000003 -> 33\n"
+      "load: 0x00000004 -> 44\n"
+  );
+}
+
+void test_error_on_missing_segment_header() {
+  Hide_errors = true;
+  parse_and_load(
+      "01 02\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "error: input does not start with a '==' section header\n"
+  );
+}
+
 //: helper for tests
 void parse_and_load(const string& text_bytes) {
   program p;
@@ -362,9 +417,9 @@ case 0xb8: {  // copy imm32 to EAX
 }
 
 :(code)
-void test_copy_imm32_to_EAX() {
+void test_copy_imm32_to_EAX_again() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  b8                                 0a 0b 0c 0d \n"  // copy 0x0d0c0b0a to EAX
   );
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc
index 9c314b02..ca76acfb 100644
--- a/subx/013direct_addressing.cc
+++ b/subx/013direct_addressing.cc
@@ -8,7 +8,7 @@ void test_add_r32_to_r32() {
   Reg[EAX].i = 0x10;
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  01     d8                                    \n" // add EBX to EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -47,7 +47,7 @@ void test_add_r32_to_r32_signed_overflow() {
   Reg[EAX].i = 0x7fffffff;  // largest positive signed integer
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  01     d8                                    \n" // add EBX to EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -64,7 +64,7 @@ void test_add_r32_to_r32_unsigned_overflow() {
   Reg[EAX].u = 0xffffffff;  // largest unsigned number
   Reg[EBX].u = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  01     d8                                    \n" // add EBX to EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -80,7 +80,7 @@ void test_add_r32_to_r32_unsigned_overflow() {
 void test_add_r32_to_r32_unsigned_and_signed_overflow() {
   Reg[EAX].u = Reg[EBX].u = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  01     d8                                    \n" // add EBX to EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -157,7 +157,7 @@ void test_subtract_r32_from_r32() {
   Reg[EAX].i = 10;
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  29     d8                                    \n"  // subtract EBX from EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -196,7 +196,7 @@ void test_subtract_r32_from_r32_signed_overflow() {
   Reg[EAX].i = 0x80000000;  // smallest negative signed integer
   Reg[EBX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  29     d8                                    \n"  // subtract EBX from EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -213,7 +213,7 @@ void test_subtract_r32_from_r32_unsigned_overflow() {
   Reg[EAX].i = 0;
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  29     d8                                    \n"  // subtract EBX from EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -230,7 +230,7 @@ void test_subtract_r32_from_r32_signed_and_unsigned_overflow() {
   Reg[EAX].i = 0;
   Reg[EBX].i = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  29     d8                                    \n"  // subtract EBX from EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -253,7 +253,7 @@ void test_multiply_EAX_by_r32() {
   Reg[EAX].i = 4;
   Reg[ECX].i = 3;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     e1                                    \n"  // multiply EAX by ECX
       // ModR/M in binary: 11 (direct mode) 100 (subop mul) 001 (src ECX)
@@ -302,7 +302,7 @@ void test_multiply_r32_into_r32() {
   Reg[EAX].i = 4;
   Reg[EBX].i = 2;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  0f af  d8                                    \n"  // subtract EBX into EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -338,7 +338,7 @@ case 0xaf: {  // multiply r32 by r/m32
 void test_negate_r32() {
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     db                                    \n"  // negate EBX
       // ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX)
@@ -378,7 +378,7 @@ case 3: {  // negate r/m32
 void test_negate_can_overflow() {
   Reg[EBX].i = 0x80000000;  // INT_MIN
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     db                                    \n"  // negate EBX
       // ModR/M in binary: 11 (direct mode) 011 (subop negate) 011 (dest EBX)
@@ -398,7 +398,7 @@ void test_divide_EAX_by_rm32() {
   Reg[EDX].u = 0;
   Reg[ECX].i = 3;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     f9                                    \n"  // multiply EAX by ECX
       // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX)
@@ -432,7 +432,7 @@ void test_divide_EAX_by_negative_rm32() {
   Reg[EDX].u = 0;
   Reg[ECX].i = -3;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     f9                                    \n"  // multiply EAX by ECX
       // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX)
@@ -451,7 +451,7 @@ void test_divide_negative_EAX_by_rm32() {
   Reg[EDX].i = -1;  // sign extend
   Reg[ECX].i = 3;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     f9                                    \n"  // multiply EAX by ECX
       // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX)
@@ -470,7 +470,7 @@ void test_divide_negative_EDX_EAX_by_rm32() {
   Reg[EDX].i = -7;
   Reg[ECX].i = 0x40000000;  // 2^30 (largest positive power of 2)
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     f9                                    \n"  // multiply EAX by ECX
       // ModR/M in binary: 11 (direct mode) 111 (subop idiv) 001 (divisor ECX)
@@ -494,7 +494,7 @@ void test_shift_left_r32_with_cl() {
   Reg[EBX].i = 13;
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     e3                                    \n"  // shift EBX left by CL bits
       // ModR/M in binary: 11 (direct mode) 100 (subop shift left) 011 (dest EBX)
@@ -547,7 +547,7 @@ void test_shift_right_arithmetic_r32_with_cl() {
   Reg[EBX].i = 26;
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     fb                                    \n"  // shift EBX right by CL bits, while preserving sign
       // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
@@ -579,7 +579,7 @@ void test_shift_right_arithmetic_odd_r32_with_cl() {
   Reg[EBX].i = 27;
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     fb                                    \n"  // shift EBX right by CL bits, while preserving sign
       // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
@@ -597,7 +597,7 @@ void test_shift_right_arithmetic_negative_r32_with_cl() {
   Reg[EBX].i = 0xfffffffd;  // -3
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     fb                                    \n"  // shift EBX right by CL bits, while preserving sign
       // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
@@ -618,7 +618,7 @@ void test_shift_right_logical_r32_with_cl() {
   Reg[EBX].i = 26;
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     eb                                    \n"  // shift EBX right by CL bits, while padding zeroes
       // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
@@ -657,7 +657,7 @@ void test_shift_right_logical_odd_r32_with_cl() {
   Reg[EBX].i = 27;
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     eb                                    \n"  // shift EBX right by CL bits, while padding zeroes
       // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
@@ -675,7 +675,7 @@ void test_shift_right_logical_negative_r32_with_cl() {
   Reg[EBX].i = 0xfffffffd;
   Reg[ECX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  d3     eb                                    \n"  // shift EBX right by CL bits, while padding zeroes
       // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
@@ -698,7 +698,7 @@ void test_and_r32_with_r32() {
   Reg[EAX].i = 0x0a0b0c0d;
   Reg[EBX].i = 0x000000ff;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  21     d8                                    \n"  // and EBX with destination EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -738,7 +738,7 @@ void test_or_r32_with_r32() {
   Reg[EAX].i = 0x0a0b0c0d;
   Reg[EBX].i = 0xa0b0c0d0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  09     d8                                    \n"  // or EBX with destination EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -778,7 +778,7 @@ void test_xor_r32_with_r32() {
   Reg[EAX].i = 0x0a0b0c0d;
   Reg[EBX].i = 0xaabbc0d0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  31     d8                                    \n"  // xor EBX with destination EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -814,7 +814,7 @@ case 0x31: {  // xor r32 with r/m32
 void test_not_r32() {
   Reg[EBX].i = 0x0f0f00ff;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  f7     d3                                    \n"  // not EBX
       // ModR/M in binary: 11 (direct mode) 010 (subop not) 011 (dest EBX)
@@ -846,7 +846,7 @@ void test_compare_r32_with_r32_greater() {
   Reg[EAX].i = 0x0a0b0c0d;
   Reg[EBX].i = 0x0a0b0c07;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  39     d8                                    \n"  // compare EAX with EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -883,7 +883,7 @@ void test_compare_r32_with_r32_lesser_unsigned_and_signed() {
   Reg[EAX].i = 0x0a0b0c07;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  39     d8                                    \n"  // compare EAX with EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -899,7 +899,7 @@ void test_compare_r32_with_r32_lesser_unsigned_and_signed_due_to_overflow() {
   Reg[EAX].i = 0x7fffffff;  // largest positive signed integer
   Reg[EBX].i = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  39     d8                                    \n"  // compare EAX with EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -915,7 +915,7 @@ void test_compare_r32_with_r32_lesser_signed() {
   Reg[EAX].i = 0xffffffff;  // -1
   Reg[EBX].i = 0x00000001;  // 1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  39     d8                                    \n"  // compare EAX with EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -931,7 +931,7 @@ void test_compare_r32_with_r32_lesser_unsigned() {
   Reg[EAX].i = 0x00000001;  // 1
   Reg[EBX].i = 0xffffffff;  // -1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  39     d8                                    \n"  // compare EAX with EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -947,7 +947,7 @@ void test_compare_r32_with_r32_equal() {
   Reg[EAX].i = 0x0a0b0c0d;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  39     d8                                    \n"  // compare EAX and EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -968,7 +968,7 @@ put_new(Name, "89", "copy r32 to rm32 (mov)");
 void test_copy_r32_to_r32() {
   Reg[EBX].i = 0xaf;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  89     d8                                    \n"  // copy EBX to EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -1001,7 +1001,7 @@ void test_xchg_r32_with_r32() {
   Reg[EBX].i = 0xaf;
   Reg[EAX].i = 0x2e;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  87     d8                                    \n"  // exchange EBX with EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
@@ -1044,7 +1044,7 @@ put_new(Name, "47", "increment EDI (inc)");
 void test_increment_r32() {
   Reg[ECX].u = 0x1f;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  41                                           \n"  // increment ECX
   );
@@ -1077,7 +1077,7 @@ put_new(Name, "ff", "increment/decrement/jump/push/call rm32 based on subop (inc
 void test_increment_rm32() {
   Reg[EAX].u = 0x20;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  ff     c0                                    \n"  // increment EAX
       // ModR/M in binary: 11 (direct mode) 000 (subop inc) 000 (EAX)
@@ -1126,7 +1126,7 @@ put_new(Name, "4f", "decrement EDI (dec)");
 void test_decrement_r32() {
   Reg[ECX].u = 0x1f;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  49                                           \n"  // decrement ECX
   );
@@ -1156,7 +1156,7 @@ case 0x4f: {  // decrement r32
 void test_decrement_rm32() {
   Reg[EAX].u = 0x20;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  ff     c8                                    \n"  // decrement EAX
       // ModR/M in binary: 11 (direct mode) 001 (subop inc) 000 (EAX)
@@ -1195,7 +1195,7 @@ void test_push_r32() {
   Reg[ESP].u = 0xbd000008;
   Reg[EBX].i = 0x0000000a;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  53                                           \n"  // push EBX to stack
   );
@@ -1240,10 +1240,10 @@ void test_pop_r32() {
   Reg[ESP].u = 0xbd000008;
   write_mem_i32(0xbd000008, 0x0000000a);  // ..before this write
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       // op     ModR/M  SIB   displacement  immediate
       "  5b                                           \n"  // pop stack to EBX
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"  // data segment
       "0a 00 00 00\n"  // 0x0000000a
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc
index ce523b3f..dd00c614 100644
--- a/subx/014indirect_addressing.cc
+++ b/subx/014indirect_addressing.cc
@@ -5,11 +5,11 @@ void test_add_r32_to_mem_at_r32() {
   Reg[EBX].i = 0x10;
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     18                                    \n"  // add EBX to *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -40,11 +40,11 @@ void test_add_mem_at_r32_to_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x10;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  03     18                                    \n"  // add *EAX to EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -81,11 +81,11 @@ void test_add_mem_at_r32_to_r32_signed_overflow() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  03     18                                    \n" // add *EAX to EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 1
   );
   CHECK_TRACE_CONTENTS(
@@ -101,11 +101,11 @@ void test_add_mem_at_r32_to_r32_unsigned_overflow() {
   Reg[EAX].u = 0x2000;
   Reg[EBX].u = 0xffffffff;  // largest unsigned number
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  03     18                                    \n" // add *EAX to EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -121,11 +121,11 @@ void test_add_mem_at_r32_to_r32_unsigned_and_signed_overflow() {
   Reg[EAX].u = 0x2000;
   Reg[EBX].u = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  03     18                                    \n" // add *EAX to EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "00 00 00 80\n"  // smallest negative signed integer
   );
   CHECK_TRACE_CONTENTS(
@@ -144,11 +144,11 @@ void test_subtract_r32_from_mem_at_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  29     18                                    \n"  // subtract EBX from *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0a 00 00 00\n"  // 0x0000000a
   );
   CHECK_TRACE_CONTENTS(
@@ -168,11 +168,11 @@ void test_subtract_mem_at_r32_from_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 10;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2b     18                                    \n"  // subtract *EAX from EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -209,11 +209,11 @@ void test_subtract_mem_at_r32_from_r32_signed_overflow() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2b     18                                    \n"  // subtract *EAX from EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "ff ff ff 7f\n"  // largest positive signed integer
   );
   CHECK_TRACE_CONTENTS(
@@ -229,11 +229,11 @@ void test_subtract_mem_at_r32_from_r32_unsigned_overflow() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2b     18                                    \n"  // subtract *EAX from EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 1
   );
   CHECK_TRACE_CONTENTS(
@@ -249,11 +249,11 @@ void test_subtract_mem_at_r32_from_r32_signed_and_unsigned_overflow() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2b     18                                    \n"  // subtract *EAX from EBX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "00 00 00 80\n"  // smallest negative signed integer
   );
   CHECK_TRACE_CONTENTS(
@@ -271,11 +271,11 @@ void test_and_r32_with_mem_at_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0xff;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  21     18                                    \n"  // and EBX with *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -295,11 +295,11 @@ void test_and_mem_at_r32_with_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  23     18                                    \n"  // and *EAX with EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "ff 00 00 00\n"  // 0x000000ff
   );
   CHECK_TRACE_CONTENTS(
@@ -334,11 +334,11 @@ void test_or_r32_with_mem_at_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0xa0b0c0d0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  09     18                                   #\n"  // EBX with *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -358,11 +358,11 @@ void test_or_mem_at_r32_with_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0xa0b0c0d0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0b     18                                    \n"  // or *EAX with EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -397,10 +397,10 @@ void test_xor_r32_with_mem_at_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0xa0b0c0d0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  31     18                                    \n"  // xor EBX with *EAX
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c bb aa\n"  // 0xaabb0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -420,11 +420,11 @@ void test_xor_mem_at_r32_with_r32() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0xa0b0c0d0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  33     18                                    \n"  // xor *EAX with EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -458,11 +458,11 @@ case 0x33: {  // xor r/m32 with r32
 void test_not_of_mem_at_r32() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  f7     13                                    \n"  // not *EBX
       // ModR/M in binary: 00 (indirect mode) 010 (subop not) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "ff 00 0f 0f\n"  // 0x0f0f00ff
   );
   CHECK_TRACE_CONTENTS(
@@ -480,11 +480,11 @@ void test_compare_mem_at_r32_with_r32_greater() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c07;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  39     18                                    \n"  // compare *EAX with EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -499,11 +499,11 @@ void test_compare_mem_at_r32_with_r32_lesser() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  39     18                                    \n"  // compare *EAX with EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "07 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -518,11 +518,11 @@ void test_compare_mem_at_r32_with_r32_equal() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  39     18                                    \n"  // compare *EAX and EBX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -542,11 +542,11 @@ void test_compare_r32_with_mem_at_r32_greater() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "07 0c 0b 0a\n"  // 0x0a0b0c07
   );
   CHECK_TRACE_CONTENTS(
@@ -580,11 +580,11 @@ void test_compare_r32_with_mem_at_r32_lesser_unsigned_and_signed() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c07;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -599,11 +599,11 @@ void test_compare_r32_with_mem_at_r32_lesser_unsigned_and_signed_due_to_overflow
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "00 00 00 80\n"  // smallest negative signed integer
   );
   CHECK_TRACE_CONTENTS(
@@ -618,11 +618,11 @@ void test_compare_r32_with_mem_at_r32_lesser_signed() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0xffffffff;  // -1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 1
   );
   CHECK_TRACE_CONTENTS(
@@ -637,11 +637,11 @@ void test_compare_r32_with_mem_at_r32_lesser_unsigned() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x00000001;  // 1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "ff ff ff ff\n"  // -1
   );
   CHECK_TRACE_CONTENTS(
@@ -656,11 +656,11 @@ void test_compare_r32_with_mem_at_r32_equal() {
   Reg[EAX].i = 0x2000;
   Reg[EBX].i = 0x0a0b0c0d;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3b     18                                    \n"  // compare EBX with *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0d 0c 0b 0a\n"  // 0x0a0b0c0d
   );
   CHECK_TRACE_CONTENTS(
@@ -676,7 +676,7 @@ void test_copy_r32_to_mem_at_r32() {
   Reg[EBX].i = 0xaf;
   Reg[EAX].i = 0x60;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  89     18                                    \n"  // copy EBX to *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
@@ -697,10 +697,10 @@ put_new(Name, "8b", "copy rm32 to r32 (mov)");
 void test_copy_mem_at_r32_to_r32() {
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  8b     18                                    \n"  // copy *EAX to EBX
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "af 00 00 00\n"  // 0x000000af
   );
   CHECK_TRACE_CONTENTS(
@@ -727,13 +727,13 @@ case 0x8b: {  // copy r32 to r/m32
 void test_jump_mem_at_r32() {
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  ff     20                                    \n"  // jump to *EAX
       // ModR/M in binary: 00 (indirect mode) 100 (jump to r/m32) 000 (src EAX)
       "  b8                                 00 00 00 01\n"
       "  b8                                 00 00 00 02\n"
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "08 00 00 00\n"  // 0x00000008
   );
   CHECK_TRACE_CONTENTS(
@@ -763,10 +763,10 @@ void test_push_mem_at_r32() {
   Mem.push_back(vma(0xbd000000));  // manually allocate memory
   Reg[ESP].u = 0xbd000014;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  ff     30                                    \n"  // push *EAX to stack
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "af 00 00 00\n"  // 0x000000af
   );
   CHECK_TRACE_CONTENTS(
@@ -797,7 +797,7 @@ void test_pop_mem_at_r32() {
   Reg[ESP].u = 0xbd000000;
   write_mem_i32(0xbd000000, 0x00000030);
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  8f     00                                    \n"  // pop stack into *EAX
       // ModR/M in binary: 00 (indirect mode) 000 (pop r/m32) 000 (dest EAX)
@@ -831,11 +831,11 @@ case 0x8f: {  // pop stack into r/m32
 void test_add_r32_to_mem_at_displacement() {
   Reg[EBX].i = 0x10;  // source
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     1d            00 20 00 00             \n"  // add EBX to *0x2000
       // ModR/M in binary: 00 (indirect mode) 011 (src EBX) 101 (dest in disp32)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -858,11 +858,11 @@ void test_add_r32_to_mem_at_r32_plus_disp8() {
   Reg[EBX].i = 0x10;  // source
   Reg[EAX].i = 0x1ffe;  // dest
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     58            02                      \n"  // add EBX to *(EAX+2)
       // ModR/M in binary: 01 (indirect+disp8 mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -893,11 +893,11 @@ void test_add_r32_to_mem_at_r32_plus_negative_disp8() {
   Reg[EBX].i = 0x10;  // source
   Reg[EAX].i = 0x2001;  // dest
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     58            ff                      \n"  // add EBX to *(EAX-1)
       // ModR/M in binary: 01 (indirect+disp8 mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -915,11 +915,11 @@ void test_add_r32_to_mem_at_r32_plus_disp32() {
   Reg[EBX].i = 0x10;  // source
   Reg[EAX].i = 0x1ffe;  // dest
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     98            02 00 00 00             \n"  // add EBX to *(EAX+2)
       // ModR/M in binary: 10 (indirect+disp32 mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -950,11 +950,11 @@ void test_add_r32_to_mem_at_r32_plus_negative_disp32() {
   Reg[EBX].i = 0x10;  // source
   Reg[EAX].i = 0x2001;  // dest
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     98            ff ff ff ff             \n"  // add EBX to *(EAX-1)
       // ModR/M in binary: 10 (indirect+disp32 mode) 011 (src EBX) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -974,7 +974,7 @@ put_new(Name, "8d", "copy address in rm32 into r32 (lea)");
 void test_copy_address() {
   Reg[EAX].u = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  8d     18                                    \n"  // copy address in EAX into EBX
       // ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX)
diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc
index 478e3592..782a16b9 100644
--- a/subx/015immediate_addressing.cc
+++ b/subx/015immediate_addressing.cc
@@ -27,7 +27,7 @@ case 0x05: {  // add imm32 to EAX
 void test_add_imm32_to_EAX_signed_overflow() {
   Reg[EAX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  05                                 01 00 00 00 \n" // add 1 to EAX
   );
@@ -42,7 +42,7 @@ void test_add_imm32_to_EAX_unsigned_overflow() {
   Reg[EAX].u = 0xffffffff;  // largest unsigned number
   Reg[EBX].u = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  05                                 01 00 00 00 \n" // add 1 to EAX
   );
@@ -56,7 +56,7 @@ void test_add_imm32_to_EAX_unsigned_overflow() {
 void test_add_imm32_to_EAX_unsigned_and_signed_overflow() {
   Reg[EAX].u = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  05                                 00 00 00 80 \n" // add 0x80000000 to EAX
   );
@@ -76,7 +76,7 @@ put_new(Name, "81", "combine rm32 with imm32 based on subop (add/sub/and/or/xor/
 void test_add_imm32_to_r32() {
   Reg[EBX].i = 1;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     c3                          0a 0b 0c 0d\n"  // add 0x0d0c0b0a to EBX
       // ModR/M in binary: 11 (direct mode) 000 (subop add) 011 (dest EBX)
@@ -129,7 +129,7 @@ case 0x81: {  // combine r/m32 with imm32
 void test_add_imm32_to_r32_signed_overflow() {
   Reg[EBX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     c3                          01 00 00 00\n"  // add 1 to EBX
       // ModR/M in binary: 11 (direct mode) 000 (subop add) 011 (dest EBX)
@@ -147,7 +147,7 @@ void test_add_imm32_to_r32_signed_overflow() {
 void test_add_imm32_to_r32_unsigned_overflow() {
   Reg[EBX].u = 0xffffffff;  // largest unsigned number
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     c3                          01 00 00 00\n"  // add 1 to EBX
       // ModR/M in binary: 11 (direct mode) 011 (subop add) 011 (dest EBX)
@@ -165,7 +165,7 @@ void test_add_imm32_to_r32_unsigned_overflow() {
 void test_add_imm32_to_r32_unsigned_and_signed_overflow() {
   Reg[EBX].u = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     c3                          00 00 00 80\n"  // add 0x80000000 to EBX
       // ModR/M in binary: 11 (direct mode) 011 (subop add) 011 (dest EBX)
@@ -186,11 +186,11 @@ void test_add_imm32_to_r32_unsigned_and_signed_overflow() {
 void test_add_imm32_to_mem_at_r32() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     03                          0a 0b 0c 0d \n"  // add 0x0d0c0b0a to *EBX
       // ModR/M in binary: 00 (indirect mode) 000 (subop add) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -211,7 +211,7 @@ put_new(Name, "2d", "subtract imm32 from EAX (sub)");
 void test_subtract_imm32_from_EAX() {
   Reg[EAX].i = 0x0d0c0baa;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2d                                 0a 0b 0c 0d \n"  // subtract 0x0d0c0b0a from EAX
   );
@@ -245,7 +245,7 @@ case 0x2d: {  // subtract imm32 from EAX
 void test_subtract_imm32_from_EAX_signed_overflow() {
   Reg[EAX].i = 0x80000000;  // smallest negative signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2d                                 ff ff ff 7f \n"  // subtract largest positive signed integer from EAX
   );
@@ -259,7 +259,7 @@ void test_subtract_imm32_from_EAX_signed_overflow() {
 void test_subtract_imm32_from_EAX_unsigned_overflow() {
   Reg[EAX].i = 0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2d                                 01 00 00 00 \n"  // subtract 1 from EAX
   );
@@ -273,7 +273,7 @@ void test_subtract_imm32_from_EAX_unsigned_overflow() {
 void test_subtract_imm32_from_EAX_signed_and_unsigned_overflow() {
   Reg[EAX].i = 0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  2d                                 00 00 00 80 \n"  // subtract smallest negative signed integer from EAX
   );
@@ -289,11 +289,11 @@ void test_subtract_imm32_from_EAX_signed_and_unsigned_overflow() {
 void test_subtract_imm32_from_mem_at_r32() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     2b                          01 00 00 00 \n"  // subtract 1 from *EBX
       // ModR/M in binary: 00 (indirect mode) 101 (subop subtract) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0a 00 00 00\n"  // 0x0000000a
   );
   CHECK_TRACE_CONTENTS(
@@ -329,11 +329,11 @@ case 5: {
 void test_subtract_imm32_from_mem_at_r32_signed_overflow() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     2b                          ff ff ff 7f \n"  // subtract largest positive signed integer from *EBX
       // ModR/M in binary: 00 (indirect mode) 101 (subop subtract) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "00 00 00 80\n"  // smallest negative signed integer
   );
   CHECK_TRACE_CONTENTS(
@@ -350,11 +350,11 @@ void test_subtract_imm32_from_mem_at_r32_signed_overflow() {
 void test_subtract_imm32_from_mem_at_r32_unsigned_overflow() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     2b                          01 00 00 00 \n"  // subtract 1 from *EBX
       // ModR/M in binary: 00 (indirect mode) 101 (subop subtract) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "00 00 00 00\n"  // 0
   );
   CHECK_TRACE_CONTENTS(
@@ -371,11 +371,11 @@ void test_subtract_imm32_from_mem_at_r32_unsigned_overflow() {
 void test_subtract_imm32_from_mem_at_r32_signed_and_unsigned_overflow() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     2b                          00 00 00 80 \n"  // subtract smallest negative signed integer from *EBX
       // ModR/M in binary: 00 (indirect mode) 101 (subop subtract) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "00 00 00 00\n"  // 0
   );
   CHECK_TRACE_CONTENTS(
@@ -394,7 +394,7 @@ void test_subtract_imm32_from_mem_at_r32_signed_and_unsigned_overflow() {
 void test_subtract_imm32_from_r32() {
   Reg[EBX].i = 10;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     eb                          01 00 00 00 \n"  // subtract 1 from EBX
       // ModR/M in binary: 11 (direct mode) 101 (subop subtract) 011 (dest EBX)
@@ -417,7 +417,7 @@ put_new(Name, "c1", "shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr
 void test_shift_left_r32_with_imm8() {
   Reg[EBX].i = 13;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     e3                          01          \n"  // shift EBX left by 1 bit
       // ModR/M in binary: 11 (direct mode) 100 (subop shift left) 011 (dest EBX)
@@ -468,7 +468,7 @@ case 0xc1: {
 void test_shift_right_arithmetic_r32_with_imm8() {
   Reg[EBX].i = 26;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     fb                          01          \n"  // shift EBX right by 1 bit
       // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
@@ -502,7 +502,7 @@ case 7: {  // shift right r/m32 by CL, preserving sign
 void test_shift_right_arithmetic_odd_r32_with_imm8() {
   Reg[EBX].i = 27;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     fb                          01          \n"  // shift EBX right by 1 bit
       // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
@@ -520,7 +520,7 @@ void test_shift_right_arithmetic_odd_r32_with_imm8() {
 void test_shift_right_arithmetic_negative_r32_with_imm8() {
   Reg[EBX].i = 0xfffffffd;  // -3
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     fb                          01          \n"  // shift EBX right by 1 bit, while preserving sign
       // ModR/M in binary: 11 (direct mode) 111 (subop shift right arithmetic) 011 (dest EBX)
@@ -540,7 +540,7 @@ void test_shift_right_arithmetic_negative_r32_with_imm8() {
 void test_shift_right_logical_r32_with_imm8() {
   Reg[EBX].i = 26;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     eb                          01          \n"  // shift EBX right by 1 bit, while padding zeroes
       // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
@@ -578,7 +578,7 @@ case 5: {  // shift right r/m32 by CL, preserving sign
 void test_shift_right_logical_odd_r32_with_imm8() {
   Reg[EBX].i = 27;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     eb                          01          \n"  // shift EBX right by 1 bit, while padding zeroes
   );
@@ -595,7 +595,7 @@ void test_shift_right_logical_odd_r32_with_imm8() {
 void test_shift_right_logical_negative_r32_with_imm8() {
   Reg[EBX].i = 0xfffffffd;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c1     eb                          01          \n"  // shift EBX right by 1 bit, while padding zeroes
       // ModR/M in binary: 11 (direct mode) 101 (subop shift right logical) 011 (dest EBX)
@@ -617,7 +617,7 @@ put_new(Name, "25", "EAX = bitwise AND of imm32 with EAX (and)");
 void test_and_EAX_with_imm32() {
   Reg[EAX].i = 0xff;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  25                                 0a 0b 0c 0d \n"  // and 0x0d0c0b0a with EAX
   );
@@ -649,11 +649,11 @@ case 0x25: {  // and imm32 with EAX
 void test_and_imm32_with_mem_at_r32() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     23                          0a 0b 0c 0d \n"  // and 0x0d0c0b0a with *EBX
       // ModR/M in binary: 00 (indirect mode) 100 (subop and) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "ff 00 00 00\n"  // 0x000000ff
   );
   CHECK_TRACE_CONTENTS(
@@ -686,7 +686,7 @@ case 4: {
 void test_and_imm32_with_r32() {
   Reg[EBX].i = 0xff;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     e3                          0a 0b 0c 0d \n"  // and 0x0d0c0b0a with EBX
       // ModR/M in binary: 11 (direct mode) 100 (subop and) 011 (dest EBX)
@@ -709,7 +709,7 @@ put_new(Name, "0d", "EAX = bitwise OR of imm32 with EAX (or)");
 void test_or_EAX_with_imm32() {
   Reg[EAX].i = 0xd0c0b0a0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0d                                 0a 0b 0c 0d \n"  // or 0x0d0c0b0a with EAX
   );
@@ -741,11 +741,11 @@ case 0x0d: {  // or imm32 with EAX
 void test_or_imm32_with_mem_at_r32() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     0b                          0a 0b 0c 0d \n"  // or 0x0d0c0b0a with *EBX
       // ModR/M in binary: 00 (indirect mode) 001 (subop or) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "a0 b0 c0 d0\n"  // 0xd0c0b0a0
   );
   CHECK_TRACE_CONTENTS(
@@ -776,7 +776,7 @@ case 1: {
 void test_or_imm32_with_r32() {
   Reg[EBX].i = 0xd0c0b0a0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     cb                          0a 0b 0c 0d \n"  // or 0x0d0c0b0a with EBX
       // ModR/M in binary: 11 (direct mode) 001 (subop or) 011 (dest EBX)
@@ -799,7 +799,7 @@ put_new(Name, "35", "EAX = bitwise XOR of imm32 with EAX (xor)");
 void test_xor_EAX_with_imm32() {
   Reg[EAX].i = 0xddccb0a0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  35                                 0a 0b 0c 0d \n"  // xor 0x0d0c0b0a with EAX
   );
@@ -831,11 +831,11 @@ case 0x35: {  // xor imm32 with EAX
 void test_xor_imm32_with_mem_at_r32() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     33                          0a 0b 0c 0d \n"  // xor 0x0d0c0b0a with *EBX
       // ModR/M in binary: 00 (indirect mode) 110 (subop xor) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "a0 b0 c0 d0\n"  // 0xd0c0b0a0
   );
   CHECK_TRACE_CONTENTS(
@@ -866,7 +866,7 @@ case 6: {
 void test_xor_imm32_with_r32() {
   Reg[EBX].i = 0xd0c0b0a0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     f3                          0a 0b 0c 0d \n"  // xor 0x0d0c0b0a with EBX
       // ModR/M in binary: 11 (direct mode) 110 (subop xor) 011 (dest EBX)
@@ -889,7 +889,7 @@ put_new(Name, "3d", "compare: set SF if EAX < imm32 (cmp)");
 void test_compare_EAX_with_imm32_greater() {
   Reg[EAX].i = 0x0d0c0b0a;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3d                                 07 0b 0c 0d \n"  // compare EAX with 0x0d0c0b07
   );
@@ -922,7 +922,7 @@ case 0x3d: {  // compare EAX with imm32
 void test_compare_EAX_with_imm32_lesser_unsigned_and_signed() {
   Reg[EAX].i = 0x0a0b0c07;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3d                                 0d 0c 0b 0a \n"  // compare EAX with imm32
   );
@@ -935,7 +935,7 @@ void test_compare_EAX_with_imm32_lesser_unsigned_and_signed() {
 void test_compare_EAX_with_imm32_lesser_unsigned_and_signed_due_to_overflow() {
   Reg[EAX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3d                                 00 00 00 80\n"  // compare EAX with smallest negative signed integer
   );
@@ -948,7 +948,7 @@ void test_compare_EAX_with_imm32_lesser_unsigned_and_signed_due_to_overflow() {
 void test_compare_EAX_with_imm32_lesser_signed() {
   Reg[EAX].i = 0xffffffff;  // -1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3d                                 01 00 00 00\n"  // compare EAX with 1
   );
@@ -961,7 +961,7 @@ void test_compare_EAX_with_imm32_lesser_signed() {
 void test_compare_EAX_with_imm32_lesser_unsigned() {
   Reg[EAX].i = 0x00000001;  // 1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3d                                 ff ff ff ff\n"  // compare EAX with -1
   );
@@ -974,7 +974,7 @@ void test_compare_EAX_with_imm32_lesser_unsigned() {
 void test_compare_EAX_with_imm32_equal() {
   Reg[EAX].i = 0x0d0c0b0a;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  3d                                 0a 0b 0c 0d \n"  // compare 0x0d0c0b0a with EAX
   );
@@ -989,7 +989,7 @@ void test_compare_EAX_with_imm32_equal() {
 void test_compare_imm32_with_r32_greater() {
   Reg[EBX].i = 0x0d0c0b0a;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     fb                          07 0b 0c 0d \n"  // compare 0x0d0c0b07 with EBX
       // ModR/M in binary: 11 (direct mode) 111 (subop compare) 011 (dest EBX)
@@ -1023,7 +1023,7 @@ case 7: {
 void test_compare_rm32_with_imm32_lesser_unsigned_and_signed() {
   Reg[EAX].i = 0x0a0b0c07;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     f8                          0d 0c 0b 0a \n"  // compare EAX with imm32
       // ModR/M in binary: 11 (direct mode) 111 (subop compare) 000 (dest EAX)
@@ -1040,7 +1040,7 @@ void test_compare_rm32_with_imm32_lesser_unsigned_and_signed() {
 void test_compare_rm32_with_imm32_lesser_unsigned_and_signed_due_to_overflow() {
   Reg[EAX].i = 0x7fffffff;  // largest positive signed integer
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     f8                          00 00 00 80\n"  // compare EAX with smallest negative signed integer
       // ModR/M in binary: 11 (direct mode) 111 (subop compare) 000 (dest EAX)
@@ -1057,7 +1057,7 @@ void test_compare_rm32_with_imm32_lesser_unsigned_and_signed_due_to_overflow() {
 void test_compare_rm32_with_imm32_lesser_signed() {
   Reg[EAX].i = 0xffffffff;  // -1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     f8                          01 00 00 00\n"  // compare EAX with 1
       // ModR/M in binary: 11 (direct mode) 111 (subop compare) 000 (dest EAX)
@@ -1074,7 +1074,7 @@ void test_compare_rm32_with_imm32_lesser_signed() {
 void test_compare_rm32_with_imm32_lesser_unsigned() {
   Reg[EAX].i = 0x00000001;  // 1
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     f8                          ff ff ff ff\n"  // compare EAX with -1
       // ModR/M in binary: 11 (direct mode) 111 (subop compare) 000 (dest EAX)
@@ -1092,7 +1092,7 @@ void test_compare_rm32_with_imm32_lesser_unsigned() {
 void test_compare_imm32_with_r32_equal() {
   Reg[EBX].i = 0x0d0c0b0a;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     fb                          0a 0b 0c 0d \n"  // compare 0x0d0c0b0a with EBX
       // ModR/M in binary: 11 (direct mode) 111 (subop compare) 011 (dest EBX)
@@ -1109,11 +1109,11 @@ void test_compare_imm32_with_r32_equal() {
 void test_compare_imm32_with_mem_at_r32_greater() {
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     3b                          07 0b 0c 0d \n"  // compare 0x0d0c0b07 with *EBX
       // ModR/M in binary: 00 (indirect mode) 111 (subop compare) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0a 0b 0c 0d\n"  // 0x0d0c0b0a
   );
   CHECK_TRACE_CONTENTS(
@@ -1128,11 +1128,11 @@ void test_compare_imm32_with_mem_at_r32_greater() {
 void test_compare_imm32_with_mem_at_r32_lesser() {
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     38                          0a 0b 0c 0d \n"  // compare 0x0d0c0b0a with *EAX
       // ModR/M in binary: 00 (indirect mode) 111 (subop compare) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "07 0b 0c 0d\n"  // 0x0d0c0b07
   );
   CHECK_TRACE_CONTENTS(
@@ -1148,11 +1148,11 @@ void test_compare_imm32_with_mem_at_r32_equal() {
   Reg[EBX].i = 0x0d0c0b0a;
   Reg[EBX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  81     3b                          0a 0b 0c 0d \n"  // compare 0x0d0c0b0a with *EBX
       // ModR/M in binary: 00 (indirect mode) 111 (subop compare) 011 (dest EBX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "0a 0b 0c 0d\n"  // 0x0d0c0b0a
   );
   CHECK_TRACE_CONTENTS(
@@ -1178,7 +1178,7 @@ put_new(Name, "bf", "copy imm32 to EDI (mov)");
 :(code)
 void test_copy_imm32_to_r32() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  bb                                 0a 0b 0c 0d \n"  // copy 0x0d0c0b0a to EBX
   );
@@ -1211,7 +1211,7 @@ put_new(Name, "c7", "copy imm32 to rm32 (mov)");
 void test_copy_imm32_to_mem_at_r32() {
   Reg[EBX].i = 0x60;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c7     03                          0a 0b 0c 0d \n"  // copy 0x0d0c0b0a to *EBX
       // ModR/M in binary: 00 (indirect mode) 000 (unused) 011 (dest EBX)
@@ -1249,7 +1249,7 @@ void test_push_imm32() {
   Mem.push_back(vma(0xbd000000));  // manually allocate memory
   Reg[ESP].u = 0xbd000014;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  68                                 af 00 00 00 \n"  // push *EAX to stack
   );
diff --git a/subx/016index_addressing.cc b/subx/016index_addressing.cc
index ef72f710..6e1f63e6 100644
--- a/subx/016index_addressing.cc
+++ b/subx/016index_addressing.cc
@@ -5,12 +5,12 @@ void test_add_r32_to_mem_at_r32_with_sib() {
   Reg[EBX].i = 0x10;
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     1c      20                              \n"  // add EBX to *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src EBX) 100 (dest in SIB)
       // SIB in binary: 00 (scale 1) 100 (no index) 000 (base EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -58,12 +58,12 @@ void test_add_r32_to_mem_at_base_r32_index_r32() {
   Reg[EAX].i = 0x1ffe;  // dest base
   Reg[ECX].i = 0x2;  // dest index
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     1c      08                              \n"  // add EBX to *(EAX+ECX)
       // ModR/M in binary: 00 (indirect mode) 011 (src EBX) 100 (dest in SIB)
       // SIB in binary: 00 (scale 1) 001 (index ECX) 000 (base EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -78,12 +78,12 @@ void test_add_r32_to_mem_at_base_r32_index_r32() {
 void test_add_r32_to_mem_at_displacement_using_sib() {
   Reg[EBX].i = 0x10;  // source
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     1c      25    00 20 00 00               \n"  // add EBX to *0x2000
       // ModR/M in binary: 00 (indirect mode) 011 (src EBX) 100 (dest in SIB)
       // SIB in binary: 00 (scale 1) 100 (no index) 101 (not EBP but disp32)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -102,12 +102,12 @@ void test_add_r32_to_mem_at_base_r32_index_r32_plus_disp8() {
   Reg[EAX].i = 0x1ff9;  // dest base
   Reg[ECX].i = 0x5;  // dest index
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     5c      08    02                        \n"  // add EBX to *(EAX+ECX+2)
       // ModR/M in binary: 01 (indirect+disp8 mode) 011 (src EBX) 100 (dest in SIB)
       // SIB in binary: 00 (scale 1) 001 (index ECX) 000 (base EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
@@ -132,12 +132,12 @@ void test_add_r32_to_mem_at_base_r32_index_r32_plus_disp32() {
   Reg[EAX].i = 0x1ff9;  // dest base
   Reg[ECX].i = 0x5;  // dest index
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  01     9c      08    02 00 00 00               \n"  // add EBX to *(EAX+ECX+2)
       // ModR/M in binary: 10 (indirect+disp32 mode) 011 (src EBX) 100 (dest in SIB)
       // SIB in binary: 00 (scale 1) 001 (index ECX) 000 (base EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "01 00 00 00\n"  // 0x00000001
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/017jump_disp8.cc b/subx/017jump_disp8.cc
index 35cc1331..086765c0 100644
--- a/subx/017jump_disp8.cc
+++ b/subx/017jump_disp8.cc
@@ -8,7 +8,7 @@ put_new(Name, "eb", "jump disp8 bytes away (jmp)");
 :(code)
 void test_jump_rel8() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  eb                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -39,7 +39,7 @@ put_new(Name, "74", "jump disp8 bytes away if equal, if ZF is set (jcc/jz/je)");
 void test_je_rel8_success() {
   ZF = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  74                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -67,7 +67,7 @@ case 0x74: {  // jump rel8 if ZF
 void test_je_rel8_fail() {
   ZF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  74                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -90,7 +90,7 @@ put_new(Name, "75", "jump disp8 bytes away if not equal, if ZF is not set (jcc/j
 void test_jne_rel8_success() {
   ZF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  75                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -118,7 +118,7 @@ case 0x75: {  // jump rel8 unless ZF
 void test_jne_rel8_fail() {
   ZF = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  75                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -144,7 +144,7 @@ void test_jg_rel8_success() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7f                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -182,7 +182,7 @@ void test_jg_rel8_fail() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7f                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -207,7 +207,7 @@ void test_jge_rel8_success() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7d                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -244,7 +244,7 @@ void test_jge_rel8_fail() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7d                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -270,7 +270,7 @@ void test_jl_rel8_success() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7c                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -308,7 +308,7 @@ void test_jl_rel8_fail() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7c                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -334,7 +334,7 @@ void test_jle_rel8_equal() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7e                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -354,7 +354,7 @@ void test_jle_rel8_lesser() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7e                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -392,7 +392,7 @@ void test_jle_rel8_greater() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  7e                   05                        \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
diff --git a/subx/018jump_disp32.cc b/subx/018jump_disp32.cc
index 836146ee..524ef5f1 100644
--- a/subx/018jump_disp32.cc
+++ b/subx/018jump_disp32.cc
@@ -8,7 +8,7 @@ put_new(Name, "e9", "jump disp32 bytes away (jmp)");
 :(code)
 void test_jump_disp32() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  e9                   05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -39,7 +39,7 @@ put_new(Name_0f, "84", "jump disp32 bytes away if equal, if ZF is set (jcc/jz/je
 void test_je_disp32_success() {
   ZF = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 84                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -67,7 +67,7 @@ case 0x84: {  // jump disp32 if ZF
 void test_je_disp32_fail() {
   ZF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 84                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -90,7 +90,7 @@ put_new(Name_0f, "85", "jump disp32 bytes away if not equal, if ZF is not set (j
 void test_jne_disp32_success() {
   ZF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 85                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -118,7 +118,7 @@ case 0x85: {  // jump disp32 unless ZF
 void test_jne_disp32_fail() {
   ZF = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 85                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -143,7 +143,7 @@ void test_jg_disp32_success() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8f                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -173,7 +173,7 @@ void test_jg_disp32_fail() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8f                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -197,7 +197,7 @@ void test_jge_disp32_success() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8d                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -226,7 +226,7 @@ void test_jge_disp32_fail() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8d                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -251,7 +251,7 @@ void test_jl_disp32_success() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8c                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -281,7 +281,7 @@ void test_jl_disp32_fail() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8c                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -306,7 +306,7 @@ void test_jle_disp32_equal() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8e                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -326,7 +326,7 @@ void test_jle_disp32_lesser() {
   SF = true;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8e                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
@@ -356,7 +356,7 @@ void test_jle_disp32_greater() {
   SF = false;
   OF = false;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  0f 8e                05 00 00 00               \n"  // skip 1 instruction
       "  05                                 00 00 00 01 \n"
diff --git a/subx/019functions.cc b/subx/019functions.cc
index 00da8397..81e99e6e 100644
--- a/subx/019functions.cc
+++ b/subx/019functions.cc
@@ -8,7 +8,7 @@ void test_call_disp32() {
   Mem.push_back(vma(0xbd000000));  // manually allocate memory
   Reg[ESP].u = 0xbd000064;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  e8                                 a0 00 00 00 \n"  // call function offset at 0x000000a0
       // next EIP is 6
@@ -41,7 +41,7 @@ void test_call_r32() {
   Reg[ESP].u = 0xbd000064;
   Reg[EBX].u = 0x000000a0;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  ff     d3                                      \n"  // call function offset at EBX
       // next EIP is 3
@@ -72,11 +72,11 @@ void test_call_mem_at_r32() {
   Reg[ESP].u = 0xbd000064;
   Reg[EBX].u = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  ff     13                                      \n"  // call function offset at *EBX
       // next EIP is 3
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "a0 00 00 00\n"  // 0x000000a0
   );
   CHECK_TRACE_CONTENTS(
@@ -99,10 +99,10 @@ void test_ret() {
   Reg[ESP].u = 0xbd000064;
   write_mem_u32(Reg[ESP].u, 0x10);
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c3                                           \n"  // return
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "10 00 00 00\n"  // 0x00000010
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/021byte_addressing.cc b/subx/021byte_addressing.cc
index 106cd426..6510e2a6 100644
--- a/subx/021byte_addressing.cc
+++ b/subx/021byte_addressing.cc
@@ -45,11 +45,11 @@ void test_copy_r8_to_mem_at_r32() {
   Reg[EBX].i = 0x224488ab;
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  88     18                                      \n"  // copy BL to the byte at *EAX
       // ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "f0 cc bb aa\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -83,11 +83,11 @@ void test_copy_mem_at_r32_to_r8() {
   Reg[EBX].i = 0xaabbcc0f;  // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  8a     18                                      \n"  // copy just the byte at *EAX to BL
       // ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "ab ff ff ff\n"  // 0xab with more data in following bytes
   );
   CHECK_TRACE_CONTENTS(
@@ -119,7 +119,7 @@ void test_cannot_copy_byte_to_ESP_EBP_ESI_EDI() {
   Reg[ESI].u = 0xaabbccdd;
   Reg[EBX].u = 0x11223344;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  8a     f3                                      \n"  // copy just the byte at *EBX to 8-bit register '6'
       // ModR/M in binary: 11 (direct mode) 110 (dest 8-bit 'register 6') 011 (src EBX)
@@ -142,11 +142,11 @@ put_new(Name, "c6", "copy imm8 to r8/m8-at-r32 (mov)");
 void test_copy_imm8_to_mem_at_r32() {
   Reg[EAX].i = 0x2000;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // op     ModR/M  SIB   displacement  immediate
       "  c6     00                          dd          \n"  // copy to the byte at *EAX
       // ModR/M in binary: 00 (indirect mode) 000 (unused) 000 (dest EAX)
-      "== 0x2000\n"  // data segment
+      "== data 0x2000\n"
       "f0 cc bb aa\n"
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/022div.cc b/subx/022div.cc
index 0498d7ee..15ed89d8 100644
--- a/subx/022div.cc
+++ b/subx/022div.cc
@@ -7,7 +7,7 @@ put_new(Name, "99", "sign-extend EAX into EDX (cdq)");
 void test_cdq() {
   Reg[EAX].i = 10;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "99\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -28,7 +28,7 @@ case 0x99: {  // sign-extend EAX into EDX
 void test_cdq_negative() {
   Reg[EAX].i = -10;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "99\n"
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/028translate.cc b/subx/028translate.cc
index 42b94632..5a8c60c1 100644
--- a/subx/028translate.cc
+++ b/subx/028translate.cc
@@ -100,7 +100,7 @@ void write_elf_header(ostream& out, const program& p) {
   // e_version
   O(0x01); O(0x00); O(0x00); O(0x00);
   // e_entry
-  uint32_t e_entry = p.segments.at(0).start;  // convention
+  uint32_t e_entry = find(p, "code")->start;
   // Override e_entry
   emit(e_entry);
   // e_phoff -- immediately after ELF header
@@ -130,6 +130,7 @@ void write_elf_header(ostream& out, const program& p) {
 
   uint32_t p_offset = /*size of ehdr*/0x34 + SIZE(p.segments)*0x20/*size of each phdr*/;
   for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    const segment& curr = p.segments.at(i);
     //// phdr
     // p_type
     uint32_t p_type = 0x1;
@@ -137,18 +138,18 @@ void write_elf_header(ostream& out, const program& p) {
     // p_offset
     emit(p_offset);
     // p_vaddr
-    uint32_t p_start = p.segments.at(i).start;
+    uint32_t p_start = curr.start;
     emit(p_start);
     // p_paddr
     emit(p_start);
     // p_filesz
-    uint32_t size = num_words(p.segments.at(i));
+    uint32_t size = num_words(curr);
     assert(p_offset + size < SEGMENT_ALIGNMENT);
     emit(size);
     // p_memsz
     emit(size);
     // p_flags
-    uint32_t p_flags = (i == 0) ? /*r-x*/0x5 : /*rw-*/0x6;  // convention: only first segment is code
+    uint32_t p_flags = (curr.name == "code") ? /*r-x*/0x5 : /*rw-*/0x6;
     emit(p_flags);
 
     // p_align
diff --git a/subx/030---operands.cc b/subx/030---operands.cc
index 1a4ec563..5e6d6432 100644
--- a/subx/030---operands.cc
+++ b/subx/030---operands.cc
@@ -30,7 +30,7 @@ cerr << "  instructions\n";
 :(code)
 void test_pack_immediate_constants() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "bb  0x2a/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -161,7 +161,7 @@ Transform.push_back(pack_operands);
 :(code)
 void pack_operands(program& p) {
   if (p.segments.empty()) return;
-  segment& code = p.segments.at(0);
+  segment& code = *find(p, "code");
   // Pack Operands(segment code)
   trace(3, "transform") << "-- pack operands" << end();
   for (int i = 0;  i < SIZE(code.lines);  ++i) {
@@ -320,7 +320,7 @@ void test_preserve_metadata_when_emitting_single_byte() {
 :(code)
 void test_pack_disp8() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "74 2/disp8\n"  // jump 2 bytes away if ZF is set
   );
   CHECK_TRACE_CONTENTS(
@@ -331,7 +331,7 @@ void test_pack_disp8() {
 
 void test_pack_disp8_negative() {
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // running this will cause an infinite loop
       "74 -1/disp8\n"  // jump 1 byte before if ZF is set
   );
@@ -352,7 +352,7 @@ void transform(const string& text_bytes) {
 
 void test_pack_modrm_imm32() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // instruction                     effective address                                                   operand     displacement    immediate\n"
       // op          subop               mod             rm32          base        index         scale       r32\n"
       // 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes\n"
@@ -366,7 +366,7 @@ void test_pack_modrm_imm32() {
 
 void test_pack_imm32_large() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9  0x080490a7/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -377,7 +377,7 @@ void test_pack_imm32_large() {
 
 void test_pack_immediate_constants_hex() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9  0x2a/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -390,7 +390,7 @@ void test_pack_immediate_constants_hex() {
 void test_pack_silently_ignores_non_hex() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9  foo/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -403,7 +403,7 @@ void test_pack_silently_ignores_non_hex() {
 void test_pack_flags_bad_hex() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9  0xfoo/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc
index aad84da6..45d9e7e1 100644
--- a/subx/031check_operands.cc
+++ b/subx/031check_operands.cc
@@ -4,7 +4,7 @@
 void test_check_missing_imm8_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "cd\n"  // interrupt ??
   );
   CHECK_TRACE_CONTENTS(
@@ -348,7 +348,7 @@ uint32_t expected_bit_for_received_operand(const word& w, set<string>& instructi
 void test_conflicting_operand_type() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "cd/software-interrupt 80/imm8/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -362,7 +362,7 @@ void test_conflicting_operand_type() {
 void test_check_missing_mod_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81 0/add/subop       3/rm32/ebx 1/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -443,7 +443,7 @@ void check_operand_metadata_absent(const line& inst, const string& type, const w
 void test_modrm_with_displacement() {
   Reg[EAX].u = 0x1;
   transform(
-      "== 0x1\n"
+      "== code 0x1\n"
       // just avoid null pointer
       "8b/copy 1/mod/lookup+disp8 0/rm32/EAX 2/r32/EDX 4/disp8\n"  // copy *(EAX+4) to EDX
   );
@@ -453,7 +453,7 @@ void test_modrm_with_displacement() {
 void test_check_missing_disp8() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "89/copy 1/mod/lookup+disp8 0/rm32/EAX 1/r32/ECX\n"  // missing disp8
   );
   CHECK_TRACE_CONTENTS(
@@ -464,7 +464,7 @@ void test_check_missing_disp8() {
 void test_check_missing_disp32() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX\n"  // missing disp32
   );
   CHECK_TRACE_CONTENTS(
@@ -475,7 +475,7 @@ void test_check_missing_disp32() {
 void test_conflicting_operands_in_modrm_instruction() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 0/mod 3/mod\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -486,7 +486,7 @@ void test_conflicting_operands_in_modrm_instruction() {
 void test_conflicting_operand_type_modrm() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 0/mod 3/rm32/r32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -497,7 +497,7 @@ void test_conflicting_operand_type_modrm() {
 void test_check_missing_rm32_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81 0/add/subop 0/mod            1/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -508,7 +508,7 @@ void test_check_missing_rm32_operand() {
 void test_check_missing_subop_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81             0/mod 3/rm32/ebx 1/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -519,7 +519,7 @@ void test_check_missing_subop_operand() {
 void test_check_missing_base_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 1/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -530,7 +530,7 @@ void test_check_missing_base_operand() {
 void test_check_missing_index_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 0/base 1/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -541,7 +541,7 @@ void test_check_missing_index_operand() {
 void test_check_missing_base_operand_2() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81 0/add/subop 0/mod/indirect 4/rm32/use-sib 2/index 3/scale 1/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -552,7 +552,7 @@ void test_check_missing_base_operand_2() {
 void test_check_extra_displacement() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 4/disp8\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -563,7 +563,7 @@ void test_check_extra_displacement() {
 void test_check_duplicate_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "89/copy 0/mod/indirect 0/rm32/EAX 1/r32/ECX 1/r32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -573,7 +573,7 @@ void test_check_duplicate_operand() {
 
 void test_check_base_operand_not_needed_in_direct_mode() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "81 0/add/subop 3/mod/indirect 4/rm32/use-sib 1/imm32\n"
   );
   CHECK_TRACE_COUNT("error", 0);
@@ -582,7 +582,7 @@ void test_check_base_operand_not_needed_in_direct_mode() {
 void test_extra_modrm() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "59/pop-to-ECX  3/mod/direct 1/rm32/ECX 4/r32/ESP\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -613,8 +613,8 @@ void check_operands_f3(const line& /*unused*/) {
 void test_check_missing_disp32_operand() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
-      "  0f 84                                                                                                                                             # jmp if ZF to ??\n"
+      "== code 0x1\n"
+      "  0f 84  # jmp if ZF to ??\n"
   );
   CHECK_TRACE_CONTENTS(
       "error: '0f 84' (jump disp32 bytes away if equal, if ZF is set): missing disp32 operand\n"
diff --git a/subx/032check_operand_bounds.cc b/subx/032check_operand_bounds.cc
index 0aae0f67..72a66e3f 100644
--- a/subx/032check_operand_bounds.cc
+++ b/subx/032check_operand_bounds.cc
@@ -3,7 +3,7 @@
 void test_check_bitfield_sizes() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 4/mod 3/rm32 1/r32\n"  // add ECX to EBX
   );
   CHECK_TRACE_CONTENTS(
@@ -66,7 +66,7 @@ void check_operand_bounds(const word& w) {
 
 void test_check_bitfield_sizes_for_imm8() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX 0xff/imm8"  // shift EBX left
   );
   CHECK(!trace_contains_errors());
@@ -75,7 +75,7 @@ void test_check_bitfield_sizes_for_imm8() {
 void test_check_bitfield_sizes_for_imm8_error() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX 0x100/imm8"  // shift EBX left
   );
   CHECK_TRACE_CONTENTS(
@@ -85,7 +85,7 @@ void test_check_bitfield_sizes_for_imm8_error() {
 
 void test_check_bitfield_sizes_for_negative_imm8() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX -0x80/imm8"  // shift EBX left
   );
   CHECK(!trace_contains_errors());
@@ -94,7 +94,7 @@ void test_check_bitfield_sizes_for_negative_imm8() {
 void test_check_bitfield_sizes_for_negative_imm8_error() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX -0x81/imm8"  // shift EBX left
   );
   CHECK_TRACE_CONTENTS(
@@ -105,7 +105,7 @@ void test_check_bitfield_sizes_for_negative_imm8_error() {
 void test_check_bitfield_sizes_for_disp8() {
   // not bothering to run
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 1/mod/*+disp8 3/rm32 1/r32 0x7f/disp8\n"  // add ECX to *(EBX+0x7f)
   );
   CHECK(!trace_contains_errors());
@@ -114,7 +114,7 @@ void test_check_bitfield_sizes_for_disp8() {
 void test_check_bitfield_sizes_for_disp8_error() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 1/mod/*+disp8 3/rm32 1/r32 0x80/disp8\n"  // add ECX to *(EBX+0x80)
   );
   CHECK_TRACE_CONTENTS(
@@ -125,7 +125,7 @@ void test_check_bitfield_sizes_for_disp8_error() {
 void test_check_bitfield_sizes_for_negative_disp8() {
   // not bothering to run
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 1/mod/*+disp8 3/rm32 1/r32 -0x80/disp8\n"  // add ECX to *(EBX-0x80)
   );
   CHECK(!trace_contains_errors());
@@ -134,7 +134,7 @@ void test_check_bitfield_sizes_for_negative_disp8() {
 void test_check_bitfield_sizes_for_negative_disp8_error() {
   Hide_errors = true;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "01/add 1/mod/*+disp8 3/rm32 1/r32 -0x81/disp8\n"  // add ECX to *(EBX-0x81)
   );
   CHECK_TRACE_CONTENTS(
diff --git a/subx/034compute_segment_address.cc b/subx/034compute_segment_address.cc
index 47311219..9eb1615d 100644
--- a/subx/034compute_segment_address.cc
+++ b/subx/034compute_segment_address.cc
@@ -1,12 +1,16 @@
-//: Start allowing us to not specify precise addresses for the start of each
-//: segment.
+//: ELF binaries have finicky rules about the precise alignment each segment
+//: should start at. They depend on the amount of code in a program.
+//: We shouldn't expect people to adjust segment addresses everytime they make
+//: a change to their programs.
+//: Let's start taking the given segment addresses as guidelines, and adjust
+//: them as necessary.
 //: This gives up a measure of control in placing code and data.
 
 void test_segment_name() {
   run(
-      "== code\n"
+      "== code 0x09000000\n"
       "05/add-to-EAX  0x0d0c0b0a/imm32\n"
-      // code starts at 0x08048000 + p_offset, which is 0x54 for a single-segment binary
+      // code starts at 0x09000000 + p_offset, which is 0x54 for a single-segment binary
   );
   CHECK_TRACE_CONTENTS(
       "load: 0x09000054 -> 05\n"
@@ -19,113 +23,6 @@ void test_segment_name() {
   );
 }
 
-//: Update the parser to handle non-numeric segment name.
-//:
-//: We'll also support repeated segments with non-numeric names.
-
-:(before "End Globals")
-map</*name*/string, int> Segment_index;
-bool Currently_parsing_named_segment = false;  // global to permit cross-layer communication
-int Currently_parsing_segment_index = -1;  // global to permit cross-layer communication
-:(before "End Reset")
-Segment_index.clear();
-Currently_parsing_named_segment = false;
-Currently_parsing_segment_index = -1;
-
-:(before "End Segment Parsing Special-cases(segment_title)")
-if (!starts_with(segment_title, "0x")) {
-  Currently_parsing_named_segment = true;
-  if (!contains_key(Segment_index, segment_title)) {
-    trace(3, "parse") << "new segment '" << segment_title << "'" << end();
-    if (out.segments.empty() && segment_title != "code") {
-      raise << "first segment must be 'code' but is '" << segment_title << "'\n" << end();
-      return;
-    }
-    if (SIZE(out.segments) == 1 && segment_title != "data") {
-      raise << "second segment must be 'data' but is '" << segment_title << "'\n" << end();
-      return;
-    }
-    put(Segment_index, segment_title, SIZE(out.segments));
-    out.segments.push_back(segment());
-  }
-  else {
-    trace(3, "parse") << "appending to segment '" << segment_title << "'" << end();
-  }
-  Currently_parsing_segment_index = get(Segment_index, segment_title);
-}
-
-:(before "End flush(p, lines) Special-cases")
-if (Currently_parsing_named_segment) {
-  assert(!p.segments.empty());
-  trace(3, "parse") << "flushing segment" << end();
-  vector<line>& curr_segment_data = p.segments.at(Currently_parsing_segment_index).lines;
-  curr_segment_data.insert(curr_segment_data.end(), lines.begin(), lines.end());
-  lines.clear();
-  Currently_parsing_named_segment = false;
-  Currently_parsing_segment_index = -1;
-  return;
-}
-
-:(code)
-void test_repeated_segment_merges_data() {
-  run(
-      "== code\n"
-      "05/add-to-EAX  0x0d0c0b0a/imm32\n"
-      "== code\n"  // again
-      "2d/subtract-from-EAX  0xddccbbaa/imm32\n"
-  );
-  CHECK_TRACE_CONTENTS(
-      "parse: new segment 'code'\n"
-      "parse: appending to segment 'code'\n"
-      // first segment
-      "load: 0x09000054 -> 05\n"
-      "load: 0x09000055 -> 0a\n"
-      "load: 0x09000056 -> 0b\n"
-      "load: 0x09000057 -> 0c\n"
-      "load: 0x09000058 -> 0d\n"
-      // second segment
-      "load: 0x09000059 -> 2d\n"
-      "load: 0x0900005a -> aa\n"
-      "load: 0x0900005b -> bb\n"
-      "load: 0x0900005c -> cc\n"
-      "load: 0x0900005d -> dd\n"
-  );
-}
-
-void test_error_on_missing_segment_header() {
-  Hide_errors = true;
-  run(
-      "05/add-to-EAX 0/imm32\n"
-  );
-  CHECK_TRACE_CONTENTS(
-      "error: input does not start with a '==' section header\n"
-  );
-}
-
-void test_error_on_first_segment_not_code() {
-  Hide_errors = true;
-  run(
-      "== data\n"
-      "05 00 00 00 00\n"
-  );
-  CHECK_TRACE_CONTENTS(
-      "error: first segment must be 'code' but is 'data'\n"
-  );
-}
-
-void test_error_on_second_segment_not_data() {
-  Hide_errors = true;
-  run(
-      "== code\n"
-      "05/add-to-EAX 0/imm32\n"
-      "== bss\n"
-      "05 00 00 00 00\n"
-  );
-  CHECK_TRACE_CONTENTS(
-      "error: second segment must be 'data' but is 'bss'\n"
-  );
-}
-
 //: compute segment address
 
 :(before "End Level-2 Transforms")
@@ -137,8 +34,10 @@ void compute_segment_starts(program& p) {
   uint32_t p_offset = /*size of ehdr*/0x34 + SIZE(p.segments)*0x20/*size of each phdr*/;
   for (size_t i = 0;  i < p.segments.size();  ++i) {
     segment& curr = p.segments.at(i);
-    if (curr.start == 0) {
-      curr.start = CODE_SEGMENT + i*SPACE_FOR_SEGMENT + p_offset;
+    if (curr.start >= 0x08000000) {
+      // valid address for user space, so assume we're creating a real ELF binary, not just running a test
+      curr.start &= 0xfffff000;  // same number of zeros as the p_align used when emitting the ELF binary
+      curr.start |= p_offset;
       trace(99, "transform") << "segment " << i << " begins at address 0x" << HEXWORD << curr.start << end();
     }
     p_offset += size_of(curr);
diff --git a/subx/035labels.cc b/subx/035labels.cc
index f3131168..3c2d0dd8 100644
--- a/subx/035labels.cc
+++ b/subx/035labels.cc
@@ -23,7 +23,7 @@
 
 void test_entry_label() {
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "05 0x0d0c0b0a/imm32\n"
       "Entry:\n"
       "05 0x0d0c0b0a/imm32\n"
@@ -50,7 +50,7 @@ if (SIZE(s) == 2) return true;
 void test_pack_immediate_ignores_single_byte_nondigit_operand() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9/copy  a/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -63,7 +63,7 @@ void test_pack_immediate_ignores_single_byte_nondigit_operand() {
 void test_pack_immediate_ignores_3_hex_digit_operand() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9/copy  aaa/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -76,7 +76,7 @@ void test_pack_immediate_ignores_3_hex_digit_operand() {
 void test_pack_immediate_ignores_non_hex_operand() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "b9/copy xxx/imm32\n"
   );
   CHECK_TRACE_CONTENTS(
@@ -108,7 +108,7 @@ void check_valid_name(const string& s) {
 
 void test_map_label() {
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       "loop:\n"
       "  05  0x0d0c0b0a/imm32\n"
   );
@@ -123,7 +123,7 @@ Transform.push_back(rewrite_labels);
 void rewrite_labels(program& p) {
   trace(3, "transform") << "-- rewrite labels" << end();
   if (p.segments.empty()) return;
-  segment& code = p.segments.at(0);
+  segment& code = *find(p, "code");
   map<string, int32_t> byte_index;  // values are unsigned, but we're going to do subtractions on them so they need to fit in 31 bits
   compute_byte_indices_for_labels(code, byte_index);
   if (trace_contains_errors()) return;
@@ -278,7 +278,7 @@ string drop_last(const string& s) {
 
 void test_multiple_labels_at() {
   transform(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"
       // address 1
       "loop:\n"
       " $loop2:\n"
@@ -304,7 +304,7 @@ void test_multiple_labels_at() {
 
 void test_loading_label_as_imm32() {
   transform(
-      "== 0x1\n"
+      "== code 0x1\n"
       "label:\n"
       "  be/copy-to-ESI  label/imm32\n"
   );
@@ -317,7 +317,7 @@ void test_loading_label_as_imm32() {
 void test_duplicate_label() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"
+      "== code 0x1\n"
       "loop:\n"
       "loop:\n"
       "    05  0x0d0c0b0a/imm32\n"
@@ -330,7 +330,7 @@ void test_duplicate_label() {
 void test_label_too_short() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"
+      "== code 0x1\n"
       "xz:\n"
       "  05  0x0d0c0b0a/imm32\n"
   );
@@ -342,7 +342,7 @@ void test_label_too_short() {
 void test_label_hex() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"
+      "== code 0x1\n"
       "0xab:\n"
       "  05  0x0d0c0b0a/imm32\n"
   );
@@ -354,7 +354,7 @@ void test_label_hex() {
 void test_label_negative_hex() {
   Hide_errors = true;
   transform(
-      "== 0x1\n"
+      "== code 0x1\n"
       "-a:\n"
       "    05  0x0d0c0b0a/imm32\n"
   );
@@ -368,10 +368,10 @@ void test_label_negative_hex() {
 
 void test_segment_size_ignores_labels() {
   transform(
-      "== code\n"  // 0x09000074
+      "== code 0x09000074\n"
       "  05/add  0x0d0c0b0a/imm32\n"  // 5 bytes
       "foo:\n"                        // 0 bytes
-      "== data\n"  // 0x0a000079
+      "== data 0x0a000000\n"
       "bar:\n"
       "  00\n"
   );
diff --git a/subx/036global_variables.cc b/subx/036global_variables.cc
index fffabf72..c22ac3d3 100644
--- a/subx/036global_variables.cc
+++ b/subx/036global_variables.cc
@@ -9,14 +9,14 @@
 :(code)
 void test_global_variable() {
   run(
-      "== code\n"
+      "== code 0x1\n"
       "b9  x/imm32\n"
-      "== data\n"
+      "== data 0x2000\n"
       "x:\n"
       "  00 00 00 00\n"
   );
   CHECK_TRACE_CONTENTS(
-      "transform: global variable 'x' is at address 0x0a000079\n"
+      "transform: global variable 'x' is at address 0x00002000\n"
   );
 }
 
@@ -34,8 +34,10 @@ void rewrite_global_variables(program& p) {
 }
 
 void compute_addresses_for_global_variables(const program& p, map<string, uint32_t>& address) {
-  for (int i = /*skip code segment*/1;  i < SIZE(p.segments);  ++i)
-    compute_addresses_for_global_variables(p.segments.at(i), address);
+  for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    if (p.segments.at(i).name != "code")
+      compute_addresses_for_global_variables(p.segments.at(i), address);
+  }
 }
 
 void compute_addresses_for_global_variables(const segment& s, map<string, uint32_t>& address) {
@@ -69,15 +71,21 @@ void compute_addresses_for_global_variables(const segment& s, map<string, uint32
 }
 
 void drop_global_variables(program& p) {
-  for (int i = /*skip code segment*/1;  i < SIZE(p.segments);  ++i)
-    drop_labels(p.segments.at(i));
+  for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    if (p.segments.at(i).name != "code")
+      drop_labels(p.segments.at(i));
+  }
 }
 
 void replace_global_variables_with_addresses(program& p, const map<string, uint32_t>& address) {
   if (p.segments.empty()) return;
-  replace_global_variables_in_code_segment(p.segments.at(0), address);
-  for (int i = /*skip code*/1;  i < SIZE(p.segments);  ++i)
-    replace_global_variables_in_data_segment(p.segments.at(i), address);
+  for (int i = 0;  i < SIZE(p.segments);  ++i) {
+    segment& curr = p.segments.at(i);
+    if (curr.name == "code")
+      replace_global_variables_in_code_segment(curr, address);
+    else
+      replace_global_variables_in_data_segment(curr, address);
+  }
 }
 
 void replace_global_variables_in_code_segment(segment& code, const map<string, uint32_t>& address) {
@@ -154,7 +162,7 @@ Transform.push_back(correlate_disp32_with_mod);
 :(code)
 void correlate_disp32_with_mod(program& p) {
   if (p.segments.empty()) return;
-  segment& code = p.segments.at(0);
+  segment& code = *find(p, "code");
   for (int i = 0;  i < SIZE(code.lines);  ++i) {
     line& inst = code.lines.at(i);
     for (int j = 0;  j < SIZE(inst.words);  ++j) {
@@ -182,9 +190,9 @@ bool has_metadata(const word& w, const string& m) {
 void test_global_variable_disallowed_in_jump() {
   Hide_errors = true;
   run(
-      "== code\n"
+      "== code 0x1\n"
       "eb/jump  x/disp8\n"
-      "== data\n"
+      "== data 0x2000\n"
       "x:\n"
       "  00 00 00 00\n"
   );
@@ -198,9 +206,9 @@ void test_global_variable_disallowed_in_jump() {
 void test_global_variable_disallowed_in_call() {
   Hide_errors = true;
   run(
-      "== code\n"
+      "== code 0x1\n"
       "e8/call  x/disp32\n"
-      "== data\n"
+      "== data 0x2000\n"
       "x:\n"
       "  00 00 00 00\n"
   );
@@ -213,9 +221,9 @@ void test_global_variable_disallowed_in_call() {
 
 void test_global_variable_in_data_segment() {
   run(
-      "== 0x1\n"
+      "== code 0x1\n"
       "b9  x/imm32\n"
-      "== 0x0a000000\n"
+      "== data 0x2000\n"
       "x:\n"
       "  y/imm32\n"
       "y:\n"
@@ -223,28 +231,28 @@ void test_global_variable_in_data_segment() {
   );
   // check that we loaded 'x' with the address of 'y'
   CHECK_TRACE_CONTENTS(
-      "load: 0x0a000000 -> 04\n"
-      "load: 0x0a000001 -> 00\n"
-      "load: 0x0a000002 -> 00\n"
-      "load: 0x0a000003 -> 0a\n"
+      "load: 0x00002000 -> 04\n"
+      "load: 0x00002001 -> 20\n"
+      "load: 0x00002002 -> 00\n"
+      "load: 0x00002003 -> 00\n"
   );
   CHECK_TRACE_COUNT("error", 0);
 }
 
 void test_raw_number_with_imm32_in_data_segment() {
   run(
-      "== 0x1\n"
+      "== code 0x1\n"
       "b9  x/imm32\n"
-      "== 0x0a000000\n"
+      "== data 0x2000\n"
       "x:\n"
       "  1/imm32\n"
   );
   // check that we loaded 'x' with the address of 1
   CHECK_TRACE_CONTENTS(
-      "load: 0x0a000000 -> 01\n"
-      "load: 0x0a000001 -> 00\n"
-      "load: 0x0a000002 -> 00\n"
-      "load: 0x0a000003 -> 00\n"
+      "load: 0x00002000 -> 01\n"
+      "load: 0x00002001 -> 00\n"
+      "load: 0x00002002 -> 00\n"
+      "load: 0x00002003 -> 00\n"
   );
   CHECK_TRACE_COUNT("error", 0);
 }
@@ -252,9 +260,9 @@ void test_raw_number_with_imm32_in_data_segment() {
 void test_duplicate_global_variable() {
   Hide_errors = true;
   run(
-      "== 0x1\n"
+      "== code 0x1\n"
       "40/increment-EAX\n"
-      "== 0x0a000000\n"
+      "== data 0x2000\n"
       "x:\n"
       "x:\n"
       "  00\n"
@@ -266,9 +274,9 @@ void test_duplicate_global_variable() {
 
 void test_global_variable_disp32_with_modrm() {
   run(
-      "== code\n"
+      "== code 0x1\n"
       "8b/copy 0/mod/indirect 5/rm32/.disp32 2/r32/EDX x/disp32\n"
-      "== data\n"
+      "== data 0x2000\n"
       "x:\n"
       "  00 00 00 00\n"
   );
@@ -277,7 +285,7 @@ void test_global_variable_disp32_with_modrm() {
 
 void test_global_variable_disp32_with_call() {
   transform(
-      "== code\n"
+      "== code 0x1\n"
       "foo:\n"
       "  e8/call bar/disp32\n"
       "bar:\n"
diff --git a/subx/038---literal_strings.cc b/subx/038---literal_strings.cc
index 9b2c3902..ecc80176 100644
--- a/subx/038---literal_strings.cc
+++ b/subx/038---literal_strings.cc
@@ -5,9 +5,9 @@
 
 void test_transform_literal_string() {
   run(
-      "== code\n"
+      "== code 0x1\n"
       "b8/copy  \"test\"/imm32\n"
-      "== data\n"  // need to manually create the segment for now
+      "== data 0x2000\n"  // need an empty segment
   );
   CHECK_TRACE_CONTENTS(
       "transform: -- move literal strings to data segment\n"
@@ -30,8 +30,8 @@ int Next_auto_global = 1;
 void transform_literal_strings(program& p) {
   trace(3, "transform") << "-- move literal strings to data segment" << end();
   if (p.segments.empty()) return;
-  segment& code = p.segments.at(0);
-  segment data;
+  segment& code = *find(p, "code");
+  segment& data = *find(p, "data");
   for (int i = 0;  i < SIZE(code.lines);  ++i) {
     line& inst = code.lines.at(i);
     for (int j = 0;  j < SIZE(inst.words);  ++j) {
@@ -45,13 +45,6 @@ void transform_literal_strings(program& p) {
     }
     trace(99, "transform") << "instruction after transform: '" << data_to_string(inst) << "'" << end();
   }
-  if (data.lines.empty()) return;
-  if (SIZE(p.segments) < 2) {
-    p.segments.resize(2);
-    p.segments.at(1).lines.swap(data.lines);
-  }
-  vector<line>& existing_data = p.segments.at(1).lines;
-  existing_data.insert(existing_data.end(), data.lines.begin(), data.lines.end());
 }
 
 void add_global_to_data_segment(const string& name, const word& value, segment& data) {
diff --git a/subx/040---tests.cc b/subx/040---tests.cc
index e5949bbd..af05bff3 100644
--- a/subx/040---tests.cc
+++ b/subx/040---tests.cc
@@ -19,7 +19,7 @@ void test_run_test() {
   Mem.push_back(vma(0xbd000000));  // manually allocate memory
   Reg[ESP].u = 0xbd000100;
   run(
-      "== 0x1\n"  // code segment
+      "== code 0x1\n"  // code segment
       "main:\n"
       "  e8/call run-tests/disp32\n"  // 5 bytes
       "  f4/halt\n"                   // 1 byte
@@ -35,7 +35,7 @@ void test_run_test() {
 
 void create_test_function(program& p) {
   if (p.segments.empty()) return;
-  segment& code = p.segments.at(0);
+  segment& code = *find(p, "code");
   trace(3, "transform") << "-- create 'run-tests'" << end();
   vector<line> new_insts;
   for (int i = 0;  i < SIZE(code.lines);  ++i) {
diff --git a/subx/049memory_layout.subx b/subx/049memory_layout.subx
new file mode 100644
index 00000000..36837ade
--- /dev/null
+++ b/subx/049memory_layout.subx
@@ -0,0 +1,8 @@
+# Segment addresses aren't really the concern of any other layer, so we'll
+# define them separately. They're approximate due to fidgety ELF alignment
+# requirements, so don't get clever assuming variables are at specific
+# addresses.
+
+== code 0x09000000
+
+== data 0x0a000000
diff --git a/subx/Readme.md b/subx/Readme.md
index c91d10ab..cab1a503 100644
--- a/subx/Readme.md
+++ b/subx/Readme.md
@@ -243,10 +243,11 @@ Use it now to follow along for a more complete tour of SubX syntax.
 SubX programs map to the same ELF binaries that a conventional Linux system
 uses. Linux ELF binaries consist of a series of _segments_. In particular, they
 distinguish between code and data. Correspondingly, SubX programs consist of a
-series of segments, each starting with a header line: `==` followed by a name.
-The first segment must be named `code`; the second must be named `data`.
+series of segments, each starting with a header line: `==` followed by a name
+and approximate starting address.
 
-Execution begins at the start of the `code` segment by default.
+All code must lie in a segment called 'code'. Execution begins at the start of
+the `code` segment by default.
 
 You can reuse segment names:
 
diff --git a/subx/examples/ex1.subx b/subx/examples/ex1.subx
index 2c3f64eb..4b9f208e 100644
--- a/subx/examples/ex1.subx
+++ b/subx/examples/ex1.subx
@@ -8,7 +8,7 @@
 #   $ echo $?
 #   42
 
-== code
+== code 0x09000000
 
 # syscall(exit, 42)
 bb/copy-to-EBX  2a/imm32  # 42 in hex
diff --git a/subx/examples/ex10.subx b/subx/examples/ex10.subx
index 53148464..fd2ccc08 100644
--- a/subx/examples/ex10.subx
+++ b/subx/examples/ex10.subx
@@ -7,7 +7,7 @@
 #   $ echo $?
 #   0  # false
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
diff --git a/subx/examples/ex11.subx b/subx/examples/ex11.subx
index 78bcf5c9..ba75c1d3 100644
--- a/subx/examples/ex11.subx
+++ b/subx/examples/ex11.subx
@@ -14,7 +14,7 @@
 # because checking for it would require the function being tested! Breakage
 # would cause tests to not run, rather than to fail as we'd like.)
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
@@ -339,7 +339,7 @@ write-stderr:  # s : (address array byte) -> <void>
     5d/pop-to-EBP
     c3/return
 
-== data
+== data 0x0a000000
 
 Newline:
     # size
diff --git a/subx/examples/ex12.subx b/subx/examples/ex12.subx
index 4518aecc..4d43b033 100644
--- a/subx/examples/ex12.subx
+++ b/subx/examples/ex12.subx
@@ -6,7 +6,7 @@
 #   $ ./subx run examples/ex12
 # You shouldn't get a segmentation fault.
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
@@ -24,7 +24,7 @@
     b8/copy-to-EAX  1/imm32/exit
     cd/syscall  0x80/imm8
 
-== data
+== data 0x0a000000
 
 # various constants used here were found in the Linux sources (search for file mman-common.h)
 Mmap-new-segment:  # type mmap_arg_struct
diff --git a/subx/examples/ex2.subx b/subx/examples/ex2.subx
index 757c5220..3605fcc8 100644
--- a/subx/examples/ex2.subx
+++ b/subx/examples/ex2.subx
@@ -7,7 +7,7 @@
 #   $ echo $?
 #   2
 
-== code
+== code 0x09000000
 
 # EBX = 1
 bb/copy-to-EBX  1/imm32
diff --git a/subx/examples/ex3.subx b/subx/examples/ex3.subx
index f7352b2f..c9ad3e38 100644
--- a/subx/examples/ex3.subx
+++ b/subx/examples/ex3.subx
@@ -7,7 +7,7 @@
 #   $ echo $?
 #   55
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
diff --git a/subx/examples/ex4 b/subx/examples/ex4
index 477dab46..66fb61e6 100755
--- a/subx/examples/ex4
+++ b/subx/examples/ex4
Binary files differdiff --git a/subx/examples/ex4.subx b/subx/examples/ex4.subx
index b18a5da0..a1f042ed 100644
--- a/subx/examples/ex4.subx
+++ b/subx/examples/ex4.subx
@@ -4,7 +4,13 @@
 #   $ ./subx translate examples/ex4.subx -o examples/ex4
 #   $ ./subx run examples/ex4
 
-== code
+== data 0x0a000000
+
+# the global variable we save to
+X:
+    0/imm32  # space for read() to write to
+
+== code 0x09000000
 
 # syscall(read, stdin, X, 1)
 # . fd = 0 (stdin)
@@ -32,9 +38,4 @@ cd/syscall  0x80/imm8
 b8/copy-to-EAX  1/imm32/exit
 cd/syscall  0x80/imm8
 
-== data
-
-X:
-    0/imm32  # space for read() to write to
-
 # . . vim:nowrap:textwidth=0
diff --git a/subx/examples/ex5.subx b/subx/examples/ex5.subx
index f9ad9ea8..f051a91f 100644
--- a/subx/examples/ex5.subx
+++ b/subx/examples/ex5.subx
@@ -4,7 +4,7 @@
 #   $ ./subx translate examples/ex5.subx -o examples/ex5
 #   $ ./subx run examples/ex5
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
diff --git a/subx/examples/ex6.subx b/subx/examples/ex6.subx
index 3375fb43..c5999033 100644
--- a/subx/examples/ex6.subx
+++ b/subx/examples/ex6.subx
@@ -5,7 +5,7 @@
 #   $ ./subx run examples/ex6
 #   Hello, world!
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
@@ -25,7 +25,7 @@
     b8/copy-to-EAX  1/imm32/exit
     cd/syscall  0x80/imm8
 
-== data
+== data 0x0a000000
 
 Size:  # size of string
     0x0e/imm32  # 14
diff --git a/subx/examples/ex7.subx b/subx/examples/ex7.subx
index c6dd3423..ee043c86 100644
--- a/subx/examples/ex7.subx
+++ b/subx/examples/ex7.subx
@@ -11,7 +11,7 @@
 #   $ echo $?
 #   97
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
@@ -91,7 +91,7 @@
     b8/copy-to-EAX  1/imm32/exit
     cd/syscall  0x80/imm8
 
-== data
+== data 0x0a000000
 
 Stream:
     0/imm32
diff --git a/subx/examples/ex8.subx b/subx/examples/ex8.subx
index d31786da..85fe1568 100644
--- a/subx/examples/ex8.subx
+++ b/subx/examples/ex8.subx
@@ -14,7 +14,7 @@
 #   ...
 # Locals start from ESP-4 downwards.
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
diff --git a/subx/examples/ex9.subx b/subx/examples/ex9.subx
index 66fbf2ff..344c62ae 100644
--- a/subx/examples/ex9.subx
+++ b/subx/examples/ex9.subx
@@ -17,7 +17,7 @@
 #   ...
 # Locals start from ESP-4 downwards.
 
-== code
+== code 0x09000000
 #   instruction                     effective address                                                   register    displacement    immediate
 # . op          subop               mod             rm32          base        index         scale       r32
 # . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
diff --git a/subx/test_apps b/subx/test_apps
index 2164d1cf..3001940f 100755
--- a/subx/test_apps
+++ b/subx/test_apps
@@ -12,7 +12,7 @@ CFLAGS=$CFLAGS ./build
 
 echo ex1
 ./subx translate examples/ex1.subx  -o examples/ex1
-git diff --exit-code examples/ex1
+[ "$1" != record ]  &&  git diff --exit-code examples/ex1
 ./subx run examples/ex1  ||  ret=$?
 test $ret -eq 42  # life, the universe and everything
 test `uname` = 'Linux'  &&  {
@@ -22,7 +22,7 @@ test `uname` = 'Linux'  &&  {
 
 echo ex2
 ./subx translate examples/ex2.subx  -o examples/ex2
-git diff --exit-code examples/ex2
+[ "$1" != record ]  &&  git diff --exit-code examples/ex2
 ./subx run examples/ex2  ||  ret=$?
 test $ret -eq 2  # 1 + 1
 test `uname` = 'Linux'  &&  {
@@ -32,7 +32,7 @@ test `uname` = 'Linux'  &&  {
 
 echo ex3
 ./subx translate examples/ex3.subx  -o examples/ex3
-git diff --exit-code examples/ex3
+[ "$1" != record ]  &&  git diff --exit-code examples/ex3
 ./subx run examples/ex3  ||  ret=$?
 test $ret -eq 55  # 1 + 2 + ... + 10
 test `uname` = 'Linux'  &&  {
@@ -42,7 +42,7 @@ test `uname` = 'Linux'  &&  {
 
 echo ex4
 ./subx translate examples/ex4.subx  -o examples/ex4
-git diff --exit-code examples/ex4
+[ "$1" != record ]  &&  git diff --exit-code examples/ex4
 echo a | ./subx run examples/ex4 >ex4.out  ||  true
 test `cat ex4.out` = 'a'
 test `uname` = 'Linux'  &&  {
@@ -52,7 +52,7 @@ test `uname` = 'Linux'  &&  {
 
 echo ex5
 ./subx translate examples/ex5.subx  -o examples/ex5
-git diff --exit-code examples/ex5
+[ "$1" != record ]  &&  git diff --exit-code examples/ex5
 echo a | ./subx run examples/ex5 >ex5.out  ||  true
 test `cat ex5.out` = 'a'
 test `uname` = 'Linux'  &&  {
@@ -62,7 +62,7 @@ test `uname` = 'Linux'  &&  {
 
 echo ex6
 ./subx translate examples/ex6.subx  -o examples/ex6
-git diff --exit-code examples/ex6
+[ "$1" != record ]  &&  git diff --exit-code examples/ex6
 ./subx run examples/ex6 >ex6.out  ||  true
 test "`cat ex6.out`" = 'Hello, world!'
 test `uname` = 'Linux'  &&  {
@@ -72,7 +72,7 @@ test `uname` = 'Linux'  &&  {
 
 echo ex7
 ./subx translate examples/ex7.subx  -o examples/ex7
-git diff --exit-code examples/ex7
+[ "$1" != record ]  &&  git diff --exit-code examples/ex7
 ./subx run examples/ex7  ||  ret=$?
 test $ret -eq 97  # 'a'
 test `uname` = 'Linux'  &&  {
diff --git a/subx/test_layers b/subx/test_layers
index 688a5a99..ad5ab1a0 100755
--- a/subx/test_layers
+++ b/subx/test_layers
@@ -20,6 +20,7 @@ CFLAGS=$CFLAGS ./build  # build optimized by default since we'll be running it r
 # add SubX files one at a time
 for f in [0-9]*.subx
 do
+  [ $f == '049'* ]  &&  continue
   echo "=== $f"
   ./subx translate $(../enumerate/enumerate --until $f |grep '\.subx$') -o a.elf  &&  ./subx run a.elf
   echo