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