├── .gitignore ├── test ├── foo13.tst ├── foo14.tst ├── foo15.tst ├── foo16.tst ├── foo11.tst ├── 0005_stack16_real.tst ├── 0004_stack32_real.tst ├── 0034_ret_near_16.tst ├── timing ├── 0026_cbw.tst ├── 0034_ret_far_16.tst ├── 0034_ret_near_32.tst ├── 0027_cwde.tst ├── 0024_cwd.tst ├── 0034_ret_far_32.tst ├── 0025_cdq.tst ├── 0028_movsb.tst ├── foo12.tst ├── foo10.tst ├── foo8.tst ├── 0003_lds_real.tst ├── 0031_io.tst ├── 0030_int_rm16.tst ├── foo6.tst ├── 0009_loop32.tst ├── 0010_loop16.tst ├── 0002_8e_mov_sr.tst ├── 0029_movsb_32.tst ├── foo2.tst ├── foo17.tst ├── foo3.tst ├── 0007_seg_load_pm16.tst ├── 0008_seg_load_pm32.tst ├── foo9.tst ├── 0021_imul_b.tst ├── foo7.tst ├── 0022_imul_w.tst ├── 0023_op_A_80.tst ├── 0014_or.tst ├── 0013_add.tst ├── 0015_adc.tst ├── 0016_sbb.tst ├── 0017_and.tst ├── 0018_sub.tst ├── 0019_xor.tst ├── 0020_cmp.tst ├── 0032_rol8.tst ├── 0033_ror8.tst ├── 0032_rol32.tst ├── 0033_ror32.tst ├── 0032_rol16.tst ├── 0033_ror16.tst ├── Makefile ├── 0001_00_add.tst ├── 0006_div.tst ├── foo1.tst ├── 0004_stack32_real.done ├── 0005_stack16_real.done ├── 0026_cbw.done ├── 0024_cwd.done ├── 0034_ret_near_16.done ├── 0027_cwde.done ├── 0009_loop32.done ├── 0034_ret_far_16.done ├── 0010_loop16.done ├── 0025_cdq.done ├── 0034_ret_far_32.done ├── 0034_ret_near_32.done ├── 0003_lds_real.done ├── 0028_movsb.done ├── 0002_8e_mov_sr.done ├── 0029_movsb_32.done ├── 0021_imul_b.done ├── 0022_imul_w.done ├── 0007_seg_load_pm16.done ├── 0008_seg_load_pm32.done ├── 0016_sbb.done ├── 0013_add.done ├── 0014_or.done ├── 0017_and.done ├── 0019_xor.done ├── 0015_adc.done ├── 0018_sub.done ├── 0020_cmp.done ├── 0036_div.tst ├── 0006_div.done ├── 0011_jmp_short_cc.done ├── 0011_jmp_short_cc.tst ├── 0012_jmp_near_cc.tst ├── 0012_jmp_near_cc.done ├── 0035_idiv.tst ├── 0038_mul.tst ├── 0037_imul.tst ├── 0001_00_add.done ├── 0036_div.done ├── 0037_imul.done ├── 0038_mul.done ├── 0035_idiv.done ├── prepare_test └── x86test.c ├── demo ├── Makefile └── x86emu-demo.c ├── .github └── workflows │ └── ci.yml ├── LICENSE_INFO ├── LICENSE ├── include ├── mem.h ├── ops.h ├── x86emu_int.h ├── decode.h ├── prim_ops.h └── x86emu.h ├── Makefile ├── README.md └── api.c /.gitignore: -------------------------------------------------------------------------------- 1 | changelog 2 | VERSION 3 | -------------------------------------------------------------------------------- /test/foo13.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | [code start=0x100:0x50] 4 | 5 | mov ah,al 6 | jmp $ 7 | -------------------------------------------------------------------------------- /test/foo14.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | [code start=0x100:0x50] 4 | 5 | jmp near dword $ 6 | -------------------------------------------------------------------------------- /test/foo15.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | [code start=0x100:0x50] 4 | 5 | xxx: cli 6 | jmp xxx 7 | -------------------------------------------------------------------------------- /test/foo16.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | [code start=0x100:0x50] 4 | 5 | xxx: cli 6 | jmp near xxx 7 | -------------------------------------------------------------------------------- /test/foo11.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | [code start=0x100:0x0] 4 | 5 | lmsw ax 6 | smsw ax 7 | 8 | nop 9 | -------------------------------------------------------------------------------- /test/0005_stack16_real.tst: -------------------------------------------------------------------------------- 1 | [init srand=9 mode=real] 2 | 3 | eax=rand 4 | 5 | [code start=0x100:0 bits=16] 6 | 7 | push eax 8 | pop ebx 9 | -------------------------------------------------------------------------------- /test/0004_stack32_real.tst: -------------------------------------------------------------------------------- 1 | [init srand=8 mode=real] 2 | 3 | eax=rand 4 | 5 | ss.limit=0xffffffff 6 | 7 | [code start=0x100:0 bits=32] 8 | 9 | push eax 10 | pop ebx 11 | -------------------------------------------------------------------------------- /test/0034_ret_near_16.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | ss.limit=0xffff 4 | 5 | [code start=0x100:0x0 bits=16] 6 | 7 | push 0xAAAA 8 | call func 9 | push 0xBBBB 10 | hlt 11 | 12 | func: 13 | ret 2 14 | nop 15 | nop 16 | -------------------------------------------------------------------------------- /test/timing: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | 3 | while(<>) { 4 | if(/^\S+\s+\+(\S+)\s+\S+:\S+\s+/) { 5 | $t = hex $1; 6 | $total += $t; 7 | $count++; 8 | } 9 | } 10 | 11 | printf "%.2f\n", $total/$count if $count; 12 | -------------------------------------------------------------------------------- /test/0026_cbw.tst: -------------------------------------------------------------------------------- 1 | [init srand=26] 2 | 3 | eax=rand ebx=rand 4 | ss=0x3000 5 | 6 | [code start=0x100:0x0] 7 | 8 | mov al,34h 9 | cbw 10 | push ax 11 | 12 | mov ah,bh 13 | mov al,86h 14 | cbw 15 | push ax 16 | 17 | -------------------------------------------------------------------------------- /demo/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -g -Wall -fomit-frame-pointer -O2 3 | 4 | .PHONY: clean 5 | 6 | x86emu-demo: x86emu-demo.c 7 | $(CC) $(CFLAGS) $< -lx86emu -o $@ 8 | 9 | clean: 10 | rm -f *~ *.o x86emu-demo 11 | -------------------------------------------------------------------------------- /test/0034_ret_far_16.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | ss.limit=0xffff 4 | 5 | [code start=0x100:0x0 bits=16] 6 | 7 | push 0xAAAA 8 | push cs 9 | call func 10 | push 0xBBBB 11 | hlt 12 | 13 | func: 14 | retf 2 15 | nop 16 | nop 17 | -------------------------------------------------------------------------------- /test/0034_ret_near_32.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | ss.limit=0xffffffff 4 | 5 | [code start=0x100:0x0 bits=32] 6 | 7 | push 0xAAAAAAAA 8 | call func 9 | push 0xBBBBBBBB 10 | hlt 11 | 12 | func: 13 | ret 4 14 | nop 15 | nop 16 | -------------------------------------------------------------------------------- /test/0027_cwde.tst: -------------------------------------------------------------------------------- 1 | [init srand=27] 2 | 3 | eax=rand ebx=rand 4 | ss=0x3000 5 | 6 | [code start=0x100:0x0] 7 | 8 | mov ax,3568h 9 | cwde 10 | push eax 11 | 12 | mov eax,ebx 13 | mov ax,8175h 14 | cwde 15 | push eax 16 | 17 | -------------------------------------------------------------------------------- /test/0024_cwd.tst: -------------------------------------------------------------------------------- 1 | [init srand=24] 2 | 3 | eax=rand edx=rand ebx=rand 4 | ss=0x3000 5 | 6 | [code start=0x100:0x0] 7 | 8 | mov ax,1234h 9 | cwd 10 | push dx 11 | 12 | mov edx,ebx 13 | mov ax,9876h 14 | cwd 15 | push dx 16 | 17 | -------------------------------------------------------------------------------- /test/0034_ret_far_32.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | ss.limit=0xffffffff 4 | 5 | [code start=0x100:0x0 bits=32] 6 | 7 | push 0xAAAAAAAA 8 | push cs 9 | call func 10 | push 0xBBBBBBBB 11 | hlt 12 | 13 | func: 14 | retf 4 15 | nop 16 | nop 17 | -------------------------------------------------------------------------------- /test/0025_cdq.tst: -------------------------------------------------------------------------------- 1 | [init srand=25] 2 | 3 | eax=rand edx=rand ebx=rand 4 | ss=0x3000 5 | 6 | [code start=0x100:0x0] 7 | 8 | mov eax,12345678h 9 | cdq 10 | push edx 11 | 12 | mov edx,ebx 13 | mov eax,98765432h 14 | cdq 15 | push edx 16 | 17 | -------------------------------------------------------------------------------- /test/0028_movsb.tst: -------------------------------------------------------------------------------- 1 | [init srand=28] 2 | 3 | 0x20000-0x2000f: rand 4 | 5 | ecx=rand esi=rand edi=rand 6 | ds=0x2000 es=0x4000 7 | 8 | [code start=0x100:0x0] 9 | 10 | mov si,0 11 | mov di,0x50 12 | mov cx,0x0f 13 | movsb 14 | rep movsb 15 | 16 | -------------------------------------------------------------------------------- /test/foo12.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | idt.base=0x9000 4 | 5 | edx=0x3da 6 | 7 | [code start=0x100:0x50] 8 | 9 | in al,dx 10 | mov ah,al 11 | in al,dx 12 | shl eax,16 13 | in al,dx 14 | mov ah,al 15 | out dx,al 16 | in al,dx 17 | 18 | -------------------------------------------------------------------------------- /test/foo10.tst: -------------------------------------------------------------------------------- 1 | [init mode=real] 2 | 3 | idt.base=0x9000 4 | 5 | edx=0x1 6 | eax=0x2045 7 | 8 | [code start=0x100:0x50] 9 | 10 | int 8 11 | mov dl,0x77 12 | hlt 13 | 14 | interrupt_08: 15 | pop ebx 16 | push ebx 17 | mov cx,0x100 18 | iret 19 | 20 | -------------------------------------------------------------------------------- /test/foo8.tst: -------------------------------------------------------------------------------- 1 | [init mode=pm] 2 | 3 | gdt.base=0x2000 4 | gdt[0]=0 5 | gdt[8]=descr(base=0x1000,limit=0x8fff,acc=0x9b) 6 | gdt[16]=descr(base=0x3000,limit=0xa0000fff,acc=0xc93) 7 | 8 | [code start=8:0 bits=16] 9 | 10 | mov bx,12 11 | mov fs,bx 12 | nop 13 | 14 | -------------------------------------------------------------------------------- /test/0003_lds_real.tst: -------------------------------------------------------------------------------- 1 | [init srand=6 mode=real] 2 | 3 | 0x2000-0x2005: rand 4 | 0x2010-0x2015: rand 5 | 0x2020-0x2025: rand 6 | 7 | ebx=0x12342010 8 | ecx=0x2020 9 | 10 | [code start=0x100:0 bits=16] 11 | 12 | les esi,[dword 0x2000] 13 | lfs edi,[bx] 14 | lgs bp,[ecx] 15 | -------------------------------------------------------------------------------- /test/0031_io.tst: -------------------------------------------------------------------------------- 1 | [init mode=real srand=31] 2 | 3 | idt.base=0x9000 4 | 5 | eax=rand edx=rand 6 | 7 | [code start=0x100:0x50] 8 | 9 | out dx,al 10 | out dx,ax 11 | out dx,eax 12 | 13 | in al,dx 14 | in ax,dx 15 | in eax,dx 16 | 17 | in al,0x57 18 | out 0x67,al 19 | 20 | -------------------------------------------------------------------------------- /test/0030_int_rm16.tst: -------------------------------------------------------------------------------- 1 | [init mode=real] 2 | 3 | idt.base=0x9000 4 | 5 | edx=0x1 6 | eax=0x2045 7 | 8 | [code start=0x100:0x50] 9 | 10 | sti 11 | 12 | int 8 13 | mov dl,0x77 14 | hlt 15 | 16 | interrupt_08: 17 | pop ebx 18 | push ebx 19 | mov cx,0x100 20 | iret 21 | 22 | -------------------------------------------------------------------------------- /test/foo6.tst: -------------------------------------------------------------------------------- 1 | [init srand=25] 2 | 3 | 0x20050-0x20053: rand 4 | 5 | eax=rand 6 | ebx=rand 7 | 8 | ds=0x2000 9 | 10 | [code start=0x100:0] 11 | 12 | mov ah,8 13 | rdtsc 14 | mov cr1,ebx 15 | mov dr6,ebx 16 | mov cr2,eax 17 | mov ecx,cr2 18 | mov edx,dr6 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/0009_loop32.tst: -------------------------------------------------------------------------------- 1 | [init mode=protected] 2 | 3 | gdt.base=0x2000 4 | gdt[0x00]=0 5 | gdt[0x08]=descr(base=0x1000,limit=0xffff,acc=0x493) 6 | gdt[0x10]=descr(base=0,limit=0xffffffff,acc=0xc93) 7 | 8 | [code start=8:0 bits=32] 9 | 10 | mov ecx,0x10 11 | l1: 12 | inc ebx 13 | loop l1 14 | 15 | -------------------------------------------------------------------------------- /test/0010_loop16.tst: -------------------------------------------------------------------------------- 1 | [init mode=protected] 2 | 3 | gdt.base=0x2000 4 | gdt[0x00]=0 5 | gdt[0x08]=descr(base=0x1000,limit=0xffff,acc=0x093) 6 | gdt[0x10]=descr(base=0,limit=0xffffffff,acc=0xc93) 7 | 8 | [code start=8:0 bits=16] 9 | 10 | mov ecx,0x70010 11 | l1: 12 | inc ebx 13 | loop l1 14 | 15 | -------------------------------------------------------------------------------- /test/0002_8e_mov_sr.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | 0x1700: 1 2 4 | 5 | ecx=0x6789 6 | edx=0x5555 7 | esp=0x9000 8 | 9 | [code start=0x100:0x0] 10 | 11 | mov es,cx 12 | mov fs,edx 13 | mov gs,[cs:0x700] 14 | push gs 15 | mov [0x1704],gs 16 | 17 | jmp 0xc0:foo+0x400 18 | mov cx,0x1111 19 | foo: 20 | mov bx,0x9999 21 | 22 | -------------------------------------------------------------------------------- /test/0029_movsb_32.tst: -------------------------------------------------------------------------------- 1 | [init srand=29] 2 | 3 | 0x90020000-0x9002000f: rand 4 | 5 | ecx=rand esi=rand edi=rand 6 | ds=0x2000 es=0x4000 7 | ds.limit=0xefffffff 8 | es.limit=0xefffffff 9 | 10 | [code start=0x100:0x0 bits=32] 11 | 12 | mov esi,0x90000000 13 | mov edi,0x90000050 14 | mov ecx,0x0f 15 | movsb 16 | rep movsb 17 | 18 | -------------------------------------------------------------------------------- /test/foo2.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | ecx=0x1234 4 | 5 | [code start=0x100:0x0] 6 | 7 | mov es,ecx 8 | 9 | jmp l1 10 | mov [0x2000],es 11 | l1: 12 | mov [0x3000],es 13 | 14 | jmp near l2 15 | mov [0x2004],es 16 | l2: 17 | mov [0x3004],es 18 | 19 | jmp 0xc0:l3+0x400 20 | mov [0x2008],es 21 | 22 | l3: 23 | mov [0x3008],es 24 | 25 | -------------------------------------------------------------------------------- /test/foo17.tst: -------------------------------------------------------------------------------- 1 | [init mode=real] 2 | 3 | idt.base=0x9000 4 | 5 | edx=0x1 6 | eax=0x2045 7 | 0x0000: 0xff 0xff 0xff 0xff 8 | 0x9040: 0 0 0 0 9 | 10 | [code start=0x100:0x50] 11 | 12 | sti 13 | 14 | int 8 15 | mov dl,0x77 16 | int 0x10 17 | mov dh,0x99 18 | hlt 19 | 20 | interrupt_08: 21 | pop ebx 22 | push ebx 23 | mov cx,0x100 24 | iret 25 | 26 | -------------------------------------------------------------------------------- /test/foo3.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | ecx=0x1234 4 | 5 | [code start=0x100:0x0] 6 | 7 | mov es,ecx 8 | 9 | call l1 10 | mov [0x2000],es 11 | 12 | l1: 13 | mov [0x3000],es 14 | 15 | call l2 16 | mov [0x2004],es 17 | l2: 18 | mov [0x3004],es 19 | 20 | call 0xc0:l3+0x400 21 | mov [0x2008],es 22 | 23 | hlt 24 | l3: 25 | mov [0x3008],es 26 | 27 | retf 28 | -------------------------------------------------------------------------------- /test/0007_seg_load_pm16.tst: -------------------------------------------------------------------------------- 1 | [init mode=pm] 2 | 3 | gdt.base=0x2000 4 | gdt[0x00]=0 5 | gdt[0x08]=descr(base=0x1000,limit=0x8fff,acc=0x9b) 6 | gdt[0x10]=descr(base=0x3000,limit=0xa0000fff,acc=0xc93) 7 | gdt[0x18]=descr(base=0,limit=0x99,acc=0x013) 8 | 9 | ebx=0x10 10 | ecx=0x18 11 | 12 | [code start=8:0 bits=16] 13 | 14 | mov es,bx 15 | mov dword [es:0x50],0x12345678 16 | mov fs,cx 17 | nop 18 | 19 | -------------------------------------------------------------------------------- /test/0008_seg_load_pm32.tst: -------------------------------------------------------------------------------- 1 | [init mode=pm] 2 | 3 | gdt.base=0x2000 4 | gdt[0]=0 5 | gdt[0x08]=descr(base=0x1000,limit=0x8fff,acc=0x49b) 6 | gdt[0x10]=descr(base=0x3000,limit=0xa0000fff,acc=0xc93) 7 | gdt[0x18]=descr(base=0,limit=0x77,acc=0x013) 8 | 9 | ebx=0x10 10 | ecx=0x18 11 | 12 | [code start=8:0 bits=32] 13 | 14 | mov es,ebx 15 | mov dword [es:0x50],0x12345678 16 | mov fs,ecx 17 | nop 18 | 19 | -------------------------------------------------------------------------------- /test/foo9.tst: -------------------------------------------------------------------------------- 1 | [init mode=real] 2 | 3 | gdt.base=0x2000 4 | gdt[0x00]=0 5 | gdt[0x08]=descr(base=0x1000,limit=0x8fff,acc=0x9b) 6 | gdt[0x10]=descr(base=0x3000,limit=0xa0000fff,acc=0xc93) 7 | gdt[0x18]=descr(base=0,limit=0x99,acc=0x013) 8 | 9 | eax=1 10 | ebx=0x10 11 | ecx=0x18 12 | 13 | [code start=8:0 bits=16] 14 | 15 | mov cr0,eax 16 | 17 | mov es,bx 18 | mov dword [es:0x50],0x12345678 19 | mov fs,cx 20 | nop 21 | 22 | -------------------------------------------------------------------------------- /test/0021_imul_b.tst: -------------------------------------------------------------------------------- 1 | [init srand=18] 2 | 3 | 0x20100-0x20105: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | imul bx,cx,7 12 | pushf 13 | 14 | imul dx,si,-53 15 | pushf 16 | 17 | imul ax,[di],102 18 | pushf 19 | 20 | imul ebp,esi,38 21 | pushf 22 | 23 | imul esi,ebx,-49 24 | pushf 25 | 26 | imul ecx,[di+2],-71 27 | pushf 28 | 29 | -------------------------------------------------------------------------------- /test/foo7.tst: -------------------------------------------------------------------------------- 1 | [init mode=pm] 2 | 3 | eax=0xffff 4 | 5 | gdt.base=0x2000 6 | gdt[0]=0 7 | gdt[8]=descr(base=0x1000,limit=0x8fff,acc=0x9b) 8 | gdt[16]=descr(base=0x3000,limit=0xa0000fff,acc=0xc93) 9 | 10 | [code start=8:0 bits=16] 11 | 12 | inc ax 13 | 14 | mov bx,16 15 | mov es,bx 16 | 17 | mov dword [es:0x50],0x12345678 18 | 19 | mov ecx,0x10 20 | l1: 21 | inc ebx 22 | loop l1 23 | 24 | mov bx,12 25 | mov fs,bx 26 | 27 | nop 28 | 29 | -------------------------------------------------------------------------------- /test/0022_imul_w.tst: -------------------------------------------------------------------------------- 1 | [init srand=19] 2 | 3 | 0x20100-0x20105: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | imul bx,cx,0x529a 12 | pushf 13 | 14 | imul dx,si,-0x4287 15 | pushf 16 | 17 | imul ax,[di],0x903 18 | pushf 19 | 20 | imul ebp,esi,0x79b20a61 21 | pushf 22 | 23 | imul esi,ebx,-0x2905d2e4 24 | pushf 25 | 26 | imul ecx,[di+2],-0x6b50305a 27 | pushf 28 | 29 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Install build dependencies 17 | run: | 18 | sudo apt-get update -qq 19 | sudo apt-get install -qq nasm 20 | - name: Build 21 | run: make 22 | - name: Run tests 23 | run: make -C test 24 | -------------------------------------------------------------------------------- /test/0023_op_A_80.tst: -------------------------------------------------------------------------------- 1 | [init srand=23] 2 | 3 | 0x20000-0x20017: rand 4 | 5 | ds=0x2000 ss=0x3000 6 | 7 | [code start=0x100:0x0] 8 | 9 | mov al,0 10 | 11 | l_10: 12 | 13 | mov cl,[si] 14 | lea si,[si+1] 15 | m0: 16 | add cl,0x23 17 | pushf 18 | 19 | mov dh,[si] 20 | lea si,[si+1] 21 | m1: 22 | add dh,-0x49 23 | pushf 24 | 25 | m2: 26 | add byte[si],0x72 27 | lea si,[si+1] 28 | pushf 29 | 30 | add al,8 31 | add byte [cs:m0+1],8 32 | add byte [cs:m1+1],8 33 | add byte [cs:m2+1],8 34 | 35 | cmp al,0x40 36 | jb l_10 37 | 38 | -------------------------------------------------------------------------------- /test/0014_or.tst: -------------------------------------------------------------------------------- 1 | [init srand=11] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | or [di],cl 12 | pushf 13 | or dl,ch 14 | pushf 15 | or ch,[di+1] 16 | pushf 17 | db 0x0a, 0xf1 ; or dh,cl 18 | pushf 19 | 20 | or [di+2],bx 21 | pushf 22 | or bp,si 23 | pushf 24 | or si,[di+4] 25 | pushf 26 | db 0x0b, 0xd3 ; or dx,bx 27 | pushf 28 | 29 | or [di+6],ebx 30 | pushf 31 | or ebp,esi 32 | pushf 33 | or esi,[di+10] 34 | pushf 35 | db 0x66, 0x0b, 0xd3 ; or edx,ebx 36 | pushf 37 | 38 | or al,0x97 39 | pushf 40 | or ax,0x1257 41 | pushf 42 | or eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0013_add.tst: -------------------------------------------------------------------------------- 1 | [init srand=10] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | add [di],cl 12 | pushf 13 | add dl,ch 14 | pushf 15 | add ch,[di+1] 16 | pushf 17 | db 0x02, 0xf1 ; add dh,cl 18 | pushf 19 | 20 | add [di+2],bx 21 | pushf 22 | add bp,si 23 | pushf 24 | add si,[di+4] 25 | pushf 26 | db 0x03, 0xd3 ; add dx,bx 27 | pushf 28 | 29 | add [di+6],ebx 30 | pushf 31 | add ebp,esi 32 | pushf 33 | add esi,[di+10] 34 | pushf 35 | db 0x66, 0x03, 0xd3 ; add edx,ebx 36 | pushf 37 | 38 | add al,0x97 39 | pushf 40 | add ax,0x1257 41 | pushf 42 | add eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0015_adc.tst: -------------------------------------------------------------------------------- 1 | [init srand=12] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | adc [di],cl 12 | pushf 13 | adc dl,ch 14 | pushf 15 | adc ch,[di+1] 16 | pushf 17 | db 0x12, 0xf1 ; adc dh,cl 18 | pushf 19 | 20 | adc [di+2],bx 21 | pushf 22 | adc bp,si 23 | pushf 24 | adc si,[di+4] 25 | pushf 26 | db 0x13, 0xd3 ; adc dx,bx 27 | pushf 28 | 29 | adc [di+6],ebx 30 | pushf 31 | adc ebp,esi 32 | pushf 33 | adc esi,[di+10] 34 | pushf 35 | db 0x66, 0x13, 0xd3 ; adc edx,ebx 36 | pushf 37 | 38 | adc al,0x97 39 | pushf 40 | adc ax,0x1257 41 | pushf 42 | adc eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0016_sbb.tst: -------------------------------------------------------------------------------- 1 | [init srand=13] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | sbb [di],cl 12 | pushf 13 | sbb dl,ch 14 | pushf 15 | sbb ch,[di+1] 16 | pushf 17 | db 0x1a, 0xf1 ; sbb dh,cl 18 | pushf 19 | 20 | sbb [di+2],bx 21 | pushf 22 | sbb bp,si 23 | pushf 24 | sbb si,[di+4] 25 | pushf 26 | db 0x1b, 0xd3 ; sbb dx,bx 27 | pushf 28 | 29 | sbb [di+6],ebx 30 | pushf 31 | sbb ebp,esi 32 | pushf 33 | sbb esi,[di+10] 34 | pushf 35 | db 0x66, 0x1b, 0xd3 ; sbb edx,ebx 36 | pushf 37 | 38 | sbb al,0x97 39 | pushf 40 | sbb ax,0x1257 41 | pushf 42 | sbb eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0017_and.tst: -------------------------------------------------------------------------------- 1 | [init srand=14] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | and [di],cl 12 | pushf 13 | and dl,ch 14 | pushf 15 | and ch,[di+1] 16 | pushf 17 | db 0x22, 0xf1 ; and dh,cl 18 | pushf 19 | 20 | and [di+2],bx 21 | pushf 22 | and bp,si 23 | pushf 24 | and si,[di+4] 25 | pushf 26 | db 0x23, 0xd3 ; and dx,bx 27 | pushf 28 | 29 | and [di+6],ebx 30 | pushf 31 | and ebp,esi 32 | pushf 33 | and esi,[di+10] 34 | pushf 35 | db 0x66, 0x23, 0xd3 ; and edx,ebx 36 | pushf 37 | 38 | and al,0x97 39 | pushf 40 | and ax,0x1257 41 | pushf 42 | and eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0018_sub.tst: -------------------------------------------------------------------------------- 1 | [init srand=15] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | sub [di],cl 12 | pushf 13 | sub dl,ch 14 | pushf 15 | sub ch,[di+1] 16 | pushf 17 | db 0x2a, 0xf1 ; sub dh,cl 18 | pushf 19 | 20 | sub [di+2],bx 21 | pushf 22 | sub bp,si 23 | pushf 24 | sub si,[di+4] 25 | pushf 26 | db 0x2b, 0xd3 ; sub dx,bx 27 | pushf 28 | 29 | sub [di+6],ebx 30 | pushf 31 | sub ebp,esi 32 | pushf 33 | sub esi,[di+10] 34 | pushf 35 | db 0x66, 0x2b, 0xd3 ; sub edx,ebx 36 | pushf 37 | 38 | sub al,0x97 39 | pushf 40 | sub ax,0x1257 41 | pushf 42 | sub eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0019_xor.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | xor [di],cl 12 | pushf 13 | xor dl,ch 14 | pushf 15 | xor ch,[di+1] 16 | pushf 17 | db 0x32, 0xf1 ; xor dh,cl 18 | pushf 19 | 20 | xor [di+2],bx 21 | pushf 22 | xor bp,si 23 | pushf 24 | xor si,[di+4] 25 | pushf 26 | db 0x33, 0xd3 ; xor dx,bx 27 | pushf 28 | 29 | xor [di+6],ebx 30 | pushf 31 | xor ebp,esi 32 | pushf 33 | xor esi,[di+10] 34 | pushf 35 | db 0x66, 0x33, 0xd3 ; xor edx,ebx 36 | pushf 37 | 38 | xor al,0x97 39 | pushf 40 | xor ax,0x1257 41 | pushf 42 | xor eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0020_cmp.tst: -------------------------------------------------------------------------------- 1 | [init srand=17] 2 | 3 | 0x20100-0x2010d: rand 4 | 5 | eax=rand ebx=rand ecx=rand edx=rand esi=rand ebp=rand 6 | edi=0x100 7 | ds=0x2000 ss=0x3000 8 | 9 | [code start=0x100:0x0] 10 | 11 | cmp [di],cl 12 | pushf 13 | cmp dl,ch 14 | pushf 15 | cmp ch,[di+1] 16 | pushf 17 | db 0x3a, 0xf1 ; cmp dh,cl 18 | pushf 19 | 20 | cmp [di+2],bx 21 | pushf 22 | cmp bp,si 23 | pushf 24 | cmp si,[di+4] 25 | pushf 26 | db 0x3b, 0xd3 ; cmp dx,bx 27 | pushf 28 | 29 | cmp [di+6],ebx 30 | pushf 31 | cmp ebp,esi 32 | pushf 33 | cmp esi,[di+10] 34 | pushf 35 | db 0x66, 0x3b, 0xd3 ; cmp edx,ebx 36 | pushf 37 | 38 | cmp al,0x97 39 | pushf 40 | cmp ax,0x1257 41 | pushf 42 | cmp eax,0x87493052 43 | pushf 44 | 45 | -------------------------------------------------------------------------------- /test/0032_rol8.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20000-0x201ff: rand 4 | eax=0 ecx=0 edx=0 5 | ds=0x2000 es=0x3000 ss=0xf000 6 | 7 | [code start=0x100:0x0] 8 | 9 | x1: 10 | add bp,0x8000 ; alternately set OF flag 11 | mov dl,[si] 12 | rol dl,cl 13 | pushf 14 | mov [es:di],cx 15 | pop word [es:di + 2] 16 | mov dword [es:di + 4],edx 17 | add si,1 18 | add di,8 19 | inc cx 20 | cmp cx,200h 21 | jb x1 22 | 23 | 24 | ; with count = 1, OF flag is set 25 | mov cx,1 26 | xor bx,bx 27 | xor bp,bp 28 | xor si,si 29 | x2: 30 | add bp,0x8000 ; alternately set OF flag 31 | mov dl,[si] 32 | rol dl,cl 33 | pushf 34 | mov [es:di],cx 35 | pop word [es:di + 2] 36 | mov dword [es:di + 4],edx 37 | add si,1 38 | add di,8 39 | inc bx 40 | cmp bx,100h 41 | jb x2 42 | 43 | -------------------------------------------------------------------------------- /test/0033_ror8.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20000-0x201ff: rand 4 | eax=0 ecx=0 edx=0 5 | ds=0x2000 es=0x3000 ss=0xf000 6 | 7 | [code start=0x100:0x0] 8 | 9 | x1: 10 | add bp,0x8000 ; alternately set OF flag 11 | mov dl,[si] 12 | ror dl,cl 13 | pushf 14 | mov [es:di],cx 15 | pop word [es:di + 2] 16 | mov dword [es:di + 4],edx 17 | add si,1 18 | add di,8 19 | inc cx 20 | cmp cx,200h 21 | jb x1 22 | 23 | 24 | ; with count = 1, OF flag is set 25 | mov cx,1 26 | xor bx,bx 27 | xor bp,bp 28 | xor si,si 29 | x2: 30 | add bp,0x8000 ; alternately set OF flag 31 | mov dl,[si] 32 | ror dl,cl 33 | pushf 34 | mov [es:di],cx 35 | pop word [es:di + 2] 36 | mov dword [es:di + 4],edx 37 | add si,1 38 | add di,8 39 | inc bx 40 | cmp bx,100h 41 | jb x2 42 | 43 | -------------------------------------------------------------------------------- /test/0032_rol32.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20000-0x207ff: rand 4 | eax=0 ecx=0 edx=0 5 | ds=0x2000 es=0x3000 ss=0xf000 6 | 7 | [code start=0x100:0x0] 8 | 9 | x1: 10 | add bp,0x8000 ; alternately set OF flag 11 | mov edx,[si] 12 | rol edx,cl 13 | pushf 14 | mov [es:di],cx 15 | pop word [es:di + 2] 16 | mov dword [es:di + 4],edx 17 | add si,4 18 | add di,8 19 | inc cx 20 | cmp cx,200h 21 | jb x1 22 | 23 | 24 | ; with count = 1, OF flag is set 25 | mov cx,1 26 | xor bx,bx 27 | xor bp,bp 28 | xor si,si 29 | x2: 30 | add bp,0x8000 ; alternately set OF flag 31 | mov edx,[si] 32 | rol edx,cl 33 | pushf 34 | mov [es:di],cx 35 | pop word [es:di + 2] 36 | mov dword [es:di + 4],edx 37 | add si,4 38 | add di,8 39 | inc bx 40 | cmp bx,100h 41 | jb x2 42 | 43 | -------------------------------------------------------------------------------- /test/0033_ror32.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20000-0x207ff: rand 4 | eax=0 ecx=0 edx=0 5 | ds=0x2000 es=0x3000 ss=0xf000 6 | 7 | [code start=0x100:0x0] 8 | 9 | x1: 10 | add bp,0x8000 ; alternately set OF flag 11 | mov edx,[si] 12 | ror edx,cl 13 | pushf 14 | mov [es:di],cx 15 | pop word [es:di + 2] 16 | mov dword [es:di + 4],edx 17 | add si,4 18 | add di,8 19 | inc cx 20 | cmp cx,200h 21 | jb x1 22 | 23 | 24 | ; with count = 1, OF flag is set 25 | mov cx,1 26 | xor bx,bx 27 | xor bp,bp 28 | xor si,si 29 | x2: 30 | add bp,0x8000 ; alternately set OF flag 31 | mov edx,[si] 32 | ror edx,cl 33 | pushf 34 | mov [es:di],cx 35 | pop word [es:di + 2] 36 | mov dword [es:di + 4],edx 37 | add si,4 38 | add di,8 39 | inc bx 40 | cmp bx,100h 41 | jb x2 42 | 43 | -------------------------------------------------------------------------------- /test/0032_rol16.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20000-0x203ff: rand 4 | eax=0 ecx=0 edx=0 ebp=0 5 | ds=0x2000 es=0x3000 ss=0xf000 6 | 7 | [code start=0x100:0x0] 8 | 9 | x1: 10 | add bp,0x8000 ; alternately set OF flag 11 | mov dx,[si] 12 | rol dx,cl 13 | pushf 14 | mov [es:di],cx 15 | pop word [es:di + 2] 16 | mov dword [es:di + 4],edx 17 | add si,2 18 | add di,8 19 | inc cx 20 | cmp cx,200h 21 | jb x1 22 | 23 | 24 | ; with count = 1, OF flag is set 25 | mov cx,1 26 | xor bx,bx 27 | xor bp,bp 28 | xor si,si 29 | x2: 30 | add bp,0x8000 ; alternately set OF flag 31 | mov dx,[si] 32 | rol dx,cl 33 | pushf 34 | mov [es:di],cx 35 | pop word [es:di + 2] 36 | mov dword [es:di + 4],edx 37 | add si,2 38 | add di,8 39 | inc bx 40 | cmp bx,100h 41 | jb x2 42 | 43 | -------------------------------------------------------------------------------- /test/0033_ror16.tst: -------------------------------------------------------------------------------- 1 | [init srand=16] 2 | 3 | 0x20000-0x203ff: rand 4 | eax=0 ecx=0 edx=0 ebp=0 5 | ds=0x2000 es=0x3000 ss=0xf000 6 | 7 | [code start=0x100:0x0] 8 | 9 | x1: 10 | add bp,0x8000 ; alternately set OF flag 11 | mov dx,[si] 12 | ror dx,cl 13 | pushf 14 | mov [es:di],cx 15 | pop word [es:di + 2] 16 | mov dword [es:di + 4],edx 17 | add si,2 18 | add di,8 19 | inc cx 20 | cmp cx,200h 21 | jb x1 22 | 23 | 24 | ; with count = 1, OF flag is set 25 | mov cx,1 26 | xor bx,bx 27 | xor bp,bp 28 | xor si,si 29 | x2: 30 | add bp,0x8000 ; alternately set OF flag 31 | mov dx,[si] 32 | ror dx,cl 33 | pushf 34 | mov [es:di],cx 35 | pop word [es:di + 2] 36 | mov dword [es:di + 4],edx 37 | add si,2 38 | add di,8 39 | inc bx 40 | cmp bx,100h 41 | jb x2 42 | 43 | -------------------------------------------------------------------------------- /LICENSE_INFO: -------------------------------------------------------------------------------- 1 | License information 2 | ------------------- 3 | 4 | The x86emu library is under a BSD style license, comaptible 5 | with the XFree86 and X licenses used by XFree86. The 6 | original x86emu libraries were under the GNU General Public 7 | License. Due to license incompatibilities between the GPL 8 | and the XFree86 license, the original authors of the code 9 | decided to allow a license change. If you have submitted 10 | code to the original x86emu project, and you don't agree 11 | with the license change, please contact us and let you 12 | know. Your code will be removed to comply with your wishes. 13 | 14 | If you have any questions about this, please send email to 15 | x86emu@linuxlabs.com or KendallB@scitechsoft.com for 16 | clarification. 17 | 18 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -g -Wall -fomit-frame-pointer -O2 3 | LDFLAGS = 4 | TST_FILES = $(sort $(wildcard *.tst)) 5 | INIT_FILES = $(addsuffix .init,$(basename $(wildcard *.tst))) 6 | RES_FILES = $(sort $(addsuffix .result,$(basename $(wildcard *.tst)))) 7 | TEST_OPTS = --verbose --show code,regs,data,acc,io,ints,attr,time 8 | 9 | export LD_LIBRARY_PATH=.. 10 | 11 | .PHONY: all test clean 12 | .SECONDARY: $(INIT_FILES) 13 | 14 | test: x86test $(RES_FILES) 15 | 16 | all: x86test 17 | @./prepare_test *.tst 18 | @./x86test $(TEST_OPTS) *.init 19 | 20 | x86test: x86test.c 21 | $(CC) $(CFLAGS) $< -I ../include -L .. -lx86emu -o $@ $(LDFLAGS) 22 | 23 | %.result: %.init 24 | @./x86test $(TEST_OPTS) $< 25 | 26 | %.init: %.tst 27 | @./prepare_test $< 28 | 29 | clean: 30 | rm -f *~ *.o x86test *.init *.result *.log 31 | 32 | -------------------------------------------------------------------------------- /test/0001_00_add.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | esi=0x0000 edi=0xffff ebp=0xa000 ebx=0x5000 4 | edx=0x4433 ecx=0x6655 5 | ds=0x2000 ss=0x4000 es=0x6000 6 | 7 | [code start=0x100:0x0] 8 | 9 | add [bx+si],cl 10 | add [bx+di],cl 11 | add [bp+si],cl 12 | add [bp+di],cl 13 | add [si],cl 14 | add [di],cl 15 | add [0x9000],cl 16 | add [bx],cl 17 | 18 | add [bx+si+0x40],ch 19 | add [bx+di+0x40],ch 20 | add [bp+si+0x40],ch 21 | add [bp+di+0x40],ch 22 | add [si+0x40],ch 23 | add [di+0x40],ch 24 | add [bp+0x40],ch 25 | add [bx+0x40],ch 26 | 27 | add [es:bx+si+0x800],dl 28 | add [es:bx+di+0x800],dl 29 | add [es:bp+si+0x800],dl 30 | add [es:bp+di+0x800],dl 31 | add [es:si+0x800],dl 32 | add [es:di+0x800],dl 33 | add [es:bp+0x800],dl 34 | add [es:bx+0x800],dl 35 | 36 | add al,dh 37 | add cl,dh 38 | add dl,dh 39 | add bl,dh 40 | add ah,dh 41 | add ch,dh 42 | add dh,dh 43 | add bh,dh 44 | 45 | add [ecx],al 46 | 47 | -------------------------------------------------------------------------------- /test/0006_div.tst: -------------------------------------------------------------------------------- 1 | [init mode=real] 2 | 3 | idt.base=0x1000 4 | 5 | [code start=00:0x2000] 6 | 7 | mov ax,1 8 | mov dx,1 9 | mov cx,0 10 | div cx 11 | push ax 12 | push dx 13 | 14 | mov ax,0x567 15 | mov dx,0x67 16 | mov cx,0x89 17 | div cx 18 | push ax 19 | push dx 20 | 21 | mov ax,0x567f 22 | mov dx,0x3267 23 | div word [data_1] 24 | push ax 25 | push dx 26 | 27 | mov ax,0x7812 28 | mov cl,0x96 29 | div cl 30 | push ax 31 | 32 | mov ax,0x2812 33 | div byte [data_1] 34 | push ax 35 | 36 | mov ax,1 37 | mov dx,1 38 | mov cx,0 39 | idiv cx 40 | push ax 41 | push dx 42 | 43 | mov ax,0x567 44 | mov dx,0x67 45 | mov cx,0x1892 46 | idiv cx 47 | push ax 48 | push dx 49 | 50 | mov ax,0x567f 51 | mov dx,0x1267 52 | idiv word [data_1] 53 | push ax 54 | push dx 55 | 56 | mov ax,0x3812 57 | mov cl,0x86 58 | idiv cl 59 | push ax 60 | 61 | mov ax,0x2812 62 | idiv byte [data_1] 63 | push ax 64 | 65 | hlt 66 | 67 | interrupt_00: 68 | xor eax,eax 69 | xor edx,edx 70 | mov ecx,0x99999999 71 | iret 72 | 73 | data_1 dd 0x12345678 74 | -------------------------------------------------------------------------------- /test/foo1.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | 0x1700: 1 2 4 | 5 | ecx=0x6789 6 | edx=0x5555 7 | esp=0x9000 8 | 9 | [code start=0x100:0x0] 10 | 11 | 12 | mov es,cx 13 | mov fs,edx 14 | mov gs,[cs:0x700] 15 | push gs 16 | mov eax,0x1000 17 | mov [cs:eax],es 18 | mov [cs:eax+0x77],es 19 | mov [cs:eax-0x66],es 20 | mov [ds:bx],es 21 | mov [ss:0x1234],es 22 | mov [ss:bx+si+0x12],es 23 | mov [ss:eax+ebx],es 24 | mov [ss:eax+ebx+0x12],es 25 | mov [ss:eax+ebx+0x12345678],es 26 | mov [ss:eax+ebx*4],es 27 | mov [ss:eax+ebx*4+0x12],es 28 | mov [ss:eax+ebx*4+0x12345678],es 29 | mov [ss:ebx*8+0x12345678],es 30 | mov [ss:esi*2],es 31 | mov [ss:esi-1],es 32 | mov [ss:esi*2-1],es 33 | mov [ss:esi*2+1],es 34 | mov [ss:esi*8],es 35 | mov [ss:esi*8+1],es 36 | mov [ebp+1],es 37 | mov [esp+1],es 38 | db 0x36, 0x67, 0x8c, 0x04, 0x25, 0x01, 0x00, 0x00, 0x00 39 | db 0x36, 0x67, 0x8c, 0x04, 0x25, 0x01, 0x00, 0x00, 0xff 40 | mov ax,es 41 | mov ebx,fs 42 | mov [0x1704],gs 43 | pop gs 44 | 45 | jmp 0xc0:foo+0x400 46 | mov cx,0x1111 47 | foo: 48 | mov bx,0x9999 49 | 50 | mov bl,0x71 51 | mov dh,0x34 52 | -------------------------------------------------------------------------------- /test/0004_stack32_real.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 50 5b f4 4 | fffffff0: 72 ff 2a 23 5 | 6 | ; - - registers 7 | msr[0010] 0000000000000003 ; tsc 8 | 9 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 10 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 11 | 12 | gdt.base=00000000 gdt.limit=ffff 13 | idt.base=00000000 idt.limit=ffff 14 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 15 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 16 | 17 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=049b 18 | ss=0000 ss.base=00000000 ss.limit=ffffffff ss.acc=0c93 19 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 20 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 21 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 22 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 23 | 24 | eax=232aff72 ebx=232aff72 ecx=00000000 edx=00000000 25 | esi=00000000 edi=00000000 ebp=00000000 esp=00000000 26 | eip=00000003 eflags=00000002 27 | 28 | -------------------------------------------------------------------------------- /test/0005_stack16_real.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 66 50 66 5b f4 4 | 0000fff0: 73 1f 11 02 5 | 6 | ; - - registers 7 | msr[0010] 0000000000000003 ; tsc 8 | 9 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 10 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 11 | 12 | gdt.base=00000000 gdt.limit=ffff 13 | idt.base=00000000 idt.limit=ffff 14 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 15 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 16 | 17 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 18 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 19 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 20 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 21 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 22 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 23 | 24 | eax=02111f73 ebx=02111f73 ecx=00000000 edx=00000000 25 | esi=00000000 edi=00000000 ebp=00000000 esp=00000000 26 | eip=00000005 eflags=00000002 27 | 28 | -------------------------------------------------------------------------------- /test/0026_cbw.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: b0 34 98 50 88 fc b0 86 98 50 f4 4 | 0003fff0: 86 ff 34 00 5 | 6 | ; - - registers 7 | msr[0010] 0000000000000008 ; tsc 8 | 9 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 10 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 11 | 12 | gdt.base=00000000 gdt.limit=ffff 13 | idt.base=00000000 idt.limit=ffff 14 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 15 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 16 | 17 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 18 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 19 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 20 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 21 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 22 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 23 | 24 | eax=cfcbff86 ebx=4bd9aaf3 ecx=00000000 edx=00000000 25 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fffc 26 | eip=0000000b eflags=00000002 27 | 28 | -------------------------------------------------------------------------------- /test/0024_cwd.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: b8 34 12 99 52 66 89 da b8 76 98 99 52 f4 4 | 0003fff0: ff ff 00 00 5 | 6 | ; - - registers 7 | msr[0010] 0000000000000008 ; tsc 8 | 9 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 10 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 11 | 12 | gdt.base=00000000 gdt.limit=ffff 13 | idt.base=00000000 idt.limit=ffff 14 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 15 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 16 | 17 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 18 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 19 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 20 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 21 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 22 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 23 | 24 | eax=11ff9876 ebx=4b4a8d43 ecx=00000000 edx=4b4affff 25 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fffc 26 | eip=0000000e eflags=00000002 27 | 28 | -------------------------------------------------------------------------------- /test/0034_ret_near_16.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 68 aa aa e8 04 00 68 bb bb f4 c2 02 00 90 90 f4 4 | 0000fff0: 06 00 bb bb 5 | 6 | ; - - registers 7 | msr[0010] 0000000000000005 ; tsc 8 | 9 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 10 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 11 | 12 | gdt.base=00000000 gdt.limit=ffff 13 | idt.base=00000000 idt.limit=ffff 14 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 15 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 16 | 17 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 18 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 19 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 20 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 21 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 22 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 23 | 24 | eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 25 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fffe 26 | eip=0000000a eflags=00000002 27 | 28 | -------------------------------------------------------------------------------- /test/0027_cwde.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: b8 68 35 66 98 66 50 66 89 d8 b8 75 81 66 98 66 4 | 00001010: 50 f4 5 | 0003fff0: 75 81 ff ff 68 35 00 00 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000008 ; tsc 9 | 10 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00000000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 19 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 20 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 21 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 22 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 23 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 24 | 25 | eax=ffff8175 ebx=08d83a9f ecx=00000000 edx=00000000 26 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fff8 27 | eip=00000012 eflags=00000002 28 | 29 | -------------------------------------------------------------------------------- /test/0009_loop32.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: b9 10 00 00 00 43 e2 fd f4 4 | 00002000: 00 00 00 00 00 00 00 00 ff ff 00 10 00 93 40 00 5 | 00002010: ff ff 00 00 00 93 cf 00 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000022 ; tsc 9 | 10 | cr0=00000001 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00002000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0008 cs.base=00001000 cs.limit=0000ffff cs.acc=0493 19 | ss=0000 ss.base=00000000 ss.limit=00000000 ss.acc=0000 20 | ds=0000 ds.base=00000000 ds.limit=00000000 ds.acc=0000 21 | es=0000 es.base=00000000 es.limit=00000000 es.acc=0000 22 | fs=0000 fs.base=00000000 fs.limit=00000000 fs.acc=0000 23 | gs=0000 gs.base=00000000 gs.limit=00000000 gs.acc=0000 24 | 25 | eax=00000000 ebx=00000010 ecx=00000000 edx=00000000 26 | esi=00000000 edi=00000000 ebp=00000000 esp=00000000 27 | eip=00000009 eflags=00000012 ; af 28 | 29 | -------------------------------------------------------------------------------- /test/0034_ret_far_16.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 68 aa aa 0e e8 04 00 68 bb bb f4 ca 02 00 90 90 4 | 00001010: f4 5 | 0000fff0: 07 00 00 01 bb bb 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000006 ; tsc 9 | 10 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00000000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 19 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 20 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 21 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 22 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 23 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 24 | 25 | eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 26 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fffe 27 | eip=0000000b eflags=00000002 28 | 29 | -------------------------------------------------------------------------------- /test/0010_loop16.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 66 b9 10 00 07 00 66 43 e2 fc f4 4 | 00002000: 00 00 00 00 00 00 00 00 ff ff 00 10 00 93 00 00 5 | 00002010: ff ff 00 00 00 93 cf 00 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000022 ; tsc 9 | 10 | cr0=00000001 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00002000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0008 cs.base=00001000 cs.limit=0000ffff cs.acc=0093 19 | ss=0000 ss.base=00000000 ss.limit=00000000 ss.acc=0000 20 | ds=0000 ds.base=00000000 ds.limit=00000000 ds.acc=0000 21 | es=0000 es.base=00000000 es.limit=00000000 es.acc=0000 22 | fs=0000 fs.base=00000000 fs.limit=00000000 fs.acc=0000 23 | gs=0000 gs.base=00000000 gs.limit=00000000 gs.acc=0000 24 | 25 | eax=00000000 ebx=00000010 ecx=00070000 edx=00000000 26 | esi=00000000 edi=00000000 ebp=00000000 esp=00000000 27 | eip=0000000b eflags=00000012 ; af 28 | 29 | -------------------------------------------------------------------------------- /test/0025_cdq.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 66 b8 78 56 34 12 66 99 66 52 66 89 da 66 b8 32 4 | 00001010: 54 76 98 66 99 66 52 f4 5 | 0003fff0: ff ff ff ff 00 00 00 00 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000008 ; tsc 9 | 10 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00000000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 19 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 20 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 21 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 22 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 23 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 24 | 25 | eax=98765432 ebx=48314e23 ecx=00000000 edx=ffffffff 26 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fff8 27 | eip=00000018 eflags=00000002 28 | 29 | -------------------------------------------------------------------------------- /test/0034_ret_far_32.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 68 aa aa aa aa 0e e8 06 00 00 00 68 bb bb bb bb 4 | 00001010: f4 ca 04 00 90 90 f4 5 | fffffff0: 0b 00 00 00 00 01 00 00 bb bb bb bb 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000006 ; tsc 9 | 10 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00000000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=049b 19 | ss=0000 ss.base=00000000 ss.limit=ffffffff ss.acc=0c93 20 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 21 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 22 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 23 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 24 | 25 | eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 26 | esi=00000000 edi=00000000 ebp=00000000 esp=fffffffc 27 | eip=00000011 eflags=00000002 28 | 29 | -------------------------------------------------------------------------------- /test/0034_ret_near_32.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 68 aa aa aa aa e8 06 00 00 00 68 bb bb bb bb f4 4 | 00001010: c2 04 00 90 90 f4 5 | fffffff0: 0a 00 00 00 bb bb bb bb 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000005 ; tsc 9 | 10 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00000000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=049b 19 | ss=0000 ss.base=00000000 ss.limit=ffffffff ss.acc=0c93 20 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 21 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 22 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 23 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 24 | 25 | eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 26 | esi=00000000 edi=00000000 ebp=00000000 esp=fffffffc 27 | eip=00000010 eflags=00000002 28 | 29 | -------------------------------------------------------------------------------- /test/0003_lds_real.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 66 67 c4 35 00 20 00 00 66 0f b4 3f 67 0f b5 29 4 | 00001010: f4 5 | 00002000: 70 8c 30 78 14 41 6 | 00002010: cb e3 c8 da 8c a3 7 | 00002020: 5b 34 d5 eb 1b d8 8 | 9 | ; - - registers 10 | msr[0010] 0000000000000004 ; tsc 11 | 12 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 13 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 14 | 15 | gdt.base=00000000 gdt.limit=ffff 16 | idt.base=00000000 idt.limit=ffff 17 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 18 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 19 | 20 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 21 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 22 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 23 | es=4114 es.base=00041140 es.limit=0000ffff es.acc=0093 24 | fs=a38c fs.base=000a38c0 fs.limit=0000ffff fs.acc=0093 25 | gs=ebd5 gs.base=000ebd50 gs.limit=0000ffff gs.acc=0093 26 | 27 | eax=00000000 ebx=12342010 ecx=00002020 edx=00000000 28 | esi=78308c70 edi=dac8e3cb ebp=0000345b esp=00000000 29 | eip=00000011 eflags=00000002 30 | 31 | -------------------------------------------------------------------------------- /test/0028_movsb.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: be 00 00 bf 50 00 b9 0f 00 a4 f3 a4 f4 4 | 00020000: 6d 1c 3a 14 bd ca 7e 5b 41 93 1a af 55 82 6d 2b 5 | 00040050: 6d 1c 3a 14 bd ca 7e 5b 41 93 1a af 55 82 6d 2b 6 | 7 | ; - - registers 8 | msr[0010] 0000000000000006 ; tsc 9 | 10 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 11 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 12 | 13 | gdt.base=00000000 gdt.limit=ffff 14 | idt.base=00000000 idt.limit=ffff 15 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 16 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 17 | 18 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 19 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 20 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 21 | es=4000 es.base=00040000 es.limit=0000ffff es.acc=0093 22 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 23 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 24 | 25 | eax=00000000 ebx=00000000 ecx=a23b0000 edx=00000000 26 | esi=e32a0010 edi=94350060 ebp=00000000 esp=00000000 27 | eip=0000000d eflags=00000002 28 | 29 | -------------------------------------------------------------------------------- /test/0002_8e_mov_sr.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 8e c1 8e e2 2e 8e 2e 00 07 0f a8 8c 2e 04 17 ea 4 | 00001010: 17 04 c0 00 b9 11 11 bb 99 99 f4 5 | 00001700: 01 02 01 02 6 | 00008ff0: 01 02 7 | 8 | ; - - registers 9 | msr[0010] 0000000000000008 ; tsc 10 | 11 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 12 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 13 | 14 | gdt.base=00000000 gdt.limit=ffff 15 | idt.base=00000000 idt.limit=ffff 16 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 17 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 18 | 19 | cs=00c0 cs.base=00000c00 cs.limit=0000ffff cs.acc=009b 20 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 21 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 22 | es=6789 es.base=00067890 es.limit=0000ffff es.acc=0093 23 | fs=5555 fs.base=00055550 fs.limit=0000ffff fs.acc=0093 24 | gs=0201 gs.base=00002010 gs.limit=0000ffff gs.acc=0093 25 | 26 | eax=00000000 ebx=00009999 ecx=00006789 edx=00005555 27 | esi=00000000 edi=00000000 ebp=00000000 esp=00008ffe 28 | eip=0000041b eflags=00000002 29 | 30 | -------------------------------------------------------------------------------- /test/0029_movsb_32.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: be 00 00 00 90 bf 50 00 00 90 b9 0f 00 00 00 a4 4 | 00001010: f3 a4 f4 5 | 90020000: 6e c7 1b 0b 9b 3a 6e 16 35 f7 b3 a8 fe 71 3f fe 6 | 90040050: 6e c7 1b 0b 9b 3a 6e 16 35 f7 b3 a8 fe 71 3f fe 7 | 8 | ; - - registers 9 | msr[0010] 0000000000000006 ; tsc 10 | 11 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 12 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 13 | 14 | gdt.base=00000000 gdt.limit=ffff 15 | idt.base=00000000 idt.limit=ffff 16 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 17 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 18 | 19 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=049b 20 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0493 21 | ds=2000 ds.base=00020000 ds.limit=efffffff ds.acc=0893 22 | es=4000 es.base=00040000 es.limit=efffffff es.acc=0893 23 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 24 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 25 | 26 | eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 27 | esi=90000010 edi=90000060 ebp=00000000 esp=00000000 28 | eip=00000013 eflags=00000002 29 | 30 | -------------------------------------------------------------------------------- /test/0021_imul_b.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 6b d9 07 9c 6b d6 cb 9c 6b 05 66 9c 66 6b ee 26 4 | 00001010: 9c 66 6b f3 cf 9c 66 6b 4d 02 b9 9c f4 5 | 00020100: ef 7f e7 26 c7 0d 6 | 0003fff0: 03 08 83 08 03 08 87 08 87 08 87 08 7 | 8 | ; - - registers 9 | msr[0010] 000000000000000d ; tsc 10 | 11 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 12 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 13 | 14 | gdt.base=00000000 gdt.limit=ffff 15 | idt.base=00000000 idt.limit=ffff 16 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 17 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 18 | 19 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 20 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 21 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 22 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 23 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 24 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 25 | 26 | eax=eef3f93a ebx=699ef348 ecx=2dc435ef edx=5a589eaa 27 | esi=c8936f38 edi=00000100 ebp=099fc834 esp=0000fff4 28 | eip=0000001d eflags=00000803 ; of cf 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 1996-1999 SciTech Software, Inc. 2 | Copyright (c) David Mosberger-Tang 3 | Copyright (c) 1999 Egbert Eich 4 | Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 5 | 6 | Permission to use, copy, modify, distribute, and sell this software and 7 | its documentation for any purpose is hereby granted without fee, 8 | provided that the above copyright notice appear in all copies and that 9 | both that copyright notice and this permission notice appear in 10 | supporting documentation, and that the name of the authors not be used 11 | in advertising or publicity pertaining to distribution of the software 12 | without specific, written prior permission. The authors makes no 13 | representations about the suitability of this software for any purpose. 14 | It is provided "as is" without express or implied warranty. 15 | 16 | THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 | EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 20 | USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 | PERFORMANCE OF THIS SOFTWARE. 23 | -------------------------------------------------------------------------------- /test/0022_imul_w.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 69 d9 9a 52 9c 69 d6 79 bd 9c 69 05 03 09 9c 66 4 | 00001010: 69 ee 61 0a b2 79 9c 66 69 f3 1c 2d fa d6 9c 66 5 | 00001020: 69 4d 02 a6 cf af 94 9c f4 6 | 00020100: f0 fc 99 1d d4 7d 7 | 0003fff0: 87 08 87 08 83 08 03 08 83 08 07 08 8 | 9 | ; - - registers 10 | msr[0010] 000000000000000d ; tsc 11 | 12 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 13 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 14 | 15 | gdt.base=00000000 gdt.limit=ffff 16 | idt.base=00000000 idt.limit=ffff 17 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 18 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 19 | 20 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 21 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 22 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 23 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 24 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 25 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 26 | 27 | eax=555766d0 ebx=f82012b2 ecx=cb10e836 edx=71a3da1f 28 | esi=d49f5578 edi=00000100 ebp=e37c6cf7 esp=0000fff4 29 | eip=00000029 eflags=00000887 ; of sf pf cf 30 | 31 | -------------------------------------------------------------------------------- /test/0007_seg_load_pm16.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 8e c3 26 66 c7 06 50 00 78 56 34 12 8e e1 90 f4 4 | 00002000: 00 00 00 00 00 00 00 00 ff 8f 00 10 00 9b 00 00 5 | 00002010: 00 00 00 30 00 93 ca 00 99 00 00 00 00 13 00 00 6 | 00003050: 78 56 34 12 7 | 0000fff0: 18 00 00 00 0c 00 08 00 02 00 8 | 9 | ; - - registers 10 | msr[0010] 0000000000000003 ; tsc 11 | 12 | cr0=00000001 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 13 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 14 | 15 | gdt.base=00002000 gdt.limit=ffff 16 | idt.base=00000000 idt.limit=ffff 17 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 18 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 19 | 20 | cs=0008 cs.base=00001000 cs.limit=00008fff cs.acc=009b 21 | ss=0000 ss.base=00000000 ss.limit=00000000 ss.acc=0000 22 | ds=0000 ds.base=00000000 ds.limit=00000000 ds.acc=0000 23 | es=0010 es.base=00003000 es.limit=a0000fff es.acc=0c93 24 | fs=0000 fs.base=00000000 fs.limit=00000000 fs.acc=0000 25 | gs=0000 gs.base=00000000 gs.limit=00000000 gs.acc=0000 26 | 27 | eax=00000000 ebx=00000010 ecx=00000018 edx=00000000 28 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fff6 29 | eip=0000000c eflags=00000002 30 | 31 | -------------------------------------------------------------------------------- /test/0008_seg_load_pm32.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 8e c3 26 c7 05 50 00 00 00 78 56 34 12 8e e1 90 4 | 00001010: f4 5 | 00002000: 00 00 00 00 00 00 00 00 ff 8f 00 10 00 9b 40 00 6 | 00002010: 00 00 00 30 00 93 ca 00 77 00 00 00 00 13 00 00 7 | 00003050: 78 56 34 12 8 | 0000fff0: 18 00 00 00 0d 00 00 00 08 00 00 00 02 00 00 00 9 | 10 | ; - - registers 11 | msr[0010] 0000000000000003 ; tsc 12 | 13 | cr0=00000001 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 14 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 15 | 16 | gdt.base=00002000 gdt.limit=ffff 17 | idt.base=00000000 idt.limit=ffff 18 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 19 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 20 | 21 | cs=0008 cs.base=00001000 cs.limit=00008fff cs.acc=049b 22 | ss=0000 ss.base=00000000 ss.limit=00000000 ss.acc=0000 23 | ds=0000 ds.base=00000000 ds.limit=00000000 ds.acc=0000 24 | es=0010 es.base=00003000 es.limit=a0000fff es.acc=0c93 25 | fs=0000 fs.base=00000000 fs.limit=00000000 fs.acc=0000 26 | gs=0000 gs.base=00000000 gs.limit=00000000 gs.acc=0000 27 | 28 | eax=00000000 ebx=00000010 ecx=00000018 edx=00000000 29 | esi=00000000 edi=00000000 ebp=00000000 esp=0000fff0 30 | eip=0000000d eflags=00000002 31 | 32 | -------------------------------------------------------------------------------- /test/0016_sbb.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 18 0d 9c 18 ea 9c 1a 6d 01 9c 1a f1 9c 19 5d 02 4 | 00001010: 9c 19 f5 9c 1b 75 04 9c 1b d3 9c 66 19 5d 06 9c 5 | 00001020: 66 19 f5 9c 66 1b 75 0a 9c 66 1b d3 9c 1c 97 9c 6 | 00001030: 1d 57 12 9c 66 1d 52 30 49 87 9c f4 7 | 00020100: b4 83 e9 71 e3 ae a8 1b b5 a0 a7 9a 11 44 8 | 0003ffe0: 02 00 12 00 83 08 83 08 97 00 16 00 83 00 9 | 0003fff0: 16 00 87 08 86 00 02 08 06 08 06 00 12 00 87 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=45f5ef0b ebx=f2303d55 ecx=09e50a65 edx=828de867 30 | esi=f202ecca edi=00000100 ebp=10190fee esp=0000ffe2 31 | eip=0000003c eflags=00000002 32 | 33 | -------------------------------------------------------------------------------- /test/0013_add.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 00 0d 9c 00 ea 9c 02 6d 01 9c 02 f1 9c 01 5d 02 4 | 00001010: 9c 01 f5 9c 03 75 04 9c 03 d3 9c 66 01 5d 06 9c 5 | 00001020: 66 01 f5 9c 66 03 75 0a 9c 66 03 d3 9c 04 97 9c 6 | 00001030: 05 57 12 9c 66 05 52 30 49 87 9c f4 7 | 00020100: 2d dd 02 6a eb 30 65 6c 54 0a 66 b2 74 4b 8 | 0003ffe0: 82 00 02 00 17 00 03 00 03 00 13 08 17 00 9 | 0003fff0: 13 00 17 00 83 00 13 00 97 00 17 08 92 00 07 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=fa6262ba ebx=a21a7109 ecx=85107be8 edx=00c885fb 30 | esi=3b6eb629 edi=00000100 ebp=77959131 esp=0000ffe2 31 | eip=0000003c eflags=00000082 ; sf 32 | 33 | -------------------------------------------------------------------------------- /test/0014_or.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 08 0d 9c 08 ea 9c 0a 6d 01 9c 0a f1 9c 09 5d 02 4 | 00001010: 9c 09 f5 9c 0b 75 04 9c 0b d3 9c 66 09 5d 06 9c 5 | 00001020: 66 09 f5 9c 66 0b 75 0a 9c 66 0b d3 9c 0c 97 9c 6 | 00001030: 0d 57 12 9c 66 0d 52 30 49 87 9c f4 7 | 00020100: 67 5a dd ff f8 a0 df bd 6f ef d1 aa 1d 39 8 | 0003ffe0: 86 00 86 00 86 00 06 00 02 00 06 00 82 00 9 | 0003fff0: 86 00 86 00 82 00 86 00 06 00 82 00 86 00 02 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=975dbbff ebx=676e9ddd ecx=b157fe67 edx=676fffff 30 | esi=3f7dbffb edi=00000100 ebp=77f4bdfa esp=0000ffe2 31 | eip=0000003c eflags=00000086 ; sf pf 32 | 33 | -------------------------------------------------------------------------------- /test/0017_and.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 20 0d 9c 20 ea 9c 22 6d 01 9c 22 f1 9c 21 5d 02 4 | 00001010: 9c 21 f5 9c 23 75 04 9c 23 d3 9c 66 21 5d 06 9c 5 | 00001020: 66 21 f5 9c 66 23 75 0a 9c 66 23 d3 9c 24 97 9c 6 | 00001030: 25 57 12 9c 66 25 52 30 49 87 9c f4 7 | 00020100: 02 2e 20 22 f0 1e 28 40 80 b5 12 92 ba 61 8 | 0003ffe0: 82 00 06 00 06 00 02 00 02 00 06 00 86 00 9 | 0003fff0: 02 00 06 00 86 00 02 00 06 00 06 00 86 00 02 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=83410002 ebx=b7846a28 ecx=362b0ce3 edx=34006208 30 | esi=41201210 edi=00000100 ebp=00401290 esp=0000ffe2 31 | eip=0000003c eflags=00000082 ; sf 32 | 33 | -------------------------------------------------------------------------------- /test/0019_xor.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 30 0d 9c 30 ea 9c 32 6d 01 9c 32 f1 9c 31 5d 02 4 | 00001010: 9c 31 f5 9c 33 75 04 9c 33 d3 9c 66 31 5d 06 9c 5 | 00001020: 66 31 f5 9c 66 33 75 0a 9c 66 33 d3 9c 34 97 9c 6 | 00001030: 35 57 12 9c 66 35 52 30 49 87 9c f4 7 | 00020100: fd 57 4c a5 dc fe 03 75 bf a9 e8 b1 de 6d 8 | 0003ffe0: 82 00 06 00 82 00 82 00 06 00 06 00 86 00 9 | 0003fff0: 82 00 86 00 86 00 82 00 02 00 02 00 82 00 82 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=a02d60b3 ebx=422ec3cf ecx=8eba2ce1 edx=c8e1348c 30 | esi=11c81cc9 edi=00000100 ebp=78be65dd esp=0000ffe2 31 | eip=0000003c eflags=00000082 ; sf 32 | 33 | -------------------------------------------------------------------------------- /test/0015_adc.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 10 0d 9c 10 ea 9c 12 6d 01 9c 12 f1 9c 11 5d 02 4 | 00001010: 9c 11 f5 9c 13 75 04 9c 13 d3 9c 66 11 5d 06 9c 5 | 00001020: 66 11 f5 9c 66 13 75 0a 9c 66 13 d3 9c 14 97 9c 6 | 00001030: 15 57 12 9c 66 15 52 30 49 87 9c f4 7 | 00020100: 2d 06 0d c9 05 10 90 ae fb 5a 3c a2 97 56 8 | 0003ffe0: 07 08 82 00 96 00 86 08 16 00 16 00 16 00 9 | 0003fff0: 07 00 06 00 92 08 82 00 86 00 12 00 92 00 07 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=3683db8d ebx=2cdb1082 ecx=dd9e43e6 edx=9a3f20c6 30 | esi=7546057b edi=00000100 ebp=7aa41133 esp=0000ffe2 31 | eip=0000003c eflags=00000807 ; of pf cf 32 | 33 | -------------------------------------------------------------------------------- /test/0018_sub.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 28 0d 9c 28 ea 9c 2a 6d 01 9c 2a f1 9c 29 5d 02 4 | 00001010: 9c 29 f5 9c 2b 75 04 9c 2b d3 9c 66 29 5d 06 9c 5 | 00001020: 66 29 f5 9c 66 2b 75 0a 9c 66 2b d3 9c 2c 97 9c 6 | 00001030: 2d 57 12 9c 66 2d 52 30 49 87 9c f4 7 | 00020100: b9 ab d6 d8 fd 8e e1 65 f3 dc 7d b9 35 50 8 | 0003ffe0: 83 08 82 00 93 08 16 08 16 00 93 00 87 00 9 | 0003fff0: 02 00 97 08 83 00 93 08 83 00 87 08 92 00 83 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=821666e0 ebx=7cd996fb ecx=62738162 edx=069b96b8 30 | esi=147b286a edi=00000100 ebp=b5d71b0d esp=0000ffe2 31 | eip=0000003c eflags=00000883 ; of sf cf 32 | 33 | -------------------------------------------------------------------------------- /test/0020_cmp.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 38 0d 9c 38 ea 9c 3a 6d 01 9c 3a f1 9c 39 5d 02 4 | 00001010: 9c 39 f5 9c 3b 75 04 9c 3b d3 9c 66 39 5d 06 9c 5 | 00001020: 66 39 f5 9c 66 3b 75 0a 9c 66 3b d3 9c 3c 97 9c 6 | 00001030: 3d 57 12 9c 66 3d 52 30 49 87 9c f4 7 | 00020100: ee d4 35 2f e9 9d 8d 9f 85 4e 53 a9 58 5b 8 | 0003ffe0: 97 08 96 00 93 08 86 00 02 08 02 00 02 00 9 | 0003fff0: 86 00 16 00 03 00 83 00 06 08 83 00 12 00 86 00 10 | 11 | ; - - registers 12 | msr[0010] 000000000000001f ; tsc 13 | 14 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 15 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 16 | 17 | gdt.base=00000000 gdt.limit=ffff 18 | idt.base=00000000 idt.limit=ffff 19 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 20 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 21 | 22 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 23 | ss=3000 ss.base=00030000 ss.limit=0000ffff ss.acc=0093 24 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 25 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 26 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 27 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 28 | 29 | eax=4568db21 ebx=079a3674 ecx=bb00cb60 edx=9241cae5 30 | esi=9363f145 edi=00000100 ebp=eee10dfb esp=0000ffe2 31 | eip=0000003c eflags=00000897 ; of sf af pf cf 32 | 33 | -------------------------------------------------------------------------------- /test/0036_div.tst: -------------------------------------------------------------------------------- 1 | ; test 32 bit (unsigned) div 2 | ; 3 | ; note: the number of successful tests is returned on the stack 4 | ; 5 | 6 | [init mode=real] 7 | 8 | idt.base=0x1000 9 | 10 | [code start=0x0:0x2000] 11 | 12 | ; regular div 13 | %macro div_u 2 14 | dq %1 15 | dd %2 16 | dd %1 / %2 17 | dd %1 % %2 18 | dd 0 19 | %endmacro 20 | 21 | ; regular idiv 22 | %macro div_s 2 23 | dq %1 24 | dd %2 25 | dd %1 // %2 26 | dd %1 %% %2 27 | dd 0 28 | %endmacro 29 | 30 | ; (i)div with exception 31 | %macro div_x 2 32 | dq %1 33 | dd %2 34 | dd 0x44444444 35 | dd 0 36 | dd 0 37 | %endmacro 38 | 39 | mov si,table_start 40 | xor edi,edi 41 | div_10: 42 | mov eax,[si] 43 | mov edx,[si+4] 44 | mov ecx,[si+8] 45 | div ecx 46 | cmp eax,[si+12] 47 | jnz stop 48 | cmp edx,[si+16] 49 | jnz stop 50 | pushfd 51 | pop dword [si+20] 52 | inc edi 53 | add si,24 54 | cmp si,table_end 55 | jb div_10 56 | stop: 57 | xor eax,eax 58 | push eax 59 | push edi 60 | hlt 61 | 62 | interrupt_00: 63 | xor edx,edx 64 | mov eax,0x44444444 65 | mov ecx,1 66 | iret 67 | 68 | align 0x10, db 0 69 | table_start: 70 | div_u 57, 11 71 | div_u 3000, 2000 72 | div_u 1812363, 8627 73 | div_u 0xef542987, 23 74 | div_u 23, 0xef542987 75 | div_u 0x2587fe287d346534, 0x7f542987 76 | div_u 0x7587fe287d346534, 0x9239b842 77 | div_u 0x7fffffff, 1 78 | 79 | div_u 0x7fffffff000000, 0x1000000 80 | div_u 0x4587fe277d346534, 0x4587fe28 81 | div_u 0x80000000, 1 82 | div_u 0xffffffff, 1 83 | div_x 0, 0 84 | div_x 100, 0 85 | div_x 0x4587fe287d346534, 10 86 | div_x 0x4587fe287d346534, 0x4587fe28 87 | table_end: 88 | -------------------------------------------------------------------------------- /test/0006_div.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 6d 20 00 00 4 | 00002000: b8 01 00 ba 01 00 b9 00 00 f7 f1 50 52 b8 67 05 5 | 00002010: ba 67 00 b9 89 00 f7 f1 50 52 b8 7f 56 ba 67 32 6 | 00002020: f7 36 7a 20 50 52 b8 12 78 b1 96 f6 f1 50 b8 12 7 | 00002030: 28 f6 36 7a 20 50 b8 01 00 ba 01 00 b9 00 00 f7 8 | 00002040: f9 50 52 b8 67 05 ba 67 00 b9 92 18 f7 f9 50 52 9 | 00002050: b8 7f 56 ba 67 12 f7 3e 7a 20 50 52 b8 12 38 b1 10 | 00002060: 86 f6 f9 50 b8 12 28 f6 3e 7a 20 50 f4 66 31 c0 11 | 00002070: 66 31 d2 66 b9 99 99 99 99 cf 78 56 34 12 f4 12 | 0000ffe0: 55 3a 8b 50 5f 24 7c 36 75 09 31 04 00 00 00 00 13 | 0000fff0: 55 3a cc 8a c7 3d 39 95 5e 00 81 c0 00 00 00 00 14 | 15 | ; - - registers 16 | msr[0010] 000000000000003b ; tsc 17 | 18 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 19 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 20 | 21 | gdt.base=00000000 gdt.limit=ffff 22 | idt.base=00001000 idt.limit=ffff 23 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 24 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 25 | 26 | cs=0000 cs.base=00000000 cs.limit=0000ffff cs.acc=009b 27 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 28 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 29 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 30 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 31 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 32 | 33 | eax=00003a55 ebx=00000000 ecx=99991886 edx=0000245f 34 | esi=00000000 edi=00000000 ebp=00000000 esp=0000ffe0 35 | eip=0000206d eflags=00000002 36 | 37 | -------------------------------------------------------------------------------- /test/0011_jmp_short_cc.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 38 cf 70 02 b0 01 fe c4 38 d1 71 02 b0 01 fe c4 4 | 00001010: 38 d1 72 02 b0 01 fe c4 38 ca 73 02 b0 01 fe c4 5 | 00001020: 38 d2 73 02 b0 01 fe c4 38 c9 74 02 b0 01 fe c4 6 | 00001030: 38 d1 75 02 b0 01 fe c4 38 d1 76 02 b0 01 fe c4 7 | 00001040: 38 c9 76 02 b0 01 fe c4 38 ca 77 02 b0 01 fe c4 8 | 00001050: 38 d1 78 02 b0 01 fe c4 38 ca 79 02 b0 01 fe c4 9 | 00001060: 38 c9 7a 02 b0 01 fe c4 38 ca 7b 02 b0 01 fe c4 10 | 00001070: 38 d1 7c 02 b0 01 fe c4 38 cd 7c 02 b0 01 fe c4 11 | 00001080: 38 ca 7d 02 b0 01 fe c4 38 f2 7d 02 b0 01 fe c4 12 | 00001090: 38 d1 7e 02 b0 01 fe c4 38 cd 7e 02 b0 01 fe c4 13 | 000010a0: 38 ed 7e 02 b0 01 fe c4 38 ca 7f 02 b0 01 fe c4 14 | 000010b0: 38 e9 7f 02 b0 01 fe c4 f4 15 | 16 | ; - - registers 17 | msr[0010] 0000000000000046 ; tsc 18 | 19 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 20 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 21 | 22 | gdt.base=00000000 gdt.limit=ffff 23 | idt.base=00000000 idt.limit=ffff 24 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 25 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 26 | 27 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 28 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 29 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 30 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 31 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 32 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 33 | 34 | eax=00001700 ebx=0000807f ecx=0000ff01 edx=0000fe02 35 | esi=00000000 edi=00000000 ebp=00000000 esp=00000000 36 | eip=000000b9 eflags=00000007 ; pf cf 37 | 38 | -------------------------------------------------------------------------------- /test/0011_jmp_short_cc.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | eax=0 4 | ebx=0x807f 5 | ecx=0xff01 6 | edx=0xfe02 7 | 8 | 9 | [code start=0x100:0x0] 10 | 11 | cmp bh,cl 12 | jo l_o 13 | mov al,1 14 | l_o: 15 | inc ah 16 | 17 | cmp cl,dl 18 | jno l_no 19 | mov al,1 20 | l_no: 21 | inc ah 22 | 23 | cmp cl,dl 24 | jb l_b 25 | mov al,1 26 | l_b: 27 | inc ah 28 | 29 | cmp dl,cl 30 | jnb l_nb1 31 | mov al,1 32 | l_nb1: 33 | inc ah 34 | 35 | cmp dl,dl 36 | jnb l_nb2 37 | mov al,1 38 | l_nb2: 39 | inc ah 40 | 41 | cmp cl,cl 42 | jz l_z 43 | mov al,1 44 | l_z: 45 | inc ah 46 | 47 | cmp cl,dl 48 | jnz l_nz 49 | mov al,1 50 | l_nz: 51 | inc ah 52 | 53 | cmp cl,dl 54 | jna l_na1 55 | mov al,1 56 | l_na1: 57 | inc ah 58 | 59 | cmp cl,cl 60 | jna l_na2 61 | mov al,1 62 | l_na2: 63 | inc ah 64 | 65 | cmp dl,cl 66 | ja l_a 67 | mov al,1 68 | l_a: 69 | inc ah 70 | 71 | cmp cl,dl 72 | js l_s 73 | mov al,1 74 | l_s: 75 | inc ah 76 | 77 | cmp dl,cl 78 | jns l_ns 79 | mov al,1 80 | l_ns: 81 | inc ah 82 | 83 | cmp cl,cl 84 | jp l_p 85 | mov al,1 86 | l_p: 87 | inc ah 88 | 89 | cmp dl,cl 90 | jnp l_np 91 | mov al,1 92 | l_np: 93 | inc ah 94 | 95 | cmp cl,dl 96 | jl l_l1 97 | mov al,1 98 | l_l1: 99 | inc ah 100 | 101 | cmp ch,cl 102 | jl l_l2 103 | mov al,1 104 | l_l2: 105 | inc ah 106 | 107 | cmp dl,cl 108 | jnl l_nl1 109 | mov al,1 110 | l_nl1: 111 | inc ah 112 | 113 | cmp dl,dh 114 | jnl l_nl2 115 | mov al,1 116 | l_nl2: 117 | inc ah 118 | 119 | cmp cl,dl 120 | jng l_ng1 121 | mov al,1 122 | l_ng1: 123 | inc ah 124 | 125 | cmp ch,cl 126 | jng l_ng2 127 | mov al,1 128 | l_ng2: 129 | inc ah 130 | 131 | cmp ch,ch 132 | jng l_ng3 133 | mov al,1 134 | l_ng3: 135 | inc ah 136 | 137 | cmp dl,cl 138 | jg l_g1 139 | mov al,1 140 | l_g1: 141 | inc ah 142 | 143 | cmp cl,ch 144 | jg l_g2 145 | mov al,1 146 | l_g2: 147 | inc ah 148 | 149 | 150 | -------------------------------------------------------------------------------- /include/mem.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 6 | * 7 | * ======================================================================== 8 | * 9 | * Permission to use, copy, modify, distribute, and sell this software and 10 | * its documentation for any purpose is hereby granted without fee, 11 | * provided that the above copyright notice appear in all copies and that 12 | * both that copyright notice and this permission notice appear in 13 | * supporting documentation, and that the name of the authors not be used 14 | * in advertising or publicity pertaining to distribution of the software 15 | * without specific, written prior permission. The authors makes no 16 | * representations about the suitability of this software for any purpose. 17 | * It is provided "as is" without express or implied warranty. 18 | * 19 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 20 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 21 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 22 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 23 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 24 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 25 | * PERFORMANCE OF THIS SOFTWARE. 26 | * 27 | * ======================================================================== 28 | * 29 | * Description: 30 | * Header file for memory and i/o access emulation functions. 31 | * 32 | ****************************************************************************/ 33 | 34 | 35 | unsigned vm_memio(x86emu_t *emu, u32 addr, u32 *val, unsigned type); 36 | x86emu_mem_t *emu_mem_new(unsigned perm); 37 | x86emu_mem_t *emu_mem_free(x86emu_mem_t *mem); 38 | x86emu_mem_t *emu_mem_clone(x86emu_mem_t *mem); 39 | void *mem_dup(const void *src, size_t n); 40 | 41 | -------------------------------------------------------------------------------- /test/0012_jmp_near_cc.tst: -------------------------------------------------------------------------------- 1 | [init] 2 | 3 | eax=0 4 | ebx=0x807f 5 | ecx=0xff01 6 | edx=0xfe02 7 | 8 | 9 | [code start=0x100:0x0] 10 | 11 | cmp bh,cl 12 | jo near l_o 13 | mov al,1 14 | l_o: 15 | inc ah 16 | 17 | cmp cl,dl 18 | jno near l_no 19 | mov al,1 20 | l_no: 21 | inc ah 22 | 23 | cmp cl,dl 24 | jb near l_b 25 | mov al,1 26 | l_b: 27 | inc ah 28 | 29 | cmp dl,cl 30 | jnb near l_nb1 31 | mov al,1 32 | l_nb1: 33 | inc ah 34 | 35 | cmp dl,dl 36 | jnb near l_nb2 37 | mov al,1 38 | l_nb2: 39 | inc ah 40 | 41 | cmp cl,cl 42 | jz near l_z 43 | mov al,1 44 | l_z: 45 | inc ah 46 | 47 | cmp cl,dl 48 | jnz near l_nz 49 | mov al,1 50 | l_nz: 51 | inc ah 52 | 53 | cmp cl,dl 54 | jna near l_na1 55 | mov al,1 56 | l_na1: 57 | inc ah 58 | 59 | cmp cl,cl 60 | jna near l_na2 61 | mov al,1 62 | l_na2: 63 | inc ah 64 | 65 | cmp dl,cl 66 | ja near l_a 67 | mov al,1 68 | l_a: 69 | inc ah 70 | 71 | cmp cl,dl 72 | js near l_s 73 | mov al,1 74 | l_s: 75 | inc ah 76 | 77 | cmp dl,cl 78 | jns near l_ns 79 | mov al,1 80 | l_ns: 81 | inc ah 82 | 83 | cmp cl,cl 84 | jp near l_p 85 | mov al,1 86 | l_p: 87 | inc ah 88 | 89 | cmp dl,cl 90 | jnp near l_np 91 | mov al,1 92 | l_np: 93 | inc ah 94 | 95 | cmp cl,dl 96 | jl near l_l1 97 | mov al,1 98 | l_l1: 99 | inc ah 100 | 101 | cmp ch,cl 102 | jl near l_l2 103 | mov al,1 104 | l_l2: 105 | inc ah 106 | 107 | cmp dl,cl 108 | jnl near l_nl1 109 | mov al,1 110 | l_nl1: 111 | inc ah 112 | 113 | cmp dl,dh 114 | jnl near l_nl2 115 | mov al,1 116 | l_nl2: 117 | inc ah 118 | 119 | cmp cl,dl 120 | jng near l_ng1 121 | mov al,1 122 | l_ng1: 123 | inc ah 124 | 125 | cmp ch,cl 126 | jng near l_ng2 127 | mov al,1 128 | l_ng2: 129 | inc ah 130 | 131 | cmp ch,ch 132 | jng near l_ng3 133 | mov al,1 134 | l_ng3: 135 | inc ah 136 | 137 | cmp dl,cl 138 | jg near l_g1 139 | mov al,1 140 | l_g1: 141 | inc ah 142 | 143 | cmp cl,ch 144 | jg near l_g2 145 | mov al,1 146 | l_g2: 147 | inc ah 148 | 149 | 150 | -------------------------------------------------------------------------------- /include/ops.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 1996-1999 SciTech Software, Inc. 6 | * Copyright (c) David Mosberger-Tang 7 | * Copyright (c) 1999 Egbert Eich 8 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 9 | * 10 | * ======================================================================== 11 | * 12 | * Permission to use, copy, modify, distribute, and sell this software and 13 | * its documentation for any purpose is hereby granted without fee, 14 | * provided that the above copyright notice appear in all copies and that 15 | * both that copyright notice and this permission notice appear in 16 | * supporting documentation, and that the name of the authors not be used 17 | * in advertising or publicity pertaining to distribution of the software 18 | * without specific, written prior permission. The authors makes no 19 | * representations about the suitability of this software for any purpose. 20 | * It is provided "as is" without express or implied warranty. 21 | * 22 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 23 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 24 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 25 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 26 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 27 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28 | * PERFORMANCE OF THIS SOFTWARE. 29 | * 30 | * ======================================================================== 31 | * 32 | * Description: 33 | * Header file for operand decoding functions. 34 | * 35 | ****************************************************************************/ 36 | 37 | 38 | #ifndef __X86EMU_OPS_H 39 | #define __X86EMU_OPS_H 40 | 41 | extern void (*x86emu_optab[0x100])(x86emu_t *emu, u8 op1); 42 | extern void (*x86emu_optab2[0x100])(x86emu_t *emu, u8 op2); 43 | 44 | void decode_cond(x86emu_t *emu, int type); 45 | 46 | 47 | #endif /* __X86EMU_OPS_H */ 48 | -------------------------------------------------------------------------------- /test/0012_jmp_near_cc.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 38 cf 0f 80 02 00 b0 01 fe c4 38 d1 0f 81 02 00 4 | 00001010: b0 01 fe c4 38 d1 0f 82 02 00 b0 01 fe c4 38 ca 5 | 00001020: 0f 83 02 00 b0 01 fe c4 38 d2 0f 83 02 00 b0 01 6 | 00001030: fe c4 38 c9 0f 84 02 00 b0 01 fe c4 38 d1 0f 85 7 | 00001040: 02 00 b0 01 fe c4 38 d1 0f 86 02 00 b0 01 fe c4 8 | 00001050: 38 c9 0f 86 02 00 b0 01 fe c4 38 ca 0f 87 02 00 9 | 00001060: b0 01 fe c4 38 d1 0f 88 02 00 b0 01 fe c4 38 ca 10 | 00001070: 0f 89 02 00 b0 01 fe c4 38 c9 0f 8a 02 00 b0 01 11 | 00001080: fe c4 38 ca 0f 8b 02 00 b0 01 fe c4 38 d1 0f 8c 12 | 00001090: 02 00 b0 01 fe c4 38 cd 0f 8c 02 00 b0 01 fe c4 13 | 000010a0: 38 ca 0f 8d 02 00 b0 01 fe c4 38 f2 0f 8d 02 00 14 | 000010b0: b0 01 fe c4 38 d1 0f 8e 02 00 b0 01 fe c4 38 cd 15 | 000010c0: 0f 8e 02 00 b0 01 fe c4 38 ed 0f 8e 02 00 b0 01 16 | 000010d0: fe c4 38 ca 0f 8f 02 00 b0 01 fe c4 38 e9 0f 8f 17 | 000010e0: 02 00 b0 01 fe c4 f4 18 | 19 | ; - - registers 20 | msr[0010] 0000000000000046 ; tsc 21 | 22 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 23 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 24 | 25 | gdt.base=00000000 gdt.limit=ffff 26 | idt.base=00000000 idt.limit=ffff 27 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 28 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 29 | 30 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 31 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 32 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 33 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 34 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 35 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 36 | 37 | eax=00001700 ebx=0000807f ecx=0000ff01 edx=0000fe02 38 | esi=00000000 edi=00000000 ebp=00000000 esp=00000000 39 | eip=000000e7 eflags=00000007 ; pf cf 40 | 41 | -------------------------------------------------------------------------------- /test/0035_idiv.tst: -------------------------------------------------------------------------------- 1 | ; test 32 bit (signed) idiv 2 | ; 3 | ; note: the number of successful tests is returned on the stack 4 | ; 5 | 6 | [init mode=real] 7 | 8 | idt.base=0x1000 9 | 10 | [code start=0x0:0x2000] 11 | 12 | ; regular div 13 | %macro div_u 2 14 | dq %1 15 | dd %2 16 | dd %1 / %2 17 | dd %1 % %2 18 | dd 0 19 | %endmacro 20 | 21 | ; regular idiv 22 | %macro div_s 2 23 | dq %1 24 | dd %2 25 | dd %1 // %2 26 | dd %1 %% %2 27 | dd 0 28 | %endmacro 29 | 30 | ; (i)div with exception 31 | %macro div_x 2 32 | dq %1 33 | dd %2 34 | dd 0x44444444 35 | dd 0 36 | dd 0 37 | %endmacro 38 | 39 | mov si,table_start 40 | xor edi,edi 41 | div_10: 42 | mov eax,[si] 43 | mov edx,[si+4] 44 | mov ecx,[si+8] 45 | idiv ecx 46 | cmp eax,[si+12] 47 | jnz stop 48 | cmp edx,[si+16] 49 | jnz stop 50 | pushfd 51 | pop dword [si+20] 52 | inc edi 53 | add si,24 54 | cmp si,table_end 55 | jb div_10 56 | stop: 57 | xor eax,eax 58 | push eax 59 | push edi 60 | hlt 61 | 62 | interrupt_00: 63 | xor edx,edx 64 | mov eax,0x44444444 65 | mov ecx,1 66 | iret 67 | 68 | align 0x10, db 0 69 | table_start: 70 | div_s 57, 11 71 | div_s 3000, 2000 72 | div_s 1812363, 8627 73 | div_s 0xef542987, 23 74 | div_s 23, 0xef542987 75 | div_s 0x2587fe287d346534, 0x7f542987 76 | div_s 0x7fffffff, 1 77 | div_s 0x7fffffff000000, 0x1000000 78 | 79 | div_s -3000, 2000 80 | div_s 1812363, -8627 81 | div_s 0xef542987, -23 82 | div_s -23, 0xef542987 83 | div_s -0x2587fe287d346534, 0x7f542987 84 | div_s 0x3587fe287d346534, -0x7f542987 85 | div_s 0x80000000, -1 86 | div_s 0x7fffffff, -1 87 | 88 | div_s -7, -5 89 | div_s -300, -200 90 | div_s -1812363, -8627 91 | div_s -0xef542987, -23 92 | div_s -5463, 0x506152cf 93 | div_s -0x2587fe287d346534, -0x7f542987 94 | div_s -0x317506152ccf9f28, -0x68716f59 95 | div_s -0x7fffffff, -1 96 | 97 | div_x 0x80000000, 1 98 | div_x -0x80000000, -1 99 | div_x 0, 0 100 | div_x 100, 0 101 | div_x -100, 0 102 | div_x 0x4587fe287d346534, -10 103 | div_x 0x4587fe287d346534, 10 104 | div_x 0x4587fe287d346534, 0x7f542987 105 | table_end: 106 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCH := $(shell uname -m) 2 | ifneq ($(filter i386 i486 i586 i686, $(ARCH)),) 3 | ARCH := i386 4 | endif 5 | 6 | GIT2LOG := $(shell if [ -x ./git2log ] ; then echo ./git2log --update ; else echo true ; fi) 7 | GITDEPS := $(shell [ -d .git ] && echo .git/HEAD .git/refs/heads .git/refs/tags) 8 | VERSION := $(shell $(GIT2LOG) --version VERSION ; cat VERSION) 9 | BRANCH := $(shell [ -d .git ] && git branch | perl -ne 'print $$_ if s/^\*\s*//') 10 | PREFIX := libx86emu-$(VERSION) 11 | 12 | MAJOR_VERSION := $(shell $(GIT2LOG) --version VERSION ; cut -d . -f 1 VERSION) 13 | 14 | CC = gcc 15 | CFLAGS = -g -O2 -fPIC -fvisibility=hidden -fomit-frame-pointer -Wall 16 | LDFLAGS = 17 | 18 | LIBDIR = /usr/lib$(shell ldd /bin/sh | grep -q /lib64/ && echo 64) 19 | LIBX86 = libx86emu 20 | 21 | CFILES = $(wildcard *.c) 22 | OBJS = $(CFILES:.c=.o) 23 | 24 | LIB_NAME = $(LIBX86).so.$(VERSION) 25 | LIB_SONAME = $(LIBX86).so.$(MAJOR_VERSION) 26 | 27 | .PHONY: all shared install test demo clean 28 | 29 | %.o: %.c 30 | $(CC) -c $(CFLAGS) $< 31 | 32 | all: changelog shared 33 | 34 | changelog: $(GITDEPS) 35 | $(GIT2LOG) --changelog changelog 36 | 37 | shared: $(LIB_NAME) 38 | 39 | install: shared 40 | install -D $(LIB_NAME) $(DESTDIR)$(LIBDIR)/$(LIB_NAME) 41 | ln -snf $(LIB_NAME) $(DESTDIR)$(LIBDIR)/$(LIB_SONAME) 42 | ln -snf $(LIB_SONAME) $(DESTDIR)$(LIBDIR)/$(LIBX86).so 43 | install -m 644 -D include/x86emu.h $(DESTDIR)/usr/include/x86emu.h 44 | 45 | $(LIB_NAME): .depend $(OBJS) 46 | $(CC) -shared -Wl,-soname,$(LIB_SONAME) $(OBJS) -o $(LIB_NAME) $(LDFLAGS) 47 | @ln -snf $(LIB_NAME) $(LIB_SONAME) 48 | @ln -snf $(LIB_SONAME) $(LIBX86).so 49 | 50 | test: 51 | make -C test 52 | 53 | demo: 54 | make -C demo 55 | 56 | archive: changelog 57 | @if [ ! -d .git ] ; then echo no git repo ; false ; fi 58 | mkdir -p package 59 | git archive --prefix=$(PREFIX)/ $(BRANCH) > package/$(PREFIX).tar 60 | tar -r -f package/$(PREFIX).tar --mode=0664 --owner=root --group=root --mtime="`git show -s --format=%ci`" --transform='s:^:$(PREFIX)/:' VERSION changelog 61 | xz -f package/$(PREFIX).tar 62 | 63 | clean: 64 | make -C test clean 65 | make -C demo clean 66 | rm -f *.o *~ include/*~ *.so.* *.so .depend 67 | rm -rf package 68 | 69 | ifneq "$(MAKECMDGOALS)" "clean" 70 | .depend: $(CFILES) 71 | @$(CC) -MG -MM $(CFLAGS) $(CFILES) >$@ 72 | -include .depend 73 | endif 74 | 75 | -------------------------------------------------------------------------------- /test/0038_mul.tst: -------------------------------------------------------------------------------- 1 | ; test 8, 16, 32 bit (unsigned) mul 2 | ; 3 | ; note: the number of successful tests is returned on the stack 4 | ; 5 | 6 | [init mode=real] 7 | 8 | idt.base=0x1000 9 | 10 | [code start=0x0:0x2000] 11 | 12 | %macro mul_32 2 13 | dd %1 14 | dd %2 15 | dq (%1) * (%2) 16 | dd 0 17 | %endmacro 18 | 19 | %macro mul_16 2 20 | dd %1 21 | dd %2 22 | dq ((%1) % 0x10000) * ((%2) % 0x10000) 23 | dd 0 24 | %endmacro 25 | 26 | %macro mul_8 2 27 | dd %1 28 | dd %2 29 | dq ((%1) % 0x100) * ((%2) % 0x100) 30 | dd 0 31 | %endmacro 32 | 33 | xor edi,edi 34 | 35 | ; 32 bit 36 | mov si,table_start_32 37 | mul_10: 38 | xor eax,eax 39 | mov eax,[si] 40 | mov ecx,[si+4] 41 | mul ecx 42 | cmp eax,[si+8] 43 | jnz stop 44 | cmp edx,[si+12] 45 | jnz stop 46 | pushfd 47 | pop dword [si+16] 48 | inc edi 49 | add si,20 50 | cmp si,table_end_32 51 | jb mul_10 52 | 53 | ; 16 bit 54 | mov si,table_start_16 55 | mul_20: 56 | xor eax,eax 57 | mov eax,[si] 58 | mov ecx,[si+4] 59 | mul cx 60 | cmp ax,[si+8] 61 | jnz stop 62 | cmp dx,[si+10] 63 | jnz stop 64 | pushfd 65 | pop dword [si+16] 66 | inc edi 67 | add si,20 68 | cmp si,table_end_16 69 | jb mul_20 70 | 71 | ; 8 bit 72 | mov si,table_start_8 73 | mul_30: 74 | xor eax,eax 75 | mov eax,[si] 76 | mov ecx,[si+4] 77 | mul cl 78 | cmp al,[si+8] 79 | jnz stop 80 | cmp ah,[si+9] 81 | jnz stop 82 | pushfd 83 | pop dword [si+16] 84 | inc edi 85 | add si,20 86 | cmp si,table_end_8 87 | jb mul_30 88 | 89 | 90 | stop: 91 | push edi 92 | hlt 93 | 94 | align 0x10, db 0 95 | 96 | table_start_32: 97 | mul_32 0, 11 98 | mul_32 57, 11 99 | mul_32 0x9246, 73 100 | mul_32 0xa12373, 15 101 | mul_32 0x80000000, 227 102 | mul_32 0xffffffff, 227 103 | mul_32 0xe49dae82, 0xf7431dbc 104 | mul_32 0x2ebf2ff1, 0xed208954 105 | table_end_32: 106 | 107 | table_start_16: 108 | mul_16 0, 12 109 | mul_16 79, 12 110 | mul_16 0x22a9, 21 111 | mul_16 0xbae3, 0x2511 112 | mul_16 0x8000, 876 113 | mul_16 0xffff, 3327 114 | mul_16 0xf193, 0xa9da 115 | mul_16 0x9e07, 0x71fd 116 | table_end_16: 117 | 118 | table_start_8: 119 | mul_8 0, 17 120 | mul_8 57, 3 121 | mul_8 0x40, 2 122 | mul_8 0x80, 0x80 123 | mul_8 0x80, 76 124 | mul_8 0xff, 37 125 | mul_16 0x93, 0x4a 126 | mul_16 0xf7, 0xe1 127 | table_end_8: 128 | -------------------------------------------------------------------------------- /test/0037_imul.tst: -------------------------------------------------------------------------------- 1 | ; test 8, 16, 32 bit (signed) imul 2 | ; 3 | ; note: the number of successful tests is returned on the stack 4 | ; 5 | 6 | [init mode=real] 7 | 8 | idt.base=0x1000 9 | 10 | [code start=0x0:0x2000] 11 | 12 | %macro imul_32 2 13 | dd %1 14 | dd %2 15 | dq (%1) * (%2) 16 | dd 0 17 | %endmacro 18 | 19 | %macro imul_16 2 20 | dd %1 21 | dd %2 22 | dq ((%1) %% 0x10000) * ((%2) %% 0x10000) 23 | dd 0 24 | %endmacro 25 | 26 | %macro imul_8 2 27 | dd %1 28 | dd %2 29 | dq ((%1) %% 0x100) * ((%2) %% 0x100) 30 | dd 0 31 | %endmacro 32 | 33 | xor edi,edi 34 | 35 | ; 32 bit 36 | mov si,table_start_32 37 | mul_10: 38 | xor eax,eax 39 | mov eax,[si] 40 | mov ecx,[si+4] 41 | imul ecx 42 | cmp eax,[si+8] 43 | jnz stop 44 | cmp edx,[si+12] 45 | jnz stop 46 | pushfd 47 | pop dword [si+16] 48 | inc edi 49 | add si,20 50 | cmp si,table_end_32 51 | jb mul_10 52 | 53 | ; 16 bit 54 | mov si,table_start_16 55 | mul_20: 56 | xor eax,eax 57 | mov eax,[si] 58 | mov ecx,[si+4] 59 | imul cx 60 | cmp ax,[si+8] 61 | jnz stop 62 | cmp dx,[si+10] 63 | jnz stop 64 | pushfd 65 | pop dword [si+16] 66 | inc edi 67 | add si,20 68 | cmp si,table_end_16 69 | jb mul_20 70 | 71 | ; 8 bit 72 | mov si,table_start_8 73 | mul_30: 74 | xor eax,eax 75 | mov eax,[si] 76 | mov ecx,[si+4] 77 | imul cl 78 | cmp al,[si+8] 79 | jnz stop 80 | cmp ah,[si+9] 81 | jnz stop 82 | pushfd 83 | pop dword [si+16] 84 | inc edi 85 | add si,20 86 | cmp si,table_end_8 87 | jb mul_30 88 | 89 | 90 | stop: 91 | push edi 92 | hlt 93 | 94 | align 0x10, db 0 95 | 96 | table_start_32: 97 | imul_32 0, 11 98 | imul_32 57, -11 99 | imul_32 0x3246, 73 100 | imul_32 0xa12373, 15 101 | imul_32 -0x80000000, 227 102 | imul_32 -0x80000000, -227 103 | imul_32 0x249dae82, 0x07431dbc 104 | imul_32 -0x5ebf2ff1, -0x2d208954 105 | table_end_32: 106 | 107 | table_start_16: 108 | imul_16 0, 12 109 | imul_16 79, 12 110 | imul_16 0x22a9, -21 111 | imul_16 0x7ae3, 0x2511 112 | imul_16 -0x8000, 876 113 | imul_16 -0x8000, -3327 114 | imul_16 0x3193, 0x49da 115 | imul_16 -0x4e07,-0x71fd 116 | table_end_16: 117 | 118 | table_start_8: 119 | imul_8 0, 17 120 | imul_8 57, 3 121 | imul_8 0x40, 2 122 | imul_8 -0x40, 2 123 | imul_8 -0x80, 76 124 | imul_8 -0x80, -37 125 | imul_16 0x33, 0x4a 126 | imul_16 -0x47,-0x71 127 | table_end_8: 128 | -------------------------------------------------------------------------------- /test/0001_00_add.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 00 08 00 09 00 0a 00 0b 00 0c 00 0d 00 0e 00 90 4 | 00001010: 00 0f 00 68 40 00 69 40 00 6a 40 00 6b 40 00 6c 5 | 00001020: 40 00 6d 40 00 6e 40 00 6f 40 26 00 90 00 08 26 6 | 00001030: 00 91 00 08 26 00 92 00 08 26 00 93 00 08 26 00 7 | 00001040: 94 00 08 26 00 95 00 08 26 00 96 00 08 26 00 97 8 | 00001050: 00 08 00 f0 00 f1 00 f2 00 f3 00 f4 00 f5 00 f6 9 | 00001060: 00 f7 67 00 01 f4 10 | 00020000: *55 11 | 00020030: *66 12 | 00020040: *66 13 | 00024ff0: *55 14 | 00025000: *aa 15 | 00025030: *66 16 | 00025040: *cc 17 | 00029000: *55 18 | 0002aa90: *44 19 | 0002fff0: *55 20 | 00049ff0: *55 21 | 0004a000: *55 22 | 0004a030: *66 23 | 0004a040: *cc 24 | 000607f0: *33 25 | 00060800: *33 26 | 000657f0: *33 27 | 00065800: *66 28 | 0006a7f0: *33 29 | 0006a800: *66 30 | 31 | ; - - registers 32 | msr[0010] 0000000000000022 ; tsc 33 | 34 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 35 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 36 | 37 | gdt.base=00000000 gdt.limit=ffff 38 | idt.base=00000000 idt.limit=ffff 39 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 40 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 41 | 42 | cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b 43 | ss=4000 ss.base=00040000 ss.limit=0000ffff ss.acc=0093 44 | ds=2000 ds.base=00020000 ds.limit=0000ffff ds.acc=0093 45 | es=6000 es.base=00060000 es.limit=0000ffff es.acc=0093 46 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 47 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 48 | 49 | eax=00004444 ebx=0000d844 ecx=0000aa99 edx=00008877 50 | esi=00000000 edi=0000ffff ebp=0000a000 esp=00000000 51 | eip=00000066 eflags=00000006 ; pf 52 | 53 | -------------------------------------------------------------------------------- /test/0036_div.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 39 20 00 00 4 | 00002000: be 50 20 66 31 ff 66 8b 04 66 8b 54 04 66 8b 4c 5 | 00002010: 08 66 f7 f1 66 3b 44 0c 75 17 66 3b 54 10 75 11 6 | 00002020: 66 9c 66 8f 44 14 66 47 83 c6 18 81 fe d0 21 72 7 | 00002030: d5 66 31 c0 66 50 66 57 f4 66 31 d2 66 b8 44 44 8 | 00002040: 44 44 66 b9 01 00 00 00 cf 00 00 00 00 00 00 00 9 | 00002050: 39 00 00 00 00 00 00 00 0b 00 00 00 05 00 00 00 10 | 00002060: 02 00 00 00 46 00 00 00 b8 0b 00 00 00 00 00 00 11 | 00002070: d0 07 00 00 01 00 00 00 e8 03 00 00 46 00 00 00 12 | 00002080: 8b a7 1b 00 00 00 00 00 b3 21 00 00 d2 00 00 00 13 | 00002090: b5 02 00 00 46 00 00 00 87 29 54 ef 00 00 00 00 14 | 000020a0: 17 00 00 00 48 d5 67 0a 0f 00 00 00 46 00 00 00 15 | 000020b0: 17 00 00 00 00 00 00 00 87 29 54 ef 00 00 00 00 16 | 000020c0: 17 00 00 00 46 00 00 00 34 65 34 7d 28 fe 87 25 17 | 000020d0: 87 29 54 7f 70 49 75 4b 24 bb d7 40 46 00 00 00 18 | 000020e0: 34 65 34 7d 28 fe 87 75 42 b8 39 92 71 ae c3 cd 19 | 000020f0: 12 34 37 82 46 00 00 00 ff ff ff 7f 00 00 00 00 20 | 00002100: 01 00 00 00 ff ff ff 7f 00 00 00 00 46 00 00 00 21 | 00002110: 00 00 00 ff ff ff 7f 00 00 00 00 01 ff ff ff 7f 22 | 00002120: 00 00 00 00 46 00 00 00 34 65 34 7d 27 fe 87 45 23 | 00002130: 28 fe 87 45 fe ff ff ff 84 61 44 08 46 00 00 00 24 | 00002140: 00 00 00 80 00 00 00 00 01 00 00 00 00 00 00 80 25 | 00002150: 00 00 00 00 46 00 00 00 ff ff ff ff 00 00 00 00 26 | 00002160: 01 00 00 00 ff ff ff ff 00 00 00 00 46 00 00 00 27 | 00002170: 00 00 00 00 00 00 00 00 00 00 00 00 44 44 44 44 28 | 00002180: 00 00 00 00 46 00 00 00 64 00 00 00 00 00 00 00 29 | 00002190: 00 00 00 00 44 44 44 44 00 00 00 00 46 00 00 00 30 | 000021a0: 34 65 34 7d 28 fe 87 45 0a 00 00 00 44 44 44 44 31 | 000021b0: 00 00 00 00 46 00 00 00 34 65 34 7d 28 fe 87 45 32 | 000021c0: 28 fe 87 45 44 44 44 44 00 00 00 00 46 00 00 00 33 | 000021d0: f4 34 | 0000fff0: 10 00 00 00 00 00 00 00 35 | 36 | ; - - registers 37 | msr[0010] 00000000000000fa ; tsc 38 | 39 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 40 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 41 | 42 | gdt.base=00000000 gdt.limit=ffff 43 | idt.base=00001000 idt.limit=ffff 44 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 45 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 46 | 47 | cs=0000 cs.base=00000000 cs.limit=0000ffff cs.acc=009b 48 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 49 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 50 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 51 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 52 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 53 | 54 | eax=00000000 ebx=00000000 ecx=00000001 edx=00000000 55 | esi=000021d0 edi=00000010 ebp=00000000 esp=0000fff8 56 | eip=00002039 eflags=00000046 ; zf pf 57 | 58 | -------------------------------------------------------------------------------- /test/0037_imul.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00002000: 66 31 ff be 90 20 66 31 c0 66 8b 04 66 8b 4c 04 4 | 00002010: 66 f7 e9 66 3b 44 08 75 6b 66 3b 54 0c 75 65 66 5 | 00002020: 9c 66 8f 44 10 66 47 83 c6 14 81 fe 30 21 72 d6 6 | 00002030: be 30 21 66 31 c0 66 8b 04 66 8b 4c 04 f7 e9 3b 7 | 00002040: 44 08 75 40 3b 54 0a 75 3b 66 9c 66 8f 44 10 66 8 | 00002050: 47 83 c6 14 81 fe d0 21 72 d9 be d0 21 66 31 c0 9 | 00002060: 66 8b 04 66 8b 4c 04 f6 e9 3a 44 08 75 16 3a 64 10 | 00002070: 09 75 11 66 9c 66 8f 44 10 66 47 83 c6 14 81 fe 11 | 00002080: 70 22 72 d9 66 57 f4 00 00 00 00 00 00 00 00 00 12 | 00002090: 00 00 00 00 0b 00 00 00 00 00 00 00 00 00 00 00 13 | 000020a0: 46 00 00 00 39 00 00 00 f5 ff ff ff 8d fd ff ff 14 | 000020b0: ff ff ff ff 46 00 00 00 46 32 00 00 49 00 00 00 15 | 000020c0: f6 55 0e 00 00 00 00 00 46 00 00 00 73 23 a1 00 16 | 000020d0: 0f 00 00 00 bd 13 71 09 00 00 00 00 46 00 00 00 17 | 000020e0: 00 00 00 80 e3 00 00 00 00 00 00 80 8e ff ff ff 18 | 000020f0: 46 00 00 00 00 00 00 80 1d ff ff ff 00 00 00 80 19 | 00002100: 71 00 00 00 46 00 00 00 82 ae 9d 24 bc 1d 43 07 20 | 00002110: 78 e1 96 fa 4a e9 09 01 46 00 00 00 0f d0 40 a1 21 | 00002120: ac 76 df d2 14 b4 83 c2 26 a6 b3 10 46 00 00 00 22 | 00002130: 00 00 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 23 | 00002140: 46 00 00 00 4f 00 00 00 0c 00 00 00 b4 03 00 00 24 | 00002150: 00 00 00 00 46 00 00 00 a9 22 00 00 eb ff ff ff 25 | 00002160: 23 28 fd ff ff ff ff ff 46 00 00 00 e3 7a 00 00 26 | 00002170: 11 25 00 00 13 f8 ca 11 00 00 00 00 46 00 00 00 27 | 00002180: 00 80 ff ff 6c 03 00 00 00 00 4a fe ff ff ff ff 28 | 00002190: 46 00 00 00 00 80 ff ff 01 f3 ff ff 00 80 7f 06 29 | 000021a0: 00 00 00 00 46 00 00 00 93 31 00 00 da 49 00 00 30 | 000021b0: 2e 22 4d 0e 00 00 00 00 46 00 00 00 f9 b1 ff ff 31 | 000021c0: 03 8e ff ff eb 33 be 22 00 00 00 00 46 00 00 00 32 | 000021d0: 00 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 33 | 000021e0: 46 00 00 00 39 00 00 00 03 00 00 00 ab 00 00 00 34 | 000021f0: 00 00 00 00 46 00 00 00 40 00 00 00 02 00 00 00 35 | 00002200: 80 00 00 00 00 00 00 00 46 00 00 00 c0 ff ff ff 36 | 00002210: 02 00 00 00 80 ff ff ff ff ff ff ff 46 00 00 00 37 | 00002220: 80 ff ff ff 4c 00 00 00 00 da ff ff ff ff ff ff 38 | 00002230: 46 00 00 00 80 ff ff ff db ff ff ff 80 12 00 00 39 | 00002240: 00 00 00 00 46 00 00 00 33 00 00 00 4a 00 00 00 40 | 00002250: be 0e 00 00 00 00 00 00 46 00 00 00 b9 ff ff ff 41 | 00002260: 8f ff ff ff 57 1f 00 00 00 00 00 00 46 00 00 00 42 | 00002270: f4 43 | 0000fff0: 18 00 00 00 44 | 45 | ; - - registers 46 | msr[0010] 0000000000000156 ; tsc 47 | 48 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 49 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 50 | 51 | gdt.base=00000000 gdt.limit=ffff 52 | idt.base=00001000 idt.limit=ffff 53 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 54 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 55 | 56 | cs=0000 cs.base=00000000 cs.limit=0000ffff cs.acc=009b 57 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 58 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 59 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 60 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 61 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 62 | 63 | eax=ffff1f57 ebx=00000000 ecx=ffffff8f edx=10b322be 64 | esi=00002270 edi=00000018 ebp=00000000 esp=0000fffc 65 | eip=00002087 eflags=00000046 ; zf pf 66 | 67 | -------------------------------------------------------------------------------- /test/0038_mul.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00002000: 66 31 ff be 90 20 66 31 c0 66 8b 04 66 8b 4c 04 4 | 00002010: 66 f7 e1 66 3b 44 08 75 6b 66 3b 54 0c 75 65 66 5 | 00002020: 9c 66 8f 44 10 66 47 83 c6 14 81 fe 30 21 72 d6 6 | 00002030: be 30 21 66 31 c0 66 8b 04 66 8b 4c 04 f7 e1 3b 7 | 00002040: 44 08 75 40 3b 54 0a 75 3b 66 9c 66 8f 44 10 66 8 | 00002050: 47 83 c6 14 81 fe d0 21 72 d9 be d0 21 66 31 c0 9 | 00002060: 66 8b 04 66 8b 4c 04 f6 e1 3a 44 08 75 16 3a 64 10 | 00002070: 09 75 11 66 9c 66 8f 44 10 66 47 83 c6 14 81 fe 11 | 00002080: 70 22 72 d9 66 57 f4 00 00 00 00 00 00 00 00 00 12 | 00002090: 00 00 00 00 0b 00 00 00 00 00 00 00 00 00 00 00 13 | 000020a0: 46 00 00 00 39 00 00 00 0b 00 00 00 73 02 00 00 14 | 000020b0: 00 00 00 00 46 00 00 00 46 92 00 00 49 00 00 00 15 | 000020c0: f6 b5 29 00 00 00 00 00 46 00 00 00 73 23 a1 00 16 | 000020d0: 0f 00 00 00 bd 13 71 09 00 00 00 00 46 00 00 00 17 | 000020e0: 00 00 00 80 e3 00 00 00 00 00 00 80 71 00 00 00 18 | 000020f0: 46 00 00 00 ff ff ff ff e3 00 00 00 1d ff ff ff 19 | 00002100: e2 00 00 00 46 00 00 00 82 ae 9d e4 bc 1d 43 f7 20 | 00002110: 78 e1 96 da 31 13 d0 dc 46 00 00 00 f1 2f bf 2e 21 | 00002120: 54 89 20 ed 14 b4 83 c2 5b f0 4c 2b 46 00 00 00 22 | 00002130: 00 00 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 23 | 00002140: 46 00 00 00 4f 00 00 00 0c 00 00 00 b4 03 00 00 24 | 00002150: 00 00 00 00 46 00 00 00 a9 22 00 00 15 00 00 00 25 | 00002160: dd d7 02 00 00 00 00 00 46 00 00 00 e3 ba 00 00 26 | 00002170: 11 25 00 00 13 38 0f 1b 00 00 00 00 46 00 00 00 27 | 00002180: 00 80 00 00 6c 03 00 00 00 00 b6 01 00 00 00 00 28 | 00002190: 46 00 00 00 ff ff 00 00 ff 0c 00 00 01 f3 fe 0c 29 | 000021a0: 00 00 00 00 46 00 00 00 93 f1 00 00 da a9 00 00 30 | 000021b0: 2e c2 47 a0 00 00 00 00 46 00 00 00 07 9e 00 00 31 | 000021c0: fd 71 00 00 eb 43 5d 46 00 00 00 00 46 00 00 00 32 | 000021d0: 00 00 00 00 11 00 00 00 00 00 00 00 00 00 00 00 33 | 000021e0: 46 00 00 00 39 00 00 00 03 00 00 00 ab 00 00 00 34 | 000021f0: 00 00 00 00 46 00 00 00 40 00 00 00 02 00 00 00 35 | 00002200: 80 00 00 00 00 00 00 00 46 00 00 00 80 00 00 00 36 | 00002210: 80 00 00 00 00 40 00 00 00 00 00 00 46 00 00 00 37 | 00002220: 80 00 00 00 4c 00 00 00 00 26 00 00 00 00 00 00 38 | 00002230: 46 00 00 00 ff 00 00 00 25 00 00 00 db 24 00 00 39 | 00002240: 00 00 00 00 46 00 00 00 93 00 00 00 4a 00 00 00 40 | 00002250: 7e 2a 00 00 00 00 00 00 46 00 00 00 f7 00 00 00 41 | 00002260: e1 00 00 00 17 d9 00 00 00 00 00 00 46 00 00 00 42 | 00002270: f4 43 | 0000fff0: 18 00 00 00 44 | 45 | ; - - registers 46 | msr[0010] 0000000000000156 ; tsc 47 | 48 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 49 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 50 | 51 | gdt.base=00000000 gdt.limit=ffff 52 | idt.base=00001000 idt.limit=ffff 53 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 54 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 55 | 56 | cs=0000 cs.base=00000000 cs.limit=0000ffff cs.acc=009b 57 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 58 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 59 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 60 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 61 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 62 | 63 | eax=0000d917 ebx=00000000 ecx=000000e1 edx=2b4c465d 64 | esi=00002270 edi=00000018 ebp=00000000 esp=0000fffc 65 | eip=00002087 eflags=00000046 ; zf pf 66 | 67 | -------------------------------------------------------------------------------- /test/0035_idiv.done: -------------------------------------------------------------------------------- 1 | ; - - memory 2 | ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 3 | 00001000: 39 20 00 00 4 | 00002000: be 50 20 66 31 ff 66 8b 04 66 8b 54 04 66 8b 4c 5 | 00002010: 08 66 f7 f9 66 3b 44 0c 75 17 66 3b 54 10 75 11 6 | 00002020: 66 9c 66 8f 44 14 66 47 83 c6 18 81 fe 50 23 72 7 | 00002030: d5 66 31 c0 66 50 66 57 f4 66 31 d2 66 b8 44 44 8 | 00002040: 44 44 66 b9 01 00 00 00 cf 00 00 00 00 00 00 00 9 | 00002050: 39 00 00 00 00 00 00 00 0b 00 00 00 05 00 00 00 10 | 00002060: 02 00 00 00 46 00 00 00 b8 0b 00 00 00 00 00 00 11 | 00002070: d0 07 00 00 01 00 00 00 e8 03 00 00 46 00 00 00 12 | 00002080: 8b a7 1b 00 00 00 00 00 b3 21 00 00 d2 00 00 00 13 | 00002090: b5 02 00 00 46 00 00 00 87 29 54 ef 00 00 00 00 14 | 000020a0: 17 00 00 00 48 d5 67 0a 0f 00 00 00 46 00 00 00 15 | 000020b0: 17 00 00 00 00 00 00 00 87 29 54 ef 00 00 00 00 16 | 000020c0: 17 00 00 00 46 00 00 00 34 65 34 7d 28 fe 87 25 17 | 000020d0: 87 29 54 7f 70 49 75 4b 24 bb d7 40 46 00 00 00 18 | 000020e0: ff ff ff 7f 00 00 00 00 01 00 00 00 ff ff ff 7f 19 | 000020f0: 00 00 00 00 46 00 00 00 00 00 00 ff ff ff 7f 00 20 | 00002100: 00 00 00 01 ff ff ff 7f 00 00 00 00 46 00 00 00 21 | 00002110: 48 f4 ff ff ff ff ff ff d0 07 00 00 ff ff ff ff 22 | 00002120: 18 fc ff ff 46 00 00 00 8b a7 1b 00 00 00 00 00 23 | 00002130: 4d de ff ff 2e ff ff ff b5 02 00 00 46 00 00 00 24 | 00002140: 87 29 54 ef 00 00 00 00 e9 ff ff ff b8 2a 98 f5 25 | 00002150: 0f 00 00 00 46 00 00 00 e9 ff ff ff ff ff ff ff 26 | 00002160: 87 29 54 ef 00 00 00 00 e9 ff ff ff 46 00 00 00 27 | 00002170: cc 9a cb 82 d7 01 78 da 87 29 54 7f 90 b6 8a b4 28 | 00002180: dc 44 28 bf 46 00 00 00 34 65 34 7d 28 fe 87 35 29 | 00002190: 79 d6 ab 80 f8 86 5f 94 fc 49 92 59 46 00 00 00 30 | 000021a0: 00 00 00 80 00 00 00 00 ff ff ff ff 00 00 00 80 31 | 000021b0: 00 00 00 00 46 00 00 00 ff ff ff 7f 00 00 00 00 32 | 000021c0: ff ff ff ff 01 00 00 80 00 00 00 00 46 00 00 00 33 | 000021d0: f9 ff ff ff ff ff ff ff fb ff ff ff 01 00 00 00 34 | 000021e0: fe ff ff ff 46 00 00 00 d4 fe ff ff ff ff ff ff 35 | 000021f0: 38 ff ff ff 01 00 00 00 9c ff ff ff 46 00 00 00 36 | 00002200: 75 58 e4 ff ff ff ff ff 4d de ff ff d2 00 00 00 37 | 00002210: 4b fd ff ff 46 00 00 00 79 d6 ab 10 ff ff ff ff 38 | 00002220: e9 ff ff ff 48 d5 67 0a f1 ff ff ff 46 00 00 00 39 | 00002230: a9 ea ff ff ff ff ff ff cf 52 61 50 00 00 00 00 40 | 00002240: a9 ea ff ff 46 00 00 00 cc 9a cb 82 d7 01 78 da 41 | 00002250: 79 d6 ab 80 70 49 75 4b dc 44 28 bf 46 00 00 00 42 | 00002260: d8 60 30 d3 ea f9 8a ce a7 90 8e 97 13 60 39 79 43 | 00002270: 73 04 2e f9 46 00 00 00 01 00 00 80 ff ff ff ff 44 | 00002280: ff ff ff ff ff ff ff 7f 00 00 00 00 46 00 00 00 45 | 00002290: 00 00 00 80 00 00 00 00 01 00 00 00 44 44 44 44 46 | 000022a0: 00 00 00 00 46 00 00 00 00 00 00 80 ff ff ff ff 47 | 000022b0: ff ff ff ff 44 44 44 44 00 00 00 00 46 00 00 00 48 | 000022c0: 00 00 00 00 00 00 00 00 00 00 00 00 44 44 44 44 49 | 000022d0: 00 00 00 00 46 00 00 00 64 00 00 00 00 00 00 00 50 | 000022e0: 00 00 00 00 44 44 44 44 00 00 00 00 46 00 00 00 51 | 000022f0: 9c ff ff ff ff ff ff ff 00 00 00 00 44 44 44 44 52 | 00002300: 00 00 00 00 46 00 00 00 34 65 34 7d 28 fe 87 45 53 | 00002310: f6 ff ff ff 44 44 44 44 00 00 00 00 46 00 00 00 54 | 00002320: 34 65 34 7d 28 fe 87 45 0a 00 00 00 44 44 44 44 55 | 00002330: 00 00 00 00 46 00 00 00 34 65 34 7d 28 fe 87 45 56 | 00002340: 87 29 54 7f 44 44 44 44 00 00 00 00 46 00 00 00 57 | 00002350: f4 58 | 0000fff0: 20 00 00 00 00 00 00 00 59 | 60 | ; - - registers 61 | msr[0010] 00000000000001ee ; tsc 62 | 63 | cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 64 | dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 65 | 66 | gdt.base=00000000 gdt.limit=ffff 67 | idt.base=00001000 idt.limit=ffff 68 | tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 69 | ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 70 | 71 | cs=0000 cs.base=00000000 cs.limit=0000ffff cs.acc=009b 72 | ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 73 | ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 74 | es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 75 | fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 76 | gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 77 | 78 | eax=00000000 ebx=00000000 ecx=00000001 edx=00000000 79 | esi=00002350 edi=00000020 ebp=00000000 esp=0000fff8 80 | eip=00002039 eflags=00000046 ; zf pf 81 | 82 | -------------------------------------------------------------------------------- /demo/x86emu-demo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a simple program demonstrating the libx86emu usage. 3 | * 4 | * It lets you load a binary blob at some address and run the emulation.The 5 | * emulation trace is logged to the console to show what it is doing. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void help(void); 14 | void flush_log(x86emu_t *emu, char *buf, unsigned size); 15 | x86emu_t *emu_new(void); 16 | int emu_init(x86emu_t *emu, char *file); 17 | void emu_run(char *file); 18 | 19 | 20 | struct option options[] = { 21 | { "help", 0, NULL, 'h' }, 22 | { "load", 1, NULL, 'l' }, 23 | { "start", 1, NULL, 's' }, 24 | { "max", 1, NULL, 'm' }, 25 | { "32", 0, NULL, 1001 }, 26 | { } 27 | }; 28 | 29 | 30 | struct { 31 | struct { 32 | unsigned segment; 33 | unsigned offset; 34 | } start; 35 | unsigned load; 36 | unsigned max_instructions; 37 | unsigned bits_32:1; 38 | char *file; 39 | } opt; 40 | 41 | 42 | /* 43 | * Parse options, then run emulation. 44 | */ 45 | int main(int argc, char **argv) 46 | { 47 | int i; 48 | char *str; 49 | 50 | opt.start.segment = 0; 51 | opt.start.offset = opt.load = 0x7c00; 52 | opt.max_instructions = 10000000; 53 | 54 | opterr = 0; 55 | 56 | while((i = getopt_long(argc, argv, "hm:l:s:", options, NULL)) != -1) { 57 | switch(i) { 58 | case 'm': 59 | opt.max_instructions = strtoul(optarg, NULL, 0); 60 | break; 61 | 62 | case 'l': 63 | opt.load = strtoul(optarg, NULL, 0); 64 | break; 65 | 66 | case 's': 67 | opt.start.offset = strtoul(optarg, &str, 0); 68 | if(*str == ':') { 69 | opt.start.segment = opt.start.offset; 70 | opt.start.offset = strtoul(str + 1, NULL, 0); 71 | } 72 | break; 73 | 74 | case 1001: 75 | opt.bits_32 = 1; 76 | break; 77 | 78 | default: 79 | help(); 80 | return i == 'h' ? 0 : 1; 81 | } 82 | } 83 | 84 | if(argc == optind + 1) { 85 | opt.file = argv[optind]; 86 | } 87 | else { 88 | help(); 89 | return 1; 90 | } 91 | 92 | emu_run(opt.file); 93 | 94 | return 0; 95 | } 96 | 97 | 98 | /* 99 | * Display short usage message. 100 | */ 101 | void help() 102 | { 103 | printf( 104 | "Usage: x86emu-demo [OPTIONS] FILE\n" 105 | "\n" 106 | "Load FILE and run x86 emulation.\n" 107 | "\n" 108 | "Options:\n" 109 | " -l, --load ADDRESS Load FILE at ADDRESS into memory (default 0x7c00).\n" 110 | " -s, --start ADDRESS Start emulation at ADDRESS (default 0:0x7c00).\n" 111 | " ADDRESS may contain a colon (':') to separate segment and\n" 112 | " offset values. Without colon, segment 0 is assumed.\n" 113 | " -m, --max N Stop after emulating N instructions.\n" 114 | " --32 Start in 32-bit mode (default 16-bit mode).\n" 115 | " -h, --help Show this text\n" 116 | ); 117 | } 118 | 119 | 120 | /* 121 | * Write emulation log to console. 122 | */ 123 | void flush_log(x86emu_t *emu, char *buf, unsigned size) 124 | { 125 | if(!buf || !size) return; 126 | 127 | fwrite(buf, size, 1, stdout); 128 | } 129 | 130 | 131 | /* 132 | * Create new emulation object. 133 | */ 134 | x86emu_t *emu_new() 135 | { 136 | x86emu_t *emu = x86emu_new(X86EMU_PERM_R | X86EMU_PERM_W | X86EMU_PERM_X, 0); 137 | 138 | /* log buf size of 1000000 is purely arbitrary */ 139 | x86emu_set_log(emu, 1000000, flush_log); 140 | 141 | emu->log.trace = X86EMU_TRACE_DEFAULT; 142 | 143 | return emu; 144 | } 145 | 146 | 147 | /* 148 | * Setup registers and memory. 149 | */ 150 | int emu_init(x86emu_t *emu, char *file) 151 | { 152 | FILE *f; 153 | unsigned addr; 154 | int i; 155 | 156 | addr = opt.load; 157 | 158 | x86emu_set_seg_register(emu, emu->x86.R_CS_SEL, opt.start.segment); 159 | emu->x86.R_EIP = opt.start.offset; 160 | if(opt.bits_32) { 161 | /* set default data/address size to 32 bit */ 162 | emu->x86.R_CS_ACC |= (1 << 10); 163 | 164 | /* maximize descriptor limits */ 165 | emu->x86.R_CS_LIMIT = 166 | emu->x86.R_DS_LIMIT = 167 | emu->x86.R_ES_LIMIT = 168 | emu->x86.R_FS_LIMIT = 169 | emu->x86.R_GS_LIMIT = 170 | emu->x86.R_SS_LIMIT = ~0; 171 | } 172 | 173 | if(!(f = fopen(file, "r"))) return 0; 174 | 175 | while((i = fgetc(f)) != EOF) { 176 | x86emu_write_byte(emu, addr++, i); 177 | } 178 | 179 | fclose(f); 180 | 181 | return 1; 182 | } 183 | 184 | 185 | /* 186 | * Run emulation. 187 | */ 188 | void emu_run(char *file) 189 | { 190 | x86emu_t *emu = emu_new(); 191 | unsigned flags = X86EMU_RUN_MAX_INSTR | X86EMU_RUN_NO_EXEC | X86EMU_RUN_NO_CODE | X86EMU_RUN_LOOP; 192 | int ok = 0; 193 | 194 | if(!file) return; 195 | 196 | ok = emu_init(emu, file); 197 | 198 | if(ok) { 199 | printf("*** running %s ***\n\n", file); 200 | 201 | x86emu_dump(emu, X86EMU_DUMP_MEM | X86EMU_DUMP_ASCII); 202 | 203 | x86emu_reset_access_stats(emu); 204 | 205 | emu->max_instr = opt.max_instructions; 206 | x86emu_run(emu, flags); 207 | 208 | x86emu_dump(emu, X86EMU_DUMP_DEFAULT | X86EMU_DUMP_ACC_MEM); 209 | 210 | x86emu_clear_log(emu, 1); 211 | } 212 | 213 | x86emu_done(emu); 214 | } 215 | 216 | -------------------------------------------------------------------------------- /include/x86emu_int.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 6 | * 7 | * ======================================================================== 8 | * 9 | * Permission to use, copy, modify, distribute, and sell this software and 10 | * its documentation for any purpose is hereby granted without fee, 11 | * provided that the above copyright notice appear in all copies and that 12 | * both that copyright notice and this permission notice appear in 13 | * supporting documentation, and that the name of the authors not be used 14 | * in advertising or publicity pertaining to distribution of the software 15 | * without specific, written prior permission. The authors makes no 16 | * representations about the suitability of this software for any purpose. 17 | * It is provided "as is" without express or implied warranty. 18 | * 19 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 20 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 21 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 22 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 23 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 24 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 25 | * PERFORMANCE OF THIS SOFTWARE. 26 | * 27 | * ======================================================================== 28 | * 29 | * Description: 30 | * Header file for library internal macros and definitions. 31 | * 32 | ****************************************************************************/ 33 | 34 | 35 | #ifndef __X86EMU_X86EMU_INT_H 36 | #define __X86EMU_X86EMU_INT_H 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | // exported symbol - all others are not exported by the library 44 | #define API_SYM __attribute__((visibility("default"))) 45 | 46 | #include "x86emu.h" 47 | #include "decode.h" 48 | #include "ops.h" 49 | #include "prim_ops.h" 50 | #include "mem.h" 51 | 52 | #define INTR_RAISE_DIV0(a) x86emu_intr_raise(a, 0, INTR_TYPE_SOFT | INTR_MODE_RESTART, 0) 53 | #define INTR_RAISE_SOFT(a, n) x86emu_intr_raise(a, n, INTR_TYPE_SOFT, 0) 54 | #define INTR_RAISE_GP(a, err) x86emu_intr_raise(a, 0x0d, INTR_TYPE_FAULT | INTR_MODE_RESTART | INTR_MODE_ERRCODE, err) 55 | #define INTR_RAISE_UD(a) x86emu_intr_raise(a, 0x06, INTR_TYPE_FAULT | INTR_MODE_RESTART, 0) 56 | 57 | #define MODE_REPE ((emu)->x86.mode & _MODE_REPE) 58 | #define MODE_REPNE ((emu)->x86.mode & _MODE_REPNE) 59 | #define MODE_REP ((emu)->x86.mode & (_MODE_REPE | _MODE_REPNE)) 60 | #define MODE_DATA32 ((emu)->x86.mode & _MODE_DATA32) 61 | #define MODE_ADDR32 ((emu)->x86.mode & _MODE_ADDR32) 62 | #define MODE_STACK32 ((emu)->x86.mode & _MODE_STACK32) 63 | #define MODE_CODE32 ((emu)->x86.mode & _MODE_CODE32) 64 | #define MODE_HALTED ((emu)->x86.mode & _MODE_HALTED) 65 | 66 | #define MODE_PROTECTED(a) ((a)->x86.R_CR0 & 1) 67 | #define MODE_REAL(a) (!MODE_PROTECTED(a)) 68 | 69 | #define TOGGLE_FLAG(flag) ((emu)->x86.R_FLG ^= (flag)) 70 | #define SET_FLAG(flag) ((emu)->x86.R_FLG |= (flag)) 71 | #define CLEAR_FLAG(flag) ((emu)->x86.R_FLG &= ~(flag)) 72 | #define ACCESS_FLAG(flag) ((emu)->x86.R_FLG & (flag)) 73 | #define CLEARALL_FLAG(m) ((emu)->x86.R_FLG = 0) 74 | 75 | #define CONDITIONAL_SET_FLAG(COND,FLAG) \ 76 | if(COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG) 77 | 78 | /* 79 | * Processor manuals say Z, S, P, A flags are 'undefined'. Experiments on 80 | * some CPUs show they are set based on the result resp. lower half of the 81 | * result. 82 | * 83 | * RES_ZERO: value to check for zero flag (whole result) 84 | * RES_LO: value to check for sign and parity (lower half) 85 | * BITS: argument size (8, 16, 32) 86 | */ 87 | #define SET_FLAGS_FOR_MUL(RES_ZERO, RES_LO, BITS) \ 88 | CONDITIONAL_SET_FLAG((RES_ZERO) == 0, F_ZF); \ 89 | CONDITIONAL_SET_FLAG((RES_LO) & (1 << ((BITS) - 1)), F_SF); \ 90 | CONDITIONAL_SET_FLAG(PARITY((RES_LO) & 0xff), F_PF); \ 91 | CLEAR_FLAG(F_AF) 92 | 93 | #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 94 | 95 | extern u32 x86emu_parity_tab[8]; 96 | 97 | #define LOG_STR(a) memcpy(*p, a, sizeof (a) - 1), *p += sizeof (a) - 1 98 | #define LOG_FREE(emu) ((emu)->log.size + (emu)->log.buf - (emu)->log.ptr) 99 | 100 | #if defined(__i386__) || defined (__x86_64__) 101 | #define WITH_TSC 1 102 | #define WITH_IOPL 1 103 | #else 104 | #define WITH_TSC 0 105 | #define WITH_IOPL 0 106 | #endif 107 | 108 | 109 | #if WITH_TSC 110 | #if defined(__i386__) 111 | static inline u64 tsc(void) 112 | { 113 | register u64 tsc asm ("%eax"); 114 | 115 | asm ( 116 | "rdtsc" 117 | : "=r" (tsc) 118 | ); 119 | 120 | return tsc; 121 | } 122 | #endif 123 | 124 | #if defined (__x86_64__) 125 | static inline u64 tsc(void) 126 | { 127 | register u64 tsc asm ("%rax"); 128 | 129 | asm ( 130 | "push %%rdx\n" 131 | "rdtsc\n" 132 | "xchg %%edx,%%eax\n" 133 | "shl $32,%%rax\n" 134 | "add %%rdx,%%rax\n" 135 | "pop %%rdx" 136 | : "=r" (tsc) 137 | ); 138 | 139 | return tsc; 140 | } 141 | #endif 142 | 143 | #endif 144 | 145 | 146 | #if WITH_IOPL 147 | #if defined(__i386__) 148 | static inline unsigned getiopl(void) 149 | { 150 | register u32 i asm ("%eax"); 151 | 152 | asm( 153 | "pushf\n" 154 | "pop %%eax" 155 | : "=r" (i) 156 | ); 157 | 158 | i = (i >> 12) & 3; 159 | 160 | return i; 161 | } 162 | #endif 163 | 164 | #if defined (__x86_64__) 165 | static inline unsigned getiopl(void) 166 | { 167 | register unsigned i asm ("%rax"); 168 | 169 | asm( 170 | "pushf\n" 171 | "pop %%rax" 172 | : "=r" (i) 173 | ); 174 | 175 | i = (i >> 12) & 3; 176 | 177 | return i; 178 | } 179 | #endif 180 | 181 | #endif 182 | 183 | 184 | #endif /* __X86EMU_X86EMU_INT_H */ 185 | 186 | -------------------------------------------------------------------------------- /include/decode.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 1996-1999 SciTech Software, Inc. 6 | * Copyright (c) David Mosberger-Tang 7 | * Copyright (c) 1999 Egbert Eich 8 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 9 | * 10 | * ======================================================================== 11 | * 12 | * Permission to use, copy, modify, distribute, and sell this software and 13 | * its documentation for any purpose is hereby granted without fee, 14 | * provided that the above copyright notice appear in all copies and that 15 | * both that copyright notice and this permission notice appear in 16 | * supporting documentation, and that the name of the authors not be used 17 | * in advertising or publicity pertaining to distribution of the software 18 | * without specific, written prior permission. The authors makes no 19 | * representations about the suitability of this software for any purpose. 20 | * It is provided "as is" without express or implied warranty. 21 | * 22 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 23 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 24 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 25 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 26 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 27 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28 | * PERFORMANCE OF THIS SOFTWARE. 29 | * 30 | * ======================================================================== 31 | * 32 | * Description: 33 | * Header file for instruction decoding logic. 34 | * 35 | ****************************************************************************/ 36 | 37 | 38 | #ifndef __X86EMU_DECODE_H 39 | #define __X86EMU_DECODE_H 40 | 41 | /*---------------------- Macros and type definitions ----------------------*/ 42 | 43 | /* Instruction Decoding */ 44 | 45 | #define OP_DECODE(a) \ 46 | memcpy((emu)->x86.disasm_ptr, a, sizeof a - 1), \ 47 | (emu)->x86.disasm_ptr += sizeof a - 1 48 | 49 | #define SEGPREF_DECODE \ 50 | memcpy((emu)->x86.disasm_ptr, (emu)->x86.decode_seg, 4), \ 51 | (emu)->x86.disasm_ptr += (emu)->x86.default_seg ? 4 : 1 52 | 53 | #define DECODE_HEX1(ofs) decode_hex1((emu), &(emu)->x86.disasm_ptr, ofs) 54 | #define DECODE_HEX2(ofs) decode_hex2((emu), &(emu)->x86.disasm_ptr, ofs) 55 | #define DECODE_HEX4(ofs) decode_hex4((emu), &(emu)->x86.disasm_ptr, ofs) 56 | #define DECODE_HEX8(ofs) decode_hex8((emu), &(emu)->x86.disasm_ptr, ofs) 57 | #define DECODE_HEX2S(ofs) decode_hex2s((emu), &(emu)->x86.disasm_ptr, ofs) 58 | #define DECODE_HEX4S(ofs) decode_hex4s((emu), &(emu)->x86.disasm_ptr, ofs) 59 | #define DECODE_HEX8S(ofs) decode_hex8s((emu), &(emu)->x86.disasm_ptr, ofs) 60 | #define DECODE_HEX_ADDR(ofs) decode_hex_addr((emu), &(emu)->x86.disasm_ptr, ofs) 61 | 62 | /*-------------------------- Function Prototypes --------------------------*/ 63 | 64 | #ifdef __cplusplus 65 | extern "C" { /* Use "C" linkage when in C++ mode */ 66 | #endif 67 | 68 | void fetch_decode_modrm(x86emu_t *emu, int *mod, int *regh, int *regl); 69 | u8 fetch_byte(x86emu_t *emu); 70 | u16 fetch_word(x86emu_t *emu); 71 | u32 fetch_long(x86emu_t *emu); 72 | u8 fetch_data_byte(x86emu_t *emu, u32 offset); 73 | u8 fetch_data_byte_abs(x86emu_t *emu, sel_t *seg, u32 offset); 74 | u16 fetch_data_word(x86emu_t *emu, u32 offset); 75 | u16 fetch_data_word_abs(x86emu_t *emu, sel_t *seg, u32 offset); 76 | u32 fetch_data_long(x86emu_t *emu, u32 offset); 77 | u32 fetch_data_long_abs(x86emu_t *emu, sel_t *seg, u32 offset); 78 | I128_reg_t fetch_data_qlong(x86emu_t *emu, u32 ofs); 79 | void store_data_byte(x86emu_t *emu, u32 offset, u8 val); 80 | void store_data_byte_abs(x86emu_t *emu, sel_t *seg, u32 offset, u8 val); 81 | void store_data_word(x86emu_t *emu, u32 offset, u16 val); 82 | void store_data_word_abs(x86emu_t *emu, sel_t *seg, u32 offset, u16 val); 83 | void store_data_long(x86emu_t *emu, u32 offset, u32 val); 84 | void store_data_long_abs(x86emu_t *emu, sel_t *seg, u32 offset, u32 val); 85 | void store_data_qlong(x86emu_t *emu, u32 ofs, I128_reg_t val); 86 | u8 fetch_io_byte(x86emu_t *emu, u32 offset); 87 | u16 fetch_io_word(x86emu_t *emu, u32 offset); 88 | u32 fetch_io_long(x86emu_t *emu, u32 offset); 89 | void store_io_byte(x86emu_t *emu, u32 port, u8 val); 90 | void store_io_word(x86emu_t *emu, u32 port, u16 val); 91 | void store_io_long(x86emu_t *emu, u32 port, u32 val); 92 | u8* decode_rm_byte_register(x86emu_t *emu, int reg); 93 | u16* decode_rm_word_register(x86emu_t *emu, int reg); 94 | u32* decode_rm_long_register(x86emu_t *emu, int reg); 95 | sel_t *decode_rm_seg_register(x86emu_t *emu, int reg); 96 | I128_reg_t* decode_rm_sse_register(x86emu_t *emu, int reg); 97 | u32 decode_rm00_address(x86emu_t *emu, int rm); 98 | u32 decode_rm01_address(x86emu_t *emu, int rm); 99 | u32 decode_rm10_address(x86emu_t *emu, int rm); 100 | u32 decode_sib_address(x86emu_t *emu, int sib, int mod); 101 | u32 decode_rm_address(x86emu_t *emu, int mod, int rl); 102 | 103 | void decode_hex(x86emu_t *emu, char **p, u32 ofs); 104 | void decode_hex1(x86emu_t *emu, char **p, u32 ofs); 105 | void decode_hex2(x86emu_t *emu, char **p, u32 ofs); 106 | void decode_hex4(x86emu_t *emu, char **p, u32 ofs); 107 | void decode_hex8(x86emu_t *emu, char **p, u32 ofs); 108 | void decode_hex32(x86emu_t *emu, char **p, I128_reg_t ofs); 109 | void decode_hex_addr(x86emu_t *emu, char **p, u32 ofs); 110 | void decode_hex2s(x86emu_t *emu, char **p, s32 ofs); 111 | void decode_hex4s(x86emu_t *emu, char **p, s32 ofs); 112 | void decode_hex8s(x86emu_t *emu, char **p, s32 ofs); 113 | 114 | void decode_descriptor(x86emu_t *emu, descr_t *d, u32 dl, u32 dh); 115 | 116 | void emu_process_debug(x86emu_t *emu, unsigned start, unsigned len); 117 | 118 | 119 | #ifdef __cplusplus 120 | } /* End of "C" linkage for C++ */ 121 | #endif 122 | 123 | #endif /* __X86EMU_DECODE_H */ 124 | -------------------------------------------------------------------------------- /include/prim_ops.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 1996-1999 SciTech Software, Inc. 6 | * Copyright (c) David Mosberger-Tang 7 | * Copyright (c) 1999 Egbert Eich 8 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 9 | * 10 | * ======================================================================== 11 | * 12 | * Permission to use, copy, modify, distribute, and sell this software and 13 | * its documentation for any purpose is hereby granted without fee, 14 | * provided that the above copyright notice appear in all copies and that 15 | * both that copyright notice and this permission notice appear in 16 | * supporting documentation, and that the name of the authors not be used 17 | * in advertising or publicity pertaining to distribution of the software 18 | * without specific, written prior permission. The authors makes no 19 | * representations about the suitability of this software for any purpose. 20 | * It is provided "as is" without express or implied warranty. 21 | * 22 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 23 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 24 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 25 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 26 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 27 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28 | * PERFORMANCE OF THIS SOFTWARE. 29 | * 30 | * ======================================================================== 31 | * 32 | * Description: 33 | * Header file for primitive operation functions. 34 | * 35 | ****************************************************************************/ 36 | 37 | 38 | #ifndef __X86EMU_PRIM_OPS_H 39 | #define __X86EMU_PRIM_OPS_H 40 | 41 | #ifdef __cplusplus 42 | extern "C" { /* Use "C" linkage when in C++ mode */ 43 | #endif 44 | 45 | u16 aaa_word (x86emu_t *emu, u16 d); 46 | u16 aas_word (x86emu_t *emu, u16 d); 47 | u16 aad_word (x86emu_t *emu, u16 d, u8 base); 48 | u16 aam_word (x86emu_t *emu, u8 d, u8 base); 49 | u8 adc_byte (x86emu_t *emu, u8 d, u8 s); 50 | u16 adc_word (x86emu_t *emu, u16 d, u16 s); 51 | u32 adc_long (x86emu_t *emu, u32 d, u32 s); 52 | u8 add_byte (x86emu_t *emu, u8 d, u8 s); 53 | u16 add_word (x86emu_t *emu, u16 d, u16 s); 54 | u32 add_long (x86emu_t *emu, u32 d, u32 s); 55 | u8 and_byte (x86emu_t *emu, u8 d, u8 s); 56 | u16 and_word (x86emu_t *emu, u16 d, u16 s); 57 | u32 and_long (x86emu_t *emu, u32 d, u32 s); 58 | u8 cmp_byte (x86emu_t *emu, u8 d, u8 s); 59 | u16 cmp_word (x86emu_t *emu, u16 d, u16 s); 60 | u32 cmp_long (x86emu_t *emu, u32 d, u32 s); 61 | u8 daa_byte (x86emu_t *emu, u8 d); 62 | u8 das_byte (x86emu_t *emu, u8 d); 63 | u8 dec_byte (x86emu_t *emu, u8 d); 64 | u16 dec_word (x86emu_t *emu, u16 d); 65 | u32 dec_long (x86emu_t *emu, u32 d); 66 | u8 inc_byte (x86emu_t *emu, u8 d); 67 | u16 inc_word (x86emu_t *emu, u16 d); 68 | u32 inc_long (x86emu_t *emu, u32 d); 69 | u8 or_byte (x86emu_t *emu, u8 d, u8 s); 70 | u16 or_word (x86emu_t *emu, u16 d, u16 s); 71 | u32 or_long (x86emu_t *emu, u32 d, u32 s); 72 | u8 neg_byte (x86emu_t *emu, u8 s); 73 | u16 neg_word (x86emu_t *emu, u16 s); 74 | u32 neg_long (x86emu_t *emu, u32 s); 75 | u8 not_byte (x86emu_t *emu, u8 s); 76 | u16 not_word (x86emu_t *emu, u16 s); 77 | u32 not_long (x86emu_t *emu, u32 s); 78 | u8 rcl_byte (x86emu_t *emu, u8 d, u8 s); 79 | u16 rcl_word (x86emu_t *emu, u16 d, u8 s); 80 | u32 rcl_long (x86emu_t *emu, u32 d, u8 s); 81 | u8 rcr_byte (x86emu_t *emu, u8 d, u8 s); 82 | u16 rcr_word (x86emu_t *emu, u16 d, u8 s); 83 | u32 rcr_long (x86emu_t *emu, u32 d, u8 s); 84 | u8 rol_byte (x86emu_t *emu, u8 d, u8 s); 85 | u16 rol_word (x86emu_t *emu, u16 d, u8 s); 86 | u32 rol_long (x86emu_t *emu, u32 d, u8 s); 87 | u8 ror_byte (x86emu_t *emu, u8 d, u8 s); 88 | u16 ror_word (x86emu_t *emu, u16 d, u8 s); 89 | u32 ror_long (x86emu_t *emu, u32 d, u8 s); 90 | u8 shl_byte (x86emu_t *emu, u8 d, u8 s); 91 | u16 shl_word (x86emu_t *emu, u16 d, u8 s); 92 | u32 shl_long (x86emu_t *emu, u32 d, u8 s); 93 | u8 shr_byte (x86emu_t *emu, u8 d, u8 s); 94 | u16 shr_word (x86emu_t *emu, u16 d, u8 s); 95 | u32 shr_long (x86emu_t *emu, u32 d, u8 s); 96 | u8 sar_byte (x86emu_t *emu, u8 d, u8 s); 97 | u16 sar_word (x86emu_t *emu, u16 d, u8 s); 98 | u32 sar_long (x86emu_t *emu, u32 d, u8 s); 99 | u16 shld_word (x86emu_t *emu, u16 d, u16 fill, u8 s); 100 | u32 shld_long (x86emu_t *emu, u32 d, u32 fill, u8 s); 101 | u16 shrd_word (x86emu_t *emu, u16 d, u16 fill, u8 s); 102 | u32 shrd_long (x86emu_t *emu, u32 d, u32 fill, u8 s); 103 | u8 sbb_byte (x86emu_t *emu, u8 d, u8 s); 104 | u16 sbb_word (x86emu_t *emu, u16 d, u16 s); 105 | u32 sbb_long (x86emu_t *emu, u32 d, u32 s); 106 | u8 sub_byte (x86emu_t *emu, u8 d, u8 s); 107 | u16 sub_word (x86emu_t *emu, u16 d, u16 s); 108 | u32 sub_long (x86emu_t *emu, u32 d, u32 s); 109 | void test_byte (x86emu_t *emu, u8 d, u8 s); 110 | void test_word (x86emu_t *emu, u16 d, u16 s); 111 | void test_long (x86emu_t *emu, u32 d, u32 s); 112 | u8 xor_byte (x86emu_t *emu, u8 d, u8 s); 113 | u16 xor_word (x86emu_t *emu, u16 d, u16 s); 114 | u32 xor_long (x86emu_t *emu, u32 d, u32 s); 115 | void imul_byte (x86emu_t *emu, u8 s); 116 | void imul_word (x86emu_t *emu, u16 s); 117 | int imul_word_direct(u16 *res_lo, u16* res_hi, u16 d, u16 s); 118 | void imul_long (x86emu_t *emu, u32 s); 119 | int imul_long_direct(u32 *res_lo, u32* res_hi, u32 d, u32 s); 120 | void mul_byte (x86emu_t *emu, u8 s); 121 | void mul_word (x86emu_t *emu, u16 s); 122 | void mul_long (x86emu_t *emu, u32 s); 123 | void idiv_byte (x86emu_t *emu, u8 s); 124 | void idiv_word (x86emu_t *emu, u16 s); 125 | void idiv_long (x86emu_t *emu, u32 s); 126 | void div_byte (x86emu_t *emu, u8 s); 127 | void div_word (x86emu_t *emu, u16 s); 128 | void div_long (x86emu_t *emu, u32 s); 129 | void ins (x86emu_t *emu, int size); 130 | void outs (x86emu_t *emu, int size); 131 | void push_word (x86emu_t *emu, u16 w); 132 | void push_long (x86emu_t *emu, u32 w); 133 | u16 pop_word (x86emu_t *emu); 134 | u32 pop_long (x86emu_t *emu); 135 | int eval_condition(x86emu_t *emu, unsigned type); 136 | 137 | #ifdef __cplusplus 138 | } /* End of "C" linkage for C++ */ 139 | #endif 140 | 141 | #endif /* __X86EMU_PRIM_OPS_H */ 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # x86 emulation library 2 | 3 | libx86emu is a small library to emulate x86 instructions. The focus here is not a complete emulation (go for qemu for this) but to cover enough for typical firmware blobs. 4 | 5 | At the moment 'regular' 32-bit instructions are covered together with basic protected mode support. 6 | 7 | Not done are fpu, mmx, or any of the other instruction set extensions. 8 | 9 | The library lets you 10 | 11 | - intercept any memory access or directly map real memory ranges 12 | - intercept any i/o access, map real i/o ports, or block any real i/o 13 | - intercept any interrupt 14 | - provides hook to run after each instruction 15 | - recognizes a special x86 instruction that can trigger logging 16 | - has integrated logging to 17 | - trace code execution, including register content and decoded instruction 18 | - trace memory and i/o accesses 19 | - provide statistics about accessed memory locations, i/o ports, and interrupts 20 | 21 | ## Major versions 22 | 23 | Programs should generally work fine with newer library versions without any changes (except re-compiling). 24 | 25 | ### Version 3 26 | 27 | Extend API to include CPUID and MSR handlers. 28 | 29 | ### Version 2 30 | 31 | Essentially the same API as version 1. The major difference is that version 2 is re-entrant (no global state variable). 32 | 33 | ### Version 1 34 | 35 | Version 1 relies internally on a global variable `x86emu` holding the emulator state. It has been eliminated in version 2. 36 | 37 | ## Downloads 38 | 39 | Get the latest version from the [openSUSE Build Service](https://software.opensuse.org/package/libx86emu). 40 | 41 | ## Examples 42 | 43 | Have a look at this minimalistic [demo](demo/x86emu-demo.c) program. 44 | 45 | The library is used by [hwinfo](https://github.com/openSUSE/hwinfo) to emulate Video BIOS (VBE) calls. 46 | 47 | ## API functions 48 | 49 | ### x86emu_new 50 | 51 | Create new emulation object 52 | 53 | x86emu_t *x86emu_new(unsigned def_mem_perm, unsigned def_io_perm); 54 | 55 | def_mem_perm are the default permissions for memory accesses, def_io_perm for io. See 56 | x86emu_set_perm(), x86emu_set_io_perm(). 57 | 58 | Free object later with x86emu_done(). 59 | 60 | ### x86emu_done 61 | 62 | Delete emulation object 63 | 64 | x86emu_t *x86emu_done(x86emu_t *emu); 65 | 66 | Frees all memory; returns NULL; 67 | 68 | ### x86emu_clone 69 | 70 | Clone emulation object 71 | 72 | x86emu_t *x86emu_clone(x86emu_t *emu); 73 | 74 | Creates a copy of emu. Free the copy later with x86emu_done(). 75 | 76 | ### x86emu_reset 77 | 78 | Reset cpu state 79 | 80 | void x86emu_reset(x86emu_t *emu); 81 | 82 | Does a normal cpu reset (clear registers, set cs:eip). 83 | 84 | ### x86emu_run 85 | 86 | Start emulation 87 | 88 | unsigned x86emu_run(x86emu_t *emu, unsigned flags); 89 | 90 | Flags: 91 | 92 | X86EMU_RUN_TIMEOUT 93 | X86EMU_RUN_MAX_INSTR 94 | X86EMU_RUN_NO_EXEC 95 | X86EMU_RUN_NO_CODE 96 | X86EMU_RUN_LOOP 97 | 98 | * `X86EMU_RUN_TIMEOUT`: set `emu->timeout` to max. seconds to run. 99 | * `X86EMU_RUN_MAX_INSTR`: set `emu->max_instr` to max. instructions to emulate. 100 | 101 | Return value indicates why `x86emu_run()` stopped (see flags). 102 | 103 | ### x86emu_stop 104 | 105 | Stop emulation 106 | 107 | void x86emu_stop(x86emu_t *emu); 108 | 109 | Use this function in callbacks (e.g. interrupt handler) to tell the emulator 110 | to stop. The emulator returns from `x86emu_run()` when the current instruction 111 | has been finished. 112 | 113 | ### x86emu_set_log 114 | 115 | Set log buffer 116 | 117 | void x86emu_set_log(x86emu_t *emu, char *buffer, unsigned buffer_size, x86emu_flush_func_t flush); 118 | typedef void (* x86emu_flush_func_t)(x86emu_t *emu, char *buf, unsigned size); 119 | 120 | If the log buffer is full, `flush()` is called (if not NULL). The buffer is freed in `x86emu_done()`. 121 | 122 | The log buffer must be larger than 1024 bytes. 123 | 124 | ### x86emu_log 125 | 126 | Write to log 127 | 128 | void x86emu_log(x86emu_t *emu, const char *format, ...) __attribute__ ((format (printf, 1, 2))); 129 | 130 | 131 | ### x86emu_clear_log 132 | 133 | Clear log 134 | 135 | unsigned x86emu_clear_log(x86emu_t *emu, int flush); 136 | 137 | Clear log buffer. If flush != 0, write current log via flush() function (see x86emu_set_log()). 138 | 139 | Returns buffer size. 140 | 141 | ### x86emu_dump 142 | 143 | Dump emulator state 144 | 145 | void x86emu_dump(x86emu_t *emu, int flags); 146 | 147 | Flags: 148 | 149 | X86EMU_DUMP_REGS 150 | X86EMU_DUMP_MEM 151 | X86EMU_DUMP_ACC_MEM 152 | X86EMU_DUMP_INV_MEM 153 | X86EMU_DUMP_ATTR 154 | X86EMU_DUMP_ASCII 155 | X86EMU_DUMP_IO 156 | X86EMU_DUMP_INTS 157 | X86EMU_DUMP_TIME 158 | 159 | Writes emulator state to log. 160 | 161 | ### x86emu_set_perm 162 | 163 | Memory permissions 164 | 165 | void x86emu_set_perm(x86emu_t *emu, unsigned start, unsigned end, unsigned perm); 166 | 167 | `perm` is a bitmask of: 168 | 169 | X86EMU_PERM_R 170 | X86EMU_PERM_W 171 | X86EMU_PERM_X 172 | X86EMU_PERM_VALID 173 | X86EMU_ACC_R 174 | X86EMU_ACC_W 175 | X86EMU_ACC_X 176 | X86EMU_ACC_INVALID 177 | 178 | * `X86EMU_PERM_{R,W,X}`: memory is readable, writable, executable 179 | * `X86EMU_PERM_VALID`: memory has been initialized (say, been written to) 180 | * `X86EMU_ACC_{R,W,X}`: memory has been read, written, executed 181 | * `X86EMU_ACC_INVALID`: there was an invalid access (e.g. tried to read but not readable) 182 | 183 | ### x86emu_set_page 184 | 185 | Direct memory access 186 | 187 | void x86emu_set_page(x86emu_t *emu, unsigned offset, void *address); 188 | 189 | Map memory area of `X86EMU_PAGE_SIZE` size at address into emulator at offset. offset 190 | must be `X86EMU_PAGE_SIZE` aligned, address needs not. 191 | 192 | Memory permissions still apply (via `x86emu_set_perm()`). 193 | 194 | If address is NULL, switch back to emulated memory. 195 | 196 | ### x86emu_set_io_perm 197 | 198 | io permissions 199 | 200 | void x86emu_set_io_perm(x86emu_t *emu, unsigned start, unsigned end, unsigned perm); 201 | 202 | `perm`: see `x86emu_set_perm()`. 203 | 204 | ### x86emu_reset_access_stats 205 | 206 | Reset memory access statistics 207 | 208 | void x86emu_reset_access_stats(x86emu_t *emu); 209 | 210 | Resets the `X86EMU_ACC_*` bits for the whole memory (see `x86emu_set_perm()`). 211 | 212 | ### x86emu_set_code_handler 213 | 214 | Execution hook 215 | 216 | x86emu_code_handler_t x86emu_set_code_handler(x86emu_t *emu, x86emu_code_handler_t handler); 217 | typedef int (* x86emu_code_handler_t)(x86emu_t *emu); 218 | 219 | If defined, the function is called before a new instruction is decoded and 220 | emulated. If logging is enabled the current cpu state has already been 221 | logged. If the function returns a value != 0, the emulation is stopped. 222 | 223 | ### x86emu_set_intr_handler 224 | 225 | Set interrupt handler 226 | 227 | x86emu_intr_handler_t x86emu_set_intr_handler(x86emu_t *emu, x86emu_intr_handler_t handler); 228 | typedef int (* x86emu_intr_handler_t)(x86emu_t *emu, u8 num, unsigned type); 229 | 230 | type: 231 | 232 | INTR_TYPE_SOFT 233 | INTR_TYPE_FAULT 234 | 235 | and bitmask of: 236 | 237 | INTR_MODE_RESTART 238 | INTR_MODE_ERRCODE 239 | 240 | If defined, the interrupt handler is called at the start of the interrupt 241 | handling procedure. The handler should return 1 to indicate the interrupt 242 | handling is complete and the emulator can skip its own interrupt processing 243 | or 0 to indicate the emulator should continue with normal interrupt processing. 244 | 245 | ### x86emu_set_memio_handler 246 | 247 | Set alternative callback function that handles memory and io accesses 248 | 249 | x86emu_memio_handler_t x86emu_set_memio_handler(x86emu_t *emu, x86emu_memio_handler_t handler); 250 | 251 | typedef unsigned (* x86emu_memio_handler_t)(x86emu_t *emu, u32 addr, u32 *val, unsigned type); 252 | 253 | type: one of 254 | 255 | X86EMU_MEMIO_8 256 | X86EMU_MEMIO_16 257 | X86EMU_MEMIO_32 258 | X86EMU_MEMIO_8_NOPERM 259 | 260 | and one of: 261 | 262 | X86EMU_MEMIO_R 263 | X86EMU_MEMIO_W 264 | X86EMU_MEMIO_X 265 | X86EMU_MEMIO_I 266 | X86EMU_MEMIO_O 267 | 268 | Returns old function. 269 | 270 | ### x86emu_set_cpuid_handler 271 | 272 | Execution hook 273 | 274 | x86emu_cpuid_handler_t x86emu_set_cpuid_handler(x86emu_t *emu, x86emu_cpuid_handler_t handler); 275 | typedef void (* x86emu_cpuid_handler_t)(x86emu_t *emu); 276 | 277 | Set a callback function that handles the CPUID instruction. 278 | Allows the user to use the host's CPUID or provide a custom implementation 279 | to emulate a specific CPU. 280 | 281 | Returns old function. 282 | 283 | There's no default implementation. Without the handler installed the programm 284 | will raise an #UD exception. 285 | 286 | ### x86emu_set_rdmsr_handler 287 | 288 | Execution hook 289 | 290 | x86emu_rdmsr_handler_t x86emu_set_rdmsr_handler(x86emu_t *emu, x86emu_rdmsr_handler_t handler); 291 | typedef void (* x86emu_rdmsr_handler_t)(struct x86emu_s *); 292 | 293 | Set alternative callback function that handles the RDMSR instruction. 294 | Allows the user to use the host's MSR or provide a custom implementation 295 | to emulate a specific platform. 296 | 297 | Returns old function. 298 | 299 | The default callback function uses the *msr* array in the *x86emu_t* structure 300 | to read MSRs from and updates the *msr_perm* array. 301 | 302 | ### x86emu_set_wrmsr_handler 303 | 304 | Execution hook 305 | 306 | x86emu_wrmsr_handler_t x86emu_set_wrmsr_handler(x86emu_t *emu, x86emu_wrmsr_handler_t handler); 307 | typedef void (* x86emu_wrmsr_handler_t)(struct x86emu_s *); 308 | 309 | Set alternative callback function that handles the WRMSR instruction. 310 | Allows the user to use the host's MSR or provide a custom implementation 311 | to emulate a specific platform. 312 | 313 | Returns old function. 314 | 315 | The default callback function uses the *msr* array in the *x86emu_t* structure 316 | to write MSRs to and updates the *msr_perm* array. 317 | 318 | ### x86emu_intr_raise 319 | 320 | Raise an interrupt 321 | 322 | void x86emu_intr_raise(x86emu_t *emu, u8 intr_nr, unsigned type, unsigned err); 323 | 324 | The interrupt is handled before the next instruction. For type see 325 | `x86emu_set_intr_func()`; if `INTR_MODE_ERRCODE` is set, err is the error 326 | code pushed to the stack. 327 | 328 | ### memory access functions 329 | 330 | unsigned x86emu_read_byte(x86emu_t *emu, unsigned addr); 331 | unsigned x86emu_read_byte_noperm(x86emu_t *emu, unsigned addr); 332 | unsigned x86emu_read_word(x86emu_t *emu, unsigned addr); 333 | unsigned x86emu_read_dword(x86emu_t *emu, unsigned addr); 334 | void x86emu_write_byte(x86emu_t *emu, unsigned addr, unsigned val); 335 | void x86emu_write_byte_noperm(x86emu_t *emu, unsigned addr, unsigned val); 336 | void x86emu_write_word(x86emu_t *emu, unsigned addr, unsigned val); 337 | void x86emu_write_dword(x86emu_t *emu, unsigned addr, unsigned val); 338 | 339 | Convenience functions to access emulator memory. Memory access restrictions 340 | (see `x86emu_set_perm()`) apply except for `x86emu_*_noperm()` which do not 341 | check permissions. 342 | 343 | ### x86emu_set_seg_register 344 | 345 | Set segment register 346 | 347 | void x86emu_set_seg_register(x86emu_t *emu, sel_t *seg, u16 val); 348 | R_CS_SEL, R_DS_SEL, R_ES_SEL, R_FS_SEL, R_GS_SEL, R_SS_SEL 349 | 350 | Example: 351 | 352 | x86emu_set_seg_register(emu, emu->x86.R_CS_SEL, 0x7c0); 353 | 354 | 355 | ## Debug instruction 356 | 357 | If the `X86EMU_TRACE_DEBUG` flags is set, the emulator interprets a special debug instruction: 358 | 359 | db 0x67, 0xeb, LEN, DATA... 360 | 361 | which is basically a short jump with address size prefix (an instruction normally not 362 | used). LEN is the size of DATA. 363 | 364 | DATA can be: 365 | 366 | db 0x01 367 | db STRING 368 | 369 | Print STRING to log. STRING is not 0-zerminated. 370 | 371 | db 0x02 372 | dd flags 373 | 374 | Set trace flags. 375 | 376 | db 0x03 377 | dd flags 378 | 379 | Clear trace flags. 380 | 381 | db 0x04 382 | dd flags 383 | 384 | Dump emulator state. For flags, see `x86emu_dump()`. 385 | 386 | db 0x05 387 | 388 | Reset memory access stats. See `x86emu_reset_access_stats()`. 389 | 390 | ## openSUSE Development 391 | 392 | To build, simply run `make`. Install with `make install`. 393 | 394 | Basically every new commit into the master branch of the repository will be auto-submitted 395 | to all current SUSE products. No further action is needed except accepting the pull request. 396 | 397 | Submissions are managed by a SUSE internal [jenkins](https://jenkins.io) node in the InstallTools tab. 398 | 399 | Each time a new commit is integrated into the master branch of the repository, 400 | a new submit request is created to the openSUSE Build Service. The devel project 401 | is [system:install:head](https://build.opensuse.org/package/show/system:install:head/libx86emu). 402 | 403 | `*.changes` and version numbers are auto-generated from git commits, you don't have to worry about this. 404 | 405 | The spec file is maintained in the Build Service only. If you need to change it for the `master` branch, 406 | submit to the 407 | [devel project](https://build.opensuse.org/package/show/system:install:head/libx86emu) 408 | in the build service directly. 409 | 410 | Development happens exclusively in the `master` branch. The branch is used for all current products. 411 | 412 | You can find more information about the changes auto-generation and the 413 | tools used for jenkis submissions in the [linuxrc-devtools 414 | documentation](https://github.com/openSUSE/linuxrc-devtools#opensuse-development). 415 | -------------------------------------------------------------------------------- /test/prepare_test: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | 3 | use Getopt::Long; 4 | 5 | sub prepare; 6 | sub add_interrupt_table; 7 | sub print_listing; 8 | sub print_mem; 9 | sub print_regs; 10 | sub nr; 11 | sub seg_ofs; 12 | sub decode_descr; 13 | sub new_tmp_file; 14 | sub cleanup; 15 | 16 | END { cleanup } 17 | $SIG{INT} = \&cleanup; 18 | $SIG{TERM} = \&cleanup; 19 | 20 | $opt_save_temp = 0; 21 | 22 | GetOptions( 23 | 'save-temp' => \$opt_save_temp 24 | ); 25 | 26 | 27 | for $name (@ARGV) { 28 | prepare $name; 29 | } 30 | 31 | sub prepare 32 | { 33 | $file_name = shift; 34 | my ($section_name, $section, $line, $addr, $v, @i, $i); 35 | my ($asm, $bin, $start_cs, $start_eip, $bits, $listing); 36 | 37 | if(!open(F, $file_name)) { 38 | print STDERR "$file_name: $!\n"; 39 | return; 40 | } 41 | 42 | while(1) { 43 | $_ = ; 44 | chomp; 45 | next if /^\s*;/; 46 | $line = $_; 47 | if(/^\s*\[(\S*)(\s+(.*?))?\]/ || !defined($_)) { 48 | if(defined $_) { 49 | $section_name = $1; 50 | map { $section->{$section_name}{args}{$1} = $2 if /(.*)=(.*)/ } split ' ', $3; 51 | 52 | srand $section->{$section_name}{args}{srand} if exists $section->{$section_name}{args}{srand}; 53 | 54 | if($section_name eq 'init') { 55 | if( 56 | $section->{$section_name}{args}{mode} eq 'pm' || 57 | $section->{$section_name}{args}{mode} eq 'protected' 58 | ) { 59 | $section->{$section_name}{args}{mode} = 'protected'; 60 | $section->{$section_name}{regs}{cr0} = 1; 61 | } 62 | else { 63 | $section->{$section_name}{args}{mode} = 'real'; 64 | } 65 | } 66 | } 67 | 68 | if($asm) { 69 | print A "\n\thlt\n"; 70 | close A; 71 | $bin = new_tmp_file; 72 | $lst = new_tmp_file; 73 | $i = system "nasm -f bin -O99 -o $bin -l $lst $asm"; 74 | die "nasm failed\n" if $i; 75 | @{$section->{init}{listing}} = `ndisasm -o $start_eip -b $bits $bin`; 76 | # map { s/^(0000| )// } @{$section->{init}{listing}} if $bits == 16; 77 | map { s/^(.)/($1 eq ' ' ? " " : "cs:") . $1/e } @{$section->{init}{listing}}; 78 | add_interrupt_table $section, $lst; 79 | $i = `cat $bin`; 80 | if($section->{init}{regs}{cr0} & 1) { 81 | $addr = decode_descr($section, $start_cs)->{base}; 82 | } 83 | else { 84 | $addr = $start_cs << 4; 85 | } 86 | $addr += $start_eip; 87 | for $v (unpack "C*", $i) { 88 | $section->{init}{mem}{$addr++} = $v; 89 | } 90 | } 91 | 92 | last unless defined $_; 93 | 94 | next; 95 | } 96 | 97 | if($section_name eq 'init') { 98 | if(s/^\s*(\d\S+?)\s*-\s*(\d\S+?)\s*:\s*//) { 99 | undef $v; 100 | @i = split ' '; 101 | for ($addr = nr $1; $addr <= nr $2; $addr++) { 102 | $v = $i[0]; 103 | shift @i if @i > 1; 104 | $section->{$section_name}{mem}{$addr} = nr($v) & 0xff; 105 | } 106 | # print "$1 $2 >$_<\n"; 107 | } 108 | elsif(s/^\s*(\d\S*?)\s*:\s*//) { 109 | $addr = nr $1; 110 | map { $section->{$section_name}{mem}{$addr++} = nr($_) & 0xff } split ' '; 111 | # print "$1 >$_<\n"; 112 | } 113 | else { 114 | map { 115 | if(/(.+?)=(.*)/) { 116 | $r = $1; 117 | $v = $2; 118 | if($r =~ /^gdt\[(\S+)\]$/) { 119 | die "$file_name:$.: no gdb base set\n" unless exists $section->{$section_name}{regs}{'gdt.base'}; 120 | my $gdt_base = $section->{$section_name}{regs}{'gdt.base'}; 121 | $idx = nr $1; 122 | die "$file_name:$.: $idx: invalid gdt index\n" if $idx & 7; 123 | $gdt_base += $idx; 124 | if($v eq '0') { 125 | for ($i = 0; $i < 8; $i++) { 126 | $section->{$section_name}{mem}{$gdt_base + $i} = 0; 127 | } 128 | } 129 | else { 130 | die "$file_name:$.: invalid data: \"$_\"\n$line\n" unless $v =~ /^descr\((\S+)\)/; 131 | $v = $1; 132 | my $base = 0; 133 | my $limit = 0; 134 | my $acc = 0; 135 | for $vv (split /,/, $v) { 136 | if($vv =~ /(.+?)=(.*)/) { 137 | $base = nr $2 if $1 eq 'base'; 138 | $limit = nr $2 if $1 eq 'limit'; 139 | $acc = nr $2 if $1 eq 'acc'; 140 | } 141 | } 142 | die "$file_name:$.: invalid access rights\n" if ($acc & ~0xcff); 143 | if(($acc & 0x800)) { 144 | die "$file_name:$.: invalid limit\n" unless ($limit & 0xfff) == 0xfff; 145 | $limit >>= 12; 146 | $limit &= 0xfffff; 147 | } 148 | die "$file_name:$.: invalid limit\n" unless $limit <= 0xfffff; 149 | $section->{$section_name}{mem}{$gdt_base} = $limit & 0xff; 150 | $section->{$section_name}{mem}{$gdt_base + 1} = ($limit >> 8) & 0xff; 151 | $section->{$section_name}{mem}{$gdt_base + 2} = $base & 0xff; 152 | $section->{$section_name}{mem}{$gdt_base + 3} = ($base >> 8) & 0xff; 153 | $section->{$section_name}{mem}{$gdt_base + 4} = ($base >> 16) & 0xff; 154 | $section->{$section_name}{mem}{$gdt_base + 5} = $acc & 0xff; 155 | $section->{$section_name}{mem}{$gdt_base + 6} = (($acc >> 4) & 0xf0) + (($limit >> 16) & 0xf); 156 | $section->{$section_name}{mem}{$gdt_base + 7} = ($base >> 24) & 0xff; 157 | } 158 | } 159 | else { 160 | $section->{$section_name}{regs}{$r} = nr $v; 161 | } 162 | } 163 | else { 164 | die "$file_name:$.: invalid data: \"$_\"\n$line\n"; 165 | } 166 | } split ' '; 167 | } 168 | } 169 | elsif($section_name eq 'code') { 170 | if(! $asm) { 171 | ($start_cs, $start_eip) = seg_ofs $section->{$section_name}{args}{start}; 172 | $bits = nr $section->{$section_name}{args}{bits}; 173 | $bits = 16 if $bits != 16 && $bits != 32; 174 | $section->{init}{regs}{bits} = $bits; 175 | $section->{init}{args}{bits} = $bits; 176 | $section->{init}{regs}{eip} = $start_eip; 177 | $section->{init}{regs}{cs} = $start_cs; 178 | $asm = new_tmp_file; 179 | open A, ">$asm"; 180 | print A "\tsection .text\n\n"; 181 | print A "\tbits $bits\n\n"; 182 | print A "\torg $start_eip\n\n"; 183 | } 184 | print A "$_\n"; 185 | } 186 | } 187 | close F; 188 | 189 | ($i = $file_name) =~ s/\.tst$/.init/; 190 | open W, ">$i"; 191 | 192 | $section_name = 'init'; 193 | 194 | if(%{$section->{$section_name}{args}}) { 195 | print W "; " . 196 | join(', ', map "$_=$section->{$section_name}{args}{$_}", sort keys %{$section->{$section_name}{args}}) . 197 | "\n"; 198 | print W "\n"; 199 | } 200 | 201 | if($section->{$section_name}{listing}) { 202 | print_listing $section->{$section_name}{listing}; 203 | print W "\n"; 204 | } 205 | 206 | if($section->{$section_name}{mem}) { 207 | print_mem $section->{$section_name}{mem}; 208 | print W "\n"; 209 | } 210 | 211 | if($section->{$section_name}{regs}) { 212 | print_regs $section, $section->{$section_name}{regs}; 213 | print W "\n"; 214 | } 215 | 216 | close W; 217 | } 218 | 219 | 220 | sub add_interrupt_table 221 | { 222 | local $_; 223 | my (%int, $i, $eip, $org, $idt_base, $cs, $addr); 224 | my $section = shift; 225 | my $file = shift; 226 | 227 | open L, $file; 228 | 229 | while() { 230 | if(/^\s*(\S+)\s+interrupt_([0-9a-f]{2})(:|\s)/) { 231 | $i = $2; 232 | $_ = ; 233 | $int{$i} = $2 if(/^\s*(\S+)\s+(\S+)/); 234 | } 235 | elsif(/^\s*(\S+)\s+(\S+)\s+\S+\s+interrupt_([0-9a-f]{2})(:|\s)/) { 236 | $int{$3} = $2; 237 | } 238 | } 239 | 240 | close L; 241 | 242 | $idt_base = $section->{init}{regs}{'idt.base'}; 243 | $cs = $section->{init}{regs}{cs}; 244 | $org = $section->{init}{regs}{eip}; 245 | 246 | for (sort keys %int) { 247 | $i = nr "0x$_"; 248 | $eip = $org + nr "0x$int{$_}"; 249 | 250 | if($section->{init}{regs}{cr0} & 1) { 251 | $addr = 8*$i + $idt_base; 252 | 253 | } 254 | else { 255 | $addr = 4*$i + $idt_base; 256 | 257 | $section->{init}{mem}{$addr} = $eip & 0xff; 258 | $section->{init}{mem}{$addr+1} = ($eip >> 8) & 0xff; 259 | $section->{init}{mem}{$addr+2} = $cs & 0xff; 260 | $section->{init}{mem}{$addr+3} = ($cs >> 8) & 0xff; 261 | } 262 | } 263 | } 264 | 265 | 266 | sub print_listing 267 | { 268 | my $l = shift; 269 | local $_; 270 | 271 | for (@$l) { 272 | print W "; \L$1\E$2\n" if /^(\S+\s+\S+|\s+\-\S+)(.*)/; 273 | } 274 | } 275 | 276 | 277 | sub print_mem 278 | { 279 | my $mem = shift; 280 | my ($base_addr, $last_addr, $i); 281 | local $_; 282 | 283 | print W "; "; 284 | printf W " %x", $_ for (0..15); 285 | print W "\n"; 286 | 287 | for (sort { $a <=> $b } keys %{$mem}) { 288 | $i = $_ & ~0xf; 289 | if($i != $base_addr || !defined $base_addr) { 290 | print W "\n" if defined $base_addr; 291 | $base_addr = $i; 292 | $last_addr = $base_addr - 1; 293 | printf W "%08x:", $base_addr; 294 | } 295 | 296 | $i = $_ - $last_addr - 1; 297 | print W " " x $i; 298 | printf W " %02x", $mem->{$_}; 299 | 300 | $last_addr = $_; 301 | } 302 | print W "\n" if defined $last_addr; 303 | 304 | } 305 | 306 | 307 | sub print_regs 308 | { 309 | my $section = shift; 310 | my $regs = shift; 311 | my ($i, $rl, $w, $v); 312 | local $_; 313 | my @reg_list = ( 314 | 'cr0 cr1 cr2 cr3 cr4', 315 | 'dr0 dr1 dr2 dr3 dr6 dr7', 316 | '', 317 | 'gdt.base gdt.limit', 318 | 'idt.base idt.limit', 319 | 'tr ldt', 320 | '', 321 | 'cs ss ds es fs gs', 322 | '', 323 | 'eax ebx ecx edx', 324 | 'esi edi ebp esp', 325 | 'eip eflags' 326 | ); 327 | 328 | $regs->{'gdt.limit'} = 0xffff unless defined $regs->{'gdt.limit'}; 329 | $regs->{'idt.limit'} = 0xffff unless defined $regs->{'idt.limit'}; 330 | $regs->{'eflags'} = 2 unless defined $regs->{'eflags'}; 331 | 332 | for (qw (cs ss ds es fs gs)) { 333 | if($regs->{cr0} & 1) { 334 | $x = decode_descr $section, $regs->{$_}; 335 | $regs->{"$_.base"} = $x->{base} unless defined $regs->{"$_.base"}; 336 | $regs->{"$_.limit"} = $x->{limit} unless defined $regs->{"$_.limit"}; 337 | $regs->{"$_.acc"} = $x->{acc} unless defined $regs->{"$_.acc"}; 338 | 339 | if( 340 | $regs->{"$_.base"} != $x->{base} || 341 | $regs->{"$_.limit"} != $x->{limit} || 342 | $regs->{"$_.acc"} != $x->{acc} 343 | ) { 344 | die "$file_name: $_: selector cache does not match gdt\n"; 345 | } 346 | 347 | } 348 | else { 349 | $regs->{"$_.base"} = $regs->{$_} << 4 unless defined $regs->{"$_.base"}; 350 | $regs->{"$_.limit"} = 0xffff unless defined $regs->{"$_.limit"}; 351 | if(!defined $regs->{"$_.acc"}) { 352 | $regs->{"$_.acc"} = $_ eq 'cs' ? 0x9b : 0x93; 353 | $regs->{"$_.acc"} |= 0x400 if ($_ eq 'cs' || $_ eq 'ss') && $regs->{bits} == 32; 354 | if($regs->{"$_.limit"} & ~0xfffff) { 355 | $regs->{"$_.limit"} |= 0xfff; 356 | $regs->{"$_.acc"} |= 0x800; 357 | } 358 | } 359 | } 360 | } 361 | 362 | for $rl (@reg_list) { 363 | $i = 0; 364 | if($rl eq '') { 365 | print W "\n"; 366 | next; 367 | } 368 | for (split ' ', $rl) { 369 | $v = $regs->{$_} + 0; 370 | if(/^(cs|ds|es|fs|gs|ss|tr|ldt)$/) { 371 | print W "\n" if $i; 372 | printf W "%s=%04x %s.base=%08x %s.limit=%08x %s.acc=%04x", 373 | $_, $regs->{$_}, 374 | $_, $regs->{"$_.base"}, 375 | $_, $regs->{"$_.limit"}, 376 | $_, $regs->{"$_.acc"}; 377 | } 378 | else { 379 | $w = /^(gdt\.limit|idt\.limit)$/ ? 4 : 8; 380 | printf W "%s%s=%0${w}x", $i ? ' ' : '', $_, $regs->{$_}; 381 | if($_ eq 'eflags') { 382 | my $f = $regs->{$_}; 383 | my $d; 384 | 385 | $d .= " of" if $f & 0x800; 386 | $d .= " df" if $f & 0x400; 387 | $d .= " if" if $f & 0x200; 388 | $d .= " sf" if $f & 0x080; 389 | $d .= " zf" if $f & 0x040; 390 | $d .= " af" if $f & 0x010; 391 | $d .= " pf" if $f & 0x004; 392 | $d .= " cf" if $f & 0x001; 393 | 394 | printf W " ;$d" if $d; 395 | } 396 | } 397 | $i++; 398 | } 399 | print W "\n" if $i; 400 | } 401 | } 402 | 403 | 404 | sub nr 405 | { 406 | my $n = shift; 407 | my $foo; 408 | 409 | if($n ne 'rand') { 410 | $n = oct $n if $n =~ /^0/; 411 | return $n + 0; 412 | } 413 | 414 | $n = ((int rand 0x1000000) & 0xffff00) << 8; 415 | $n += int((rand 0x1000000) / 11); 416 | 417 | # Limit the result to a 32 bit number but avoid '&' to ensure it works 418 | # with 32 bit perl. 419 | return $n % 2 ** 32; 420 | } 421 | 422 | 423 | sub seg_ofs 424 | { 425 | my @n = split /:/, $_[0]; 426 | 427 | $n[0] = nr $n[0]; 428 | $n[1] = nr $n[1] if @n > 1; 429 | 430 | unshift @n, undef if @n <= 1; 431 | 432 | return @n; 433 | } 434 | 435 | 436 | sub decode_descr 437 | { 438 | my ($i, $gdt, $base, $limit, $acc); 439 | my $section = shift; 440 | my $sel = shift; 441 | 442 | die "$file_name: no gdt\n" unless exists $section->{init}{regs}{'gdt.base'}; 443 | $gdt = $section->{init}{regs}{'gdt.base'} + ($sel & ~7); 444 | 445 | die "$file_name: selector $sel not in gdt\n" if $sel & 4; 446 | 447 | for ($i = 0; $i < 8; $i++) { 448 | die "$file_name: selector $sel not found\n" unless defined $section->{init}{mem}{$gdt + $i}; 449 | } 450 | 451 | $base = 452 | $section->{init}{mem}{$gdt + 2} + 453 | ($section->{init}{mem}{$gdt + 3} << 8) + 454 | ($section->{init}{mem}{$gdt + 4} << 16) + 455 | ($section->{init}{mem}{$gdt + 7} << 24); 456 | 457 | $limit = 458 | $section->{init}{mem}{$gdt} + 459 | ($section->{init}{mem}{$gdt + 1} << 8) + 460 | (($section->{init}{mem}{$gdt + 6} & 0xf) << 16); 461 | 462 | $acc = 463 | $section->{init}{mem}{$gdt + 5} + 464 | (($section->{init}{mem}{$gdt + 6} & 0xf0) << 4); 465 | 466 | $limit = ($limit << 12) + 0xfff if $acc & 0x800; 467 | 468 | return { base => $base, limit => $limit, acc => $acc }; 469 | } 470 | 471 | 472 | sub new_tmp_file 473 | { 474 | local $_; 475 | 476 | chomp ($_ = `mktemp /tmp/x86test.XXXXXXXXXX`); 477 | die "error: mktemp failed\n" if $?; 478 | 479 | push @tmp_files, $_; 480 | 481 | return $_; 482 | } 483 | 484 | 485 | sub cleanup 486 | { 487 | unlink @tmp_files unless $opt_save_temp; 488 | undef @tmp_files; 489 | } 490 | 491 | 492 | -------------------------------------------------------------------------------- /test/x86test.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 6 | * 7 | * ======================================================================== 8 | * 9 | * Permission to use, copy, modify, distribute, and sell this software and 10 | * its documentation for any purpose is hereby granted without fee, 11 | * provided that the above copyright notice appear in all copies and that 12 | * both that copyright notice and this permission notice appear in 13 | * supporting documentation, and that the name of the authors not be used 14 | * in advertising or publicity pertaining to distribution of the software 15 | * without specific, written prior permission. The authors makes no 16 | * representations about the suitability of this software for any purpose. 17 | * It is provided "as is" without express or implied warranty. 18 | * 19 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 20 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 21 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 22 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 23 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 24 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 25 | * PERFORMANCE OF THIS SOFTWARE. 26 | * 27 | * ======================================================================== 28 | * 29 | * Description: 30 | * Program to run test suite. 31 | * 32 | ****************************************************************************/ 33 | 34 | 35 | #define _GNU_SOURCE 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | typedef struct { 49 | x86emu_t *emu; 50 | } vm_t; 51 | 52 | 53 | void lprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); 54 | void flush_log(x86emu_t *emu, char *buf, unsigned size); 55 | 56 | void help(void); 57 | int do_int(x86emu_t *emu, u8 num, unsigned type); 58 | char *skip_spaces(char *s); 59 | vm_t *vm_new(void); 60 | void vm_free(vm_t *vm); 61 | int vm_init(vm_t *vm, char *file); 62 | void vm_run(vm_t *vm); 63 | void vm_dump(vm_t *vm, char *file); 64 | 65 | char *build_file_name(char *file, char *suffix); 66 | int result_cmp(char *file); 67 | int run_test(char *file); 68 | 69 | 70 | struct option options[] = { 71 | { "help", 0, NULL, 'h' }, 72 | { "verbose", 0, NULL, 'v' }, 73 | { "show", 1, NULL, 1001 }, 74 | { "max", 1, NULL, 1003 }, 75 | { "stderr", 0, NULL, 1004 }, 76 | { } 77 | }; 78 | 79 | struct { 80 | unsigned verbose; 81 | unsigned inst_max; 82 | 83 | unsigned trace_flags; 84 | unsigned dump_flags; 85 | 86 | struct { 87 | unsigned print_to_stderr:1; 88 | } show; 89 | 90 | FILE *log_file; 91 | } opt; 92 | 93 | 94 | int main(int argc, char **argv) 95 | { 96 | int i, err = 0; 97 | char *s, *t; 98 | unsigned u, tbits, dbits; 99 | 100 | opterr = 0; 101 | 102 | while((i = getopt_long(argc, argv, "hv", options, NULL)) != -1) { 103 | switch(i) { 104 | case 'v': 105 | opt.verbose++; 106 | break; 107 | 108 | case 1001: 109 | for(s = optarg; (t = strsep(&s, ",")); ) { 110 | u = 1; 111 | tbits = dbits = 0; 112 | while(*t == '+' || *t == '-') u = *t++ == '+' ? 1 : 0; 113 | if(!strcmp(t, "trace")) tbits = X86EMU_TRACE_DEFAULT; 114 | else if(!strcmp(t, "code")) tbits = X86EMU_TRACE_CODE; 115 | else if(!strcmp(t, "regs")) tbits = X86EMU_TRACE_REGS; 116 | else if(!strcmp(t, "data")) tbits = X86EMU_TRACE_DATA; 117 | else if(!strcmp(t, "acc")) tbits = X86EMU_TRACE_ACC; 118 | else if(!strcmp(t, "io")) tbits = X86EMU_TRACE_IO; 119 | else if(!strcmp(t, "ints")) tbits = X86EMU_TRACE_INTS; 120 | else if(!strcmp(t, "time")) tbits = X86EMU_TRACE_TIME; 121 | else if(!strcmp(t, "attr")) dbits = X86EMU_DUMP_ATTR; 122 | else if(!strcmp(t, "ascii")) dbits = X86EMU_DUMP_ASCII; 123 | else err = 5; 124 | if(err) { 125 | fprintf(stderr, "error: invalid flag '%s'\n", t); 126 | return 1; 127 | } 128 | else { 129 | if(tbits) { 130 | if(u) { 131 | opt.trace_flags |= tbits; 132 | } 133 | else { 134 | opt.trace_flags &= ~tbits; 135 | } 136 | } 137 | if(dbits) { 138 | if(u) { 139 | opt.dump_flags |= dbits; 140 | } 141 | else { 142 | opt.dump_flags &= ~dbits; 143 | } 144 | } 145 | } 146 | } 147 | break; 148 | 149 | case 1003: 150 | opt.inst_max = strtoul(optarg, NULL, 0); 151 | break; 152 | 153 | case 1004: 154 | opt.show.print_to_stderr = 1; 155 | break; 156 | 157 | default: 158 | help(); 159 | return i == 'h' ? 0 : 1; 160 | } 161 | } 162 | 163 | argc -= optind; 164 | argv += optind; 165 | 166 | if(!argc) { 167 | help(); 168 | 169 | return 1; 170 | } 171 | 172 | 173 | do { 174 | err |= run_test(argv[0]); 175 | } 176 | while(argv++, --argc); 177 | 178 | return err; 179 | } 180 | 181 | 182 | void lprintf(const char *format, ...) 183 | { 184 | va_list args; 185 | 186 | va_start(args, format); 187 | if(opt.log_file) vfprintf(opt.log_file, format, args); 188 | va_end(args); 189 | } 190 | 191 | 192 | void flush_log(x86emu_t *emu, char *buf, unsigned size) 193 | { 194 | if(!buf || !size || !opt.log_file) return; 195 | 196 | fwrite(buf, size, 1, opt.log_file); 197 | } 198 | 199 | 200 | void help() 201 | { 202 | fprintf(stderr, 203 | "libx86 Test\nusage: x86test test_file\n" 204 | ); 205 | } 206 | 207 | 208 | int do_int(x86emu_t *emu, u8 num, unsigned type) 209 | { 210 | if((type & 0xff) == INTR_TYPE_FAULT) { 211 | x86emu_stop(emu); 212 | } 213 | 214 | return 0; 215 | } 216 | 217 | 218 | char *skip_spaces(char *s) 219 | { 220 | while(isspace(*s)) s++; 221 | 222 | return s; 223 | } 224 | 225 | 226 | vm_t *vm_new() 227 | { 228 | vm_t *vm; 229 | 230 | vm = calloc(1, sizeof *vm); 231 | 232 | vm->emu = x86emu_new(X86EMU_PERM_R | X86EMU_PERM_W | X86EMU_PERM_X, 0); 233 | vm->emu->private = vm; 234 | 235 | x86emu_set_log(vm->emu, 1000000, flush_log); 236 | x86emu_set_intr_handler(vm->emu, do_int); 237 | 238 | vm->emu->log.trace = opt.trace_flags; 239 | 240 | return vm; 241 | } 242 | 243 | 244 | void vm_free(vm_t *vm) 245 | { 246 | x86emu_done(vm->emu); 247 | free(vm); 248 | } 249 | 250 | 251 | int vm_init(vm_t *vm, char *file) 252 | { 253 | FILE *f; 254 | char buf[1024], *s, *s1, *s2; 255 | unsigned u, addr, line = 0; 256 | 257 | if(!vm || !file) return 1; 258 | 259 | if(!(f = fopen(file, "r"))) return 0; 260 | 261 | lprintf("- - - - - - - - initial vm state [%s] - - - - - - - -\n", file); 262 | 263 | while(fgets(buf, sizeof buf, f)) { 264 | lprintf("%s", buf); 265 | line++; 266 | if((s = strchr(buf, ';'))) *s = 0; 267 | s = skip_spaces(buf); 268 | if(*s == 0) continue; 269 | addr = strtoul(s, &s1, 16); 270 | if(s1 - s == 8 && *s1 == ':') { 271 | s = s1 + 1; 272 | while( 273 | isspace(s[0]) && isspace(s[1]) && 274 | ((isxdigit(s[2]) && isxdigit(s[3])) || (isspace(s[2]) && isspace(s[3]))) && 275 | !isxdigit(s[4]) 276 | ) { 277 | if(isxdigit(s[2])) x86emu_write_byte(vm->emu, addr, strtoul(s, NULL, 16)); 278 | 279 | addr++; 280 | s += 4; 281 | } 282 | } 283 | else { 284 | while((s1 = strchr(s, '='))) { 285 | u = strtoul(s1 + 1, &s2, 16); 286 | if(*s2 && !isspace(*s2)) { 287 | lprintf("%s:%u: invalid line:\n%s", file, line, buf); 288 | return 0; 289 | } 290 | s1++; 291 | if(!memcmp(s, "eax=", s1 - s)) vm->emu->x86.R_EAX = u; 292 | else if(!memcmp(s, "ebx=", s1 - s)) vm->emu->x86.R_EBX = u; 293 | else if(!memcmp(s, "ecx=", s1 - s)) vm->emu->x86.R_ECX = u; 294 | else if(!memcmp(s, "edx=", s1 - s)) vm->emu->x86.R_EDX = u; 295 | else if(!memcmp(s, "esi=", s1 - s)) vm->emu->x86.R_ESI = u; 296 | else if(!memcmp(s, "edi=", s1 - s)) vm->emu->x86.R_EDI = u; 297 | else if(!memcmp(s, "ebp=", s1 - s)) vm->emu->x86.R_EBP = u; 298 | else if(!memcmp(s, "esp=", s1 - s)) vm->emu->x86.R_ESP = u; 299 | else if(!memcmp(s, "eip=", s1 - s)) vm->emu->x86.R_EIP = u; 300 | else if(!memcmp(s, "eflags=", s1 - s)) vm->emu->x86.R_EFLG = u; 301 | else if(!memcmp(s, "cs=", s1 - s)) { 302 | vm->emu->x86.R_CS = u; 303 | vm->emu->x86.R_CS_BASE = vm->emu->x86.R_CS << 4; 304 | } 305 | else if(!memcmp(s, "ds=", s1 - s)) { 306 | vm->emu->x86.R_DS = u; 307 | vm->emu->x86.R_DS_BASE = vm->emu->x86.R_DS << 4; 308 | } 309 | else if(!memcmp(s, "es=", s1 - s)) { 310 | vm->emu->x86.R_ES = u; 311 | vm->emu->x86.R_ES_BASE = vm->emu->x86.R_ES << 4; 312 | } 313 | else if(!memcmp(s, "fs=", s1 - s)) { 314 | vm->emu->x86.R_FS = u; 315 | vm->emu->x86.R_FS_BASE = vm->emu->x86.R_FS << 4; 316 | } 317 | else if(!memcmp(s, "gs=", s1 - s)) { 318 | vm->emu->x86.R_GS = u; 319 | vm->emu->x86.R_GS_BASE = vm->emu->x86.R_GS << 4; 320 | } 321 | else if(!memcmp(s, "ss=", s1 - s)) { 322 | vm->emu->x86.R_SS = u; 323 | vm->emu->x86.R_SS_BASE = vm->emu->x86.R_SS << 4; 324 | } 325 | else if(!memcmp(s, "cs.base=", s1 - s)) vm->emu->x86.R_CS_BASE = u; 326 | else if(!memcmp(s, "ds.base=", s1 - s)) vm->emu->x86.R_DS_BASE = u; 327 | else if(!memcmp(s, "es.base=", s1 - s)) vm->emu->x86.R_ES_BASE = u; 328 | else if(!memcmp(s, "fs.base=", s1 - s)) vm->emu->x86.R_FS_BASE = u; 329 | else if(!memcmp(s, "gs.base=", s1 - s)) vm->emu->x86.R_GS_BASE = u; 330 | else if(!memcmp(s, "ss.base=", s1 - s)) vm->emu->x86.R_SS_BASE = u; 331 | else if(!memcmp(s, "cs.limit=", s1 - s)) vm->emu->x86.R_CS_LIMIT = u; 332 | else if(!memcmp(s, "ds.limit=", s1 - s)) vm->emu->x86.R_DS_LIMIT = u; 333 | else if(!memcmp(s, "es.limit=", s1 - s)) vm->emu->x86.R_ES_LIMIT = u; 334 | else if(!memcmp(s, "fs.limit=", s1 - s)) vm->emu->x86.R_FS_LIMIT = u; 335 | else if(!memcmp(s, "gs.limit=", s1 - s)) vm->emu->x86.R_GS_LIMIT = u; 336 | else if(!memcmp(s, "ss.limit=", s1 - s)) vm->emu->x86.R_SS_LIMIT = u; 337 | else if(!memcmp(s, "cs.acc=", s1 - s)) vm->emu->x86.R_CS_ACC = u; 338 | else if(!memcmp(s, "ds.acc=", s1 - s)) vm->emu->x86.R_DS_ACC = u; 339 | else if(!memcmp(s, "es.acc=", s1 - s)) vm->emu->x86.R_ES_ACC = u; 340 | else if(!memcmp(s, "fs.acc=", s1 - s)) vm->emu->x86.R_FS_ACC = u; 341 | else if(!memcmp(s, "gs.acc=", s1 - s)) vm->emu->x86.R_GS_ACC = u; 342 | else if(!memcmp(s, "ss.acc=", s1 - s)) vm->emu->x86.R_SS_ACC = u; 343 | else if(!memcmp(s, "tr=", s1 - s)) vm->emu->x86.R_TR = u; 344 | else if(!memcmp(s, "tr.base=", s1 - s)) vm->emu->x86.R_TR_BASE = u; 345 | else if(!memcmp(s, "tr.limit=", s1 - s)) vm->emu->x86.R_TR_LIMIT = u; 346 | else if(!memcmp(s, "tr.acc=", s1 - s)) vm->emu->x86.R_TR_ACC = u; 347 | else if(!memcmp(s, "ldt=", s1 - s)) vm->emu->x86.R_LDT = u; 348 | else if(!memcmp(s, "ldt.base=", s1 - s)) vm->emu->x86.R_LDT_BASE = u; 349 | else if(!memcmp(s, "ldt.limit=", s1 - s)) vm->emu->x86.R_LDT_LIMIT = u; 350 | else if(!memcmp(s, "ldt.acc=", s1 - s)) vm->emu->x86.R_LDT_ACC = u; 351 | else if(!memcmp(s, "gdt.base=", s1 - s)) vm->emu->x86.R_GDT_BASE = u; 352 | else if(!memcmp(s, "gdt.limit=", s1 - s)) vm->emu->x86.R_GDT_LIMIT = u; 353 | else if(!memcmp(s, "idt.base=", s1 - s)) vm->emu->x86.R_IDT_BASE = u; 354 | else if(!memcmp(s, "idt.limit=", s1 - s)) vm->emu->x86.R_IDT_LIMIT = u; 355 | else if(!memcmp(s, "cr0=", s1 - s)) vm->emu->x86.R_CR0 = u; 356 | else if(!memcmp(s, "cr1=", s1 - s)) vm->emu->x86.R_CR1 = u; 357 | else if(!memcmp(s, "cr2=", s1 - s)) vm->emu->x86.R_CR2 = u; 358 | else if(!memcmp(s, "cr3=", s1 - s)) vm->emu->x86.R_CR3 = u; 359 | else if(!memcmp(s, "cr4=", s1 - s)) vm->emu->x86.R_CR4 = u; 360 | else if(!memcmp(s, "dr0=", s1 - s)) vm->emu->x86.R_DR0 = u; 361 | else if(!memcmp(s, "dr1=", s1 - s)) vm->emu->x86.R_DR1 = u; 362 | else if(!memcmp(s, "dr2=", s1 - s)) vm->emu->x86.R_DR2 = u; 363 | else if(!memcmp(s, "dr3=", s1 - s)) vm->emu->x86.R_DR3 = u; 364 | else if(!memcmp(s, "dr6=", s1 - s)) vm->emu->x86.R_DR6 = u; 365 | else if(!memcmp(s, "dr7=", s1 - s)) vm->emu->x86.R_DR7 = u; 366 | else break; 367 | 368 | s = skip_spaces(s2); 369 | } 370 | s = skip_spaces(s); 371 | if(*s) { 372 | lprintf("%s:%u: invalid line:\n%s", file, line, buf); 373 | return 0; 374 | } 375 | } 376 | } 377 | 378 | lprintf("- - - - - - - - - - - - - - - -\n"); 379 | 380 | fclose(f); 381 | 382 | return 1; 383 | } 384 | 385 | 386 | void vm_run(vm_t *vm) 387 | { 388 | unsigned flags; 389 | 390 | // x86emu_set_perm(vm->emu, 0x1004, 0x1004, X86EMU_PERM_VALID | X86EMU_PERM_R); 391 | 392 | // x86emu_set_io_perm(vm->emu, 0, 0x3ff, X86EMU_PERM_R | X86EMU_PERM_W); 393 | // iopl(3); 394 | 395 | flags = X86EMU_RUN_LOOP | X86EMU_RUN_NO_CODE; 396 | 397 | if(opt.inst_max) { 398 | vm->emu->max_instr = opt.inst_max; 399 | flags |= X86EMU_RUN_MAX_INSTR; 400 | } 401 | x86emu_run(vm->emu, flags); 402 | 403 | x86emu_clear_log(vm->emu, 1); 404 | } 405 | 406 | 407 | void vm_dump(vm_t *vm, char *file) 408 | { 409 | FILE *old_log; 410 | 411 | old_log = opt.log_file; 412 | 413 | if(file) opt.log_file = fopen(file, "w"); 414 | 415 | if(opt.log_file) { 416 | x86emu_dump(vm->emu, 417 | X86EMU_DUMP_MEM | X86EMU_DUMP_REGS | (!file && opt.dump_flags ? opt.dump_flags : 0) 418 | ); 419 | x86emu_clear_log(vm->emu, 1); 420 | } 421 | 422 | if(file) fclose(opt.log_file); 423 | 424 | opt.log_file = old_log; 425 | } 426 | 427 | 428 | char *build_file_name(char *file, char *suffix) 429 | { 430 | int i; 431 | static char *s = NULL; 432 | 433 | free(s); 434 | s = NULL; 435 | 436 | if(!file || !suffix) return s; 437 | 438 | i = strlen(file); 439 | // 5 = strlen(".init") 440 | if(i >= 5 && !strcmp(file + i - 5, ".init")) { 441 | s = calloc(1, i - 5 + strlen(suffix) + 1); 442 | memcpy(s, file, i - 5); 443 | strcat(s, suffix); 444 | } 445 | else { 446 | asprintf(&s, "%s%s", file, suffix); 447 | } 448 | 449 | return s; 450 | } 451 | 452 | 453 | int result_cmp(char *file) 454 | { 455 | FILE *f0, *f1; 456 | int err = 1; 457 | unsigned char *buf0, *buf1; 458 | int i, l0, l1; 459 | 460 | f0 = fopen(build_file_name(file, ".result"), "r"); 461 | f1 = fopen(build_file_name(file, ".done"), "r"); 462 | 463 | if(!f1) err = 2; 464 | 465 | if(f0 && f1) { 466 | l0 = fseek(f0, 0, SEEK_END); 467 | l1 = fseek(f1, 0, SEEK_END); 468 | if(!l0 && !l1) { 469 | l0 = ftell(f0); 470 | l1 = ftell(f1); 471 | rewind(f0); 472 | rewind(f1); 473 | if(l0 && l0 == l1) { 474 | i = l0; 475 | buf0 = malloc(i); 476 | buf1 = malloc(i); 477 | l0 = fread(buf0, 1, i, f0); 478 | l1 = fread(buf1, 1, i, f1); 479 | if(l0 == i && l1 == i && !memcmp(buf0, buf1, i)) err = 0; 480 | free(buf1); 481 | free(buf0); 482 | } 483 | } 484 | } 485 | 486 | if(f1) fclose(f1); 487 | if(f0) fclose(f0); 488 | 489 | build_file_name(NULL, NULL); 490 | 491 | return err; 492 | } 493 | 494 | 495 | int run_test(char *file) 496 | { 497 | vm_t *vm = vm_new(); 498 | int ok = 0, result = 0; 499 | 500 | if(!file) return 1; 501 | 502 | opt.log_file = opt.show.print_to_stderr ? stderr : fopen(build_file_name(file, ".log"), "w"); 503 | 504 | ok = vm_init(vm, file); 505 | 506 | if(ok) { 507 | lprintf("%s: starting test\n", file); 508 | 509 | vm_run(vm); 510 | 511 | lprintf("\n- - - - - - - - final vm state - - - - - - - -\n"); 512 | vm_dump(vm, NULL); 513 | lprintf("- - - - - - - - - - - - - - - -\n"); 514 | 515 | vm_dump(vm, build_file_name(file, ".result")); 516 | } 517 | 518 | vm_free(vm); 519 | 520 | if(ok) { 521 | result = result_cmp(file); 522 | } 523 | else { 524 | result = 1; 525 | } 526 | 527 | lprintf("%s: %s\n", file, result == 0 ? "ok" : result == 1 ? "failed" : "unchecked"); 528 | fprintf(stderr, "%s %s\n", result == 0 ? "ok" : result == 1 ? "F " : "- ", file); 529 | 530 | fclose(opt.log_file); 531 | opt.log_file = NULL; 532 | 533 | build_file_name(NULL, NULL); 534 | 535 | return result == 1 ? 1 : 0; 536 | } 537 | 538 | 539 | -------------------------------------------------------------------------------- /api.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 6 | * 7 | * ======================================================================== 8 | * 9 | * Permission to use, copy, modify, distribute, and sell this software and 10 | * its documentation for any purpose is hereby granted without fee, 11 | * provided that the above copyright notice appear in all copies and that 12 | * both that copyright notice and this permission notice appear in 13 | * supporting documentation, and that the name of the authors not be used 14 | * in advertising or publicity pertaining to distribution of the software 15 | * without specific, written prior permission. The authors makes no 16 | * representations about the suitability of this software for any purpose. 17 | * It is provided "as is" without express or implied warranty. 18 | * 19 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 20 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 21 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 22 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 23 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 24 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 25 | * PERFORMANCE OF THIS SOFTWARE. 26 | * 27 | * ======================================================================== 28 | * 29 | * Description: 30 | * Public interface functions. 31 | * 32 | ****************************************************************************/ 33 | 34 | 35 | #include "include/x86emu_int.h" 36 | 37 | #define LINE_LEN 16 38 | 39 | static void x86emu_rdmsr(x86emu_t *emu) 40 | { 41 | unsigned u = emu->x86.R_ECX; 42 | 43 | emu->x86.R_EDX = emu->x86.msr[u] >> 32; 44 | emu->x86.R_EAX = emu->x86.msr[u]; 45 | emu->x86.msr_perm[u] |= X86EMU_ACC_R; 46 | } 47 | 48 | static void x86emu_wrmsr(x86emu_t *emu) 49 | { 50 | unsigned u = emu->x86.R_ECX; 51 | 52 | emu->x86.msr[u] = ((u64) emu->x86.R_EDX << 32) + emu->x86.R_EAX; 53 | emu->x86.msr_perm[u] |= X86EMU_ACC_W; 54 | } 55 | 56 | API_SYM x86emu_t *x86emu_new(unsigned def_mem_perm, unsigned def_io_perm) 57 | { 58 | x86emu_t *emu = calloc(1, sizeof *emu); 59 | 60 | emu->mem = emu_mem_new(def_mem_perm); 61 | 62 | emu->io.map = calloc(X86EMU_IO_PORTS, sizeof *emu->io.map); 63 | emu->io.stats_i = calloc(X86EMU_IO_PORTS, sizeof *emu->io.stats_i); 64 | emu->io.stats_o = calloc(X86EMU_IO_PORTS, sizeof *emu->io.stats_o); 65 | 66 | if(def_io_perm) x86emu_set_io_perm(emu, 0, X86EMU_IO_PORTS - 1, def_io_perm); 67 | 68 | x86emu_set_memio_handler(emu, vm_memio); 69 | x86emu_set_rdmsr_handler(emu, x86emu_rdmsr); 70 | x86emu_set_wrmsr_handler(emu, x86emu_wrmsr); 71 | 72 | x86emu_reset(emu); 73 | 74 | return emu; 75 | } 76 | 77 | 78 | API_SYM x86emu_t *x86emu_done(x86emu_t *emu) 79 | { 80 | if(emu) { 81 | emu_mem_free(emu->mem); 82 | 83 | free(emu->log.buf); 84 | 85 | free(emu->io.map); 86 | free(emu->io.stats_i); 87 | free(emu->io.stats_o); 88 | 89 | free(emu->x86.msr); 90 | free(emu->x86.msr_perm); 91 | 92 | free(emu); 93 | } 94 | 95 | return NULL; 96 | } 97 | 98 | 99 | API_SYM x86emu_t *x86emu_clone(x86emu_t *emu) 100 | { 101 | x86emu_t *new_emu = NULL; 102 | 103 | if(!emu) return new_emu; 104 | 105 | new_emu = mem_dup(emu, sizeof *emu); 106 | 107 | new_emu->mem = emu_mem_clone(emu->mem); 108 | 109 | if(emu->log.buf && emu->log.ptr) { 110 | new_emu->log.buf = malloc(emu->log.size); 111 | // copy only used log space 112 | if(emu->log.ptr <= emu->log.buf + emu->log.size) { 113 | new_emu->log.ptr = new_emu->log.buf + (emu->log.ptr - emu->log.buf); 114 | memcpy(new_emu->log.buf, emu->log.buf, emu->log.ptr - emu->log.buf); 115 | } 116 | } 117 | 118 | new_emu->io.map = mem_dup(emu->io.map, X86EMU_IO_PORTS * sizeof *emu->io.map); 119 | new_emu->io.stats_i = mem_dup(emu->io.stats_i, X86EMU_IO_PORTS * sizeof *emu->io.stats_i); 120 | new_emu->io.stats_o = mem_dup(emu->io.stats_o, X86EMU_IO_PORTS * sizeof *emu->io.stats_o); 121 | new_emu->x86.msr = mem_dup(emu->x86.msr, X86EMU_MSRS * sizeof *emu->x86.msr); 122 | new_emu->x86.msr_perm = mem_dup(emu->x86.msr_perm, X86EMU_MSRS * sizeof *emu->x86.msr_perm); 123 | 124 | return new_emu; 125 | } 126 | 127 | 128 | API_SYM void x86emu_reset(x86emu_t *emu) 129 | { 130 | x86emu_regs_t *x86 = &emu->x86; 131 | 132 | free(x86->msr); 133 | free(x86->msr_perm); 134 | 135 | memset(x86, 0, sizeof *x86); 136 | 137 | x86->R_EFLG = 2; 138 | 139 | x86->R_CS_LIMIT = x86->R_DS_LIMIT = x86->R_SS_LIMIT = x86->R_ES_LIMIT = 140 | x86->R_FS_LIMIT = x86->R_GS_LIMIT = 0xffff; 141 | 142 | // resp. 0x4093/9b for 4GB 143 | x86->R_CS_ACC = 0x9b; 144 | x86->R_SS_ACC = x86->R_DS_ACC = x86->R_ES_ACC = x86->R_FS_ACC = x86->R_GS_ACC = 0x93; 145 | 146 | x86->R_CS = 0xf000; 147 | x86->R_CS_BASE = 0xf0000; 148 | x86->R_EIP = 0xfff0; 149 | 150 | x86->R_GDT_LIMIT = 0xffff; 151 | x86->R_IDT_LIMIT = 0xffff; 152 | 153 | x86->msr = calloc(X86EMU_MSRS, sizeof *x86->msr); 154 | x86->msr_perm = calloc(X86EMU_MSRS, sizeof *x86->msr_perm); 155 | 156 | x86->msr_perm[0x10] = X86EMU_ACC_X; // tsc 157 | x86->msr_perm[0x11] = X86EMU_ACC_X; // last real tsc 158 | x86->msr_perm[0x12] = X86EMU_ACC_X; // real tsc 159 | } 160 | 161 | 162 | API_SYM x86emu_memio_handler_t x86emu_set_memio_handler(x86emu_t *emu, x86emu_memio_handler_t handler) 163 | { 164 | x86emu_memio_handler_t old = NULL; 165 | 166 | if(emu) { 167 | old = emu->memio; 168 | emu->memio = handler; 169 | } 170 | 171 | return old; 172 | } 173 | 174 | 175 | API_SYM x86emu_intr_handler_t x86emu_set_intr_handler(x86emu_t *emu, x86emu_intr_handler_t handler) 176 | { 177 | x86emu_intr_handler_t old = NULL; 178 | 179 | if(emu) { 180 | old = emu->intr; 181 | emu->intr = handler; 182 | } 183 | 184 | return old; 185 | } 186 | 187 | 188 | API_SYM x86emu_code_handler_t x86emu_set_code_handler(x86emu_t *emu, x86emu_code_handler_t handler) 189 | { 190 | x86emu_code_handler_t old = NULL; 191 | 192 | if(emu) { 193 | old = emu->code_check; 194 | emu->code_check = handler; 195 | } 196 | 197 | return old; 198 | } 199 | 200 | API_SYM x86emu_cpuid_handler_t x86emu_set_cpuid_handler(x86emu_t *emu, x86emu_cpuid_handler_t handler) 201 | { 202 | x86emu_cpuid_handler_t old = NULL; 203 | 204 | if(emu) { 205 | old = emu->cpuid; 206 | emu->cpuid = handler; 207 | } 208 | 209 | return old; 210 | } 211 | 212 | API_SYM x86emu_wrmsr_handler_t x86emu_set_wrmsr_handler(x86emu_t *emu, x86emu_wrmsr_handler_t handler) 213 | { 214 | x86emu_wrmsr_handler_t old = NULL; 215 | 216 | if(emu) { 217 | old = emu->wrmsr; 218 | emu->wrmsr = handler; 219 | } 220 | 221 | return old; 222 | } 223 | 224 | API_SYM x86emu_rdmsr_handler_t x86emu_set_rdmsr_handler(x86emu_t *emu, x86emu_rdmsr_handler_t handler) 225 | { 226 | x86emu_rdmsr_handler_t old = NULL; 227 | 228 | if(emu) { 229 | old = emu->rdmsr; 230 | emu->rdmsr = handler; 231 | } 232 | 233 | return old; 234 | } 235 | 236 | API_SYM unsigned x86emu_read_byte(x86emu_t *emu, unsigned addr) 237 | { 238 | u32 val = 0xff; 239 | 240 | if(emu) emu->memio(emu, addr, &val, X86EMU_MEMIO_R | X86EMU_MEMIO_8); 241 | 242 | return val; 243 | } 244 | 245 | 246 | API_SYM unsigned x86emu_read_byte_noperm(x86emu_t *emu, unsigned addr) 247 | { 248 | u32 val = 0xff; 249 | 250 | if(emu) emu->memio(emu, addr, &val, X86EMU_MEMIO_R | X86EMU_MEMIO_8_NOPERM); 251 | 252 | return val; 253 | } 254 | 255 | 256 | API_SYM unsigned x86emu_read_word(x86emu_t *emu, unsigned addr) 257 | { 258 | u32 val = 0xffff; 259 | 260 | if(emu) emu->memio(emu, addr, &val, X86EMU_MEMIO_R | X86EMU_MEMIO_16); 261 | 262 | return val; 263 | } 264 | 265 | 266 | API_SYM unsigned x86emu_read_dword(x86emu_t *emu, unsigned addr) 267 | { 268 | u32 val = 0xffffffff; 269 | 270 | if(emu) emu->memio(emu, addr, &val, X86EMU_MEMIO_R | X86EMU_MEMIO_32); 271 | 272 | return val; 273 | } 274 | 275 | 276 | API_SYM void x86emu_write_byte(x86emu_t *emu, unsigned addr, unsigned val) 277 | { 278 | u32 val32 = val; 279 | 280 | if(emu) emu->memio(emu, addr, &val32, X86EMU_MEMIO_W | X86EMU_MEMIO_8); 281 | } 282 | 283 | 284 | API_SYM void x86emu_write_byte_noperm(x86emu_t *emu, unsigned addr, unsigned val) 285 | { 286 | u32 val32 = val; 287 | 288 | if(emu) emu->memio(emu, addr, &val32, X86EMU_MEMIO_W | X86EMU_MEMIO_8_NOPERM); 289 | } 290 | 291 | 292 | API_SYM void x86emu_write_word(x86emu_t *emu, unsigned addr, unsigned val) 293 | { 294 | u32 val32 = val; 295 | 296 | if(emu) emu->memio(emu, addr, &val32, X86EMU_MEMIO_W | X86EMU_MEMIO_16); 297 | } 298 | 299 | 300 | API_SYM void x86emu_write_dword(x86emu_t *emu, unsigned addr, unsigned val) 301 | { 302 | u32 val32 = val; 303 | 304 | if(emu) emu->memio(emu, addr, &val32, X86EMU_MEMIO_W | X86EMU_MEMIO_32); 305 | } 306 | 307 | 308 | API_SYM void x86emu_set_log(x86emu_t *emu, unsigned buffer_size, x86emu_flush_func_t flush) 309 | { 310 | if(emu) { 311 | if(emu->log.buf) free(emu->log.buf); 312 | emu->log.size = buffer_size; 313 | emu->log.buf = buffer_size ? calloc(1, buffer_size) : NULL; 314 | emu->log.ptr = emu->log.buf; 315 | emu->log.flush = flush; 316 | } 317 | } 318 | 319 | 320 | API_SYM unsigned x86emu_clear_log(x86emu_t *emu, int flush) 321 | { 322 | if(flush && emu->log.flush) { 323 | if(emu->log.ptr && emu->log.ptr != emu->log.buf) { 324 | emu->log.flush(emu, emu->log.buf, emu->log.ptr - emu->log.buf); 325 | } 326 | } 327 | if((emu->log.ptr = emu->log.buf)) *emu->log.ptr = 0; 328 | 329 | return emu->log.ptr ? LOG_FREE(emu) : 0; 330 | } 331 | 332 | 333 | API_SYM void x86emu_log(x86emu_t *emu, const char *format, ...) 334 | { 335 | va_list args; 336 | int size, log_free; 337 | 338 | if(!emu || !emu->log.ptr) return; 339 | 340 | log_free = LOG_FREE(emu); 341 | 342 | va_start(args, format); 343 | size = vsnprintf(emu->log.ptr, log_free, format, args); 344 | va_end(args); 345 | 346 | /* not enough space, free log and try again */ 347 | if(size >= log_free) { 348 | log_free = x86emu_clear_log(emu, 1); 349 | va_start(args, format); 350 | size = vsnprintf(emu->log.ptr, log_free, format, args); 351 | va_end(args); 352 | } 353 | 354 | if(size < log_free) { 355 | emu->log.ptr += size; 356 | } 357 | else { 358 | *emu->log.ptr = 0; 359 | } 360 | } 361 | 362 | 363 | /* 364 | * flags: 365 | * bits 0-7: 366 | * 0: show all initialized memory 367 | * 1: show only accessed memory 368 | * 2: show only invalidly accessed memory 369 | * 370 | * bit 8: show ascii, too 371 | */ 372 | static void dump_data(x86emu_t *emu, unsigned char *data, unsigned char *attr, char *str_data, char *str_attr, int flags) 373 | { 374 | unsigned u, u1, flag_ascii; 375 | char c; 376 | int ok = 0; 377 | char *sd = str_data, *sa = str_attr; 378 | char *ascii = str_data + 4 * LINE_LEN + 2; 379 | 380 | flag_ascii = flags & 0x100; 381 | flags &= 0xff; 382 | 383 | for(u = 0; u < LINE_LEN; u++) { 384 | *str_data++ = (attr[u] & X86EMU_ACC_INVALID) ? '*' : ' '; 385 | if( 386 | (flags == 0 && (attr[u] & X86EMU_PERM_VALID)) || 387 | (flags == 1 && (attr[u] & (X86EMU_ACC_R | X86EMU_ACC_W | X86EMU_ACC_X | X86EMU_ACC_INVALID))) || 388 | (flags == 2 && (attr[u] & X86EMU_ACC_INVALID)) 389 | ) { 390 | ok = 1; 391 | decode_hex2(emu, &str_data, u1 = data[u]); 392 | 393 | c = (attr[u] & X86EMU_PERM_R) ? (attr[u] & X86EMU_ACC_R) ? 'R' : 'r' : ' '; 394 | *str_attr++ = c; 395 | c = (attr[u] & X86EMU_PERM_W) ? (attr[u] & X86EMU_ACC_W) ? 'W' : 'w' : ' '; 396 | *str_attr++ = c; 397 | c = (attr[u] & X86EMU_PERM_X) ? (attr[u] & X86EMU_ACC_X) ? 'X' : 'x' : ' '; 398 | *str_attr++ = c; 399 | 400 | if(u1 < 0x20 || u1 >= 0x7f) u1 = '.'; 401 | ascii[u] = u1; 402 | } 403 | else { 404 | *str_data++ = ' '; 405 | *str_data++ = ' '; 406 | 407 | *str_attr++ = ' '; 408 | *str_attr++ = ' '; 409 | *str_attr++ = ' '; 410 | 411 | ascii[u] = ' '; 412 | } 413 | *str_data++ = ' '; 414 | *str_attr++ = ' '; 415 | } 416 | 417 | if(ok) { 418 | if(flag_ascii) { 419 | str_data[0] = ' '; 420 | str_data[1] = ' '; 421 | str_data += 2 + LINE_LEN; 422 | } 423 | } 424 | else { 425 | str_data = sd; 426 | str_attr = sa; 427 | } 428 | 429 | *str_data = *str_attr = 0; 430 | 431 | while(str_data > sd && str_data[-1] == ' ') *--str_data = 0; 432 | while(str_attr > sa && str_attr[-1] == ' ') *--str_attr = 0; 433 | } 434 | 435 | 436 | API_SYM void x86emu_dump(x86emu_t *emu, int flags) 437 | { 438 | x86emu_mem_t *mem = emu->mem; 439 | mem2_pdir_t *pdir; 440 | mem2_ptable_t *ptable; 441 | mem2_page_t page; 442 | unsigned pdir_idx, u, u1, u2, addr; 443 | char str_data[LINE_LEN * 8], str_attr[LINE_LEN * 8], fbuf[64]; 444 | unsigned char def_data[LINE_LEN], def_attr[LINE_LEN]; 445 | int dump_flags; 446 | 447 | if( 448 | mem && 449 | mem->pdir && 450 | (flags & (X86EMU_DUMP_MEM | X86EMU_DUMP_ACC_MEM | X86EMU_DUMP_INV_MEM | X86EMU_DUMP_ATTR)) 451 | ) { 452 | x86emu_log(emu, "; - - memory\n"); 453 | x86emu_log(emu, "; "); 454 | for(u1 = 0; u1 < 16; u1++) x86emu_log(emu, "%4x", u1); 455 | x86emu_log(emu, "\n"); 456 | 457 | dump_flags = 0; 458 | if(flags & X86EMU_DUMP_INV_MEM) dump_flags = 2; 459 | if(flags & X86EMU_DUMP_ACC_MEM) dump_flags = 1; 460 | if(flags & X86EMU_DUMP_MEM) dump_flags = 0; 461 | if(flags & X86EMU_DUMP_ASCII) dump_flags |= 0x100; 462 | 463 | pdir = mem->pdir; 464 | for(pdir_idx = 0; pdir_idx < (1 << X86EMU_PDIR_BITS); pdir_idx++) { 465 | ptable = (*pdir)[pdir_idx]; 466 | if(!ptable) continue; 467 | for(u1 = 0; u1 < (1 << X86EMU_PTABLE_BITS); u1++) { 468 | page = (*ptable)[u1]; 469 | if(page.data) { 470 | for(u2 = 0; u2 < X86EMU_PAGE_SIZE; u2 += LINE_LEN) { 471 | memcpy(def_data, page.data + u2, LINE_LEN); 472 | if(page.attr) { 473 | memcpy(def_attr, page.attr + u2, LINE_LEN); 474 | } 475 | else { 476 | memset(def_attr, page.def_attr, LINE_LEN); 477 | } 478 | dump_data(emu, def_data, def_attr, str_data, str_attr, dump_flags); 479 | if(*str_data) { 480 | addr = (((pdir_idx << X86EMU_PTABLE_BITS) + u1) << X86EMU_PAGE_BITS) + u2; 481 | x86emu_log(emu, "%08x: %s\n", addr, str_data); 482 | if((flags & X86EMU_DUMP_ATTR)) x86emu_log(emu, " %s\n", str_attr); 483 | } 484 | } 485 | } 486 | } 487 | } 488 | 489 | x86emu_log(emu, "\n"); 490 | } 491 | 492 | if((flags & X86EMU_DUMP_IO)) { 493 | x86emu_log(emu, "; - - io accesses\n"); 494 | 495 | for(u = 0; u < X86EMU_IO_PORTS; u++) { 496 | if(emu->io.map[u] & (X86EMU_ACC_R | X86EMU_ACC_W | X86EMU_ACC_INVALID)) { 497 | x86emu_log(emu, 498 | "%04x: %c%c%c in=%08x out=%08x\n", 499 | u, 500 | (emu->io.map[u] & X86EMU_ACC_INVALID) ? '*' : ' ', 501 | (emu->io.map[u] & X86EMU_PERM_R) ? 'r' : ' ', 502 | (emu->io.map[u] & X86EMU_PERM_W) ? 'w' : ' ', 503 | emu->io.stats_i[u], emu->io.stats_o[u] 504 | ); 505 | } 506 | } 507 | 508 | x86emu_log(emu, "\n"); 509 | } 510 | 511 | if((flags & X86EMU_DUMP_INTS)) { 512 | x86emu_log(emu, "; - - interrupt statistics\n"); 513 | for(u1 = 0; u1 < 0x100; u1++) { 514 | if(emu->x86.intr_stats[u1]) x86emu_log(emu, "int %02x: %08x\n", u1, emu->x86.intr_stats[u1]); 515 | } 516 | 517 | x86emu_log(emu, "\n"); 518 | } 519 | 520 | if((flags & X86EMU_DUMP_REGS)) { 521 | x86emu_log(emu, "; - - registers\n"); 522 | 523 | for(u = u1 = 0; u < X86EMU_MSRS; u++) { 524 | if(u >= 0x11 && u <= 0x12 && !(flags & X86EMU_DUMP_TIME)) continue; 525 | if(emu->x86.msr_perm[u]) { 526 | u1 = 1; 527 | x86emu_log(emu, "msr[%04x] %c%c %016llx", 528 | u, 529 | (emu->x86.msr_perm[u] & X86EMU_ACC_R) ? 'r' : ' ', 530 | (emu->x86.msr_perm[u] & X86EMU_ACC_W) ? 'w' : ' ', 531 | (unsigned long long) emu->x86.msr[u] 532 | ); 533 | switch(u) { 534 | case 0x10: 535 | x86emu_log(emu, " ; tsc"); 536 | break; 537 | case 0x11: 538 | x86emu_log(emu, " ; real tsc (previous)"); 539 | break; 540 | case 0x12: 541 | x86emu_log(emu, " ; real tsc"); 542 | if(emu->x86.R_TSC) { 543 | x86emu_log(emu, ", ratio=%.2f", (double) emu->x86.R_REAL_TSC / emu->x86.R_TSC); 544 | } 545 | break; 546 | } 547 | x86emu_log(emu, "\n"); 548 | } 549 | } 550 | 551 | if(u1) x86emu_log(emu, "\n"); 552 | 553 | x86emu_log(emu, "cr0=%08x cr1=%08x cr2=%08x cr3=%08x cr4=%08x\n", 554 | emu->x86.R_CR0, emu->x86.R_CR1, emu->x86.R_CR2, emu->x86.R_CR3, emu->x86.R_CR4 555 | ); 556 | 557 | x86emu_log(emu, "dr0=%08x dr1=%08x dr2=%08x dr3=%08x dr6=%08x dr7=%08x\n\n", 558 | emu->x86.R_DR0, emu->x86.R_DR1, emu->x86.R_DR2, emu->x86.R_DR3, 559 | emu->x86.R_DR6, emu->x86.R_DR7 560 | ); 561 | 562 | x86emu_log(emu, 563 | "gdt.base=%08x gdt.limit=%04x\n", 564 | emu->x86.R_GDT_BASE, emu->x86.R_GDT_LIMIT 565 | ); 566 | 567 | x86emu_log(emu, 568 | "idt.base=%08x idt.limit=%04x\n", 569 | emu->x86.R_IDT_BASE, emu->x86.R_IDT_LIMIT 570 | ); 571 | 572 | x86emu_log(emu, 573 | "tr=%04x tr.base=%08x tr.limit=%08x tr.acc=%04x\n", 574 | emu->x86.R_TR, emu->x86.R_TR_BASE, emu->x86.R_TR_LIMIT, emu->x86.R_TR_ACC 575 | ); 576 | x86emu_log(emu, 577 | "ldt=%04x ldt.base=%08x ldt.limit=%08x ldt.acc=%04x\n\n", 578 | emu->x86.R_LDT, emu->x86.R_LDT_BASE, emu->x86.R_LDT_LIMIT, emu->x86.R_LDT_ACC 579 | ); 580 | 581 | x86emu_log(emu, 582 | "cs=%04x cs.base=%08x cs.limit=%08x cs.acc=%04x\n", 583 | emu->x86.R_CS, emu->x86.R_CS_BASE, emu->x86.R_CS_LIMIT, emu->x86.R_CS_ACC 584 | ); 585 | x86emu_log(emu, 586 | "ss=%04x ss.base=%08x ss.limit=%08x ss.acc=%04x\n", 587 | emu->x86.R_SS, emu->x86.R_SS_BASE, emu->x86.R_SS_LIMIT, emu->x86.R_SS_ACC 588 | ); 589 | x86emu_log(emu, 590 | "ds=%04x ds.base=%08x ds.limit=%08x ds.acc=%04x\n", 591 | emu->x86.R_DS, emu->x86.R_DS_BASE, emu->x86.R_DS_LIMIT, emu->x86.R_DS_ACC 592 | ); 593 | x86emu_log(emu, 594 | "es=%04x es.base=%08x es.limit=%08x es.acc=%04x\n", 595 | emu->x86.R_ES, emu->x86.R_ES_BASE, emu->x86.R_ES_LIMIT, emu->x86.R_ES_ACC 596 | ); 597 | x86emu_log(emu, 598 | "fs=%04x fs.base=%08x fs.limit=%08x fs.acc=%04x\n", 599 | emu->x86.R_FS, emu->x86.R_FS_BASE, emu->x86.R_FS_LIMIT, emu->x86.R_FS_ACC 600 | ); 601 | x86emu_log(emu, 602 | "gs=%04x gs.base=%08x gs.limit=%08x gs.acc=%04x\n\n", 603 | emu->x86.R_GS, emu->x86.R_GS_BASE, emu->x86.R_GS_LIMIT, emu->x86.R_GS_ACC 604 | ); 605 | x86emu_log(emu, "eax=%08x ebx=%08x ecx=%08x edx=%08x\n", 606 | emu->x86.R_EAX, emu->x86.R_EBX, emu->x86.R_ECX, emu->x86.R_EDX 607 | ); 608 | x86emu_log(emu, "esi=%08x edi=%08x ebp=%08x esp=%08x\n", 609 | emu->x86.R_ESI, emu->x86.R_EDI, emu->x86.R_EBP, emu->x86.R_ESP 610 | ); 611 | x86emu_log(emu, "eip=%08x eflags=%08x", emu->x86.R_EIP, emu->x86.R_EFLG); 612 | 613 | *fbuf = 0; 614 | if(emu->x86.R_EFLG & 0x800) strcat(fbuf, " of"); 615 | if(emu->x86.R_EFLG & 0x400) strcat(fbuf, " df"); 616 | if(emu->x86.R_EFLG & 0x200) strcat(fbuf, " if"); 617 | if(emu->x86.R_EFLG & 0x080) strcat(fbuf, " sf"); 618 | if(emu->x86.R_EFLG & 0x040) strcat(fbuf, " zf"); 619 | if(emu->x86.R_EFLG & 0x010) strcat(fbuf, " af"); 620 | if(emu->x86.R_EFLG & 0x004) strcat(fbuf, " pf"); 621 | if(emu->x86.R_EFLG & 0x001) strcat(fbuf, " cf"); 622 | 623 | if(*fbuf) x86emu_log(emu, " ;%s", fbuf); 624 | 625 | x86emu_log(emu, "\n\n"); 626 | } 627 | } 628 | 629 | -------------------------------------------------------------------------------- /include/x86emu.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * Realmode X86 Emulator Library 4 | * 5 | * Copyright (c) 1996-1999 SciTech Software, Inc. 6 | * Copyright (c) David Mosberger-Tang 7 | * Copyright (c) 1999 Egbert Eich 8 | * Copyright (c) 2007-2017 SUSE LINUX GmbH; Author: Steffen Winterfeldt 9 | * 10 | * ======================================================================== 11 | * 12 | * Permission to use, copy, modify, distribute, and sell this software and 13 | * its documentation for any purpose is hereby granted without fee, 14 | * provided that the above copyright notice appear in all copies and that 15 | * both that copyright notice and this permission notice appear in 16 | * supporting documentation, and that the name of the authors not be used 17 | * in advertising or publicity pertaining to distribution of the software 18 | * without specific, written prior permission. The authors makes no 19 | * representations about the suitability of this software for any purpose. 20 | * It is provided "as is" without express or implied warranty. 21 | * 22 | * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 23 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 24 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 25 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 26 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 27 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28 | * PERFORMANCE OF THIS SOFTWARE. 29 | * 30 | * ======================================================================== 31 | * 32 | * Description: 33 | * Header file for public interface functions. 34 | * 35 | * Applications linking against libx86emu should only include this header. 36 | * 37 | ****************************************************************************/ 38 | 39 | 40 | #ifndef __X86EMU_X86EMU_H 41 | #define __X86EMU_X86EMU_H 42 | 43 | #ifdef __cplusplus 44 | extern "C" { /* Use "C" linkage when in C++ mode */ 45 | #endif 46 | 47 | #include 48 | 49 | 50 | /*---------------------- Macros and type definitions ----------------------*/ 51 | 52 | #define u8 uint8_t 53 | #define u16 uint16_t 54 | #define u32 uint32_t 55 | #define u64 uint64_t 56 | #define s8 int8_t 57 | #define s16 int16_t 58 | #define s32 int32_t 59 | #define s64 int64_t 60 | 61 | #define FP_SP_SIZE 4 62 | #define FP_DP_SIZE 8 63 | 64 | /* 65 | * General EAX, EBX, ECX, EDX type registers. Note that for 66 | * portability, and speed, the issue of byte swapping is not addressed 67 | * in the registers. All registers are stored in the default format 68 | * available on the host machine. The only critical issue is that the 69 | * registers should line up EXACTLY in the same manner as they do in 70 | * the 386. That is: 71 | * 72 | * EAX & 0xff === AL 73 | * EAX & 0xffff == AX 74 | * 75 | * etc. The result is that alot of the calculations can then be 76 | * done using the native instruction set fully. 77 | */ 78 | 79 | #ifdef __BIG_ENDIAN__ 80 | 81 | typedef struct { 82 | u8 reg[16]; 83 | } I128_reg_t; 84 | 85 | typedef struct { 86 | u32 e_reg; 87 | } I32_reg_t; 88 | 89 | typedef struct { 90 | u16 filler0, x_reg; 91 | } I16_reg_t; 92 | 93 | typedef struct { 94 | u8 filler0, filler1, h_reg, l_reg; 95 | } I8_reg_t; 96 | 97 | #else /* !__BIG_ENDIAN__ */ 98 | 99 | typedef struct { 100 | u8 reg[16]; 101 | } I128_reg_t; 102 | 103 | typedef struct { 104 | u32 e_reg; 105 | } I32_reg_t; 106 | 107 | typedef struct { 108 | u16 x_reg; 109 | } I16_reg_t; 110 | 111 | typedef struct { 112 | u8 l_reg, h_reg; 113 | } I8_reg_t; 114 | 115 | #endif /* BIG_ENDIAN */ 116 | 117 | typedef union { 118 | I32_reg_t I32_reg; 119 | I16_reg_t I16_reg; 120 | I8_reg_t I8_reg; 121 | } i386_general_register; 122 | 123 | struct i386_general_regs { 124 | i386_general_register A, B, C, D; 125 | }; 126 | 127 | struct i386_special_regs { 128 | i386_general_register SP, BP, SI, DI, IP; 129 | u32 FLAGS; 130 | }; 131 | 132 | struct i386_see_regs { 133 | I128_reg_t XMM[8]; 134 | }; 135 | 136 | typedef struct { 137 | union { 138 | u32 base; // segment base 139 | u32 offset; // gate offset 140 | }; 141 | union { 142 | u32 limit; // segment limit 143 | struct { 144 | u16 sel; // gate selector 145 | u16 w_count; // gate (d)word count 146 | }; 147 | }; 148 | u16 acc; // access flags (12 bits) 149 | unsigned invalid:1; // invalid descriptor type 150 | unsigned seg:1; // is segment 151 | unsigned dpl:2; 152 | unsigned r:1; // readable seg 153 | unsigned w:1; // writable seg 154 | unsigned x:1; // executable seg 155 | unsigned c:1; // conforming code seg 156 | unsigned a:1; // accessed seg 157 | unsigned p:1; // present 158 | unsigned g:1; // granularity 159 | unsigned ed:1; // expand down data seg 160 | unsigned ldt:1; // ldt 161 | unsigned c_gate:1; // call gate 162 | unsigned i_gate:1; // interrupt gate 163 | unsigned t_gate:1; // task gate 164 | unsigned tss:1; // tss 165 | unsigned busy:1; // tss is busy 166 | unsigned trap:1; // interrupt gate is trap gate 167 | unsigned is_i386:1; // i386 (32 bit) descriptor or 32 bit segment 168 | } descr_t; 169 | 170 | 171 | /* 172 | * segment registers here represent 16 bit selectors & base/limit cache 173 | * ldt & tr are quite similar to segment selectors 174 | */ 175 | typedef struct { 176 | u32 base, limit; 177 | u16 sel; 178 | u16 acc; 179 | } sel_t; 180 | 181 | #define ACC_G(a) ((a >> 11) & 1) /* 0/1: granularity bytes/4k */ 182 | #define ACC_D(a) ((a >> 10) & 1) /* 0/1: default size 16/32 bit */ 183 | #define ACC_P(a) ((a >> 7) & 1) /* 0/1: present no/yes */ 184 | #define ACC_DPL(a) ((a >> 5) & 3) /* 0..3: dpl */ 185 | #define ACC_S(a) ((a >> 4) & 1) /* 0/1: system/normal */ 186 | #define ACC_E(a) ((a >> 3) & 1) /* 0/1: type data/code (ACC_S = normal) */ 187 | #define ACC_ED(a) ((a >> 2) & 1) /* 0/1: expand up/down (ACC_E = data) */ 188 | #define ACC_C(a) ((a >> 2) & 1) /* 0/1: conforming no/yes (ACC_E = code) */ 189 | #define ACC_W(a) ((a >> 1) & 1) /* 0/1: writable no/yes (ACC_E = data) */ 190 | #define ACC_R(a) ((a >> 1) & 1) /* 0/1: readable no/yes (ACC_E = code) */ 191 | #define ACC_A(a) (a & 1) /* 0/1: accessed no/yes */ 192 | #define ACC_TYPE(a) (a & 0xf) /* 0..0xf: system descr type (ACC_S = system) */ 193 | 194 | /* 8 bit registers */ 195 | #define R_AH gen.A.I8_reg.h_reg 196 | #define R_AL gen.A.I8_reg.l_reg 197 | #define R_BH gen.B.I8_reg.h_reg 198 | #define R_BL gen.B.I8_reg.l_reg 199 | #define R_CH gen.C.I8_reg.h_reg 200 | #define R_CL gen.C.I8_reg.l_reg 201 | #define R_DH gen.D.I8_reg.h_reg 202 | #define R_DL gen.D.I8_reg.l_reg 203 | 204 | /* 16 bit registers */ 205 | #define R_AX gen.A.I16_reg.x_reg 206 | #define R_BX gen.B.I16_reg.x_reg 207 | #define R_CX gen.C.I16_reg.x_reg 208 | #define R_DX gen.D.I16_reg.x_reg 209 | 210 | /* 32 bit extended registers */ 211 | #define R_EAX gen.A.I32_reg.e_reg 212 | #define R_EBX gen.B.I32_reg.e_reg 213 | #define R_ECX gen.C.I32_reg.e_reg 214 | #define R_EDX gen.D.I32_reg.e_reg 215 | 216 | /* special registers */ 217 | #define R_SP spc.SP.I16_reg.x_reg 218 | #define R_BP spc.BP.I16_reg.x_reg 219 | #define R_SI spc.SI.I16_reg.x_reg 220 | #define R_DI spc.DI.I16_reg.x_reg 221 | #define R_IP spc.IP.I16_reg.x_reg 222 | #define R_FLG spc.FLAGS 223 | 224 | /* special registers */ 225 | #define R_ESP spc.SP.I32_reg.e_reg 226 | #define R_EBP spc.BP.I32_reg.e_reg 227 | #define R_ESI spc.SI.I32_reg.e_reg 228 | #define R_EDI spc.DI.I32_reg.e_reg 229 | #define R_EIP spc.IP.I32_reg.e_reg 230 | #define R_EFLG spc.FLAGS 231 | 232 | /* SSE registers */ 233 | #define R_XMM0 sse.XMM[0] 234 | #define R_XMM1 sse.XMM[1] 235 | #define R_XMM2 sse.XMM[2] 236 | #define R_XMM3 sse.XMM[3] 237 | #define R_XMM4 sse.XMM[4] 238 | #define R_XMM5 sse.XMM[5] 239 | #define R_XMM6 sse.XMM[6] 240 | #define R_XMM7 sse.XMM[7] 241 | 242 | /* segment registers */ 243 | #define R_ES_INDEX 0 244 | #define R_CS_INDEX 1 245 | #define R_SS_INDEX 2 246 | #define R_DS_INDEX 3 247 | #define R_FS_INDEX 4 248 | #define R_GS_INDEX 5 249 | #define R_NOSEG_INDEX 6 250 | 251 | #define R_ES_SEL seg + R_ES_INDEX 252 | #define R_ES seg[R_ES_INDEX].sel 253 | #define R_ES_BASE seg[R_ES_INDEX].base 254 | #define R_ES_LIMIT seg[R_ES_INDEX].limit 255 | #define R_ES_ACC seg[R_ES_INDEX].acc 256 | 257 | #define R_CS_SEL seg + R_CS_INDEX 258 | #define R_CS seg[R_CS_INDEX].sel 259 | #define R_CS_BASE seg[R_CS_INDEX].base 260 | #define R_CS_LIMIT seg[R_CS_INDEX].limit 261 | #define R_CS_ACC seg[R_CS_INDEX].acc 262 | 263 | #define R_SS_SEL seg + R_SS_INDEX 264 | #define R_SS seg[R_SS_INDEX].sel 265 | #define R_SS_BASE seg[R_SS_INDEX].base 266 | #define R_SS_LIMIT seg[R_SS_INDEX].limit 267 | #define R_SS_ACC seg[R_SS_INDEX].acc 268 | 269 | #define R_DS_SEL seg + R_DS_INDEX 270 | #define R_DS seg[R_DS_INDEX].sel 271 | #define R_DS_BASE seg[R_DS_INDEX].base 272 | #define R_DS_LIMIT seg[R_DS_INDEX].limit 273 | #define R_DS_ACC seg[R_DS_INDEX].acc 274 | 275 | #define R_FS_SEL seg + R_FS_INDEX 276 | #define R_FS seg[R_FS_INDEX].sel 277 | #define R_FS_BASE seg[R_FS_INDEX].base 278 | #define R_FS_LIMIT seg[R_FS_INDEX].limit 279 | #define R_FS_ACC seg[R_FS_INDEX].acc 280 | 281 | #define R_GS_SEL seg + R_GS_INDEX 282 | #define R_GS seg[R_GS_INDEX].sel 283 | #define R_GS_BASE seg[R_GS_INDEX].base 284 | #define R_GS_LIMIT seg[R_GS_INDEX].limit 285 | #define R_GS_ACC seg[R_GS_INDEX].acc 286 | 287 | #define R_NOSEG_SEL seg + R_NOSEG_INDEX 288 | #define R_NOSEG seg[R_NOSEG_INDEX].sel 289 | #define R_NOSEG_BASE seg[R_NOSEG_INDEX].base 290 | #define R_NOSEG_LIMIT seg[R_NOSEG_INDEX].limit 291 | #define R_NOSEG_ACC seg[R_NOSEG_INDEX].acc 292 | 293 | /* other registers: tr, ldt, gdt, idt */ 294 | #define R_TR tr.sel 295 | #define R_TR_BASE tr.base 296 | #define R_TR_LIMIT tr.limit 297 | #define R_TR_ACC tr.acc 298 | #define R_LDT ldt.sel 299 | #define R_LDT_BASE ldt.base 300 | #define R_LDT_LIMIT ldt.limit 301 | #define R_LDT_ACC ldt.acc 302 | #define R_GDT_BASE gdt.base 303 | #define R_GDT_LIMIT gdt.limit 304 | #define R_IDT_BASE idt.base 305 | #define R_IDT_LIMIT idt.limit 306 | 307 | /* machine status & debug registers: CRx, DRx, TRx */ 308 | #define R_CR0 crx[0] 309 | #define R_CR1 crx[1] 310 | #define R_CR2 crx[2] 311 | #define R_CR3 crx[3] 312 | #define R_CR4 crx[4] 313 | #define R_CR5 crx[5] 314 | #define R_CR6 crx[6] 315 | #define R_CR7 crx[7] 316 | #define R_DR0 drx[0] 317 | #define R_DR1 drx[1] 318 | #define R_DR2 drx[2] 319 | #define R_DR3 drx[3] 320 | #define R_DR4 drx[4] 321 | #define R_DR5 drx[5] 322 | #define R_DR6 drx[6] 323 | #define R_DR7 drx[7] 324 | 325 | #define R_TSC msr[0x10] 326 | #define R_LAST_REAL_TSC msr[0x11] 327 | #define R_REAL_TSC msr[0x12] 328 | 329 | /* flag conditions */ 330 | #define FB_CF 0x000001 /* CARRY flag */ 331 | #define FB_PF 0x000004 /* PARITY flag */ 332 | #define FB_AF 0x000010 /* AUX flag */ 333 | #define FB_ZF 0x000040 /* ZERO flag */ 334 | #define FB_SF 0x000080 /* SIGN flag */ 335 | #define FB_TF 0x000100 /* TRAP flag */ 336 | #define FB_IF 0x000200 /* INTERRUPT ENABLE flag */ 337 | #define FB_DF 0x000400 /* DIR flag */ 338 | #define FB_OF 0x000800 /* OVERFLOW flag */ 339 | #define FB_ID 0x200000 /* ID flag */ 340 | 341 | /* 80286 and above always have bit#1 set */ 342 | #define F_ALWAYS_ON (0x0002) /* flag bits always on */ 343 | 344 | /* 345 | * Define a mask for only those flag bits we will ever pass back 346 | * (via PUSHF) 347 | */ 348 | #define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF) 349 | 350 | /* following bits masked in to a 16bit quantity */ 351 | 352 | #define F_CF 0x0001 /* CARRY flag */ 353 | #define F_PF 0x0004 /* PARITY flag */ 354 | #define F_AF 0x0010 /* AUX flag */ 355 | #define F_ZF 0x0040 /* ZERO flag */ 356 | #define F_SF 0x0080 /* SIGN flag */ 357 | #define F_TF 0x0100 /* TRAP flag */ 358 | #define F_IF 0x0200 /* INTERRUPT ENABLE flag */ 359 | #define F_DF 0x0400 /* DIR flag */ 360 | #define F_OF 0x0800 /* OVERFLOW flag */ 361 | 362 | #define CR0_MP (1 << 1) 363 | #define CR0_EM (1 << 2) 364 | #define CR4_OSFXSR (1 << 9) 365 | #define CR4_OSXMMEXCPT (1 << 10) 366 | 367 | #define X86EMU_TOGGLE_FLAG(emu, flag) (emu->x86.R_FLG ^= (flag)) 368 | #define X86EMU_SET_FLAG(emu, flag) (emu->x86.R_FLG |= (flag)) 369 | #define X86EMU_CLEAR_FLAG(emu, flag) (emu->x86.R_FLG &= ~(flag)) 370 | 371 | /* 372 | * Emulator machine state. 373 | * Segment usage control. 374 | */ 375 | #define _MODE_SEG_DS_SS 0x00000001 376 | #define _MODE_REPE 0x00000002 377 | #define _MODE_REPNE 0x00000004 378 | #define _MODE_DATA32 0x00000008 379 | #define _MODE_ADDR32 0x00000010 380 | #define _MODE_STACK32 0x00000020 381 | #define _MODE_CODE32 0x00000040 382 | #define _MODE_HALTED 0x00000080 383 | 384 | #define INTR_TYPE_SOFT 1 385 | #define INTR_TYPE_FAULT 2 386 | #define INTR_MODE_RESTART 0x100 387 | #define INTR_MODE_ERRCODE 0x200 388 | 389 | #define X86EMU_RUN_TIMEOUT (1 << 0) 390 | #define X86EMU_RUN_MAX_INSTR (1 << 1) 391 | #define X86EMU_RUN_NO_EXEC (1 << 2) 392 | #define X86EMU_RUN_NO_CODE (1 << 3) 393 | #define X86EMU_RUN_LOOP (1 << 4) 394 | 395 | #define X86EMU_MEMIO_8 0 396 | #define X86EMU_MEMIO_16 1 397 | #define X86EMU_MEMIO_32 2 398 | #define X86EMU_MEMIO_8_NOPERM 3 399 | #define X86EMU_MEMIO_R (0 << 8) 400 | #define X86EMU_MEMIO_W (1 << 8) 401 | #define X86EMU_MEMIO_X (2 << 8) 402 | #define X86EMU_MEMIO_I (3 << 8) 403 | #define X86EMU_MEMIO_O (4 << 8) 404 | 405 | #define X86EMU_MSRS 0x800 406 | 407 | struct x86emu_s; 408 | 409 | typedef unsigned (* x86emu_memio_handler_t)(struct x86emu_s *, u32 addr, u32 *val, unsigned type); 410 | typedef int (* x86emu_intr_handler_t)(struct x86emu_s *, u8 num, unsigned type); 411 | typedef int (* x86emu_code_handler_t)(struct x86emu_s *); 412 | typedef void (* x86emu_cpuid_handler_t)(struct x86emu_s *); 413 | typedef void (* x86emu_wrmsr_handler_t)(struct x86emu_s *); 414 | typedef void (* x86emu_rdmsr_handler_t)(struct x86emu_s *); 415 | typedef void (* x86emu_flush_func_t)(struct x86emu_s *, char *buf, unsigned size); 416 | 417 | typedef struct { 418 | struct i386_general_regs gen; 419 | struct i386_special_regs spc; 420 | struct i386_see_regs sse; 421 | sel_t seg[8]; 422 | sel_t ldt; 423 | sel_t tr; 424 | u32 crx[8]; 425 | u32 drx[8]; 426 | struct { 427 | u32 base, limit; 428 | } gdt; 429 | struct { 430 | u32 base, limit; 431 | } idt; 432 | u64 *msr; /* X86EMU_MSRS */ 433 | unsigned char *msr_perm; /* X86EMU_MSRS */ 434 | u32 mode; 435 | sel_t *default_seg; 436 | u32 saved_eip; 437 | u16 saved_cs; 438 | char decode_seg[4]; 439 | unsigned char instr_buf[32]; /* instruction bytes */ 440 | unsigned instr_len; /* bytes in instr_buf */ 441 | char disasm_buf[256]; 442 | char *disasm_ptr; 443 | u8 intr_nr; 444 | unsigned intr_type; 445 | unsigned intr_errcode; 446 | unsigned intr_stats[0x100]; 447 | unsigned debug_start, debug_len; 448 | } x86emu_regs_t; 449 | 450 | 451 | #define X86EMU_TRACE_REGS (1 << 0) 452 | #define X86EMU_TRACE_CODE (1 << 1) 453 | #define X86EMU_TRACE_DATA (1 << 2) 454 | #define X86EMU_TRACE_ACC (1 << 3) 455 | #define X86EMU_TRACE_IO (1 << 4) 456 | #define X86EMU_TRACE_INTS (1 << 5) 457 | #define X86EMU_TRACE_TIME (1 << 6) 458 | #define X86EMU_TRACE_DEBUG (1 << 7) 459 | #define X86EMU_TRACE_DEFAULT (X86EMU_TRACE_REGS | X86EMU_TRACE_CODE | X86EMU_TRACE_DATA | X86EMU_TRACE_IO | X86EMU_TRACE_INTS) 460 | 461 | #define X86EMU_DUMP_REGS (1 << 0) 462 | #define X86EMU_DUMP_MEM (1 << 1) 463 | #define X86EMU_DUMP_ACC_MEM (1 << 2) 464 | #define X86EMU_DUMP_INV_MEM (1 << 3) 465 | #define X86EMU_DUMP_ATTR (1 << 4) 466 | #define X86EMU_DUMP_ASCII (1 << 5) 467 | #define X86EMU_DUMP_IO (1 << 6) 468 | #define X86EMU_DUMP_INTS (1 << 7) 469 | #define X86EMU_DUMP_TIME (1 << 8) 470 | #define X86EMU_DUMP_DEFAULT (X86EMU_DUMP_REGS | X86EMU_DUMP_INV_MEM | X86EMU_DUMP_ATTR | X86EMU_DUMP_ASCII | X86EMU_DUMP_IO | X86EMU_DUMP_INTS | X86EMU_DUMP_TIME) 471 | 472 | #define X86EMU_PERM_R (1 << 0) 473 | #define X86EMU_PERM_W (1 << 1) 474 | #define X86EMU_PERM_X (1 << 2) 475 | #define X86EMU_PERM_VALID (1 << 3) 476 | #define X86EMU_ACC_R (1 << 4) 477 | #define X86EMU_ACC_W (1 << 5) 478 | #define X86EMU_ACC_X (1 << 6) 479 | #define X86EMU_ACC_INVALID (1 << 7) 480 | 481 | /* for convenience */ 482 | #define X86EMU_PERM_RW (X86EMU_PERM_R | X86EMU_PERM_W) 483 | #define X86EMU_PERM_RX (X86EMU_PERM_R | X86EMU_PERM_X) 484 | #define X86EMU_PERM_RWX (X86EMU_PERM_R | X86EMU_PERM_W | X86EMU_PERM_X) 485 | 486 | 487 | /* 4k pages */ 488 | #define X86EMU_PAGE_BITS 12 489 | #define X86EMU_PTABLE_BITS 10 490 | #define X86EMU_PDIR_BITS (32 - X86EMU_PTABLE_BITS - X86EMU_PAGE_BITS) 491 | #define X86EMU_PAGE_SIZE (1 << X86EMU_PAGE_BITS) 492 | 493 | #define X86EMU_IO_PORTS (1 << 16) 494 | 495 | typedef struct { 496 | unsigned char *attr; // malloc'ed 497 | unsigned char *data; // NOT malloc'ed 498 | unsigned char def_attr; 499 | } mem2_page_t; 500 | 501 | typedef mem2_page_t mem2_ptable_t[1 << X86EMU_PTABLE_BITS]; 502 | typedef mem2_ptable_t *mem2_pdir_t[1 << X86EMU_PDIR_BITS]; 503 | 504 | typedef struct { 505 | mem2_pdir_t *pdir; 506 | unsigned invalid:1; 507 | unsigned char def_attr; 508 | } x86emu_mem_t; 509 | 510 | 511 | /**************************************************************************** 512 | REMARKS: 513 | Structure maintaining the emulator machine state. 514 | 515 | MEMBERS: 516 | private - private data pointer 517 | x86 - X86 registers 518 | ****************************************************************************/ 519 | typedef struct x86emu_s { 520 | x86emu_regs_t x86; 521 | x86emu_code_handler_t code_check; 522 | x86emu_cpuid_handler_t cpuid; 523 | x86emu_memio_handler_t memio; 524 | x86emu_intr_handler_t intr; 525 | x86emu_wrmsr_handler_t wrmsr; 526 | x86emu_wrmsr_handler_t rdmsr; 527 | x86emu_mem_t *mem; 528 | struct { 529 | unsigned char *map; 530 | unsigned *stats_i, *stats_o; 531 | unsigned iopl_needed:1; 532 | unsigned iopl_ok:1; 533 | } io; 534 | struct { 535 | x86emu_flush_func_t flush; 536 | unsigned size; 537 | char *buf; 538 | char *ptr; 539 | unsigned trace; /* trace flags: X86EMU_TRACE_* */ 540 | } log; 541 | unsigned timeout; 542 | u64 max_instr; 543 | union { 544 | void *_private; 545 | #ifndef __cplusplus 546 | void *private; /* deprecated: use _private */ 547 | #endif 548 | }; 549 | } x86emu_t; 550 | 551 | /*-------------------------- Function Prototypes --------------------------*/ 552 | 553 | x86emu_t *x86emu_new(unsigned def_mem_perm, unsigned def_io_perm); 554 | x86emu_t *x86emu_done(x86emu_t *emu); 555 | x86emu_t *x86emu_clone(x86emu_t *emu); 556 | 557 | void x86emu_reset(x86emu_t *emu); 558 | unsigned x86emu_run(x86emu_t *emu, unsigned flags) __attribute__ ((nonnull (1))); 559 | void x86emu_stop(x86emu_t *emu); 560 | 561 | void x86emu_set_log(x86emu_t *emu, unsigned buffer_size, x86emu_flush_func_t flush); 562 | unsigned x86emu_clear_log(x86emu_t *emu, int flush) __attribute__ ((nonnull (1))); 563 | void x86emu_log(x86emu_t *emu, const char *format, ...) __attribute__ ((format (printf, 2, 3))); 564 | void x86emu_dump(x86emu_t *emu, int flags); 565 | 566 | void x86emu_set_perm(x86emu_t *emu, unsigned start, unsigned end, unsigned perm); 567 | void x86emu_set_io_perm(x86emu_t *emu, unsigned start, unsigned end, unsigned perm); 568 | void x86emu_set_page(x86emu_t *emu, unsigned page, void *address); 569 | void x86emu_reset_access_stats(x86emu_t *emu); 570 | 571 | x86emu_rdmsr_handler_t x86emu_set_rdmsr_handler(x86emu_t *emu, x86emu_rdmsr_handler_t handler); 572 | x86emu_wrmsr_handler_t x86emu_set_wrmsr_handler(x86emu_t *emu, x86emu_wrmsr_handler_t handler); 573 | x86emu_cpuid_handler_t x86emu_set_cpuid_handler(x86emu_t *emu, x86emu_cpuid_handler_t handler); 574 | x86emu_code_handler_t x86emu_set_code_handler(x86emu_t *emu, x86emu_code_handler_t handler); 575 | x86emu_intr_handler_t x86emu_set_intr_handler(x86emu_t *emu, x86emu_intr_handler_t handler); 576 | x86emu_memio_handler_t x86emu_set_memio_handler(x86emu_t *emu, x86emu_memio_handler_t handler); 577 | 578 | void x86emu_intr_raise(x86emu_t *emu, u8 intr_nr, unsigned type, unsigned err); 579 | 580 | unsigned x86emu_read_byte(x86emu_t *emu, unsigned addr); 581 | unsigned x86emu_read_byte_noperm(x86emu_t *emu, unsigned addr); 582 | unsigned x86emu_read_word(x86emu_t *emu, unsigned addr); 583 | unsigned x86emu_read_dword(x86emu_t *emu, unsigned addr); 584 | void x86emu_write_byte(x86emu_t *emu, unsigned addr, unsigned val); 585 | void x86emu_write_byte_noperm(x86emu_t *emu, unsigned addr, unsigned val); 586 | void x86emu_write_word(x86emu_t *emu, unsigned addr, unsigned val); 587 | void x86emu_write_dword(x86emu_t *emu, unsigned addr, unsigned val); 588 | 589 | void x86emu_set_seg_register(x86emu_t *emu, sel_t *seg, u16 val); 590 | 591 | #ifdef __cplusplus 592 | } /* End of "C" linkage for C++ */ 593 | #endif 594 | 595 | #endif /* __X86EMU_X86EMU_H */ 596 | 597 | --------------------------------------------------------------------------------