1
2
3 :(before "End Initialize Op Names(name)")
4 put(name, "01", "add r32 to rm32");
5
6 :(scenario add_r32_to_r32)
7 % Reg[EAX].i = 0x10;
8 % Reg[EBX].i = 1;
9 == 0x1
10
11 01 d8
12
13 +run: add EBX to r/m32
14 +run: r/m32 is EAX
15 +run: storing 0x00000011
16
17 :(before "End Single-Byte Opcodes")
18 case 0x01: {
19 uint8_t modrm = next();
20 uint8_t arg2 = (modrm>>3)&0x7;
21 trace(90, "run") << "add " << rname(arg2) << " to r/m32" << end();
22 int32_t* arg1 = effective_address(modrm);
23 BINARY_ARITHMETIC_OP(+, *arg1, Reg[arg2].i);
24 break;
25 }
26
27 :(code)
28
29
30
31 int32_t* effective_address(uint8_t modrm) {
32 uint8_t mod = (modrm>>6);
33
34 uint8_t rm = modrm & 0x7;
35 if (mod == 3) {
36
37 trace(90, "run") << "r/m32 is " << rname(rm) << end();
38 return &Reg[rm].i;
39 }
40 return mem_addr_i32(effective_address_number(modrm));
41 }
42
43 uint32_t effective_address_number(uint8_t modrm) {
44 uint8_t mod = (modrm>>6);
45
46 uint8_t rm = modrm & 0x7;
47 uint32_t addr = 0;
48 switch (mod) {
49 case 3:
50
51 raise << "unexpected direct addressing mode\n" << end();
52 return 0;
53
54 default:
55 cerr << "unrecognized mod bits: " << NUM(mod) << '\n';
56 exit(1);
57 }
58
59 return addr;
60 }
61
62 string rname(uint8_t r) {
63 switch (r) {
64 case 0: return "EAX";
65 case 1: return "ECX";
66 case 2: return "EDX";
67 case 3: return "EBX";
68 case 4: return "ESP";
69 case 5: return "EBP";
70 case 6: return "ESI";
71 case 7: return "EDI";
72 default: raise << "invalid register " << r << '\n' << end(); return "";
73 }
74 }
75
76
77
78 :(before "End Initialize Op Names(name)")
79 put(name, "29", "subtract r32 from rm32");
80
81 :(scenario subtract_r32_from_r32)
82 % Reg[EAX].i = 10;
83 % Reg[EBX].i = 1;
84 == 0x1
85
86 29 d8
87
88 +run: subtract EBX from r/m32
89 +run: r/m32 is EAX
90 +run: storing 0x00000009
91
92 :(before "End Single-Byte Opcodes")
93 case 0x29: {
94 uint8_t modrm = next();
95 uint8_t arg2 = (modrm>>3)&0x7;
96 trace(90, "run") << "subtract " << rname(arg2) << " from r/m32" << end();
97 int32_t* arg1 = effective_address(modrm);
98 BINARY_ARITHMETIC_OP(-, *arg1, Reg[arg2].i);
99 break;
100 }
101
102
103
104 :(before "End Initialize Op Names(name)")
105 put(name, "f7", "test/negate/mul/div rm32 (with EAX if necessary) depending on subop");
106
107 :(scenario multiply_eax_by_r32)
108 % Reg[EAX].i = 4;
109 % Reg[ECX].i = 3;
110 == 0x1
111
112 f7 e1
113
114 +run: operate on r/m32
115 +run: r/m32 is ECX
116 +run: subop: multiply EAX by r/m32
117 +run: storing 0x0000000c
118
119 :(before "End Single-Byte Opcodes")
120 case 0xf7: {
121 uint8_t modrm = next();
122 trace(90, "run") << "operate on r/m32" << end();
123 int32_t* arg1 = effective_address(modrm);
124 uint8_t subop = (modrm>>3)&0x7;
125 switch (subop) {
126 case 4: {
127 trace(90, "run") << "subop: multiply EAX by r/m32" << end();
128 uint64_t result = Reg[EAX].u * static_cast<uint32_t>(*arg1);
129 Reg[EAX].u = result & 0xffffffff;
130 Reg[EDX].u = result >> 32;
131 OF = (Reg[EDX].u != 0);
132 trace(90, "run") << "storing 0x" << HEXWORD << Reg[EAX].u << end();
133 break;
134 }
135
136 default:
137 cerr << "unrecognized sub-opcode after f7: " << NUM(subop) << '\n';
138 exit(1);
139 }
140 break;
141 }
142
143
144
145 :(before "End Initialize Op Names(name)")
146 put(name_0f, "af", "multiply rm32 into r32");
147
148 :(scenario multiply_r32_into_r32)
149 % Reg[EAX].i = 4;
150 % Reg[EBX].i = 2;
151 == 0x1
152
153 0f af d8
154
155 +run: multiply r/m32 into EBX
156 +run: r/m32 is EAX
157 +run: storing 0x00000008
158
159 :(before "End Two-Byte Opcodes Starting With 0f")
160 case 0xaf: {
161 uint8_t modrm = next();
162 uint8_t arg2 = (modrm>>3)&0x7;
163 trace(90, "run") << "multiply r/m32 into " << rname(arg2) << end();
164 int32_t* arg1 = effective_address(modrm);
165 BINARY_ARITHMETIC_OP(*, Reg[arg2].i, *arg1);
166 break;
167 }
168
169
170
171 :(before "End Initialize Op Names(name)")
172 put(name, "21", "rm32 = bitwise AND of r32 with rm32");
173
174 :(scenario and_r32_with_r32)
175 % Reg[EAX].i = 0x0a0b0c0d;
176 % Reg[EBX].i = 0x000000ff;
177 == 0x1
178
179 21 d8
180
181 +run: and EBX with r/m32
182 +run: r/m32 is EAX
183 +run: storing 0x0000000d
184
185 :(before "End Single-Byte Opcodes")
186 case 0x21: {
187 uint8_t modrm = next();
188 uint8_t arg2 = (modrm>>3)&0x7;
189 trace(90, "run") << "and " << rname(arg2) << " with r/m32" << end();
190 int32_t* arg1 = effective_address(modrm);
191 BINARY_BITWISE_OP(&, *arg1, Reg[arg2].u);
192 break;
193 }
194
195
196
197 :(before "End Initialize Op Names(name)")
198 put(name, "09", "rm32 = bitwise OR of r32 with rm32");
199
200 :(scenario or_r32_with_r32)
201 % Reg[EAX].i = 0x0a0b0c0d;
202 % Reg[EBX].i = 0xa0b0c0d0;
203 == 0x1
204
205 09 d8
206
207 +run: or EBX with r/m32
208 +run: r/m32 is EAX
209 +run: storing 0xaabbccdd
210
211 :(before "End Single-Byte Opcodes")
212 case 0x09: {
213 uint8_t modrm = next();
214 uint8_t arg2 = (modrm>>3)&0x7;
215 trace(90, "run") << "or " << rname(arg2) << " with r/m32" << end();
216 int32_t* arg1 = effective_address(modrm);
217 BINARY_BITWISE_OP(|, *arg1, Reg[arg2].u);
218 break;
219 }
220
221
222
223 :(before "End Initialize Op Names(name)")
224 put(name, "31", "rm32 = bitwise XOR of r32 with rm32");
225
226 :(scenario xor_r32_with_r32)
227 % Reg[EAX].i = 0x0a0b0c0d;
228 % Reg[EBX].i = 0xaabbc0d0;
229 == 0x1
230
231 31 d8
232
233 +run: xor EBX with r/m32
234 +run: r/m32 is EAX
235 +run: storing 0xa0b0ccdd
236
237 :(before "End Single-Byte Opcodes")
238 case 0x31: {
239 uint8_t modrm = next();
240 uint8_t arg2 = (modrm>>3)&0x7;
241 trace(90, "run") << "xor " << rname(arg2) << " with r/m32" << end();
242 int32_t* arg1 = effective_address(modrm);
243 BINARY_BITWISE_OP(^, *arg1, Reg[arg2].u);
244 break;
245 }
246
247
248
249 :(before "End Initialize Op Names(name)")
250 put(name, "f7", "bitwise complement of rm32");
251
252 :(scenario not_r32)
253 % Reg[EBX].i = 0x0f0f00ff;
254 == 0x1
255
256 f7 d3
257
258 +run: operate on r/m32
259 +run: r/m32 is EBX
260 +run: subop: not
261 +run: storing 0xf0f0ff00
262
263 :(before "End Op f7 Subops")
264 case 2: {
265 trace(90, "run") << "subop: not" << end();
266 *arg1 = ~(*arg1);
267 trace(90, "run") << "storing 0x" << HEXWORD << *arg1 << end();
268 SF = (*arg1 >> 31);
269 ZF = (*arg1 == 0);
270 OF = false;
271 break;
272 }
273
274
275
276 :(before "End Initialize Op Names(name)")
277 put(name, "39", "compare: set SF if rm32 < r32");
278
279 :(scenario compare_r32_with_r32_greater)
280 % Reg[EAX].i = 0x0a0b0c0d;
281 % Reg[EBX].i = 0x0a0b0c07;
282 == 0x1
283
284 39 d8
285
286 +run: compare EBX with r/m32
287 +run: r/m32 is EAX
288 +run: SF=0; ZF=0; OF=0
289
290 :(before "End Single-Byte Opcodes")
291 case 0x39: {
292 uint8_t modrm = next();
293 uint8_t reg2 = (modrm>>3)&0x7;
294 trace(90, "run") << "compare " << rname(reg2) << " with r/m32" << end();
295 int32_t* arg1 = effective_address(modrm);
296 int32_t arg2 = Reg[reg2].i;
297 int32_t tmp1 = *arg1 - arg2;
298 SF = (tmp1 < 0);
299 ZF = (tmp1 == 0);
300 int64_t tmp2 = *arg1 - arg2;
301 OF = (tmp1 != tmp2);
302 trace(90, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
303 break;
304 }
305
306 :(scenario compare_r32_with_r32_lesser)
307 % Reg[EAX].i = 0x0a0b0c07;
308 % Reg[EBX].i = 0x0a0b0c0d;
309 == 0x1
310
311 39 d8
312
313 +run: compare EBX with r/m32
314 +run: r/m32 is EAX
315 +run: SF=1; ZF=0; OF=0
316
317 :(scenario compare_r32_with_r32_equal)
318 % Reg[EAX].i = 0x0a0b0c0d;
319 % Reg[EBX].i = 0x0a0b0c0d;
320 == 0x1
321
322 39 d8
323
324 +run: compare EBX with r/m32
325 +run: r/m32 is EAX
326 +run: SF=0; ZF=1; OF=0
327
328
329
330 :(before "End Initialize Op Names(name)")
331 put(name, <dl><dt><a name="Widget-contains_point"><strong>contains_point</strong></a>(self, y, x)</dt><dd><tt>Test whether the point (with absolute coordinates) lies<br>
within the boundaries of this object.</tt></dd></dl>
<dl><dt><a name="Widget-destroy"><strong>destroy</strong></a>(self)</dt><dd><tt>Called when the object is destroyed.<br>
Override this!</tt></dd></dl>
<dl><dt><a name="Widget-draw"><strong>draw</strong></a>(self)</dt><dd><tt>Draw the object. Called on every main iteration if visible.<br>
Containers should call <a href="#Widget-draw">draw</a>() on their contained objects here.<br>
Override this!</tt></dd></dl>
<dl><dt><a name="Widget-finalize"><strong>finalize</strong></a>(self)</dt><dd><tt>Called after every displayable is done drawing.<br>
Override this!</tt></dd></dl>
<dl><dt><a name="Widget-poke"><strong>poke</strong></a>(self)</dt><dd><tt>Called before drawing, even if invisible</tt></dd></dl>
<dl><dt><a name="Widget-press"><strong>press</strong></a>(self, key)</dt><dd><tt>Called when a key is pressed and self.<strong>focused</strong> is True.<br>
Override this!</tt></dd></dl>
<dl><dt><a name="Widget-resize"><strong>resize</strong></a>(self, y, x, hei<font color="#909090">=None</font>, wid<font color="#909090">=None</font>)</dt><dd><tt>Resize the widget</tt></dd></dl>
<hr>
Data and other attributes inherited from <a href="ranger.shared.html#EnvironmentAware">ranger.shared.EnvironmentAware</a>:<br>
<dl><dt><strong>env</strong> = None</dl>
<hr>
Data and other attributes inherited from <a href="ranger.shared.html#FileManagerAware">ranger.shared.FileManagerAware</a>:<br>
<dl><dt><strong>fm</strong> = None</dl>
<hr>
Data descriptors inherited from <a href="ranger.shared.html#Awareness">ranger.shared.Awareness</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary for instance variables (if defined)</tt></dd>
</dl>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list of weak references to the object (if defined)</tt></dd>
</dl>
<hr>
Methods inherited from <a href="ranger.gui.curses_shortcuts.html#CursesShortcuts">ranger.gui.curses_shortcuts.CursesShortcuts</a>:<br>
<dl><dt><a name="Widget-addnstr"><strong>addnstr</strong></a>(self, *args)</dt></dl>
<dl><dt><a name="Widget-addstr"><strong>addstr</strong></a>(self, *args)</dt></dl>
<dl><dt><a name="Widget-color"><strong>color</strong></a>(self, *keys)</dt><dd><tt>Change the colors from now on.</tt></dd></dl>
<dl><dt><a name="Widget-color_at"><strong>color_at</strong></a>(self, y, x, wid, *keys)</dt><dd><tt>Change the colors at the specified position</tt></dd></dl>
<dl><dt><a name="Widget-color_reset"><strong>color_reset</strong></a>(self)</dt><dd><tt>Change the colors to the default colors</tt></dd></dl>
<hr>
Data and other attributes inherited from <a href="ranger.shared.settings.html#SettingsAware">ranger.shared.settings.SettingsAware</a>:<br>
<dl><dt><strong>settings</strong> = {}</dl>
</td></tr></table></td></tr></table>
</body></html>