1 //: instructions that (immediately) contain an argument to act with
 2 
 3 :(scenario add_imm32_to_r32)
 4 % Reg[3].i = 1;
 5 # op  ModRM   SIB   displacement  immediate
 6   81  c3                          0a 0b 0c 0d  # add 0x0d0c0b0a to EBX (reg 3)
 7 +run: combine imm32 0x0d0c0b0a with effective address
 8 +run: effective address is reg 3
 9 +run: subop add
10 +run: storing 0x0d0c0b0b
11 
12 :(before "End Single-Byte Opcodes")
13 case 0x81: {  // combine imm32 with r/m32
14   uint8_t modrm = next();
15   int32_t arg2 = imm32();
16   trace(2, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with effective address" << end();
17   int32_t* arg1 = effective_address(modrm);
18   uint8_t subop = (modrm>>3)&0x7;  // middle 3 'reg opcode' bits
19   switch (subop) {
20   case 0:
21   ¦ trace(2, "run") << "subop add" << end();
22   ¦ BINARY_ARITHMETIC_OP(+, *arg1, arg2);
23   ¦ break;
24   // End Op 81 Subops
25   default:
26   ¦ cerr << "unrecognized sub-opcode after 81: " << NUM(subop) << '\n';
27   ¦ exit(1);
28   }
29   break;
30 }
31 
32 //:
33 
34 :(scenario add_imm32_to_mem_at_r32)
35 % Reg[3].i = 0x60;
36 % Mem.at(0x60) = 1;
37 # op  ModR/M  SIB   displacement  immediate
38   81  03                          0a 0b 0c 0d  # add 0x0d0c0b0a to *EBX (reg 3)
39 +run: combine imm32 0x0d0c0b0a with effective address
40 +run: effective address is mem at address 0x60 (reg 3)
41 +run: subop add
42 +run: storing 0x0d0c0b0b
43 
44 //:: subtract
45 
46 :(scenario subtract_imm32_from_eax)
47 % Reg[EAX].i = 0x0d0c0baa;
48 # op  ModR/M  SIB   displacement  immediate
49   2d                              0a 0b 0c 0d  # subtract 0x0d0c0b0a from EAX (reg 0)
50 +run: subtract imm32 0x0d0c0b0a from reg EAX
51 +run: storing 0x000000a0
52 
53 :(before "End Single-Byte Opcodes")
54 case 0x2d: {  // subtract imm32 from EAX
55   int32_t arg2 = imm32();
56   trace(2, "run") << "subtract imm32 0x" << HEXWORD << arg2 << " from reg EAX" << end();
57   BINARY_ARITHMETIC_OP(-, Reg[EAX].i, arg2);
58   break;
59 }
60 
61 //:
62 
63 :(scenario subtract_imm32_from_mem_at_r32)
64 % Reg[3].i = 0x60;
65 % Mem.at(0x60) = 10;
66 # op  ModRM   SIB   displacement  immediate
67   81  2b                          01 00 00 00  # subtract 1 from *EBX (reg 3)
68 +run: combine imm32 0x00000001 with effective address
69 +run: effective address is mem at address 0x60 (reg 3)
70 +run: subop subtract
71 +run: storing 0x00000009
72 
73 //:
74 
75 :(scenario subtract_imm32_from_r32)
76 % Reg[3].i = 10;
77 # op  ModRM   SIB   displacement  immediate
78   81  eb                          01 00 00 00  # subtract 1 from EBX (reg 3)
79 +run: combine imm32 0x00000001 with effective address
80 +run: effective address is reg 3
81 +run: subop subtract
82 +run: storing 0x00000009
83 
84 :(before "End Op 81 Subops")
85 case 5: {
86   trace(2, "run") << "subop subtract" << end();
87   BINARY_ARITHMETIC_OP(-, *arg1, arg2);
88   break;
89 }