1 #ifndef USE_SERIAL 2 #define USE_SERIAL 3 #endif 4 5 asm(".code16gcc"); 6 7 typedef unsigned char u8; 8 typedef unsigned short u16; 9 typedef unsigned u32; 10 typedef unsigned long long u64; 11 12 void test_function(void); 13 14 asm( 15 "test_function: \n\t" 16 "mov $0x1234, %eax \n\t" 17 "ret" 18 ); 19 20 static int strlen(const char *str) 21 { 22 int n; 23 24 for (n = 0; *str; ++str) 25 ++n; 26 return n; 27 } 28 29 static void outb(u8 data, u16 port) 30 { 31 asm volatile("out %0, %1" : : "a"(data), "d"(port)); 32 } 33 34 #ifdef USE_SERIAL 35 static int serial_iobase = 0x3f8; 36 static int serial_inited = 0; 37 38 static u8 inb(u16 port) 39 { 40 u8 data; 41 asm volatile("in %1, %0" : "=a"(data) : "d"(port)); 42 return data; 43 } 44 45 static void serial_outb(char ch) 46 { 47 u8 lsr; 48 49 do { 50 lsr = inb(serial_iobase + 0x05); 51 } while (!(lsr & 0x20)); 52 53 outb(ch, serial_iobase + 0x00); 54 } 55 56 static void serial_init(void) 57 { 58 u8 lcr; 59 60 /* set DLAB */ 61 lcr = inb(serial_iobase + 0x03); 62 lcr |= 0x80; 63 outb(lcr, serial_iobase + 0x03); 64 65 /* set baud rate to 115200 */ 66 outb(0x01, serial_iobase + 0x00); 67 outb(0x00, serial_iobase + 0x01); 68 69 /* clear DLAB */ 70 lcr = inb(serial_iobase + 0x03); 71 lcr &= ~0x80; 72 outb(lcr, serial_iobase + 0x03); 73 } 74 #endif 75 76 static void print_serial(const char *buf) 77 { 78 unsigned long len = strlen(buf); 79 #ifdef USE_SERIAL 80 unsigned long i; 81 if (!serial_inited) { 82 serial_init(); 83 serial_inited = 1; 84 } 85 86 for (i = 0; i < len; i++) { 87 serial_outb(buf[i]); 88 } 89 #else 90 asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1)); 91 #endif 92 } 93 94 static void exit(int code) 95 { 96 outb(code, 0xf4); 97 } 98 99 struct regs { 100 u32 eax, ebx, ecx, edx; 101 u32 esi, edi, esp, ebp; 102 u32 eip, eflags; 103 }; 104 105 static u64 gdt[] = { 106 0, 107 0x00cf9b000000ffffull, // flat 32-bit code segment 108 0x00cf93000000ffffull, // flat 32-bit data segment 109 }; 110 111 static struct { 112 u16 limit; 113 void *base; 114 } __attribute__((packed)) gdt_descr = { 115 sizeof(gdt) - 1, 116 gdt, 117 }; 118 119 struct insn_desc { 120 u16 ptr; 121 u16 len; 122 }; 123 124 static struct regs inregs, outregs; 125 126 static void exec_in_big_real_mode(struct insn_desc *insn) 127 { 128 unsigned long tmp; 129 static struct regs save; 130 int i; 131 extern u8 test_insn[], test_insn_end[]; 132 133 for (i = 0; i < insn->len; ++i) 134 test_insn[i] = ((u8 *)(unsigned long)insn->ptr)[i]; 135 for (; i < test_insn_end - test_insn; ++i) 136 test_insn[i] = 0x90; // nop 137 138 save = inregs; 139 asm volatile( 140 "lgdtl %[gdt_descr] \n\t" 141 "mov %%cr0, %[tmp] \n\t" 142 "or $1, %[tmp] \n\t" 143 "mov %[tmp], %%cr0 \n\t" 144 "mov %[bigseg], %%gs \n\t" 145 "and $-2, %[tmp] \n\t" 146 "mov %[tmp], %%cr0 \n\t" 147 148 "pushw %[save]+36; popfw \n\t" 149 "xchg %%eax, %[save]+0 \n\t" 150 "xchg %%ebx, %[save]+4 \n\t" 151 "xchg %%ecx, %[save]+8 \n\t" 152 "xchg %%edx, %[save]+12 \n\t" 153 "xchg %%esi, %[save]+16 \n\t" 154 "xchg %%edi, %[save]+20 \n\t" 155 "xchg %%esp, %[save]+24 \n\t" 156 "xchg %%ebp, %[save]+28 \n\t" 157 158 "test_insn: . = . + 32\n\t" 159 "test_insn_end: \n\t" 160 161 "xchg %%eax, %[save]+0 \n\t" 162 "xchg %%ebx, %[save]+4 \n\t" 163 "xchg %%ecx, %[save]+8 \n\t" 164 "xchg %%edx, %[save]+12 \n\t" 165 "xchg %%esi, %[save]+16 \n\t" 166 "xchg %%edi, %[save]+20 \n\t" 167 "xchg %%esp, %[save]+24 \n\t" 168 "xchg %%ebp, %[save]+28 \n\t" 169 170 /* Save EFLAGS in outregs*/ 171 "pushfl \n\t" 172 "popl %[save]+36 \n\t" 173 174 /* Restore DF for the harness code */ 175 "cld\n\t" 176 "xor %[tmp], %[tmp] \n\t" 177 "mov %[tmp], %%gs \n\t" 178 : [tmp]"=&r"(tmp), [save]"+m"(save) 179 : [gdt_descr]"m"(gdt_descr), [bigseg]"r"((short)16) 180 : "cc", "memory" 181 ); 182 outregs = save; 183 } 184 185 #define R_AX 1 186 #define R_BX 2 187 #define R_CX 4 188 #define R_DX 8 189 #define R_SI 16 190 #define R_DI 32 191 #define R_SP 64 192 #define R_BP 128 193 194 int regs_equal(int ignore) 195 { 196 const u32 *p1 = &inregs.eax, *p2 = &outregs.eax; // yuck 197 int i; 198 199 for (i = 0; i < 8; ++i) 200 if (!(ignore & (1 << i)) && p1[i] != p2[i]) 201 return 0; 202 return 1; 203 } 204 205 static void report(const char *name, u16 regs_ignore, _Bool ok) 206 { 207 if (!regs_equal(regs_ignore)) { 208 ok = 0; 209 } 210 print_serial(ok ? "PASS: " : "FAIL: "); 211 print_serial(name); 212 print_serial("\n"); 213 } 214 215 #define MK_INSN(name, str) \ 216 asm ( \ 217 ".pushsection .data.insn \n\t" \ 218 "insn_" #name ": \n\t" \ 219 ".word 1001f, 1002f - 1001f \n\t" \ 220 ".popsection \n\t" \ 221 ".pushsection .text.insn, \"ax\" \n\t" \ 222 "1001: \n\t" \ 223 "insn_code_" #name ": " str " \n\t" \ 224 "1002: \n\t" \ 225 ".popsection" \ 226 ); \ 227 extern struct insn_desc insn_##name; 228 229 void test_xchg(void) 230 { 231 MK_INSN(xchg_test1, "xchg %eax,%eax\n\t"); 232 MK_INSN(xchg_test2, "xchg %eax,%ebx\n\t"); 233 MK_INSN(xchg_test3, "xchg %eax,%ecx\n\t"); 234 MK_INSN(xchg_test4, "xchg %eax,%edx\n\t"); 235 MK_INSN(xchg_test5, "xchg %eax,%esi\n\t"); 236 MK_INSN(xchg_test6, "xchg %eax,%edi\n\t"); 237 MK_INSN(xchg_test7, "xchg %eax,%ebp\n\t"); 238 MK_INSN(xchg_test8, "xchg %eax,%esp\n\t"); 239 240 inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = 7}; 241 242 exec_in_big_real_mode(&insn_xchg_test1); 243 report("xchg 1", 0, 1); 244 245 exec_in_big_real_mode(&insn_xchg_test2); 246 report("xchg 2", R_AX | R_BX, 247 outregs.eax == inregs.ebx && outregs.ebx == inregs.eax); 248 249 exec_in_big_real_mode(&insn_xchg_test3); 250 report("xchg 3", R_AX | R_CX, 251 outregs.eax == inregs.ecx && outregs.ecx == inregs.eax); 252 253 exec_in_big_real_mode(&insn_xchg_test4); 254 report("xchg 4", R_AX | R_DX, 255 outregs.eax == inregs.edx && outregs.edx == inregs.eax); 256 257 exec_in_big_real_mode(&insn_xchg_test5); 258 report("xchg 5", R_AX | R_SI, 259 outregs.eax == inregs.esi && outregs.esi == inregs.eax); 260 261 exec_in_big_real_mode(&insn_xchg_test6); 262 report("xchg 6", R_AX | R_DI, 263 outregs.eax == inregs.edi && outregs.edi == inregs.eax); 264 265 exec_in_big_real_mode(&insn_xchg_test7); 266 report("xchg 7", R_AX | R_BP, 267 outregs.eax == inregs.ebp && outregs.ebp == inregs.eax); 268 269 exec_in_big_real_mode(&insn_xchg_test8); 270 report("xchg 8", R_AX | R_SP, 271 outregs.eax == inregs.esp && outregs.esp == inregs.eax); 272 } 273 274 void test_shld(void) 275 { 276 MK_INSN(shld_test, "shld $8,%edx,%eax\n\t"); 277 278 inregs = (struct regs){ .eax = 0xbe, .edx = 0xef000000 }; 279 exec_in_big_real_mode(&insn_shld_test); 280 report("shld", ~0, outregs.eax == 0xbeef); 281 } 282 283 void test_mov_imm(void) 284 { 285 MK_INSN(mov_r32_imm_1, "mov $1234567890, %eax"); 286 MK_INSN(mov_r16_imm_1, "mov $1234, %ax"); 287 MK_INSN(mov_r8_imm_1, "mov $0x12, %ah"); 288 MK_INSN(mov_r8_imm_2, "mov $0x34, %al"); 289 MK_INSN(mov_r8_imm_3, "mov $0x12, %ah\n\t" "mov $0x34, %al\n\t"); 290 291 inregs = (struct regs){ 0 }; 292 293 exec_in_big_real_mode(&insn_mov_r16_imm_1); 294 report("mov 1", R_AX, outregs.eax == 1234); 295 296 /* test mov $imm, %eax */ 297 exec_in_big_real_mode(&insn_mov_r32_imm_1); 298 report("mov 2", R_AX, outregs.eax == 1234567890); 299 300 /* test mov $imm, %al/%ah */ 301 exec_in_big_real_mode(&insn_mov_r8_imm_1); 302 report("mov 3", R_AX, outregs.eax == 0x1200); 303 304 exec_in_big_real_mode(&insn_mov_r8_imm_2); 305 report("mov 4", R_AX, outregs.eax == 0x34); 306 307 exec_in_big_real_mode(&insn_mov_r8_imm_3); 308 report("mov 5", R_AX, outregs.eax == 0x1234); 309 } 310 311 void test_sub_imm(void) 312 { 313 MK_INSN(sub_r32_imm_1, "mov $1234567890, %eax\n\t" "sub $10, %eax\n\t"); 314 MK_INSN(sub_r16_imm_1, "mov $1234, %ax\n\t" "sub $10, %ax\n\t"); 315 MK_INSN(sub_r8_imm_1, "mov $0x12, %ah\n\t" "sub $0x10, %ah\n\t"); 316 MK_INSN(sub_r8_imm_2, "mov $0x34, %al\n\t" "sub $0x10, %al\n\t"); 317 318 inregs = (struct regs){ 0 }; 319 320 exec_in_big_real_mode(&insn_sub_r16_imm_1); 321 report("sub 1", R_AX, outregs.eax == 1224); 322 323 /* test mov $imm, %eax */ 324 exec_in_big_real_mode(&insn_sub_r32_imm_1); 325 report("sub 2", R_AX, outregs.eax == 1234567880); 326 327 /* test mov $imm, %al/%ah */ 328 exec_in_big_real_mode(&insn_sub_r8_imm_1); 329 report("sub 3", R_AX, outregs.eax == 0x0200); 330 331 exec_in_big_real_mode(&insn_sub_r8_imm_2); 332 report("sub 4", R_AX, outregs.eax == 0x24); 333 } 334 335 void test_xor_imm(void) 336 { 337 MK_INSN(xor_r32_imm_1, "mov $1234567890, %eax\n\t" "xor $1234567890, %eax\n\t"); 338 MK_INSN(xor_r16_imm_1, "mov $1234, %ax\n\t" "xor $1234, %ax\n\t"); 339 MK_INSN(xor_r8_imm_1, "mov $0x12, %ah\n\t" "xor $0x12, %ah\n\t"); 340 MK_INSN(xor_r8_imm_2, "mov $0x34, %al\n\t" "xor $0x34, %al\n\t"); 341 342 inregs = (struct regs){ 0 }; 343 344 exec_in_big_real_mode(&insn_xor_r16_imm_1); 345 report("xor 1", R_AX, outregs.eax == 0); 346 347 /* test mov $imm, %eax */ 348 exec_in_big_real_mode(&insn_xor_r32_imm_1); 349 report("xor 2", R_AX, outregs.eax == 0); 350 351 /* test mov $imm, %al/%ah */ 352 exec_in_big_real_mode(&insn_xor_r8_imm_1); 353 report("xor 3", R_AX, outregs.eax == 0); 354 355 exec_in_big_real_mode(&insn_xor_r8_imm_2); 356 report("xor 4", R_AX, outregs.eax == 0); 357 } 358 359 void test_cmp_imm(void) 360 { 361 MK_INSN(cmp_test1, "mov $0x34, %al\n\t" 362 "cmp $0x34, %al\n\t"); 363 MK_INSN(cmp_test2, "mov $0x34, %al\n\t" 364 "cmp $0x39, %al\n\t"); 365 MK_INSN(cmp_test3, "mov $0x34, %al\n\t" 366 "cmp $0x24, %al\n\t"); 367 368 inregs = (struct regs){ 0 }; 369 370 /* test cmp imm8 with AL */ 371 /* ZF: (bit 6) Zero Flag becomes 1 if an operation results 372 * in a 0 writeback, or 0 register 373 */ 374 exec_in_big_real_mode(&insn_cmp_test1); 375 report("cmp 1", ~0, (outregs.eflags & (1<<6)) == (1<<6)); 376 377 exec_in_big_real_mode(&insn_cmp_test2); 378 report("cmp 2", ~0, (outregs.eflags & (1<<6)) == 0); 379 380 exec_in_big_real_mode(&insn_cmp_test3); 381 report("cmp 3", ~0, (outregs.eflags & (1<<6)) == 0); 382 } 383 384 void test_add_imm(void) 385 { 386 MK_INSN(add_test1, "mov $0x43211234, %eax \n\t" 387 "add $0x12344321, %eax \n\t"); 388 MK_INSN(add_test2, "mov $0x12, %eax \n\t" 389 "add $0x21, %al\n\t"); 390 391 inregs = (struct regs){ 0 }; 392 393 exec_in_big_real_mode(&insn_add_test1); 394 report("add 1", ~0, outregs.eax == 0x55555555); 395 396 exec_in_big_real_mode(&insn_add_test2); 397 report("add 2", ~0, outregs.eax == 0x33); 398 } 399 400 void test_eflags_insn(void) 401 { 402 MK_INSN(clc, "clc"); 403 MK_INSN(stc, "stc"); 404 MK_INSN(cli, "cli"); 405 MK_INSN(sti, "sti"); 406 MK_INSN(cld, "cld"); 407 MK_INSN(std, "std"); 408 409 inregs = (struct regs){ 0 }; 410 411 exec_in_big_real_mode(&insn_clc); 412 report("clc", ~0, (outregs.eflags & 1) == 0); 413 414 exec_in_big_real_mode(&insn_stc); 415 report("stc", ~0, (outregs.eflags & 1) == 1); 416 417 exec_in_big_real_mode(&insn_cli); 418 report("cli", ~0, !(outregs.eflags & (1 << 9))); 419 420 exec_in_big_real_mode(&insn_sti); 421 report("sti", ~0, outregs.eflags & (1 << 9)); 422 423 exec_in_big_real_mode(&insn_cld); 424 report("cld", ~0, !(outregs.eflags & (1 << 10))); 425 426 exec_in_big_real_mode(&insn_std); 427 report("std", ~0, (outregs.eflags & (1 << 10))); 428 } 429 430 void test_io(void) 431 { 432 MK_INSN(io_test1, "mov $0xff, %al \n\t" 433 "out %al, $0xe0 \n\t" 434 "mov $0x00, %al \n\t" 435 "in $0xe0, %al \n\t"); 436 MK_INSN(io_test2, "mov $0xffff, %ax \n\t" 437 "out %ax, $0xe0 \n\t" 438 "mov $0x0000, %ax \n\t" 439 "in $0xe0, %ax \n\t"); 440 MK_INSN(io_test3, "mov $0xffffffff, %eax \n\t" 441 "out %eax, $0xe0 \n\t" 442 "mov $0x000000, %eax \n\t" 443 "in $0xe0, %eax \n\t"); 444 MK_INSN(io_test4, "mov $0xe0, %dx \n\t" 445 "mov $0xff, %al \n\t" 446 "out %al, %dx \n\t" 447 "mov $0x00, %al \n\t" 448 "in %dx, %al \n\t"); 449 MK_INSN(io_test5, "mov $0xe0, %dx \n\t" 450 "mov $0xffff, %ax \n\t" 451 "out %ax, %dx \n\t" 452 "mov $0x0000, %ax \n\t" 453 "in %dx, %ax \n\t"); 454 MK_INSN(io_test6, "mov $0xe0, %dx \n\t" 455 "mov $0xffffffff, %eax \n\t" 456 "out %eax, %dx \n\t" 457 "mov $0x00000000, %eax \n\t" 458 "in %dx, %eax \n\t"); 459 460 inregs = (struct regs){ 0 }; 461 462 exec_in_big_real_mode(&insn_io_test1); 463 report("pio 1", R_AX, outregs.eax == 0xff); 464 465 exec_in_big_real_mode(&insn_io_test2); 466 report("pio 2", R_AX, outregs.eax == 0xffff); 467 468 exec_in_big_real_mode(&insn_io_test3); 469 report("pio 3", R_AX, outregs.eax == 0xffffffff); 470 471 exec_in_big_real_mode(&insn_io_test4); 472 report("pio 4", R_AX|R_DX, outregs.eax == 0xff); 473 474 exec_in_big_real_mode(&insn_io_test5); 475 report("pio 5", R_AX|R_DX, outregs.eax == 0xffff); 476 477 exec_in_big_real_mode(&insn_io_test6); 478 report("pio 6", R_AX|R_DX, outregs.eax == 0xffffffff); 479 } 480 481 asm ("retf: lretw"); 482 extern void retf(); 483 484 asm ("retf_imm: lretw $10"); 485 extern void retf_imm(); 486 487 void test_call(void) 488 { 489 u32 esp[16]; 490 u32 addr; 491 492 inregs = (struct regs){ 0 }; 493 inregs.esp = (u32)esp; 494 495 MK_INSN(call1, "mov $test_function, %eax \n\t" 496 "call *%eax\n\t"); 497 MK_INSN(call_near1, "jmp 2f\n\t" 498 "1: mov $0x1234, %eax\n\t" 499 "ret\n\t" 500 "2: call 1b\t"); 501 MK_INSN(call_near2, "call 1f\n\t" 502 "jmp 2f\n\t" 503 "1: mov $0x1234, %eax\n\t" 504 "ret\n\t" 505 "2:\t"); 506 MK_INSN(call_far1, "lcallw *(%ebx)\n\t"); 507 MK_INSN(call_far2, "lcallw $0, $retf\n\t"); 508 MK_INSN(ret_imm, "sub $10, %sp; jmp 2f; 1: retw $10; 2: callw 1b"); 509 MK_INSN(retf_imm, "sub $10, %sp; lcallw $0, $retf_imm"); 510 511 exec_in_big_real_mode(&insn_call1); 512 report("call 1", R_AX, outregs.eax == 0x1234); 513 514 exec_in_big_real_mode(&insn_call_near1); 515 report("call near 1", R_AX, outregs.eax == 0x1234); 516 517 exec_in_big_real_mode(&insn_call_near2); 518 report("call near 2", R_AX, outregs.eax == 0x1234); 519 520 addr = (((unsigned)retf >> 4) << 16) | ((unsigned)retf & 0x0f); 521 inregs.ebx = (unsigned)&addr; 522 exec_in_big_real_mode(&insn_call_far1); 523 report("call far 1", 0, 1); 524 525 exec_in_big_real_mode(&insn_call_far2); 526 report("call far 2", 0, 1); 527 528 exec_in_big_real_mode(&insn_ret_imm); 529 report("ret imm 1", 0, 1); 530 531 exec_in_big_real_mode(&insn_retf_imm); 532 report("retf imm 1", 0, 1); 533 } 534 535 void test_jcc_short(void) 536 { 537 MK_INSN(jnz_short1, "jnz 1f\n\t" 538 "mov $0x1234, %eax\n\t" 539 "1:\n\t"); 540 MK_INSN(jnz_short2, "1:\n\t" 541 "cmp $0x1234, %eax\n\t" 542 "mov $0x1234, %eax\n\t" 543 "jnz 1b\n\t"); 544 MK_INSN(jmp_short1, "jmp 1f\n\t" 545 "mov $0x1234, %eax\n\t" 546 "1:\n\t"); 547 548 inregs = (struct regs){ 0 }; 549 550 exec_in_big_real_mode(&insn_jnz_short1); 551 report("jnz short 1", ~0, 1); 552 553 exec_in_big_real_mode(&insn_jnz_short2); 554 report("jnz short 2", R_AX, (outregs.eflags & (1 << 6))); 555 556 exec_in_big_real_mode(&insn_jmp_short1); 557 report("jmp short 1", ~0, 1); 558 } 559 560 void test_jcc_near(void) 561 { 562 /* encode near jmp manually. gas will not do it if offsets < 127 byte */ 563 MK_INSN(jnz_near1, ".byte 0x0f, 0x85, 0x06, 0x00\n\t" 564 "mov $0x1234, %eax\n\t"); 565 MK_INSN(jnz_near2, "cmp $0x1234, %eax\n\t" 566 "mov $0x1234, %eax\n\t" 567 ".byte 0x0f, 0x85, 0xf0, 0xff\n\t"); 568 MK_INSN(jmp_near1, ".byte 0xE9, 0x06, 0x00\n\t" 569 "mov $0x1234, %eax\n\t"); 570 571 inregs = (struct regs){ 0 }; 572 573 exec_in_big_real_mode(&insn_jnz_near1); 574 report("jnz near 1", 0, 1); 575 576 exec_in_big_real_mode(&insn_jnz_near2); 577 report("jnz near 2", R_AX, outregs.eflags & (1 << 6)); 578 579 exec_in_big_real_mode(&insn_jmp_near1); 580 report("jmp near 1", 0, 1); 581 } 582 583 void test_long_jmp() 584 { 585 u32 esp[16]; 586 587 inregs = (struct regs){ 0 }; 588 inregs.esp = (u32)(esp+16); 589 MK_INSN(long_jmp, "call 1f\n\t" 590 "jmp 2f\n\t" 591 "1: jmp $0, $test_function\n\t" 592 "2:\n\t"); 593 exec_in_big_real_mode(&insn_long_jmp); 594 report("jmp far 1", R_AX, outregs.eax == 0x1234); 595 } 596 597 void test_push_pop() 598 { 599 MK_INSN(push32, "mov $0x12345678, %eax\n\t" 600 "push %eax\n\t" 601 "pop %ebx\n\t"); 602 MK_INSN(push16, "mov $0x1234, %ax\n\t" 603 "push %ax\n\t" 604 "pop %bx\n\t"); 605 606 MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten 607 "mov $0x123, %ax\n\t" 608 "mov %ax, %es\n\t" 609 "push %es\n\t" 610 "pop %bx \n\t" 611 ); 612 MK_INSN(pop_es, "push %ax\n\t" 613 "pop %es\n\t" 614 "mov %es, %bx\n\t" 615 ); 616 MK_INSN(push_pop_ss, "push %ss\n\t" 617 "pushw %ax\n\t" 618 "popw %ss\n\t" 619 "mov %ss, %bx\n\t" 620 "pop %ss\n\t" 621 ); 622 MK_INSN(push_pop_fs, "push %fs\n\t" 623 "pushl %eax\n\t" 624 "popl %fs\n\t" 625 "mov %fs, %ebx\n\t" 626 "pop %fs\n\t" 627 ); 628 MK_INSN(push_pop_high_esp_bits, 629 "xor $0x12340000, %esp \n\t" 630 "push %ax; \n\t" 631 "xor $0x12340000, %esp \n\t" 632 "pop %bx"); 633 634 inregs = (struct regs){ 0 }; 635 636 exec_in_big_real_mode(&insn_push32); 637 report("push/pop 1", R_AX|R_BX, 638 outregs.eax == outregs.ebx && outregs.eax == 0x12345678); 639 640 exec_in_big_real_mode(&insn_push16); 641 report("push/pop 2", R_AX|R_BX, 642 outregs.eax == outregs.ebx && outregs.eax == 0x1234); 643 644 exec_in_big_real_mode(&insn_push_es); 645 report("push/pop 3", R_AX|R_BX, 646 outregs.ebx == outregs.eax && outregs.eax == 0x123); 647 648 exec_in_big_real_mode(&insn_pop_es); 649 report("push/pop 4", R_AX|R_BX, outregs.ebx == outregs.eax); 650 651 exec_in_big_real_mode(&insn_push_pop_ss); 652 report("push/pop 5", R_AX|R_BX, outregs.ebx == outregs.eax); 653 654 exec_in_big_real_mode(&insn_push_pop_fs); 655 report("push/pop 6", R_AX|R_BX, outregs.ebx == outregs.eax); 656 657 inregs.eax = 0x9977; 658 inregs.ebx = 0x7799; 659 exec_in_big_real_mode(&insn_push_pop_high_esp_bits); 660 report("push/pop with high bits set in %esp", R_BX, outregs.ebx == 0x9977); 661 } 662 663 void test_null(void) 664 { 665 MK_INSN(null, ""); 666 667 inregs = (struct regs){ 0 }; 668 669 exec_in_big_real_mode(&insn_null); 670 report("null", 0, 1); 671 } 672 673 struct { 674 char stack[500]; 675 char top[]; 676 } tmp_stack; 677 678 void test_pusha_popa() 679 { 680 MK_INSN(pusha, "pusha\n\t" 681 "pop %edi\n\t" 682 "pop %esi\n\t" 683 "pop %ebp\n\t" 684 "add $4, %esp\n\t" 685 "pop %ebx\n\t" 686 "pop %edx\n\t" 687 "pop %ecx\n\t" 688 "pop %eax\n\t" 689 ); 690 691 MK_INSN(popa, "push %eax\n\t" 692 "push %ecx\n\t" 693 "push %edx\n\t" 694 "push %ebx\n\t" 695 "push %esp\n\t" 696 "push %ebp\n\t" 697 "push %esi\n\t" 698 "push %edi\n\t" 699 "popa\n\t" 700 ); 701 702 inregs = (struct regs){ .eax = 0, .ebx = 1, .ecx = 2, .edx = 3, .esi = 4, .edi = 5, .ebp = 6, .esp = (unsigned long)&tmp_stack.top }; 703 704 exec_in_big_real_mode(&insn_pusha); 705 report("pusha/popa 1", 0, 1); 706 707 exec_in_big_real_mode(&insn_popa); 708 report("pusha/popa 1", 0, 1); 709 } 710 711 void test_iret() 712 { 713 MK_INSN(iret32, "pushf\n\t" 714 "pushl %cs\n\t" 715 "call 1f\n\t" /* a near call will push eip onto the stack */ 716 "jmp 2f\n\t" 717 "1: iret\n\t" 718 "2:\n\t" 719 ); 720 721 MK_INSN(iret16, "pushfw\n\t" 722 "pushw %cs\n\t" 723 "callw 1f\n\t" 724 "jmp 2f\n\t" 725 "1: iretw\n\t" 726 "2:\n\t"); 727 728 MK_INSN(iret_flags32, "pushfl\n\t" 729 "popl %eax\n\t" 730 "andl $~0x2, %eax\n\t" 731 "orl $0xffc08028, %eax\n\t" 732 "pushl %eax\n\t" 733 "pushl %cs\n\t" 734 "call 1f\n\t" 735 "jmp 2f\n\t" 736 "1: iret\n\t" 737 "2:\n\t"); 738 739 MK_INSN(iret_flags16, "pushfw\n\t" 740 "popw %ax\n\t" 741 "and $~0x2, %ax\n\t" 742 "or $0x8028, %ax\n\t" 743 "pushw %ax\n\t" 744 "pushw %cs\n\t" 745 "callw 1f\n\t" 746 "jmp 2f\n\t" 747 "1: iretw\n\t" 748 "2:\n\t"); 749 750 inregs = (struct regs){ 0 }; 751 752 exec_in_big_real_mode(&insn_iret32); 753 report("iret 1", 0, 1); 754 755 exec_in_big_real_mode(&insn_iret16); 756 report("iret 2", 0, 1); 757 758 exec_in_big_real_mode(&insn_iret_flags32); 759 report("iret 3", R_AX, 1); 760 761 exec_in_big_real_mode(&insn_iret_flags16); 762 report("iret 4", R_AX, 1); 763 } 764 765 void test_int() 766 { 767 inregs = (struct regs){ 0 }; 768 769 *(u32 *)(0x11 * 4) = 0x1000; /* Store a pointer to address 0x1000 in IDT entry 0x11 */ 770 *(u8 *)(0x1000) = 0xcf; /* 0x1000 contains an IRET instruction */ 771 772 MK_INSN(int11, "int $0x11\n\t"); 773 774 exec_in_big_real_mode(&insn_int11); 775 report("int 1", 0, 1); 776 } 777 778 void test_imul() 779 { 780 MK_INSN(imul8_1, "mov $2, %al\n\t" 781 "mov $-4, %cx\n\t" 782 "imul %cl\n\t"); 783 784 MK_INSN(imul16_1, "mov $2, %ax\n\t" 785 "mov $-4, %cx\n\t" 786 "imul %cx\n\t"); 787 788 MK_INSN(imul32_1, "mov $2, %eax\n\t" 789 "mov $-4, %ecx\n\t" 790 "imul %ecx\n\t"); 791 792 MK_INSN(imul8_2, "mov $0x12340002, %eax\n\t" 793 "mov $4, %cx\n\t" 794 "imul %cl\n\t"); 795 796 MK_INSN(imul16_2, "mov $2, %ax\n\t" 797 "mov $4, %cx\n\t" 798 "imul %cx\n\t"); 799 800 MK_INSN(imul32_2, "mov $2, %eax\n\t" 801 "mov $4, %ecx\n\t" 802 "imul %ecx\n\t"); 803 804 inregs = (struct regs){ 0 }; 805 806 exec_in_big_real_mode(&insn_imul8_1); 807 report("imul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == (u8)-8); 808 809 exec_in_big_real_mode(&insn_imul16_1); 810 report("imul 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-8); 811 812 exec_in_big_real_mode(&insn_imul32_1); 813 report("imul 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-8); 814 815 exec_in_big_real_mode(&insn_imul8_2); 816 report("imul 4", R_AX | R_CX | R_DX, 817 (outregs.eax & 0xffff) == 8 818 && (outregs.eax & 0xffff0000) == 0x12340000); 819 820 exec_in_big_real_mode(&insn_imul16_2); 821 report("imul 5", R_AX | R_CX | R_DX, outregs.eax == 8); 822 823 exec_in_big_real_mode(&insn_imul32_2); 824 report("imul 6", R_AX | R_CX | R_DX, outregs.eax == 8); 825 } 826 827 void test_mul() 828 { 829 MK_INSN(mul8, "mov $2, %al\n\t" 830 "mov $4, %cx\n\t" 831 "imul %cl\n\t"); 832 833 MK_INSN(mul16, "mov $2, %ax\n\t" 834 "mov $4, %cx\n\t" 835 "imul %cx\n\t"); 836 837 MK_INSN(mul32, "mov $2, %eax\n\t" 838 "mov $4, %ecx\n\t" 839 "imul %ecx\n\t"); 840 841 inregs = (struct regs){ 0 }; 842 843 exec_in_big_real_mode(&insn_mul8); 844 report("mul 1", R_AX | R_CX | R_DX, (outregs.eax & 0xff) == 8); 845 846 exec_in_big_real_mode(&insn_mul16); 847 report("mul 2", R_AX | R_CX | R_DX, outregs.eax == 8); 848 849 exec_in_big_real_mode(&insn_mul32); 850 report("mul 3", R_AX | R_CX | R_DX, outregs.eax == 8); 851 } 852 853 void test_div() 854 { 855 MK_INSN(div8, "mov $257, %ax\n\t" 856 "mov $2, %cl\n\t" 857 "div %cl\n\t"); 858 859 MK_INSN(div16, "mov $512, %ax\n\t" 860 "mov $5, %cx\n\t" 861 "div %cx\n\t"); 862 863 MK_INSN(div32, "mov $512, %eax\n\t" 864 "mov $5, %ecx\n\t" 865 "div %ecx\n\t"); 866 867 inregs = (struct regs){ 0 }; 868 869 exec_in_big_real_mode(&insn_div8); 870 report("div 1", R_AX | R_CX | R_DX, outregs.eax == 384); 871 872 exec_in_big_real_mode(&insn_div16); 873 report("div 2", R_AX | R_CX | R_DX, 874 outregs.eax == 102 && outregs.edx == 2); 875 876 exec_in_big_real_mode(&insn_div32); 877 report("div 3", R_AX | R_CX | R_DX, 878 outregs.eax == 102 && outregs.edx == 2); 879 } 880 881 void test_idiv() 882 { 883 MK_INSN(idiv8, "mov $256, %ax\n\t" 884 "mov $-2, %cl\n\t" 885 "idiv %cl\n\t"); 886 887 MK_INSN(idiv16, "mov $512, %ax\n\t" 888 "mov $-2, %cx\n\t" 889 "idiv %cx\n\t"); 890 891 MK_INSN(idiv32, "mov $512, %eax\n\t" 892 "mov $-2, %ecx\n\t" 893 "idiv %ecx\n\t"); 894 895 inregs = (struct regs){ 0 }; 896 897 exec_in_big_real_mode(&insn_idiv8); 898 report("idiv 1", R_AX | R_CX | R_DX, outregs.eax == (u8)-128); 899 900 exec_in_big_real_mode(&insn_idiv16); 901 report("idiv 2", R_AX | R_CX | R_DX, outregs.eax == (u16)-256); 902 903 exec_in_big_real_mode(&insn_idiv32); 904 report("idiv 3", R_AX | R_CX | R_DX, outregs.eax == (u32)-256); 905 } 906 907 void test_cbw(void) 908 { 909 MK_INSN(cbw, "mov $0xFE, %eax \n\t" 910 "cbw\n\t"); 911 MK_INSN(cwde, "mov $0xFFFE, %eax \n\t" 912 "cwde\n\t"); 913 914 inregs = (struct regs){ 0 }; 915 916 exec_in_big_real_mode(&insn_cbw); 917 report("cbq 1", ~0, outregs.eax == 0xFFFE); 918 919 exec_in_big_real_mode(&insn_cwde); 920 report("cwde 1", ~0, outregs.eax == 0xFFFFFFFE); 921 } 922 923 void test_loopcc(void) 924 { 925 MK_INSN(loop, "mov $10, %ecx\n\t" 926 "1: inc %eax\n\t" 927 "loop 1b\n\t"); 928 929 MK_INSN(loope, "mov $10, %ecx\n\t" 930 "mov $1, %eax\n\t" 931 "1: dec %eax\n\t" 932 "loope 1b\n\t"); 933 934 MK_INSN(loopne, "mov $10, %ecx\n\t" 935 "mov $5, %eax\n\t" 936 "1: dec %eax\n\t" 937 "loopne 1b\n\t"); 938 939 inregs = (struct regs){ 0 }; 940 941 exec_in_big_real_mode(&insn_loop); 942 report("LOOPcc short 1", R_AX, outregs.eax == 10); 943 944 exec_in_big_real_mode(&insn_loope); 945 report("LOOPcc short 2", R_AX | R_CX, 946 outregs.eax == -1 && outregs.ecx == 8); 947 948 exec_in_big_real_mode(&insn_loopne); 949 report("LOOPcc short 3", R_AX | R_CX, 950 outregs.eax == 0 && outregs.ecx == 5); 951 } 952 953 static void test_das(void) 954 { 955 short i; 956 u16 nr_fail = 0; 957 static unsigned test_cases[1024] = { 958 0x46000000, 0x8701a000, 0x9710fa00, 0x97119a00, 959 0x02000101, 0x8301a101, 0x9310fb01, 0x93119b01, 960 0x02000202, 0x8301a202, 0x9710fc02, 0x97119c02, 961 0x06000303, 0x8701a303, 0x9310fd03, 0x93119d03, 962 0x02000404, 0x8301a404, 0x9310fe04, 0x93119e04, 963 0x06000505, 0x8701a505, 0x9710ff05, 0x97119f05, 964 0x06000606, 0x8701a606, 0x56100006, 0x9711a006, 965 0x02000707, 0x8301a707, 0x12100107, 0x9311a107, 966 0x02000808, 0x8301a808, 0x12100208, 0x9311a208, 967 0x06000909, 0x8701a909, 0x16100309, 0x9711a309, 968 0x1200040a, 0x9301a40a, 0x1210040a, 0x9311a40a, 969 0x1600050b, 0x9701a50b, 0x1610050b, 0x9711a50b, 970 0x1600060c, 0x9701a60c, 0x1610060c, 0x9711a60c, 971 0x1200070d, 0x9301a70d, 0x1210070d, 0x9311a70d, 972 0x1200080e, 0x9301a80e, 0x1210080e, 0x9311a80e, 973 0x1600090f, 0x9701a90f, 0x1610090f, 0x9711a90f, 974 0x02001010, 0x8301b010, 0x16100a10, 0x9711aa10, 975 0x06001111, 0x8701b111, 0x12100b11, 0x9311ab11, 976 0x06001212, 0x8701b212, 0x16100c12, 0x9711ac12, 977 0x02001313, 0x8301b313, 0x12100d13, 0x9311ad13, 978 0x06001414, 0x8701b414, 0x12100e14, 0x9311ae14, 979 0x02001515, 0x8301b515, 0x16100f15, 0x9711af15, 980 0x02001616, 0x8301b616, 0x12101016, 0x9311b016, 981 0x06001717, 0x8701b717, 0x16101117, 0x9711b117, 982 0x06001818, 0x8701b818, 0x16101218, 0x9711b218, 983 0x02001919, 0x8301b919, 0x12101319, 0x9311b319, 984 0x1600141a, 0x9701b41a, 0x1610141a, 0x9711b41a, 985 0x1200151b, 0x9301b51b, 0x1210151b, 0x9311b51b, 986 0x1200161c, 0x9301b61c, 0x1210161c, 0x9311b61c, 987 0x1600171d, 0x9701b71d, 0x1610171d, 0x9711b71d, 988 0x1600181e, 0x9701b81e, 0x1610181e, 0x9711b81e, 989 0x1200191f, 0x9301b91f, 0x1210191f, 0x9311b91f, 990 0x02002020, 0x8701c020, 0x12101a20, 0x9311ba20, 991 0x06002121, 0x8301c121, 0x16101b21, 0x9711bb21, 992 0x06002222, 0x8301c222, 0x12101c22, 0x9311bc22, 993 0x02002323, 0x8701c323, 0x16101d23, 0x9711bd23, 994 0x06002424, 0x8301c424, 0x16101e24, 0x9711be24, 995 0x02002525, 0x8701c525, 0x12101f25, 0x9311bf25, 996 0x02002626, 0x8701c626, 0x12102026, 0x9711c026, 997 0x06002727, 0x8301c727, 0x16102127, 0x9311c127, 998 0x06002828, 0x8301c828, 0x16102228, 0x9311c228, 999 0x02002929, 0x8701c929, 0x12102329, 0x9711c329, 1000 0x1600242a, 0x9301c42a, 0x1610242a, 0x9311c42a, 1001 0x1200252b, 0x9701c52b, 0x1210252b, 0x9711c52b, 1002 0x1200262c, 0x9701c62c, 0x1210262c, 0x9711c62c, 1003 0x1600272d, 0x9301c72d, 0x1610272d, 0x9311c72d, 1004 0x1600282e, 0x9301c82e, 0x1610282e, 0x9311c82e, 1005 0x1200292f, 0x9701c92f, 0x1210292f, 0x9711c92f, 1006 0x06003030, 0x8301d030, 0x12102a30, 0x9711ca30, 1007 0x02003131, 0x8701d131, 0x16102b31, 0x9311cb31, 1008 0x02003232, 0x8701d232, 0x12102c32, 0x9711cc32, 1009 0x06003333, 0x8301d333, 0x16102d33, 0x9311cd33, 1010 0x02003434, 0x8701d434, 0x16102e34, 0x9311ce34, 1011 0x06003535, 0x8301d535, 0x12102f35, 0x9711cf35, 1012 0x06003636, 0x8301d636, 0x16103036, 0x9311d036, 1013 0x02003737, 0x8701d737, 0x12103137, 0x9711d137, 1014 0x02003838, 0x8701d838, 0x12103238, 0x9711d238, 1015 0x06003939, 0x8301d939, 0x16103339, 0x9311d339, 1016 0x1200343a, 0x9701d43a, 0x1210343a, 0x9711d43a, 1017 0x1600353b, 0x9301d53b, 0x1610353b, 0x9311d53b, 1018 0x1600363c, 0x9301d63c, 0x1610363c, 0x9311d63c, 1019 0x1200373d, 0x9701d73d, 0x1210373d, 0x9711d73d, 1020 0x1200383e, 0x9701d83e, 0x1210383e, 0x9711d83e, 1021 0x1600393f, 0x9301d93f, 0x1610393f, 0x9311d93f, 1022 0x02004040, 0x8301e040, 0x16103a40, 0x9311da40, 1023 0x06004141, 0x8701e141, 0x12103b41, 0x9711db41, 1024 0x06004242, 0x8701e242, 0x16103c42, 0x9311dc42, 1025 0x02004343, 0x8301e343, 0x12103d43, 0x9711dd43, 1026 0x06004444, 0x8701e444, 0x12103e44, 0x9711de44, 1027 0x02004545, 0x8301e545, 0x16103f45, 0x9311df45, 1028 0x02004646, 0x8301e646, 0x12104046, 0x9311e046, 1029 0x06004747, 0x8701e747, 0x16104147, 0x9711e147, 1030 0x06004848, 0x8701e848, 0x16104248, 0x9711e248, 1031 0x02004949, 0x8301e949, 0x12104349, 0x9311e349, 1032 0x1600444a, 0x9701e44a, 0x1610444a, 0x9711e44a, 1033 0x1200454b, 0x9301e54b, 0x1210454b, 0x9311e54b, 1034 0x1200464c, 0x9301e64c, 0x1210464c, 0x9311e64c, 1035 0x1600474d, 0x9701e74d, 0x1610474d, 0x9711e74d, 1036 0x1600484e, 0x9701e84e, 0x1610484e, 0x9711e84e, 1037 0x1200494f, 0x9301e94f, 0x1210494f, 0x9311e94f, 1038 0x06005050, 0x8701f050, 0x12104a50, 0x9311ea50, 1039 0x02005151, 0x8301f151, 0x16104b51, 0x9711eb51, 1040 0x02005252, 0x8301f252, 0x12104c52, 0x9311ec52, 1041 0x06005353, 0x8701f353, 0x16104d53, 0x9711ed53, 1042 0x02005454, 0x8301f454, 0x16104e54, 0x9711ee54, 1043 0x06005555, 0x8701f555, 0x12104f55, 0x9311ef55, 1044 0x06005656, 0x8701f656, 0x16105056, 0x9711f056, 1045 0x02005757, 0x8301f757, 0x12105157, 0x9311f157, 1046 0x02005858, 0x8301f858, 0x12105258, 0x9311f258, 1047 0x06005959, 0x8701f959, 0x16105359, 0x9711f359, 1048 0x1200545a, 0x9301f45a, 0x1210545a, 0x9311f45a, 1049 0x1600555b, 0x9701f55b, 0x1610555b, 0x9711f55b, 1050 0x1600565c, 0x9701f65c, 0x1610565c, 0x9711f65c, 1051 0x1200575d, 0x9301f75d, 0x1210575d, 0x9311f75d, 1052 0x1200585e, 0x9301f85e, 0x1210585e, 0x9311f85e, 1053 0x1600595f, 0x9701f95f, 0x1610595f, 0x9711f95f, 1054 0x06006060, 0x47010060, 0x16105a60, 0x9711fa60, 1055 0x02006161, 0x03010161, 0x12105b61, 0x9311fb61, 1056 0x02006262, 0x03010262, 0x16105c62, 0x9711fc62, 1057 0x06006363, 0x07010363, 0x12105d63, 0x9311fd63, 1058 0x02006464, 0x03010464, 0x12105e64, 0x9311fe64, 1059 0x06006565, 0x07010565, 0x16105f65, 0x9711ff65, 1060 0x06006666, 0x07010666, 0x16106066, 0x57110066, 1061 0x02006767, 0x03010767, 0x12106167, 0x13110167, 1062 0x02006868, 0x03010868, 0x12106268, 0x13110268, 1063 0x06006969, 0x07010969, 0x16106369, 0x17110369, 1064 0x1200646a, 0x1301046a, 0x1210646a, 0x1311046a, 1065 0x1600656b, 0x1701056b, 0x1610656b, 0x1711056b, 1066 0x1600666c, 0x1701066c, 0x1610666c, 0x1711066c, 1067 0x1200676d, 0x1301076d, 0x1210676d, 0x1311076d, 1068 0x1200686e, 0x1301086e, 0x1210686e, 0x1311086e, 1069 0x1600696f, 0x1701096f, 0x1610696f, 0x1711096f, 1070 0x02007070, 0x03011070, 0x16106a70, 0x17110a70, 1071 0x06007171, 0x07011171, 0x12106b71, 0x13110b71, 1072 0x06007272, 0x07011272, 0x16106c72, 0x17110c72, 1073 0x02007373, 0x03011373, 0x12106d73, 0x13110d73, 1074 0x06007474, 0x07011474, 0x12106e74, 0x13110e74, 1075 0x02007575, 0x03011575, 0x16106f75, 0x17110f75, 1076 0x02007676, 0x03011676, 0x12107076, 0x13111076, 1077 0x06007777, 0x07011777, 0x16107177, 0x17111177, 1078 0x06007878, 0x07011878, 0x16107278, 0x17111278, 1079 0x02007979, 0x03011979, 0x12107379, 0x13111379, 1080 0x1600747a, 0x1701147a, 0x1610747a, 0x1711147a, 1081 0x1200757b, 0x1301157b, 0x1210757b, 0x1311157b, 1082 0x1200767c, 0x1301167c, 0x1210767c, 0x1311167c, 1083 0x1600777d, 0x1701177d, 0x1610777d, 0x1711177d, 1084 0x1600787e, 0x1701187e, 0x1610787e, 0x1711187e, 1085 0x1200797f, 0x1301197f, 0x1210797f, 0x1311197f, 1086 0x82008080, 0x03012080, 0x12107a80, 0x13111a80, 1087 0x86008181, 0x07012181, 0x16107b81, 0x17111b81, 1088 0x86008282, 0x07012282, 0x12107c82, 0x13111c82, 1089 0x82008383, 0x03012383, 0x16107d83, 0x17111d83, 1090 0x86008484, 0x07012484, 0x16107e84, 0x17111e84, 1091 0x82008585, 0x03012585, 0x12107f85, 0x13111f85, 1092 0x82008686, 0x03012686, 0x92108086, 0x13112086, 1093 0x86008787, 0x07012787, 0x96108187, 0x17112187, 1094 0x86008888, 0x07012888, 0x96108288, 0x17112288, 1095 0x82008989, 0x03012989, 0x92108389, 0x13112389, 1096 0x9600848a, 0x1701248a, 0x9610848a, 0x1711248a, 1097 0x9200858b, 0x1301258b, 0x9210858b, 0x1311258b, 1098 0x9200868c, 0x1301268c, 0x9210868c, 0x1311268c, 1099 0x9600878d, 0x1701278d, 0x9610878d, 0x1711278d, 1100 0x9600888e, 0x1701288e, 0x9610888e, 0x1711288e, 1101 0x9200898f, 0x1301298f, 0x9210898f, 0x1311298f, 1102 0x86009090, 0x07013090, 0x92108a90, 0x13112a90, 1103 0x82009191, 0x03013191, 0x96108b91, 0x17112b91, 1104 0x82009292, 0x03013292, 0x92108c92, 0x13112c92, 1105 0x86009393, 0x07013393, 0x96108d93, 0x17112d93, 1106 0x82009494, 0x03013494, 0x96108e94, 0x17112e94, 1107 0x86009595, 0x07013595, 0x92108f95, 0x13112f95, 1108 0x86009696, 0x07013696, 0x96109096, 0x17113096, 1109 0x82009797, 0x03013797, 0x92109197, 0x13113197, 1110 0x82009898, 0x03013898, 0x92109298, 0x13113298, 1111 0x86009999, 0x07013999, 0x96109399, 0x17113399, 1112 0x1300349a, 0x1301349a, 0x1310349a, 0x1311349a, 1113 0x1700359b, 0x1701359b, 0x1710359b, 0x1711359b, 1114 0x1700369c, 0x1701369c, 0x1710369c, 0x1711369c, 1115 0x1300379d, 0x1301379d, 0x1310379d, 0x1311379d, 1116 0x1300389e, 0x1301389e, 0x1310389e, 0x1311389e, 1117 0x1700399f, 0x1701399f, 0x1710399f, 0x1711399f, 1118 0x030040a0, 0x030140a0, 0x17103aa0, 0x17113aa0, 1119 0x070041a1, 0x070141a1, 0x13103ba1, 0x13113ba1, 1120 0x070042a2, 0x070142a2, 0x17103ca2, 0x17113ca2, 1121 0x030043a3, 0x030143a3, 0x13103da3, 0x13113da3, 1122 0x070044a4, 0x070144a4, 0x13103ea4, 0x13113ea4, 1123 0x030045a5, 0x030145a5, 0x17103fa5, 0x17113fa5, 1124 0x030046a6, 0x030146a6, 0x131040a6, 0x131140a6, 1125 0x070047a7, 0x070147a7, 0x171041a7, 0x171141a7, 1126 0x070048a8, 0x070148a8, 0x171042a8, 0x171142a8, 1127 0x030049a9, 0x030149a9, 0x131043a9, 0x131143a9, 1128 0x170044aa, 0x170144aa, 0x171044aa, 0x171144aa, 1129 0x130045ab, 0x130145ab, 0x131045ab, 0x131145ab, 1130 0x130046ac, 0x130146ac, 0x131046ac, 0x131146ac, 1131 0x170047ad, 0x170147ad, 0x171047ad, 0x171147ad, 1132 0x170048ae, 0x170148ae, 0x171048ae, 0x171148ae, 1133 0x130049af, 0x130149af, 0x131049af, 0x131149af, 1134 0x070050b0, 0x070150b0, 0x13104ab0, 0x13114ab0, 1135 0x030051b1, 0x030151b1, 0x17104bb1, 0x17114bb1, 1136 0x030052b2, 0x030152b2, 0x13104cb2, 0x13114cb2, 1137 0x070053b3, 0x070153b3, 0x17104db3, 0x17114db3, 1138 0x030054b4, 0x030154b4, 0x17104eb4, 0x17114eb4, 1139 0x070055b5, 0x070155b5, 0x13104fb5, 0x13114fb5, 1140 0x070056b6, 0x070156b6, 0x171050b6, 0x171150b6, 1141 0x030057b7, 0x030157b7, 0x131051b7, 0x131151b7, 1142 0x030058b8, 0x030158b8, 0x131052b8, 0x131152b8, 1143 0x070059b9, 0x070159b9, 0x171053b9, 0x171153b9, 1144 0x130054ba, 0x130154ba, 0x131054ba, 0x131154ba, 1145 0x170055bb, 0x170155bb, 0x171055bb, 0x171155bb, 1146 0x170056bc, 0x170156bc, 0x171056bc, 0x171156bc, 1147 0x130057bd, 0x130157bd, 0x131057bd, 0x131157bd, 1148 0x130058be, 0x130158be, 0x131058be, 0x131158be, 1149 0x170059bf, 0x170159bf, 0x171059bf, 0x171159bf, 1150 0x070060c0, 0x070160c0, 0x17105ac0, 0x17115ac0, 1151 0x030061c1, 0x030161c1, 0x13105bc1, 0x13115bc1, 1152 0x030062c2, 0x030162c2, 0x17105cc2, 0x17115cc2, 1153 0x070063c3, 0x070163c3, 0x13105dc3, 0x13115dc3, 1154 0x030064c4, 0x030164c4, 0x13105ec4, 0x13115ec4, 1155 0x070065c5, 0x070165c5, 0x17105fc5, 0x17115fc5, 1156 0x070066c6, 0x070166c6, 0x171060c6, 0x171160c6, 1157 0x030067c7, 0x030167c7, 0x131061c7, 0x131161c7, 1158 0x030068c8, 0x030168c8, 0x131062c8, 0x131162c8, 1159 0x070069c9, 0x070169c9, 0x171063c9, 0x171163c9, 1160 0x130064ca, 0x130164ca, 0x131064ca, 0x131164ca, 1161 0x170065cb, 0x170165cb, 0x171065cb, 0x171165cb, 1162 0x170066cc, 0x170166cc, 0x171066cc, 0x171166cc, 1163 0x130067cd, 0x130167cd, 0x131067cd, 0x131167cd, 1164 0x130068ce, 0x130168ce, 0x131068ce, 0x131168ce, 1165 0x170069cf, 0x170169cf, 0x171069cf, 0x171169cf, 1166 0x030070d0, 0x030170d0, 0x17106ad0, 0x17116ad0, 1167 0x070071d1, 0x070171d1, 0x13106bd1, 0x13116bd1, 1168 0x070072d2, 0x070172d2, 0x17106cd2, 0x17116cd2, 1169 0x030073d3, 0x030173d3, 0x13106dd3, 0x13116dd3, 1170 0x070074d4, 0x070174d4, 0x13106ed4, 0x13116ed4, 1171 0x030075d5, 0x030175d5, 0x17106fd5, 0x17116fd5, 1172 0x030076d6, 0x030176d6, 0x131070d6, 0x131170d6, 1173 0x070077d7, 0x070177d7, 0x171071d7, 0x171171d7, 1174 0x070078d8, 0x070178d8, 0x171072d8, 0x171172d8, 1175 0x030079d9, 0x030179d9, 0x131073d9, 0x131173d9, 1176 0x170074da, 0x170174da, 0x171074da, 0x171174da, 1177 0x130075db, 0x130175db, 0x131075db, 0x131175db, 1178 0x130076dc, 0x130176dc, 0x131076dc, 0x131176dc, 1179 0x170077dd, 0x170177dd, 0x171077dd, 0x171177dd, 1180 0x170078de, 0x170178de, 0x171078de, 0x171178de, 1181 0x130079df, 0x130179df, 0x131079df, 0x131179df, 1182 0x830080e0, 0x830180e0, 0x13107ae0, 0x13117ae0, 1183 0x870081e1, 0x870181e1, 0x17107be1, 0x17117be1, 1184 0x870082e2, 0x870182e2, 0x13107ce2, 0x13117ce2, 1185 0x830083e3, 0x830183e3, 0x17107de3, 0x17117de3, 1186 0x870084e4, 0x870184e4, 0x17107ee4, 0x17117ee4, 1187 0x830085e5, 0x830185e5, 0x13107fe5, 0x13117fe5, 1188 0x830086e6, 0x830186e6, 0x931080e6, 0x931180e6, 1189 0x870087e7, 0x870187e7, 0x971081e7, 0x971181e7, 1190 0x870088e8, 0x870188e8, 0x971082e8, 0x971182e8, 1191 0x830089e9, 0x830189e9, 0x931083e9, 0x931183e9, 1192 0x970084ea, 0x970184ea, 0x971084ea, 0x971184ea, 1193 0x930085eb, 0x930185eb, 0x931085eb, 0x931185eb, 1194 0x930086ec, 0x930186ec, 0x931086ec, 0x931186ec, 1195 0x970087ed, 0x970187ed, 0x971087ed, 0x971187ed, 1196 0x970088ee, 0x970188ee, 0x971088ee, 0x971188ee, 1197 0x930089ef, 0x930189ef, 0x931089ef, 0x931189ef, 1198 0x870090f0, 0x870190f0, 0x93108af0, 0x93118af0, 1199 0x830091f1, 0x830191f1, 0x97108bf1, 0x97118bf1, 1200 0x830092f2, 0x830192f2, 0x93108cf2, 0x93118cf2, 1201 0x870093f3, 0x870193f3, 0x97108df3, 0x97118df3, 1202 0x830094f4, 0x830194f4, 0x97108ef4, 0x97118ef4, 1203 0x870095f5, 0x870195f5, 0x93108ff5, 0x93118ff5, 1204 0x870096f6, 0x870196f6, 0x971090f6, 0x971190f6, 1205 0x830097f7, 0x830197f7, 0x931091f7, 0x931191f7, 1206 0x830098f8, 0x830198f8, 0x931092f8, 0x931192f8, 1207 0x870099f9, 0x870199f9, 0x971093f9, 0x971193f9, 1208 0x930094fa, 0x930194fa, 0x931094fa, 0x931194fa, 1209 0x970095fb, 0x970195fb, 0x971095fb, 0x971195fb, 1210 0x970096fc, 0x970196fc, 0x971096fc, 0x971196fc, 1211 0x930097fd, 0x930197fd, 0x931097fd, 0x931197fd, 1212 0x930098fe, 0x930198fe, 0x931098fe, 0x931198fe, 1213 0x970099ff, 0x970199ff, 0x971099ff, 0x971199ff, 1214 }; 1215 1216 MK_INSN(das, "das"); 1217 1218 inregs = (struct regs){ 0 }; 1219 1220 for (i = 0; i < 1024; ++i) { 1221 unsigned tmp = test_cases[i]; 1222 inregs.eax = tmp & 0xff; 1223 inregs.eflags = (tmp >> 16) & 0xff; 1224 exec_in_big_real_mode(&insn_das); 1225 if (!regs_equal(R_AX) 1226 || outregs.eax != ((tmp >> 8) & 0xff) 1227 || (outregs.eflags & 0xff) != (tmp >> 24)) { 1228 ++nr_fail; 1229 break; 1230 } 1231 } 1232 report("DAS", ~0, nr_fail == 0); 1233 } 1234 1235 void test_cwd_cdq() 1236 { 1237 /* Sign-bit set */ 1238 MK_INSN(cwd_1, "mov $0x8000, %ax\n\t" 1239 "cwd\n\t"); 1240 1241 /* Sign-bit not set */ 1242 MK_INSN(cwd_2, "mov $0x1000, %ax\n\t" 1243 "cwd\n\t"); 1244 1245 /* Sign-bit set */ 1246 MK_INSN(cdq_1, "mov $0x80000000, %eax\n\t" 1247 "cdq\n\t"); 1248 1249 /* Sign-bit not set */ 1250 MK_INSN(cdq_2, "mov $0x10000000, %eax\n\t" 1251 "cdq\n\t"); 1252 1253 inregs = (struct regs){ 0 }; 1254 1255 exec_in_big_real_mode(&insn_cwd_1); 1256 report("cwd 1", R_AX | R_DX, 1257 outregs.eax == 0x8000 && outregs.edx == 0xffff); 1258 1259 exec_in_big_real_mode(&insn_cwd_2); 1260 report("cwd 2", R_AX | R_DX, 1261 outregs.eax == 0x1000 && outregs.edx == 0); 1262 1263 exec_in_big_real_mode(&insn_cdq_1); 1264 report("cdq 1", R_AX | R_DX, 1265 outregs.eax == 0x80000000 && outregs.edx == 0xffffffff); 1266 1267 exec_in_big_real_mode(&insn_cdq_2); 1268 report("cdq 2", R_AX | R_DX, 1269 outregs.eax == 0x10000000 && outregs.edx == 0); 1270 } 1271 1272 static struct { 1273 void *address; 1274 unsigned short sel; 1275 } __attribute__((packed)) desc = { 1276 (void *)0x1234, 1277 0x10, 1278 }; 1279 1280 void test_lds_lss() 1281 { 1282 inregs = (struct regs){ .ebx = (unsigned long)&desc }; 1283 1284 MK_INSN(lds, "push %ds\n\t" 1285 "lds (%ebx), %eax\n\t" 1286 "mov %ds, %ebx\n\t" 1287 "pop %ds\n\t"); 1288 exec_in_big_real_mode(&insn_lds); 1289 report("lds", R_AX | R_BX, 1290 outregs.eax == (unsigned long)desc.address && 1291 outregs.ebx == desc.sel); 1292 1293 MK_INSN(les, "push %es\n\t" 1294 "les (%ebx), %eax\n\t" 1295 "mov %es, %ebx\n\t" 1296 "pop %es\n\t"); 1297 exec_in_big_real_mode(&insn_les); 1298 report("les", R_AX | R_BX, 1299 outregs.eax == (unsigned long)desc.address && 1300 outregs.ebx == desc.sel); 1301 1302 MK_INSN(lfs, "push %fs\n\t" 1303 "lfs (%ebx), %eax\n\t" 1304 "mov %fs, %ebx\n\t" 1305 "pop %fs\n\t"); 1306 exec_in_big_real_mode(&insn_lfs); 1307 report("lfs", R_AX | R_BX, 1308 outregs.eax == (unsigned long)desc.address && 1309 outregs.ebx == desc.sel); 1310 1311 MK_INSN(lgs, "push %gs\n\t" 1312 "lgs (%ebx), %eax\n\t" 1313 "mov %gs, %ebx\n\t" 1314 "pop %gs\n\t"); 1315 exec_in_big_real_mode(&insn_lgs); 1316 report("lgs", R_AX | R_BX, 1317 outregs.eax == (unsigned long)desc.address && 1318 outregs.ebx == desc.sel); 1319 1320 MK_INSN(lss, "push %ss\n\t" 1321 "lss (%ebx), %eax\n\t" 1322 "mov %ss, %ebx\n\t" 1323 "pop %ss\n\t"); 1324 exec_in_big_real_mode(&insn_lss); 1325 report("lss", R_AX | R_BX, 1326 outregs.eax == (unsigned long)desc.address && 1327 outregs.ebx == desc.sel); 1328 } 1329 1330 void test_jcxz(void) 1331 { 1332 MK_INSN(jcxz1, "jcxz 1f\n\t" 1333 "mov $0x1234, %eax\n\t" 1334 "1:\n\t"); 1335 MK_INSN(jcxz2, "mov $0x100, %ecx\n\t" 1336 "jcxz 1f\n\t" 1337 "mov $0x1234, %eax\n\t" 1338 "mov $0, %ecx\n\t" 1339 "1:\n\t"); 1340 MK_INSN(jcxz3, "mov $0x10000, %ecx\n\t" 1341 "jcxz 1f\n\t" 1342 "mov $0x1234, %eax\n\t" 1343 "1:\n\t"); 1344 MK_INSN(jecxz1, "jecxz 1f\n\t" 1345 "mov $0x1234, %eax\n\t" 1346 "1:\n\t"); 1347 MK_INSN(jecxz2, "mov $0x10000, %ecx\n\t" 1348 "jecxz 1f\n\t" 1349 "mov $0x1234, %eax\n\t" 1350 "mov $0, %ecx\n\t" 1351 "1:\n\t"); 1352 1353 inregs = (struct regs){ 0 }; 1354 1355 exec_in_big_real_mode(&insn_jcxz1); 1356 report("jcxz short 1", 0, 1); 1357 1358 exec_in_big_real_mode(&insn_jcxz2); 1359 report("jcxz short 2", R_AX, outregs.eax == 0x1234); 1360 1361 exec_in_big_real_mode(&insn_jcxz3); 1362 report("jcxz short 3", R_CX, outregs.ecx == 0x10000); 1363 1364 exec_in_big_real_mode(&insn_jecxz1); 1365 report("jecxz short 1", 0, 1); 1366 1367 exec_in_big_real_mode(&insn_jecxz2); 1368 report("jecxz short 2", R_AX, outregs.eax == 0x1234); 1369 } 1370 1371 static void test_cpuid(void) 1372 { 1373 MK_INSN(cpuid, "cpuid"); 1374 unsigned function = 0x1234; 1375 unsigned eax, ebx, ecx, edx; 1376 1377 inregs.eax = eax = function; 1378 inregs.ecx = ecx = 0; 1379 asm("cpuid" : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)); 1380 exec_in_big_real_mode(&insn_cpuid); 1381 report("cpuid", R_AX|R_BX|R_CX|R_DX, 1382 outregs.eax == eax && outregs.ebx == ebx 1383 && outregs.ecx == ecx && outregs.edx == edx); 1384 } 1385 1386 static void test_ss_base_for_esp_ebp(void) 1387 { 1388 MK_INSN(ssrel1, "mov %ss, %ax; mov %bx, %ss; movl (%ebp), %ebx; mov %ax, %ss"); 1389 MK_INSN(ssrel2, "mov %ss, %ax; mov %bx, %ss; movl (%ebp,%edi,8), %ebx; mov %ax, %ss"); 1390 static unsigned array[] = { 0x12345678, 0, 0, 0, 0x87654321 }; 1391 1392 inregs.ebx = 1; 1393 inregs.ebp = (unsigned)array; 1394 exec_in_big_real_mode(&insn_ssrel1); 1395 report("ss relative addressing (1)", R_AX | R_BX, outregs.ebx == 0x87654321); 1396 inregs.ebx = 1; 1397 inregs.ebp = (unsigned)array; 1398 inregs.edi = 0; 1399 exec_in_big_real_mode(&insn_ssrel2); 1400 report("ss relative addressing (2)", R_AX | R_BX, outregs.ebx == 0x87654321); 1401 } 1402 1403 static void test_sgdt_sidt(void) 1404 { 1405 MK_INSN(sgdt, "sgdtw (%eax)"); 1406 MK_INSN(sidt, "sidtw (%eax)"); 1407 unsigned x, y; 1408 1409 inregs.eax = (unsigned)&y; 1410 asm volatile("sgdtw %0" : "=m"(x)); 1411 exec_in_big_real_mode(&insn_sgdt); 1412 report("sgdt", 0, x == y); 1413 1414 inregs.eax = (unsigned)&y; 1415 asm volatile("sidtw %0" : "=m"(x)); 1416 exec_in_big_real_mode(&insn_sidt); 1417 report("sidt", 0, x == y); 1418 } 1419 1420 static void test_sahf(void) 1421 { 1422 MK_INSN(sahf, "sahf; pushfw; mov (%esp), %al; popfw"); 1423 1424 inregs.eax = 0xfd00; 1425 exec_in_big_real_mode(&insn_sahf); 1426 report("sahf", R_AX, outregs.eax == (inregs.eax | 0xd7)); 1427 } 1428 1429 static void test_lahf(void) 1430 { 1431 MK_INSN(lahf, "pushfw; mov %al, (%esp); popfw; lahf"); 1432 1433 inregs.eax = 0xc7; 1434 exec_in_big_real_mode(&insn_lahf); 1435 report("lahf", R_AX, (outregs.eax >> 8) == inregs.eax); 1436 } 1437 1438 static void test_movzx_movsx(void) 1439 { 1440 MK_INSN(movsx, "movsx %al, %ebx"); 1441 MK_INSN(movzx, "movzx %al, %ebx"); 1442 MK_INSN(movzsah, "movsx %ah, %ebx"); 1443 MK_INSN(movzxah, "movzx %ah, %ebx"); 1444 1445 inregs.eax = 0x1234569c; 1446 inregs.esp = 0xffff; 1447 exec_in_big_real_mode(&insn_movsx); 1448 report("movsx", R_BX, outregs.ebx == (signed char)inregs.eax); 1449 exec_in_big_real_mode(&insn_movzx); 1450 report("movzx", R_BX, outregs.ebx == (unsigned char)inregs.eax); 1451 exec_in_big_real_mode(&insn_movzsah); 1452 report("movsx ah", R_BX, outregs.ebx == (signed char)(inregs.eax>>8)); 1453 exec_in_big_real_mode(&insn_movzxah); 1454 report("movzx ah", R_BX, outregs.ebx == (unsigned char)(inregs.eax >> 8)); 1455 } 1456 1457 static void test_bswap(void) 1458 { 1459 MK_INSN(bswap, "bswap %ecx"); 1460 1461 inregs.ecx = 0x12345678; 1462 exec_in_big_real_mode(&insn_bswap); 1463 report("bswap", R_CX, outregs.ecx == 0x78563412); 1464 } 1465 1466 static void test_aad(void) 1467 { 1468 MK_INSN(aad, "aad"); 1469 1470 inregs.eax = 0x12345678; 1471 exec_in_big_real_mode(&insn_aad); 1472 report("aad", R_AX, outregs.eax == 0x123400d4); 1473 } 1474 1475 static void test_aam(void) 1476 { 1477 MK_INSN(aam, "aam"); 1478 1479 inregs.eax = 0x76543210; 1480 exec_in_big_real_mode(&insn_aam); 1481 report("aam", R_AX, outregs.eax == 0x76540106); 1482 } 1483 1484 static void test_xlat(void) 1485 { 1486 MK_INSN(xlat, "xlat"); 1487 u8 table[256]; 1488 int i; 1489 1490 for (i = 0; i < 256; i++) { 1491 table[i] = i + 1; 1492 } 1493 1494 inregs.eax = 0x89abcdef; 1495 inregs.ebx = (u32)table; 1496 exec_in_big_real_mode(&insn_xlat); 1497 report("xlat", R_AX, outregs.eax == 0x89abcdf0); 1498 } 1499 1500 static void test_salc(void) 1501 { 1502 MK_INSN(clc_salc, "clc; .byte 0xd6"); 1503 MK_INSN(stc_salc, "stc; .byte 0xd6"); 1504 1505 inregs.eax = 0x12345678; 1506 exec_in_big_real_mode(&insn_clc_salc); 1507 report("salc (1)", R_AX, outregs.eax == 0x12345600); 1508 exec_in_big_real_mode(&insn_stc_salc); 1509 report("salc (2)", R_AX, outregs.eax == 0x123456ff); 1510 } 1511 1512 static void test_fninit(void) 1513 { 1514 u16 fcw = -1, fsw = -1; 1515 MK_INSN(fninit, "fninit ; fnstsw (%eax) ; fnstcw (%ebx)"); 1516 1517 inregs.eax = (u32)&fsw; 1518 inregs.ebx = (u32)&fcw; 1519 1520 exec_in_big_real_mode(&insn_fninit); 1521 report("fninit", 0, fsw == 0 && (fcw & 0x103f) == 0x003f); 1522 } 1523 1524 static void test_nopl(void) 1525 { 1526 MK_INSN(nopl1, ".byte 0x90\n\r"); // 1 byte nop 1527 MK_INSN(nopl2, ".byte 0x66, 0x90\n\r"); // 2 bytes nop 1528 MK_INSN(nopl3, ".byte 0x0f, 0x1f, 0x00\n\r"); // 3 bytes nop 1529 MK_INSN(nopl4, ".byte 0x0f, 0x1f, 0x40, 0x00\n\r"); // 4 bytes nop 1530 exec_in_big_real_mode(&insn_nopl1); 1531 exec_in_big_real_mode(&insn_nopl2); 1532 exec_in_big_real_mode(&insn_nopl3); 1533 exec_in_big_real_mode(&insn_nopl4); 1534 report("nopl", 0, 1); 1535 } 1536 1537 void realmode_start(void) 1538 { 1539 test_null(); 1540 1541 test_shld(); 1542 test_push_pop(); 1543 test_pusha_popa(); 1544 test_mov_imm(); 1545 test_cmp_imm(); 1546 test_add_imm(); 1547 test_sub_imm(); 1548 test_xor_imm(); 1549 test_io(); 1550 test_eflags_insn(); 1551 test_jcc_short(); 1552 test_jcc_near(); 1553 /* test_call() uses short jump so call it after testing jcc */ 1554 test_call(); 1555 /* long jmp test uses call near so test it after testing call */ 1556 test_long_jmp(); 1557 test_xchg(); 1558 test_iret(); 1559 test_int(); 1560 test_imul(); 1561 test_mul(); 1562 test_div(); 1563 test_idiv(); 1564 test_loopcc(); 1565 test_cbw(); 1566 test_cwd_cdq(); 1567 test_das(); 1568 test_lds_lss(); 1569 test_jcxz(); 1570 test_cpuid(); 1571 test_ss_base_for_esp_ebp(); 1572 test_sgdt_sidt(); 1573 test_lahf(); 1574 test_sahf(); 1575 test_movzx_movsx(); 1576 test_bswap(); 1577 test_aad(); 1578 test_aam(); 1579 test_xlat(); 1580 test_salc(); 1581 test_fninit(); 1582 test_nopl(); 1583 1584 exit(0); 1585 } 1586 1587 unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff }; 1588 1589 struct __attribute__((packed)) { 1590 unsigned short limit; 1591 void *base; 1592 } r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt }; 1593 1594 asm( 1595 ".section .init \n\t" 1596 1597 ".code32 \n\t" 1598 1599 "mb_magic = 0x1BADB002 \n\t" 1600 "mb_flags = 0x0 \n\t" 1601 1602 "# multiboot header \n\t" 1603 ".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t" 1604 1605 ".globl start \n\t" 1606 ".data \n\t" 1607 ". = . + 4096 \n\t" 1608 "stacktop: \n\t" 1609 1610 ".text \n\t" 1611 "start: \n\t" 1612 "lgdt r_gdt_descr \n\t" 1613 "ljmp $8, $1f; 1: \n\t" 1614 ".code16gcc \n\t" 1615 "mov $16, %eax \n\t" 1616 "mov %ax, %ds \n\t" 1617 "mov %ax, %es \n\t" 1618 "mov %ax, %fs \n\t" 1619 "mov %ax, %gs \n\t" 1620 "mov %ax, %ss \n\t" 1621 "mov %cr0, %eax \n\t" 1622 "btc $0, %eax \n\t" 1623 "mov %eax, %cr0 \n\t" 1624 "ljmp $0, $realmode_entry \n\t" 1625 1626 "realmode_entry: \n\t" 1627 1628 "xor %ax, %ax \n\t" 1629 "mov %ax, %ds \n\t" 1630 "mov %ax, %es \n\t" 1631 "mov %ax, %ss \n\t" 1632 "mov %ax, %fs \n\t" 1633 "mov %ax, %gs \n\t" 1634 "mov $stacktop, %esp\n\t" 1635 "ljmp $0, $realmode_start \n\t" 1636 1637 ".code16gcc \n\t" 1638 ); 1639