├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── disk.c ├── disk.h ├── emulator.c ├── emulator.h ├── emulator_functions.c ├── emulator_functions.h ├── gdt.c ├── gdt.h ├── instruction_defs.h ├── instructions.c ├── instructions.h ├── instructions_00.c ├── instructions_0F00.c ├── instructions_0F20.c ├── instructions_0F80.c ├── instructions_0F90.c ├── instructions_0FB0.c ├── instructions_10.c ├── instructions_20.c ├── instructions_30.c ├── instructions_40.c ├── instructions_50.c ├── instructions_60.c ├── instructions_70.c ├── instructions_80.c ├── instructions_90.c ├── instructions_A0.c ├── instructions_B0.c ├── instructions_C0.c ├── instructions_D0.c ├── instructions_E0.c ├── instructions_F0.c ├── interrupt.c ├── interrupt.h ├── io.c ├── io.h ├── ioapic.c ├── ioapic.h ├── kbd.c ├── kbd.h ├── lapic.c ├── lapic.h ├── main.c ├── modrm.c ├── modrm.h ├── mp.c ├── mp.h ├── paging.c ├── paging.h ├── shift.c ├── shift.h ├── test.sh ├── tests └── exec │ ├── and │ ├── Makefile │ ├── and.asm │ └── expected.txt │ ├── args │ ├── Makefile │ ├── args.c │ ├── crt0.asm │ └── expected.txt │ ├── call │ ├── Makefile │ ├── call.asm │ └── expected.txt │ ├── call_far │ ├── Makefile │ ├── call_far.asm │ └── expected.txt │ ├── call_far16 │ ├── Makefile │ ├── call_far16.asm │ └── expected.txt │ ├── code_80 │ ├── Makefile │ ├── code_80.asm │ └── expected.txt │ ├── code_c0 │ ├── Makefile │ ├── code_c0.asm │ └── expected.txt │ ├── code_f6 │ ├── Makefile │ └── code_f6.asm │ ├── console │ ├── Makefile │ ├── crt0.asm │ └── main.c │ ├── cwd │ ├── Makefile │ └── cwd.asm │ ├── disk │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── main_func.c │ ├── div │ ├── Makefile │ ├── div.asm │ └── expected.txt │ ├── flags_clear │ ├── Makefile │ ├── expected.txt │ └── flags_clear.asm │ ├── flags_set │ ├── Makefile │ ├── expected.txt │ └── flags_set.asm │ ├── gdt │ ├── Makefile │ ├── expected.txt │ └── gdt.asm │ ├── if │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── if.c │ ├── inst_list │ ├── Makefile │ ├── list.asm │ └── mov_rel8.asm │ ├── io │ ├── Makefile │ ├── in.asm │ └── in_display.asm │ ├── io_out │ ├── Makefile │ ├── expected.txt │ └── io_out.asm │ ├── ioapic │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── ioapic.c │ ├── jmp_c │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── jmp_c.c │ ├── jmp_far │ ├── Makefile │ ├── expected.txt │ └── jmp_far.asm │ ├── jmp_far16 │ ├── Makefile │ ├── expected.txt │ └── jmp_far16.asm │ ├── lapic │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── lapic.c │ ├── les │ ├── Makefile │ └── les.asm │ ├── loop │ ├── Makefile │ ├── expected.txt │ └── loop.asm │ ├── main_func │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── main_func.c │ ├── modrm │ ├── Makefile │ ├── expected.txt │ └── modrm.asm │ ├── moffs │ ├── Makefile │ ├── expected.txt │ └── moffs.asm │ ├── mov │ ├── Makefile │ ├── expected.txt │ └── mov.asm │ ├── mov_jmp │ ├── Makefile │ └── mov_jmp.asm │ ├── movzx │ ├── Makefile │ ├── expected.txt │ └── movzx.asm │ ├── mp │ ├── Makefile │ ├── crt0.asm │ ├── expected.txt │ └── mp.c │ ├── mul │ ├── Makefile │ ├── expected.txt │ └── mul.asm │ ├── or │ ├── Makefile │ ├── expected.txt │ └── or.asm │ ├── org_jmp │ ├── Makefile │ ├── expected.txt │ └── org_jmp.asm │ ├── paging │ ├── Makefile │ ├── expected.txt │ └── paging.asm │ ├── pop │ ├── Makefile │ ├── expected.txt │ └── pop.asm │ ├── pusha │ ├── Makefile │ ├── expected.txt │ └── pusha.asm │ ├── rep │ ├── Makefile │ └── rep.asm │ ├── seg │ ├── Makefile │ ├── expected.txt │ └── seg.asm │ ├── sib │ ├── Makefile │ └── sib.asm │ ├── str_32 │ ├── Makefile │ ├── expected.txt │ └── str_32.asm │ ├── str_8 │ ├── Makefile │ ├── expected.txt │ └── str_8.asm │ ├── sub │ ├── Makefile │ ├── expected.txt │ └── sub.asm │ ├── test │ ├── Makefile │ ├── expected.txt │ └── test.asm │ ├── xchg │ ├── Makefile │ ├── expected.txt │ └── xchg.asm │ └── xor │ ├── Makefile │ ├── expected.txt │ └── xor.asm ├── twos_complement.c ├── twos_complement.h ├── util.c ├── util.h └── xv6memfs.img /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | dax86 39 | 40 | # Debug files 41 | *.dSYM/ 42 | *.su 43 | *.idb 44 | *.pdb 45 | 46 | # Kernel Module Compile Results 47 | *.mod* 48 | *.cmd 49 | .tmp_versions/ 50 | modules.order 51 | Module.symvers 52 | Mkfile.old 53 | dkms.conf 54 | 55 | .DS_Store 56 | .vscode 57 | 58 | tests/exec/**/*.bin -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bitnami/minideb:jessie 2 | 3 | RUN apt-get -y update && apt-get -y install build-essential nasm 4 | 5 | WORKDIR /dax86/ 6 | 7 | ADD . /dax86/ 8 | 9 | USER root 10 | 11 | CMD ["/bin/bash"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yohei Kusakabe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = dax86 2 | OBJS = \ 3 | main.o\ 4 | emulator.o\ 5 | emulator_functions.o\ 6 | instructions.o\ 7 | modrm.o\ 8 | io.o\ 9 | shift.o\ 10 | gdt.o\ 11 | paging.o\ 12 | twos_complement.o\ 13 | lapic.o\ 14 | ioapic.o\ 15 | interrupt.o\ 16 | kbd.o\ 17 | disk.o\ 18 | mp.o\ 19 | util.o\ 20 | instructions_00.o\ 21 | instructions_10.o\ 22 | instructions_20.o\ 23 | instructions_30.o\ 24 | instructions_40.o\ 25 | instructions_50.o\ 26 | instructions_60.o\ 27 | instructions_70.o\ 28 | instructions_80.o\ 29 | instructions_90.o\ 30 | instructions_A0.o\ 31 | instructions_B0.o\ 32 | instructions_C0.o\ 33 | instructions_D0.o\ 34 | instructions_E0.o\ 35 | instructions_F0.o\ 36 | instructions_0F00.o\ 37 | instructions_0F20.o\ 38 | instructions_0F80.o\ 39 | instructions_0F90.o\ 40 | instructions_0FB0.o 41 | 42 | CC = /usr/bin/gcc 43 | CFLAGS += -Wall 44 | 45 | .PHONY: all create-docker clean-docker 46 | all : 47 | make $(TARGET) 48 | 49 | # Dependencies 50 | # gcc -c: only compile & assembly to .o 51 | # $<: first prerequisite 52 | %.o : %.c Makefile 53 | $(CC) $(CFLAGS) -c $< 54 | 55 | $(TARGET) : $(OBJS) Makefile 56 | $(CC) -o $@ $(OBJS) -lm -lpthread 57 | 58 | clean: 59 | rm -f *.o 60 | 61 | create-docker: 62 | docker build -t dax86 . 63 | docker run -dit -v $$(pwd):/dax86 --name dax86-c $$(docker images -q dax86) 64 | docker exec -it $$(docker ps -aqf "name=dax86-c") bash 65 | 66 | clean-docker: 67 | docker stop $$(docker ps -aqf "name=dax86-c") 68 | docker rm $$(docker ps -aqf "name=dax86-c") 69 | docker image rm $$(docker images -q dax86) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dax86 2 | 3 | x86 (i386) Emulator in C 4 | 5 | Why: 6 | 7 | - I wanted to trace how an OS runs on CPUs at archtecture / instruction level. 8 | 9 | What: 10 | 11 | - Runs vanilla xv6 (memfs) image from boot. 12 | - Each instruction is manually implemented and executed sequentially without binary translation or OoOE. 13 | - Representation of logic is prioritized over the performance. Codes have bunch of comments covering the instructions and the hardware mechanism as well. 14 | 15 | Done: 16 | 17 | - Instructions required for running xv6 18 | - Real mode 19 | - Protected mode 20 | - Paging 21 | - MP configuration 22 | - Software/Hardware interrupts 23 | - Device emulation (disk, keyboard, APIC timer, local APIC, IO APIC, UART etc) 24 | 25 | To do: 26 | 27 | - FPU-related instructions 28 | - Exception 29 | - Virtual 8086 mode 30 | - TLB 31 | 32 | System requirements: 33 | 34 | - Memory: 512MB 35 | - CPU: scheduler loop will occupy CPU resource. `nice` command, cgroups or docker resource setting might help here. 36 | 37 | ##### Build dax86 38 | 39 | ``` 40 | make 41 | ``` 42 | 43 | ##### Run 44 | 45 | ``` 46 | # basic use 47 | ./dax86 [binary_file] 48 | 49 | # run xv6 (ctrl + c to stop) 50 | ./dax86 xv6memfs.img 51 | 52 | # verbose run (prints each op) 53 | ./dax86 [binary_file] -v 54 | ``` 55 | 56 | ##### Setup Environment using Docker 57 | 58 | Though dax86 can be built for different targets and run, there's a docker image in case Debian's `build-essential` package is preferred to the build environment of your host. Mini Debian Jessie is used for the base image. 59 | 60 | The command below will build image, run a container with the image and execute shell in interactive mode. 61 | 62 | ``` 63 | make create-docker 64 | ``` 65 | 66 | To clean created container and image, run the command below. 67 | 68 | ``` 69 | make clean-docker 70 | ``` 71 | 72 | ##### Test 73 | 74 | ``` 75 | # test all 76 | ./test.sh 77 | 78 | # test specific one in tests/exec directory 79 | ./test.sh [test_name] 80 | 81 | # directory test binary (stops at EIP: 0x0) 82 | ./dax86 test [binary_file] 83 | ``` 84 | 85 | ##### Commands to Analyze Test Cases 86 | 87 | - Disassemble Binary 88 | 89 | ``` 90 | # 32 bit all the way 91 | ndisasm -b 32 [binary_file] 92 | 93 | # 32 bit after 0xFF bytes of real mode instructions 94 | ndisasm -b 32 [binary_file] -k 0,0xFF 95 | ``` 96 | 97 | - View Binary 98 | 99 | ``` 100 | # hex 101 | xxd [bin_file] 102 | 103 | # bin 104 | xxd -b [binary_file] 105 | ``` 106 | 107 | Referenced these publications with many thanks: 108 | 109 | - https://wiki.osdev.org/ 110 | - https://book.mynavi.jp/support/bookmook/x86/ 111 | - https://software.intel.com/en-us/articles/intel-sdm 112 | - http://ref.x86asm.net/ 113 | - https://x86.puri.sm/ 114 | - https://c9x.me/x86/ -------------------------------------------------------------------------------- /disk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "disk.h" 6 | #include "util.h" 7 | 8 | #define SECTOR_SIZE 512 9 | 10 | Disk *create_disk_device() 11 | { 12 | Disk *disk = malloc(sizeof(Disk)); 13 | disk->storage = malloc(DISK_SIZE); 14 | disk->data = 0; 15 | disk->sec_count = 0; 16 | disk->lba_low = 0; 17 | disk->lba_mid = 0; 18 | disk->lba_high = 0; 19 | disk->drive_head = 0; 20 | disk->status_command = 0x40; 21 | return disk; 22 | } 23 | 24 | void load_data_to_disk(Disk *disk, FILE *f) 25 | { 26 | fseek(f, 0L, SEEK_END); 27 | long binary_size = ftell(f); 28 | fseek(f, 0L, SEEK_SET); 29 | if (binary_size > DISK_SIZE) 30 | { 31 | printf("Binary file bigger than disk size."); 32 | panic(); 33 | } 34 | fread(disk->storage, 1, binary_size, f); 35 | } 36 | 37 | void set_sec_count(Disk *disk, uint8_t val) 38 | { 39 | disk->sec_count = val; 40 | } 41 | 42 | void set_lba_low(Disk *disk, uint8_t val) 43 | { 44 | disk->lba_low = val; 45 | } 46 | 47 | void set_lba_mid(Disk *disk, uint8_t val) 48 | { 49 | disk->lba_mid = val; 50 | } 51 | 52 | void set_lba_high(Disk *disk, uint8_t val) 53 | { 54 | disk->lba_high = val; 55 | } 56 | 57 | void set_drive_head(Disk *disk, uint8_t val) 58 | { 59 | disk->drive_head = val; 60 | } 61 | 62 | static void set_head_index(Disk *disk) 63 | { 64 | uint32_t head_index = 0 | disk->lba_low | (disk->lba_mid << 8) | (disk->lba_high << 16) | 65 | ((disk->drive_head & 0x0F) << 24); 66 | disk->head_index = head_index * SECTOR_SIZE; 67 | } 68 | 69 | void set_disk_command(Disk *disk, uint8_t val) 70 | { 71 | switch (val) 72 | { 73 | case 0x20: 74 | /* read sectors */ 75 | set_head_index(disk); 76 | break; 77 | default: 78 | break; 79 | } 80 | } 81 | 82 | uint8_t get_disk_status(Disk *disk) 83 | { 84 | return disk->status_command; 85 | } 86 | 87 | uint8_t read_disk_data8(Disk *disk) 88 | { 89 | uint8_t data = disk->storage[disk->head_index]; 90 | disk->head_index += 1; 91 | return data; 92 | } 93 | 94 | uint32_t read_disk_data32(Disk *disk) 95 | { 96 | int i; 97 | uint32_t data = 0; 98 | for (i = 0; i < 4; i++) 99 | { 100 | data |= read_disk_data8(disk) << (8 * i); 101 | } 102 | return data; 103 | } -------------------------------------------------------------------------------- /disk.h: -------------------------------------------------------------------------------- 1 | #ifndef DISK_H_ 2 | #define DISK_H_ 3 | 4 | #include 5 | #include 6 | 7 | /* Disk size: 10MB */ 8 | #define DISK_SIZE (1024 * 1024 * 10) 9 | 10 | /* 11 | * 12 | * 13 | * IRQ: 14 | * - primary: 14 15 | * - secondary: 15 16 | * 1. Check PCI Busmaster Status byte, to verify that the IRQ came from the disk. 17 | * 2. Read Status Register once. (clears interrupt flag) 18 | * 3a. If the ERR bit is set, read Error Register. 19 | * 3b. If READ DMA operation, must read Busmaster Status Register. 20 | * 3c. If PIO read/write, check the status. 21 | * 4. Send EOI (0x20) to both PICs. 22 | * Device Control Register nIEN bit can be set to disable IRQ. 23 | * 24 | * Addressing Modes 25 | * - 28-bit LBA 26 | * 0x0 to 0x0FFFFFFF (256M * 512 = 128GB) 27 | * 28-bit PIO is faster than 48-bit LBA 28 | * - 48-bit LBA 29 | * - CHS 30 | * 31 | * Control Bus: 32 | * - primary: 0x1F0 through 0x1F7 33 | * - secondary: 0x170 through 0x177 34 | * 35 | * Registers (port-base) 36 | * 37 | * - IO Ports (assuming base is 0x1F0) 38 | * port R/W name size_(LBA28/48) 39 | * | 0x1F0 | R/W | Data Register | 16/16 | 40 | * | 0x1F1 | R | Error Register | 8/16 | 41 | * | 0x1F1 | W | Features Register | 8/16 | 42 | * | 0x1F2 | R/W | Sector Count Register | 8/16 | *0 is special value 43 | * | 0x1F3 | R/W | LBA Low | 8/16 | 44 | * | 0x1F4 | R/W | LBA Mid | 8/16 | 45 | * | 0x1F5 | R/W | LBA High | 8/16 | 46 | * | 0x1F6 | R/W | Drive/Head Register | 8/8 | 47 | * | 0x1F7 | R | Status Register | 8/8 | 48 | * | 0x1F7 | W | Command Register | 8/8 | 49 | * 50 | * - Control Ports (assuming base is 0x3F6) 51 | * port R/W name size_(LBA28/48) 52 | * | 0x3F6 | R | Alternate Status Register | 8/8 | *status register isolated from interrupts 53 | * | 0x3F6 | W | Device Control Register | 8/8 | *resets bus or toggle interrupts 54 | * | 0x3F7 | R | Drive Address Register | 8/8 | *provides drive/head select info 55 | * 56 | * - Status Register (0x1F7) 57 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 58 | * | BSY | RDY | DF | SRV | DRQ | CORR | IDX | ERR | 59 | * 60 | * - Error Register (0x1F1) 61 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 62 | * | BBK | UNC | MC | IDNF | MCR | ABRT | TKZNF | AMNF | 63 | * 64 | * - Drive/Head Register (0x1F6) 65 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 66 | * | 1 | LBA | 1 | DRV | Bits 24:27 of blk num in LBA | *Bits 0:3 of head in CHS 67 | * 68 | * - Device Control Register (0x3F6) 69 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 70 | * | HOB | Rsv | Rsv | Rsv | Rsv | SRST | nIEN | Rsv | 71 | * 72 | * - Drive Address Register (0x3F7) 73 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 74 | * | Rsv | WTG | HS3 | HS2 | HS1 | HS0 | DS1 | DS0 | 75 | * 76 | * Ready Status 77 | * - Status port bit 7 (BSY) clears && bit 3 (DRQ) sets (& 0xC0: 1100 0000 = 0x40: 0100 0000) 78 | * - Status port bit 0 (ERR) sets 79 | * - Status port bit 5 (DF) sets 80 | */ 81 | typedef struct 82 | { 83 | uint8_t *storage; 84 | /* Registers */ 85 | uint16_t data; 86 | uint8_t sec_count; 87 | uint8_t lba_low; 88 | uint8_t lba_mid; 89 | uint8_t lba_high; 90 | uint8_t drive_head; 91 | uint8_t status_command; 92 | /* Utility */ 93 | uint32_t head_index; 94 | } Disk; 95 | 96 | Disk *create_disk_device(); 97 | 98 | /* Utility method for loading binary file to emu */ 99 | void load_data_to_disk(Disk *disk, FILE *f); 100 | 101 | void set_sec_count(Disk *disk, uint8_t val); 102 | void set_lba_low(Disk *disk, uint8_t val); 103 | void set_lba_mid(Disk *disk, uint8_t val); 104 | void set_lba_high(Disk *disk, uint8_t val); 105 | void set_drive_head(Disk *disk, uint8_t val); 106 | void set_disk_command(Disk *disk, uint8_t val); 107 | 108 | uint8_t get_disk_status(Disk *disk); 109 | uint32_t read_disk_data32(Disk *disk); 110 | 111 | #endif -------------------------------------------------------------------------------- /emulator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "emulator.h" 7 | #include "lapic.h" 8 | 9 | /* Util for Print Binary */ 10 | #define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" 11 | #define BYTE_TO_BINARY(byte) \ 12 | (byte & 0x80 ? '1' : '0'), \ 13 | (byte & 0x40 ? '1' : '0'), \ 14 | (byte & 0x20 ? '1' : '0'), \ 15 | (byte & 0x10 ? '1' : '0'), \ 16 | (byte & 0x08 ? '1' : '0'), \ 17 | (byte & 0x04 ? '1' : '0'), \ 18 | (byte & 0x02 ? '1' : '0'), \ 19 | (byte & 0x01 ? '1' : '0') 20 | 21 | Emulator *create_emu(uint8_t *memory, uint32_t eip, uint32_t esp) 22 | { 23 | Emulator *emu = malloc(sizeof(Emulator)); 24 | 25 | /* Resets registers. */ 26 | memset(emu->registers, 0, sizeof(emu->registers)); 27 | memset(emu->segment_registers, 0, sizeof(emu->segment_registers)); 28 | memset(emu->control_registers, 0, sizeof(emu->control_registers)); 29 | emu->gdtr.base = 0; 30 | emu->gdtr.limit = 0; 31 | emu->idtr.base = 0; 32 | emu->idtr.limit = 0; 33 | emu->eip = eip; 34 | emu->registers[ESP] = esp; 35 | emu->int_r = 0; 36 | emu->eflags = 0; 37 | 38 | /* Devices */ 39 | emu->lapic = create_lapic(emu); 40 | emu->memory = memory; 41 | emu->disk = NULL; 42 | 43 | /* Utility */ 44 | emu->is_pe = 0; 45 | emu->is_pg = 0; 46 | emu->int_enabled = 0; 47 | emu->exception = NO_ERR; 48 | 49 | return emu; 50 | } 51 | 52 | void destroy_emu(Emulator *emu) 53 | { 54 | free(emu->memory); 55 | free(emu); 56 | } 57 | 58 | void attach_disk(Emulator *emu, Disk *disk) 59 | { 60 | emu->disk = disk; 61 | } 62 | 63 | /* 64 | * Loads first sector of binary file into emulator. 65 | * Each index stores 1 byte of binary. 66 | * BIOS places a sector ending with 0x55AA at 0x7c00. 67 | * This check is not implemented intentionally. 68 | * 0x200 (512) * 1 byte = 512 bytes 69 | * fread(*ptr, byte, num(of byte to read), *stream) 70 | */ 71 | void load_boot_sector(Emulator *emu) 72 | { 73 | memcpy(emu->memory + 0x7c00, emu->disk->storage, 512); 74 | } 75 | 76 | char *register_names[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"}; 77 | char *seg_register_names[] = {"ES", "CS", "SS", "DS", "FS", "GS"}; 78 | char *ctr_register_names[] = {"CR0", "CR1", "CR2", "CR3", "CR4"}; 79 | 80 | void dump_registers(Emulator *emu) 81 | { 82 | int i; 83 | for (i = 0; i < REGISTERS_COUNT; i++) 84 | { 85 | printf("%s: %08x\n", register_names[i], emu->registers[i]); // %08x: prepends 0 to make 8 digits. 86 | } 87 | printf("EIP: %08x\n", emu->eip); 88 | for (i = 0; i < SEGMENT_REGISTERS_COUNT; i++) 89 | { 90 | printf("%s: %08x\n", seg_register_names[i], emu->segment_registers[i]); 91 | } 92 | for (i = 0; i < CONTROL_REGISTER_COUNT; i++) 93 | { 94 | printf("%s: %08x\n", ctr_register_names[i], emu->control_registers[i]); 95 | } 96 | printf("GDTR: %04x %08x\n", emu->gdtr.limit, emu->gdtr.base); 97 | printf("IDTR: %04x %08x\n", emu->idtr.limit, emu->idtr.base); 98 | printf("TR: %04x\n", emu->tr); 99 | } 100 | 101 | // void dump_input(Emulator *emu) 102 | // { 103 | // printf("Input:\n"); 104 | // int i; 105 | // for (i = 0; i < MEMORY_SIZE; i++) 106 | // { 107 | // if (emu->memory[i]) 108 | // { 109 | // printf("%08x\n", emu->memory[i]); 110 | // } 111 | // } 112 | // } 113 | 114 | void dump_memory(Emulator *emu, int from, int len) 115 | { 116 | int i_per_line = 32; 117 | int i = from; 118 | int end_i = i + len; 119 | int j; 120 | printf("memory %X to %X:\n", i, end_i); 121 | printf(" "); 122 | for (j = 0; j < i_per_line; j++) 123 | { 124 | printf("%02X ", j); 125 | } 126 | printf("\n"); 127 | while (i < end_i) 128 | { 129 | printf("%08X: ", i); 130 | for (j = 0; j < i_per_line; j++) 131 | { 132 | printf("%02X", emu->memory[i + j]); 133 | printf(" "); 134 | } 135 | i += i_per_line; 136 | printf("\n"); 137 | } 138 | } 139 | 140 | void dump_eflags(Emulator *emu) 141 | { 142 | int i; 143 | printf("eflags:"); 144 | for (i = 3; i > -1; i--) 145 | { 146 | printf(BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(emu->eflags >> (8 * i))); 147 | printf(" "); 148 | } 149 | printf("\n"); 150 | } -------------------------------------------------------------------------------- /emulator.h: -------------------------------------------------------------------------------- 1 | #ifndef EMULATOR_H_ 2 | #define EMULATOR_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "disk.h" 8 | 9 | /* Memory size: 512MB */ 10 | #define MEMORY_SIZE (1024 * 1024 * 512) 11 | 12 | #define APIC_REGISTERS_SIZE 64 13 | 14 | /* 15 | * In order of REG of ModR/M 16 | * EAX: 000, ECX: 001 ... EDI: 111 17 | * 18 | * 32 | 16 | 8 | 8 19 | * EAX | AX | AH | AL 20 | * EBX | BX | BH | BL 21 | * ECX | CX | CH | CL 22 | * EDX | DX | DH | DL 23 | * ESI 24 | * EDI 25 | * ESP 26 | * EBP 27 | */ 28 | enum Register 29 | { 30 | EAX, 31 | ECX, 32 | EDX, 33 | EBX, 34 | ESP, 35 | EBP, 36 | ESI, 37 | EDI, 38 | REGISTERS_COUNT, 39 | AL = EAX, 40 | CL = ECX, 41 | DL = EDX, 42 | BL = EBX, 43 | AH = AL + 4, 44 | CH = CL + 4, 45 | DH = DL + 4, 46 | BH = BL + 4 47 | }; 48 | 49 | enum SegmentRegister 50 | { 51 | ES, 52 | CS, 53 | SS, 54 | DS, 55 | FS, 56 | GS, 57 | SEGMENT_REGISTERS_COUNT 58 | }; 59 | 60 | enum ControlRegister 61 | { 62 | CR0, 63 | CR1, 64 | CR2, 65 | CR3, 66 | CR4, 67 | CONTROL_REGISTER_COUNT 68 | }; 69 | 70 | /* GDTR: 71 | * |0 15|16 47| 72 | * | LIMIT | BASE | 73 | * |_________|____________| 74 | */ 75 | typedef struct 76 | { 77 | uint16_t limit; 78 | uint32_t base; 79 | } Gdtr; 80 | 81 | typedef struct 82 | { 83 | uint16_t limit; 84 | uint32_t base; 85 | } Idtr; 86 | 87 | enum Exception 88 | { 89 | NO_ERR, 90 | E_DE, 91 | E_DB, 92 | E_BP, 93 | E_OF, 94 | E_BR, 95 | E_UD, 96 | E_NM, 97 | E_DF, 98 | E_TS, 99 | E_NP, 100 | E_SS, 101 | E_GP, 102 | E_PF, 103 | E_MF, 104 | E_AC, 105 | E_MC, 106 | E_XF, 107 | E_VE, 108 | E_SX 109 | }; 110 | 111 | typedef struct LAPIC LAPIC; 112 | typedef struct Emulator Emulator; 113 | 114 | /* 115 | * FLAGS: 116 | * | n-th bit | 117 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 118 | * | CF | Rsv | PF | Rsv | AF | Rsv | ZF | SF | 119 | * 120 | * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 121 | * | TF | IF | DF | OF | IOPL | NT* | Rsv | 122 | * 123 | * EFLAGS: 124 | * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 125 | * | RF | VM | AC | VIF | VIP | ID | Rsv | 126 | * 127 | * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 128 | * | Rsvd | 129 | * 130 | * NT: nested task flag 131 | * 132 | * RFLAGS: 133 | * Rsv... 134 | */ 135 | struct Emulator 136 | { 137 | /* Registers */ 138 | uint32_t eflags; 139 | uint32_t registers[REGISTERS_COUNT]; 140 | uint16_t segment_registers[SEGMENT_REGISTERS_COUNT]; 141 | uint32_t control_registers[CONTROL_REGISTER_COUNT]; 142 | uint32_t eip; 143 | Gdtr gdtr; 144 | Idtr idtr; 145 | uint16_t tr; 146 | uint8_t int_r; 147 | /* Devices */ 148 | struct LAPIC *lapic; 149 | uint8_t *memory; 150 | Disk *disk; 151 | /* Utility */ 152 | uint8_t is_pe; 153 | uint8_t is_pg; 154 | uint8_t int_enabled; 155 | uint8_t exception; 156 | }; 157 | 158 | struct LAPIC 159 | { 160 | uint32_t registers[APIC_REGISTERS_SIZE]; 161 | Emulator *emu; 162 | 163 | /* convenience properties */ 164 | uint8_t unit_enabled; 165 | uint8_t int_enabled; 166 | uint8_t irr[32]; 167 | uint8_t isr[32]; 168 | uint8_t isr_index; 169 | pthread_mutex_t lock; 170 | pthread_t *timer_thread; 171 | }; 172 | 173 | Emulator *create_emu(uint8_t *memory, uint32_t eip, uint32_t esp); 174 | void destroy_emu(Emulator *emu); 175 | 176 | void attach_disk(Emulator *emu, Disk *disk); 177 | void load_boot_sector(Emulator *emu); 178 | 179 | void dump_registers(Emulator *emu); 180 | void dump_memory(Emulator *emu, int from, int len); 181 | void dump_eflags(Emulator *emu); 182 | /* 183 | void dump_input(Emulator *emu); 184 | */ 185 | 186 | #endif -------------------------------------------------------------------------------- /emulator_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef EMULATOR_FUNCTIONS_H_ 2 | #define EMULATOR_FUNCTIONS_H_ 3 | 4 | #include 5 | 6 | #include "emulator.h" 7 | 8 | /* Eflags */ 9 | #define CARRY_FLAG (1) 10 | #define ZERO_FLAG (1 << 6) 11 | #define SIGN_FLAG (1 << 7) 12 | #define INT_ENABLE_FLAG (1 << 9) 13 | #define DIRECTION_FLAG (1 << 10) 14 | #define OVERFLOW_FLAG (1 << 11) 15 | 16 | /* Register Operations */ 17 | 18 | void set_register8(Emulator *emu, int index, uint8_t value); 19 | uint8_t get_register8(Emulator *emu, int index); 20 | 21 | void set_register16(Emulator *emu, int reg_index, uint16_t value); 22 | uint16_t get_register16(Emulator *emu, int reg_index); 23 | 24 | void set_register32(Emulator *emu, int reg_index, uint32_t value); 25 | uint32_t get_register32(Emulator *emu, int reg_index); 26 | 27 | /* Segment Register Operations */ 28 | 29 | void set_seg_register16(Emulator *emu, int reg_index, uint16_t value); 30 | uint16_t get_seg_register16(Emulator *emu, int reg_index); 31 | 32 | /* Control Register Operations */ 33 | 34 | void set_ctrl_register32(Emulator *emu, int reg_index, uint32_t value); 35 | uint32_t get_ctrl_register32(Emulator *emu, int reg_index); 36 | 37 | /* Source Instruction Operations */ 38 | 39 | uint8_t get_code8(Emulator *emu, int index); 40 | int8_t get_sign_code8(Emulator *emu, int index); 41 | 42 | uint16_t get_code16(Emulator *emu, int index); 43 | int16_t get_sign_code16(Emulator *emu, int index); 44 | 45 | uint32_t get_code32(Emulator *emu, int index); 46 | int32_t get_sign_code32(Emulator *emu, int index); 47 | 48 | /* Physical Memory Operations */ 49 | 50 | uint32_t get_physical_address(Emulator *emu, int seg_index, uint32_t offset, uint8_t write); 51 | 52 | void _set_memory8(Emulator *emu, uint32_t p_address, uint8_t value); 53 | void _set_memory16(Emulator *emu, uint32_t p_address, uint16_t value); 54 | void _set_memory32(Emulator *emu, uint32_t p_address, uint32_t value); 55 | 56 | uint32_t _get_memory32(Emulator *emu, uint32_t p_address); 57 | 58 | /* Memory Operations with Segment Registers */ 59 | 60 | void set_memory8(Emulator *emu, int seg_index, uint32_t address, uint32_t value); 61 | void set_memory16(Emulator *emu, int seg_index, uint32_t address, uint16_t value); 62 | void set_memory32(Emulator *emu, int seg_index, uint32_t address, uint32_t value); 63 | 64 | uint8_t get_memory8(Emulator *emu, int seg_index, uint32_t address); 65 | uint16_t get_memory16(Emulator *emu, int seg_index, uint32_t address); 66 | uint32_t get_memory32(Emulator *emu, int seg_index, uint32_t address); 67 | 68 | /* Stack Operations */ 69 | 70 | void push16(Emulator *emu, uint16_t value); 71 | uint16_t pop16(Emulator *emu); 72 | 73 | void push32(Emulator *emu, uint32_t value); 74 | uint32_t pop32(Emulator *emu); 75 | 76 | /* Segment Register to Memory */ 77 | 78 | void push_segment_register(Emulator *emu, int reg_index); 79 | void pop_segment_register(Emulator *emu, int reg_index); 80 | 81 | /* Eflag Operations */ 82 | 83 | void set_carry_flag(Emulator *emu, int is_carry); 84 | void set_zero_flag(Emulator *emu, int is_zero); 85 | void set_sign_flag(Emulator *emu, int is_sign); 86 | void set_int_flag(Emulator *emu, int is_enabled); 87 | void set_direction_flag(Emulator *emu, int is_down); 88 | void set_overflow_flag(Emulator *emu, int is_overflow); 89 | 90 | int32_t is_carry(Emulator *emu); 91 | int32_t is_zero(Emulator *emu); 92 | int32_t is_sign(Emulator *emu); 93 | int32_t is_int_enabled(Emulator *emu); 94 | int32_t is_direction_down(Emulator *emu); 95 | int32_t is_overflow(Emulator *emu); 96 | 97 | void update_eflags_add(Emulator *emu, uint32_t value1, uint32_t value2, uint64_t result); 98 | void update_eflags_add_8bit(Emulator *emu, uint8_t value1, uint8_t value2, uint16_t result); 99 | void update_eflags_add_16bit(Emulator *emu, uint8_t value1, uint8_t value2, uint16_t result); 100 | 101 | void update_eflags_sub(Emulator *emu, uint32_t value1, uint32_t value2, uint64_t result); 102 | void update_eflags_sub_8bit(Emulator *emu, uint8_t value1, uint8_t value2, uint16_t result); 103 | void update_eflags_sub_16bit(Emulator *emu, uint16_t value1, uint16_t value2, uint32_t result); 104 | 105 | void update_eflags_logical_ops(Emulator *emu, uint32_t result); 106 | void update_eflags_logical_ops_8bit(Emulator *emu, uint8_t result); 107 | void update_eflags_logical_ops_16bit(Emulator *emu, uint8_t result); 108 | 109 | void update_eflags_mul(Emulator *emu, uint64_t upper_half_result); 110 | 111 | void set_tr(Emulator *emu, uint16_t val); 112 | 113 | /* DTR Operations */ 114 | void set_gdtr(Emulator *emu, uint16_t limit, uint32_t base); 115 | void set_idtr(Emulator *emu, uint16_t limit, uint32_t base); 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /gdt.h: -------------------------------------------------------------------------------- 1 | #ifndef GDT_H_ 2 | #define GDT_H_ 3 | 4 | #include "modrm.h" 5 | 6 | #define CR0_PE (1) 7 | 8 | void lgdt(Emulator *emu, ModRM *modrm); 9 | 10 | void check_protected_mode_entry(Emulator *emu); 11 | 12 | uint32_t read_gdt_entry_base(uint32_t entry1, uint32_t entry2); 13 | 14 | uint32_t get_linear_addr(Emulator *emu, uint16_t seg_val, uint32_t offset, uint8_t write, uint8_t exec); 15 | 16 | #endif -------------------------------------------------------------------------------- /instructions.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTRUCTIONS_H_ 2 | #define INSTRUCTIONS_H_ 3 | 4 | #include "emulator.h" 5 | 6 | void init_instructions(void); 7 | 8 | typedef void instruction_func_t(Emulator *); // instruction_func_t = void func(Emulator*) 9 | 10 | extern instruction_func_t *instructions[256]; 11 | 12 | #endif -------------------------------------------------------------------------------- /instructions_0F00.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | #include "gdt.h" 12 | #include "interrupt.h" 13 | #include "util.h" 14 | 15 | void code_0f_00(Emulator *emu) 16 | { 17 | emu->eip += 2; 18 | ModRM modrm = create_modrm(); 19 | parse_modrm(emu, &modrm); 20 | 21 | switch (modrm.opcode) 22 | { 23 | /* ltr */ 24 | case 3: 25 | set_tr(emu, get_rm16(emu, &modrm)); 26 | break; 27 | default: 28 | printf("Not implemented: Op: 0F00 with ModR/M Op: %d\n", modrm.opcode); 29 | panic_exit(emu); 30 | } 31 | } 32 | 33 | void code_0f_01(Emulator *emu) 34 | { 35 | emu->eip += 2; 36 | ModRM modrm = create_modrm(); 37 | parse_modrm(emu, &modrm); 38 | 39 | switch (modrm.opcode) 40 | { 41 | case 2: 42 | lgdt(emu, &modrm); 43 | break; 44 | case 3: 45 | lidt(emu, &modrm); 46 | break; 47 | default: 48 | printf("Not implemented: Op: 0F01 with ModR/M Op: %d\n", modrm.opcode); 49 | panic_exit(emu); 50 | } 51 | } 52 | 53 | /* 54 | * push fs: 2 bytes 55 | * Pushes FS register to stack. 56 | * 2 bytes: op (0F A0) 57 | */ 58 | void push_fs(Emulator *emu) 59 | { 60 | push_segment_register(emu, FS); 61 | emu->eip += 2; 62 | } 63 | 64 | /* 65 | * pop fs: 2 bytes 66 | * Pops FS register to stack. 67 | * 2 bytes: op (0F A1) 68 | */ 69 | void pop_fs(Emulator *emu) 70 | { 71 | pop_segment_register(emu, FS); 72 | emu->eip += 2; 73 | } 74 | 75 | /* 76 | * push gs: 2 bytes 77 | * Pushes GS register to stack. 78 | * 2 bytes: op (0F A8) 79 | */ 80 | void push_gs(Emulator *emu) 81 | { 82 | push_segment_register(emu, GS); 83 | emu->eip += 2; 84 | } 85 | 86 | /* 87 | * pop gs: 2 bytes 88 | * Pops GS register to stack. 89 | * 2 bytes: op (0F A9) 90 | */ 91 | void pop_gs(Emulator *emu) 92 | { 93 | pop_segment_register(emu, GS); 94 | emu->eip += 2; 95 | } -------------------------------------------------------------------------------- /instructions_0F20.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | 11 | void mov_r32_cr(Emulator *emu) 12 | { 13 | emu->eip += 2; 14 | ModRM modrm = create_modrm(); 15 | parse_modrm(emu, &modrm); 16 | uint32_t cr_val = get_ctrl_register32(emu, modrm.reg_index); 17 | set_register32(emu, modrm.rm, cr_val); 18 | } 19 | 20 | void mov_cr_r32(Emulator *emu) 21 | { 22 | emu->eip += 2; 23 | ModRM modrm = create_modrm(); 24 | parse_modrm(emu, &modrm); 25 | uint32_t r32_val = get_register32(emu, modrm.rm); 26 | set_ctrl_register32(emu, modrm.reg_index, r32_val); 27 | } -------------------------------------------------------------------------------- /instructions_0F80.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "instruction_defs.h" 4 | #include "emulator_functions.h" 5 | 6 | /* 7 | * Macro for jump with eflag. 8 | * Replaces the matching text and ## concatenates strings. 9 | * Defined until unescaped line break. 10 | */ 11 | #define DEFINE_NEAR_JX(flag, is_flag) \ 12 | void j##flag##32(Emulator * emu) \ 13 | { \ 14 | int diff = is_flag(emu) ? get_sign_code32(emu, 2) : 0; \ 15 | emu->eip += (diff + 6); \ 16 | } \ 17 | void jn##flag##32(Emulator * emu) \ 18 | { \ 19 | int diff = is_flag(emu) ? 0 : get_sign_code32(emu, 2); \ 20 | emu->eip += (diff + 6); \ 21 | } 22 | /* 23 | * jc | jnc 24 | * Jumps near if carry (CF=1) | not carry (CF=0) 25 | * 2 bytes: op code (0F 82 | 0F 83) 26 | * 4 bytes: offset to jump 27 | */ 28 | DEFINE_NEAR_JX(c, is_carry) 29 | 30 | /* 31 | * jz | jnz 32 | * Jumps near if zero (ZF=1) | not zero (ZF=0) 33 | * 2 bytes: op code (0F 84 | 0F 85) 34 | * 4 bytes: offset to jump 35 | */ 36 | DEFINE_NEAR_JX(z, is_zero) 37 | 38 | /* 39 | * jna | ja 40 | * Jumps if not above (CF=1 or ZF=1) | above (CF=0 and ZF=0) 41 | * 2 byte: op code (0F 86 | 0F 87) 42 | * 4 bytes: offset to jump 43 | */ 44 | void jna32(Emulator *emu) 45 | { 46 | int diff = (is_carry(emu) || is_zero(emu)) ? get_sign_code32(emu, 2) : 0; 47 | emu->eip += (diff + 6); 48 | } 49 | 50 | void ja32(Emulator *emu) 51 | { 52 | int diff = (!is_carry(emu) && !is_zero(emu)) ? get_sign_code32(emu, 2) : 0; 53 | emu->eip += (diff + 6); 54 | } 55 | 56 | /* 57 | * js | jns 58 | * Jumps near if sign (SF=1) | not sign (SF=0) 59 | * 2 bytes: op code (0F 88 | 0F 89) 60 | * 4 bytes: offset to jump 61 | */ 62 | DEFINE_NEAR_JX(s, is_sign) 63 | 64 | /* 65 | * jge 66 | * Jumps if greater or equal (SF=OF) 67 | * 2 byte: op code (0F 8D) 68 | * 4 bytes: offset to jump 69 | */ 70 | void jge32(Emulator *emu) 71 | { 72 | int diff = (is_sign(emu) == is_overflow(emu)) ? get_sign_code32(emu, 2) : 0; 73 | emu->eip += (diff + 6); 74 | } 75 | /* 76 | * jng 77 | * Jumps if not greater (ZF=1 or SF!=OF) 78 | * 2 byte: op code (0F 8E) 79 | * 4 bytes: offset to jump 80 | */ 81 | void jng32(Emulator *emu) 82 | { 83 | int diff = (is_zero(emu) || (is_sign(emu) != is_overflow(emu))) ? get_sign_code32(emu, 2) : 0; 84 | emu->eip += (diff + 6); 85 | } 86 | /* 87 | * jg 88 | * Jumps if greater (ZF=0 and SF=OF) 89 | * 2 byte: op code (0F 8F) 90 | * 4 bytes: offset to jump 91 | */ 92 | void jg32(Emulator *emu) 93 | { 94 | int diff = (!is_zero(emu) && (is_sign(emu) == is_overflow(emu))) ? get_sign_code32(emu, 2) : 0; 95 | emu->eip += (diff + 6); 96 | } -------------------------------------------------------------------------------- /instructions_0F90.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "instruction_defs.h" 4 | #include "emulator_functions.h" 5 | 6 | /* 7 | * sete 8 | * Sets rm8 to 1 if zero flag is set, otherwise 0. 9 | * 2 byte: op code (0F 94) 10 | * 1|2 bytes: ModR/M 11 | */ 12 | void sete(Emulator *emu) 13 | { 14 | emu->eip += 2; 15 | ModRM modrm = create_modrm(); 16 | parse_modrm(emu, &modrm); 17 | if (is_zero(emu)) 18 | { 19 | set_rm8(emu, &modrm, 1); 20 | } 21 | else 22 | { 23 | set_rm8(emu, &modrm, 0); 24 | } 25 | } 26 | 27 | /* 28 | * setne 29 | * Sets rm8 to 1 if zero flag is not set, otherwise 0. 30 | * 2 byte: op code (0F 95) 31 | * 1|2 bytes: ModR/M 32 | */ 33 | void setne(Emulator *emu) 34 | { 35 | emu->eip += 2; 36 | ModRM modrm = create_modrm(); 37 | parse_modrm(emu, &modrm); 38 | if (is_zero(emu)) 39 | { 40 | set_rm8(emu, &modrm, 0); 41 | } 42 | else 43 | { 44 | set_rm8(emu, &modrm, 1); 45 | } 46 | } -------------------------------------------------------------------------------- /instructions_0FB0.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "instruction_defs.h" 4 | #include "emulator_functions.h" 5 | #include "modrm.h" 6 | 7 | /* 8 | * mov r32 rm8: 2 bytes 9 | * Copies value of zero-extended rm8 value to r32. 10 | * 2 byte: op (0FB6) 11 | * 1 byte: ModR/M 12 | */ 13 | void movzx_r32_rm8(Emulator *emu) 14 | { 15 | emu->eip += 2; 16 | ModRM modrm = create_modrm(); 17 | parse_modrm(emu, &modrm); 18 | uint32_t rm16 = 0 | get_rm8(emu, &modrm); 19 | set_r32(emu, &modrm, rm16); 20 | } 21 | 22 | /* 23 | * mov r32 rm16: 2 bytes 24 | * Copies value of zero-extended rm16 value to r32. 25 | * 2 byte: op (0FB7) 26 | * 1 byte: ModR/M 27 | */ 28 | void movzx_r32_rm16(Emulator *emu) 29 | { 30 | emu->eip += 2; 31 | ModRM modrm = create_modrm(); 32 | parse_modrm(emu, &modrm); 33 | uint32_t rm16 = 0 | get_rm16(emu, &modrm); 34 | set_r32(emu, &modrm, rm16); 35 | } 36 | 37 | /* 38 | * movsx r32 rm8: 3 bytes 39 | * Copies sign-extended rm8 value to r32. 40 | * 2 byte: op (0FBE) 41 | * 1 byte: ModR/M 42 | */ 43 | void movsx_r32_rm8(Emulator *emu) 44 | { 45 | emu->eip += 2; 46 | ModRM modrm = create_modrm(); 47 | parse_modrm(emu, &modrm); 48 | uint8_t rm8 = get_rm8(emu, &modrm); 49 | uint8_t sign = rm8 >> 7 & 1; 50 | if (sign == 1) 51 | { 52 | uint32_t sign_extended = 0xFFFFFF00 | rm8; 53 | set_r32(emu, &modrm, sign_extended); 54 | } 55 | else 56 | { 57 | set_r32(emu, &modrm, (uint32_t)rm8); 58 | } 59 | } 60 | 61 | /* 62 | * movsx r32 rm16: 3 bytes 63 | * Copies sign-extended rm16 value to r32. 64 | * 2 byte: op (0FBF) 65 | * 1 byte: ModR/M 66 | */ 67 | void movsx_r32_rm16(Emulator *emu) 68 | { 69 | emu->eip += 2; 70 | ModRM modrm = create_modrm(); 71 | parse_modrm(emu, &modrm); 72 | uint16_t rm16 = get_rm16(emu, &modrm); 73 | uint8_t sign = rm16 >> 15 & 1; 74 | if (sign == 1) 75 | { 76 | uint32_t sign_extended = 0xFFFF0000 | rm16; 77 | set_r32(emu, &modrm, sign_extended); 78 | } 79 | else 80 | { 81 | set_r32(emu, &modrm, (uint32_t)rm16); 82 | } 83 | } -------------------------------------------------------------------------------- /instructions_40.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | 12 | /* 13 | * inc r32: 1 byte 14 | * Increments a value of specified 32-bit register in op code. 15 | * 1 byte: op (40) + reg index (3 bits) 16 | */ 17 | void inc_r32(Emulator *emu) 18 | { 19 | uint8_t reg = get_code8(emu, 0) - 0x40; 20 | uint32_t r32_val = get_register32(emu, reg); 21 | uint32_t result = r32_val + 1; 22 | set_register32(emu, reg, result); 23 | update_eflags_add(emu, r32_val, 1, result); 24 | emu->eip += 1; 25 | } 26 | 27 | /* 28 | * dec r32: 1 byte 29 | * Decrements a value of specified 32-bit register in op code. 30 | * 1 byte: op (48) + reg index (3 bits) 31 | */ 32 | void dec_r32(Emulator *emu) 33 | { 34 | uint8_t reg = get_code8(emu, 0) - 0x48; 35 | uint32_t r32_val = get_register32(emu, reg); 36 | uint32_t result = r32_val - 1; 37 | set_register32(emu, reg, result); 38 | update_eflags_sub(emu, r32_val, 1, result); 39 | emu->eip += 1; 40 | } -------------------------------------------------------------------------------- /instructions_50.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | 12 | /* 13 | * push r32: 1 bytes 14 | * Pushes 32-bit value into memory stack from specified register. 15 | * 1 byte: op (50) + reg 16 | */ 17 | void push_r32(Emulator *emu) 18 | { 19 | u_int8_t reg = get_code8(emu, 0) - 0x50; 20 | push32(emu, get_register32(emu, reg)); 21 | emu->eip += 1; 22 | } 23 | 24 | /* 25 | * pop r32: 1 bytes 26 | * Pops 32-bit value into specified register from memory. 27 | * 1 byte: op (58) + reg 28 | */ 29 | void pop_r32(Emulator *emu) 30 | { 31 | u_int8_t reg = get_code8(emu, 0) - 0x58; 32 | set_register32(emu, reg, pop32(emu)); 33 | emu->eip += 1; 34 | } -------------------------------------------------------------------------------- /instructions_60.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | 12 | /* 13 | * pushad: 1 bytes 14 | * Pushes contents of general-purpose registers into stack. 15 | * 1 byte: op (60) 16 | */ 17 | void pushad(Emulator *emu) 18 | { 19 | uint32_t original_esp = get_register32(emu, ESP); 20 | push32(emu, get_register32(emu, EAX)); 21 | push32(emu, get_register32(emu, ECX)); 22 | push32(emu, get_register32(emu, EDX)); 23 | push32(emu, get_register32(emu, EBX)); 24 | push32(emu, original_esp); 25 | push32(emu, get_register32(emu, EBP)); 26 | push32(emu, get_register32(emu, ESI)); 27 | push32(emu, get_register32(emu, EDI)); 28 | emu->eip += 1; 29 | } 30 | 31 | /* 32 | * popad: 1 bytes 33 | * Pops from stack into general-purpose registers. 34 | * 1 byte: op (61) 35 | */ 36 | void popad(Emulator *emu) 37 | { 38 | set_register32(emu, EDI, pop32(emu)); 39 | set_register32(emu, ESI, pop32(emu)); 40 | set_register32(emu, EBP, pop32(emu)); 41 | /* Skips original ESP value by incrementing ESP by 4 bytes. */ 42 | set_register32(emu, ESP, get_register32(emu, ESP) + 4); 43 | set_register32(emu, EBX, pop32(emu)); 44 | set_register32(emu, EDX, pop32(emu)); 45 | set_register32(emu, ECX, pop32(emu)); 46 | set_register32(emu, EAX, pop32(emu)); 47 | emu->eip += 1; 48 | } 49 | 50 | /* 51 | * push imm32: 5 bytes 52 | * Pushes 32-bit immediate value into stack. 53 | * 1 byte: op (68) 54 | * 4 bytes: immediate 32-bit value 55 | */ 56 | void push_imm32(Emulator *emu) 57 | { 58 | uint32_t value = get_code32(emu, 1); 59 | push32(emu, value); 60 | emu->eip += 5; 61 | } 62 | 63 | static void imul_r32_rm32_imm(Emulator *emu, ModRM *modrm, int32_t imm_val) 64 | { 65 | uint64_t result; 66 | if (modrm->mod == 3) 67 | { 68 | /* r32 = r32 * signed imm */ 69 | int32_t r32_val = get_register32(emu, modrm->reg_index); 70 | result = (int64_t)r32_val * (int64_t)imm_val; 71 | } 72 | else 73 | { 74 | /* r32 = rm32 * signed imm */ 75 | int32_t rm32_val = get_rm32(emu, modrm); 76 | result = (int64_t)rm32_val * (int64_t)imm_val; 77 | } 78 | uint32_t res_upper_half = result >> 32; 79 | uint32_t res_lower_half = (uint32_t)result; 80 | update_eflags_mul(emu, res_upper_half); 81 | set_register32(emu, modrm->reg_index, res_lower_half); 82 | } 83 | 84 | /* 85 | * imul r32 imm8 | imul r32 rm32 imm32: 6|7 bytes 86 | * Performs signed multiplication (r32 = (r32|rm32) * imm32). 87 | * 1 byte: op (69) 88 | * 1|2 bytes: ModRm 89 | * 4 bytes: imm32 value 90 | */ 91 | void imul_r32_rm32_imm32(Emulator *emu) 92 | { 93 | /* Proceed 1 byte for op code 6B. */ 94 | emu->eip += 1; 95 | ModRM modrm = create_modrm(); 96 | parse_modrm(emu, &modrm); 97 | int32_t imm32_val = get_code32(emu, 0); 98 | emu->eip += 4; 99 | imul_r32_rm32_imm(emu, &modrm, imm32_val); 100 | } 101 | 102 | /* 103 | * push imm8: 2 bytes 104 | * Pushes 8-bit immediate value into stack. 105 | * 1 byte: op (6A) 106 | * 1 byte: immediate 8-bit value 107 | */ 108 | void push_imm8(Emulator *emu) 109 | { 110 | uint8_t value = get_code8(emu, 1); 111 | push32(emu, (uint32_t)value); 112 | emu->eip += 2; 113 | } 114 | 115 | /* 116 | * imul r32 imm8 | imul r32 rm32 imm8: 3|4 bytes 117 | * Performs signed multiplication (r32 = (r32|rm32) * imm8). 118 | * 1 byte: op (6B) 119 | * 1|2 bytes: ModRm 120 | * 1 bytes: imm8 value 121 | */ 122 | void imul_r32_rm32_imm8(Emulator *emu) 123 | { 124 | /* Proceed 1 byte for op code 6B. */ 125 | emu->eip += 1; 126 | ModRM modrm = create_modrm(); 127 | parse_modrm(emu, &modrm); 128 | int8_t imm8_val = get_code8(emu, 0); 129 | emu->eip += 1; 130 | imul_r32_rm32_imm(emu, &modrm, imm8_val); 131 | } 132 | 133 | /* 134 | * ins m32 dx 135 | * Inputs dword from DX port into ES:EDI 136 | * 1 byte: op (6D) 137 | */ 138 | void ins_m32_dx(Emulator *emu) 139 | { 140 | uint16_t dx_val = get_register16(emu, EDX); 141 | uint32_t in_val = io_in32(emu, dx_val); 142 | uint32_t edi_val = get_register32(emu, EDI); 143 | set_memory32(emu, ES, edi_val, in_val); 144 | if (is_direction_down(emu)) 145 | { 146 | set_register32(emu, EDI, edi_val - 4); 147 | } 148 | else 149 | { 150 | set_register32(emu, EDI, edi_val + 4); 151 | } 152 | emu->eip += 1; 153 | } -------------------------------------------------------------------------------- /instructions_70.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | 12 | /* 13 | * Macro for jump with eflag. 14 | * Replaces the matching text and ## concatenates strings. 15 | * Defined until unescaped line break. 16 | */ 17 | #define DEFINE_JX(flag, is_flag) \ 18 | void j##flag(Emulator *emu) \ 19 | { \ 20 | int diff = is_flag(emu) ? get_sign_code8(emu, 1) : 0; \ 21 | emu->eip += (diff + 2); \ 22 | } \ 23 | void jn##flag(Emulator *emu) \ 24 | { \ 25 | int diff = is_flag(emu) ? 0 : get_sign_code8(emu, 1); \ 26 | emu->eip += (diff + 2); \ 27 | } 28 | 29 | /* 30 | * jc (72), jnc (73), jz (74), jnz (75), js (78), jns (79), jo (70), jno (71): 2 bytes 31 | * 1 byte: op code 32 | * 1 byte: offset to jump 33 | */ 34 | DEFINE_JX(c, is_carry) 35 | DEFINE_JX(z, is_zero) 36 | DEFINE_JX(s, is_sign) 37 | DEFINE_JX(o, is_overflow) 38 | 39 | #undef DEFINE_JX 40 | 41 | /* 42 | * jna (76) 43 | * Jumps if above (CF=1 or ZF=1) 44 | * 1 byte: op code 45 | * 1 byte: offset to jump 46 | */ 47 | void jna(Emulator *emu) 48 | { 49 | int diff = (is_zero(emu) || is_carry(emu)) ? get_sign_code8(emu, 1) : 0; 50 | emu->eip += (diff + 2); 51 | } 52 | 53 | /* 54 | * ja (77) 55 | * Jumps if above (CF=0 and ZF=0) 56 | * 1 byte: op code 57 | * 1 byte: offset to jump 58 | */ 59 | void ja(Emulator *emu) 60 | { 61 | int diff = (!is_zero(emu) && !is_carry(emu)) ? get_sign_code8(emu, 1) : 0; 62 | emu->eip += (diff + 2); 63 | } 64 | 65 | /* 66 | * jl (7C) and jle (7E) 67 | * Assuming there's no overflow, which means overflow_flag == 0, 68 | * if sign_flag is 0, left is bigger. Ex: 69 | * 3, 2: 3 - 2 = 1 => sign_flag: 0 => larger 70 | * -3, 2: -3 - (2) = -5 => sign_flag: 1 => smaller 71 | * -1, -4: -1 - (-4) = 3 => sign_flag: 0 => larger 72 | */ 73 | void jl(Emulator *emu) 74 | { 75 | int diff = (is_sign(emu) != is_overflow(emu)) ? get_sign_code8(emu, 1) : 0; 76 | emu->eip += (diff + 2); 77 | } 78 | 79 | void jle(Emulator *emu) 80 | { 81 | int diff = (is_zero(emu) || (is_sign(emu) != is_overflow(emu))) ? get_sign_code8(emu, 1) : 0; 82 | emu->eip += (diff + 2); 83 | } 84 | 85 | /* 86 | * jge (7D) 87 | * Jumps if greater or equal (SF=OF) 88 | * 1 byte: op code 89 | * 1 byte: offset to jump 90 | */ 91 | void jge(Emulator *emu) 92 | { 93 | int diff = ((is_sign(emu) == is_overflow(emu))) ? get_sign_code8(emu, 1) : 0; 94 | emu->eip += (diff + 2); 95 | } 96 | 97 | /* 98 | * jg (7f) 99 | * Jumps if greater (ZF=0 and SF=OF) 100 | * 1 byte: op code 101 | * 1 byte: offset to jump 102 | */ 103 | void jg(Emulator *emu) 104 | { 105 | int diff = (!is_zero(emu) && (is_sign(emu) == is_overflow(emu))) ? get_sign_code8(emu, 1) : 0; 106 | emu->eip += (diff + 2); 107 | } 108 | -------------------------------------------------------------------------------- /instructions_90.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | 12 | /* 13 | * xchg r32 r32: 1 byte 14 | * Exchanges values of EAX and r32. 15 | * 1 byte: op (90 ~ 97) 16 | */ 17 | void xchg_r32_r32(Emulator *emu) 18 | { 19 | uint8_t reg = get_code8(emu, 0) - 0x90; 20 | uint32_t original_val = get_register32(emu, reg); 21 | set_register32(emu, reg, get_register32(emu, EAX)); 22 | set_register32(emu, EAX, original_val); 23 | emu->eip += 1; 24 | } 25 | 26 | /* 27 | * xchg r16 r16: 1 byte 28 | * Exchanges values of AX and r16. 29 | * 1 byte: op (90 ~ 97) 30 | */ 31 | void xchg_r16_r16(Emulator *emu) 32 | { 33 | uint8_t reg = get_code8(emu, 0) - 0x90; 34 | uint16_t original_val = get_register16(emu, reg); 35 | set_register16(emu, reg, get_register16(emu, EAX)); 36 | set_register16(emu, EAX, original_val); 37 | emu->eip += 1; 38 | } 39 | 40 | /* 41 | * cwde: 1 byte 42 | * Sign-extend word(AX) to double word(EAX). 43 | * 1 byte: op (98) 44 | */ 45 | void cwde(Emulator *emu) 46 | { 47 | uint32_t eax = get_register32(emu, EAX); 48 | uint16_t ax = (uint16_t)eax; 49 | uint8_t sign = ax >> 15 & 1; 50 | if (sign == 1) 51 | { 52 | uint32_t sign_extended = 0xFFFF0000 | ax; 53 | set_register32(emu, EAX, sign_extended); 54 | } 55 | else 56 | { 57 | set_register32(emu, EAX, (uint32_t)ax); 58 | } 59 | emu->eip += 1; 60 | } 61 | 62 | /* 63 | * cdq: 1 byte 64 | * Sign-extend double word(EAX) to quad word(EDX:EAX). 65 | * 1 byte: op (99) 66 | */ 67 | void cdq(Emulator *emu) 68 | { 69 | uint32_t eax = get_register32(emu, EAX); 70 | uint8_t sign = eax >> 31 & 1; 71 | if (sign == 1) 72 | set_register32(emu, EDX, 0xFFFFFFFF); 73 | else 74 | set_register32(emu, EDX, 0); 75 | emu->eip += 1; 76 | } 77 | 78 | /* 79 | * call ptr16:16/32: 7 bytes 80 | * Pushes CS and EIP in order and jumps to ptr16:32. 81 | * 1 byte: op (9A) 82 | * 2 byte: cs value 83 | * 2|4 byte: eip (ptr16|32) 84 | */ 85 | void ptr_call(Emulator *emu) 86 | { 87 | push_segment_register(emu, CS); 88 | if (emu->is_pe) 89 | push32(emu, emu->eip + 7); 90 | else 91 | push32(emu, emu->eip + 5); 92 | ptr_jump(emu); 93 | } 94 | 95 | /* 96 | * pushf / pushfd: 1 byte 97 | * Pushes EFLAGS into stack. 98 | * 1 byte: op (9C) 99 | */ 100 | void pushfd(Emulator *emu) 101 | { 102 | /* 103 | if (emu->is_pe) 104 | push32(emu, emu->eflags); 105 | else 106 | push16(emu, (uint16_t)emu->eflags); 107 | */ 108 | push32(emu, emu->eflags); 109 | emu->eip += 1; 110 | }; 111 | 112 | /* 113 | * popf / popfd: 1 byte 114 | * Pops stack into EFLAGS. 115 | * 1 byte: op (9D) 116 | */ 117 | void popfd(Emulator *emu) 118 | { 119 | /* 120 | uint32_t value; 121 | if (emu->is_pe) 122 | value = pop32(emu); 123 | else 124 | value = (uint32_t)pop16(emu); 125 | emu->eflags = value; 126 | */ 127 | emu->eflags = pop32(emu); 128 | emu->eip += 1; 129 | }; 130 | 131 | /* 132 | * sahf: 133 | * Stores AH into FLAGS (Bit 0, 2, 4, 6, 7). 134 | * 1 byte: op (9E) 135 | */ 136 | void sahf(Emulator *emu) 137 | { 138 | /* AH value AND 1101 0101 128 64 16 4 1 = 213 */ 139 | uint8_t ah_val = get_register8(emu, AH) & 213; 140 | /* Higher half of EFLAGS: AND 0xFFFF0000 */ 141 | uint32_t eflags_h = emu->eflags & 0xFFFF0000; 142 | 143 | emu->eflags = eflags_h | ah_val; 144 | emu->eip += 1; 145 | } 146 | 147 | /* 148 | * lahf: 149 | * Load FLAGS into AH (0, 2, 4, 6, 7th bits). 150 | * 1 byte: op (9F) 151 | */ 152 | void lahf(Emulator *emu) 153 | { 154 | uint8_t eflags_l = emu->eflags & 213; 155 | set_register8(emu, AH, eflags_l); 156 | emu->eip += 1; 157 | } -------------------------------------------------------------------------------- /instructions_B0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "instruction_defs.h" 8 | #include "emulator_functions.h" 9 | #include "modrm.h" 10 | #include "io.h" 11 | 12 | /* 13 | * mov r8 imm8: 2 bytes 14 | * Copies 8-bit imm value to register specified in op code. 15 | * 1 byte: op (B0) + reg index (3 bits) 16 | * 1 byte: value (8-bit unsigned) 17 | */ 18 | void mov_r8_imm8(Emulator *emu) 19 | { 20 | uint8_t reg = get_code8(emu, 0) - 0xB0; 21 | set_register8(emu, reg, get_code8(emu, 1)); 22 | emu->eip += 2; 23 | } 24 | 25 | /* 26 | * mov r32 imm32: 5 bytes 27 | * Copies imm value to register specified in op code (r32: 32 bit register). 28 | * 1 byte: op (B8) + reg index (3bits) 29 | * 4 bytes: value (32 bit unsigned) 30 | */ 31 | void mov_r32_imm32(Emulator *emu) 32 | { 33 | uint8_t reg = get_code8(emu, 0) - 0xB8; 34 | uint32_t value = get_code32(emu, 1); 35 | set_register32(emu, reg, value); 36 | emu->eip += 5; 37 | } 38 | 39 | /* 40 | * mov r16 imm16: 3 bytes 41 | * Copies imm value to register specified in op code (r32: 32 bit register). 42 | * 1 byte: op (B8) + reg index (3bits) 43 | * 2 bytes: value (16 bit unsigned) 44 | */ 45 | void mov_r16_imm16(Emulator *emu) 46 | { 47 | uint8_t reg = get_code8(emu, 0) - 0xB8; 48 | uint32_t value = get_code32(emu, 1); 49 | set_register16(emu, reg, value); 50 | emu->eip += 3; 51 | } -------------------------------------------------------------------------------- /interrupt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "interrupt.h" 5 | #include "emulator_functions.h" 6 | #include "util.h" 7 | #include "gdt.h" 8 | 9 | /* 10 | * 11 | * IDT: 12 | * 48 bits long register to hold size and the starting address of GDT. 13 | * | 31 16 | 15 0 | 14 | * | Seg Selector 0:15 | Offset 0:15 | 15 | * |____________________________|____________________________| 16 | * | 63 48 |47|46 45|44 40|39 35|34 32| 17 | * | Offset 16:31 |Pr| DPL |Type | 0 | IST | 18 | * |____________________________|______________|_____________| 19 | */ 20 | void lidt(Emulator *emu, ModRM *modrm) 21 | { 22 | uint32_t address = calc_memory_address(emu, modrm); 23 | uint16_t limit = get_memory16(emu, DS, address); 24 | uint32_t base = get_memory32(emu, DS, address + 2); 25 | set_idtr(emu, limit, get_physical_address(emu, DS, base, 0)); 26 | } 27 | 28 | /* 29 | * Real mode and VM (Virtual 8086) is not supported. 30 | */ 31 | void handle_interrupt(Emulator *emu, uint8_t vector, int sw) 32 | { 33 | if (!emu->is_pe) 34 | { 35 | printf("Interrupt in real mode not implemented.\n"); 36 | panic_exit(emu); 37 | } 38 | uint32_t entry_addr = emu->idtr.base + (vector * 8); 39 | if (entry_addr > (emu->idtr.base + emu->idtr.limit)) 40 | { 41 | printf("IDT entry is beyond table limit.\n"); 42 | panic_exit(emu); 43 | } 44 | uint32_t entry1 = _get_memory32(emu, entry_addr); 45 | uint32_t entry2 = _get_memory32(emu, entry_addr + 4); 46 | 47 | uint8_t cpl = get_seg_register16(emu, CS) & 3; 48 | uint8_t dpl = (entry2 >> 13) & 0x3; 49 | 50 | if (sw && (dpl < cpl)) 51 | { 52 | printf("Privilege not met in software interrupt.\n"); 53 | panic_exit(emu); 54 | } 55 | 56 | uint16_t gate_selector = entry1 >> 16; 57 | uint8_t gate_dpl = gate_selector & 3; 58 | uint32_t gate_offset = 0 | (entry1 & 0xFFFF) | (entry2 & 0xFFFF0000); 59 | /* Inter-privilege */ 60 | if (gate_dpl < cpl) 61 | { 62 | // printf("inter-privilege interrupt: %d\n", vector); 63 | // debug_print(); 64 | uint16_t cur_ss = get_seg_register16(emu, SS); 65 | uint32_t cur_esp = get_register32(emu, ESP); 66 | uint16_t cur_cs = get_seg_register16(emu, CS); 67 | uint32_t cur_eip = emu->eip; 68 | 69 | /* Get TSS */ 70 | uint8_t tss_desc_index = emu->tr >> 3; 71 | uint32_t tss_desc_base = emu->gdtr.base + (tss_desc_index * 8); 72 | uint32_t entry1 = _get_memory32(emu, tss_desc_base); 73 | uint32_t entry2 = _get_memory32(emu, tss_desc_base + 4); 74 | uint32_t tss_base = read_gdt_entry_base(entry1, entry2); 75 | uint16_t tss_ss = (uint16_t)get_memory32(emu, DS, tss_base + 8); 76 | uint32_t tss_esp = get_memory32(emu, DS, tss_base + 4); 77 | 78 | set_seg_register16(emu, SS, tss_ss); 79 | set_register32(emu, ESP, tss_esp); 80 | 81 | set_seg_register16(emu, CS, gate_selector); 82 | emu->eip = gate_offset; 83 | 84 | push32(emu, cur_ss); 85 | push32(emu, cur_esp); 86 | push32(emu, emu->eflags); 87 | push32(emu, cur_cs); 88 | push32(emu, cur_eip); 89 | /* error code */ 90 | // push32(emu, 0); 91 | } 92 | /* Kernel mode */ 93 | else 94 | { 95 | // printf("intra-level interrupt: %d\n", vector); 96 | uint16_t cur_cs = get_seg_register16(emu, CS); 97 | uint32_t cur_eip = emu->eip; 98 | push32(emu, emu->eflags); 99 | push32(emu, cur_cs); 100 | push32(emu, cur_eip); 101 | /* error code */ 102 | // push32(emu, 0); 103 | set_seg_register16(emu, CS, gate_selector); 104 | emu->eip = gate_offset; 105 | } 106 | if (!sw) 107 | set_int_flag(emu, 0); 108 | } -------------------------------------------------------------------------------- /interrupt.h: -------------------------------------------------------------------------------- 1 | #ifndef INT_H_ 2 | #define INT_H_ 3 | 4 | #include "emulator.h" 5 | #include "modrm.h" 6 | 7 | #define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ 8 | 9 | #define IRQ_TIMER 0 10 | #define IRQ_KBD 1 11 | #define IRQ_COM1 4 12 | #define IRQ_IDE 14 13 | #define IRQ_ERROR 19 14 | #define IRQ_SPURIOUS 31 15 | 16 | void lidt(Emulator *emu, ModRM *modrm); 17 | void handle_interrupt(Emulator *emu, uint8_t vector, int sw); 18 | 19 | #endif -------------------------------------------------------------------------------- /io.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | #include 3 | #include 4 | #include "emulator.h" 5 | #include "kbd.h" 6 | #include "instructions.h" 7 | #include "util.h" 8 | 9 | /* 10 | * PS/2 (keyboard) Controller 11 | * 0x60: in|out: Data Register 12 | * 0x64: in: Status Register | out: Command Register 13 | */ 14 | #define PS2DATA 0x60 15 | #define PS2STACMD 0x64 16 | 17 | /* 18 | * Serial (COM1) 19 | * 0x3f8: in|out: Data port 20 | * 0x3fd: in: Status port 21 | */ 22 | #define SERIALSTA 0x3fd 23 | #define SERIALDATA 0x3f8 24 | #define SERIALLINESTA 0x3fd 25 | 26 | /* 27 | * Disk 28 | * 0x1F0: Data Register 29 | * 0x1F2: in|out: Sector Count Register 30 | * 0x1F3: in|out: LBA Low 31 | * 0x1F4: in|out: LBA Mid 32 | * 0x1F5: in|out: LBA High 33 | * 0x1F6: in|out: Drive/Head Register 34 | * 0x1F7: in: Status Register | out: Command Register 35 | */ 36 | #define DISKDATA 0x1f0 37 | #define DISKSECCOUNT 0x1f2 38 | #define DISKLBALOW 0x1f3 39 | #define DISKLBAMID 0x1f4 40 | #define DISKLBAHIGH 0x1f5 41 | #define DISKDRVHEAD 0x1f6 42 | #define DISKSTACMD 0x1f7 43 | 44 | uint8_t io_in8(Emulator *emu, uint16_t address) 45 | { 46 | switch (address) 47 | { 48 | case PS2DATA: 49 | return get_kbd_data(); 50 | case PS2STACMD: 51 | return get_kbd_status(); 52 | case DISKSTACMD: 53 | return get_disk_status(emu->disk); 54 | case SERIALDATA: 55 | return 0; 56 | // return getchar(); 57 | case SERIALLINESTA: 58 | return 0x20; 59 | default: 60 | if (config.verbose) 61 | printf("IN8 on port %x not implemented.\n", address); 62 | return 0; 63 | } 64 | } 65 | 66 | uint32_t io_in32(Emulator *emu, uint16_t address) 67 | { 68 | switch (address) 69 | { 70 | case 0x1F0: 71 | return read_disk_data32(emu->disk); 72 | case SERIALDATA: 73 | return 0; 74 | // return getchar(); 75 | default: 76 | if (config.verbose) 77 | printf("IN32 on port %x not implemented.\n", address); 78 | return 0; 79 | } 80 | } 81 | 82 | void io_out8(Emulator *emu, uint16_t address, uint8_t value) 83 | { 84 | switch (address) 85 | { 86 | case PS2DATA: 87 | write_ps2_config_byte(value); 88 | break; 89 | case PS2STACMD: 90 | write_ps2_output_port(value); 91 | break; 92 | case DISKSECCOUNT: 93 | set_sec_count(emu->disk, value); 94 | break; 95 | case DISKLBALOW: 96 | set_lba_low(emu->disk, value); 97 | break; 98 | case DISKLBAMID: 99 | set_lba_mid(emu->disk, value); 100 | break; 101 | case DISKLBAHIGH: 102 | set_lba_high(emu->disk, value); 103 | break; 104 | case DISKDRVHEAD: 105 | set_drive_head(emu->disk, value); 106 | break; 107 | case DISKSTACMD: 108 | set_disk_command(emu->disk, value); 109 | break; 110 | case SERIALDATA: 111 | putchar(value); 112 | break; 113 | default: 114 | if (config.verbose) 115 | printf("OUT8 on port %x not implemented.\n", address); 116 | break; 117 | } 118 | } 119 | 120 | void io_out32(Emulator *emu, uint16_t address, uint32_t value) 121 | { 122 | switch (address) 123 | { 124 | case SERIALDATA: 125 | putchar(value); 126 | break; 127 | default: 128 | if (config.verbose) 129 | printf("OUT32 on port %x not implemented.\n", address); 130 | break; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_H_ 2 | #define IO_H_ 3 | 4 | #include 5 | 6 | #include "emulator.h" 7 | 8 | uint8_t io_in8(Emulator *emu, uint16_t address); 9 | uint32_t io_in32(Emulator *emu, uint16_t address); 10 | 11 | void io_out8(Emulator *emu, uint16_t address, uint8_t value); 12 | void io_out32(Emulator *emu, uint16_t address, uint32_t value); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /ioapic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ioapic.h" 5 | #include "lapic.h" 6 | 7 | IOAPIC *ioapic; 8 | 9 | void init_ioapic() 10 | { 11 | ioapic = malloc(sizeof(IOAPIC)); 12 | ioapic->select_register = 0x0; 13 | ioapic->window_register = 0x0; 14 | ioapic->id_register = 0x0; 15 | ioapic->ver_register = 0x170011; 16 | ioapic->arb_register = 0x0; 17 | memset(ioapic->redirect_tbl, 0, sizeof(ioapic->redirect_tbl)); 18 | } 19 | 20 | void add_lapic(uint8_t index, LAPIC *lapic) 21 | { 22 | ioapic->lapic[index] = lapic; 23 | } 24 | 25 | static uint8_t get_dest_id(uint8_t irq) 26 | { 27 | uint8_t i; 28 | for (i = 0; i < 48; i += 2) 29 | { 30 | if (irq == ioapic->redirect_tbl[i]) 31 | { 32 | return ioapic->redirect_tbl[i + 1]; 33 | } 34 | } 35 | return 0; 36 | } 37 | 38 | void ioapic_int_to_lapic(uint8_t irq) 39 | { 40 | uint8_t dest_id = get_dest_id(irq); 41 | lapic_write_to_irr(ioapic->lapic[dest_id], irq); 42 | } 43 | 44 | void ioapic_write_reg(uint32_t addr, uint32_t val) 45 | { 46 | uint8_t offset = addr - IOAPIC_DEFAULT_BASE; 47 | /* Writing on selector register. */ 48 | if (offset == 0x0) 49 | { 50 | ioapic->select_register = val; 51 | /* Moves value into window register when selector register is set. */ 52 | if (val == 0x0) 53 | { 54 | ioapic->window_register = ioapic->id_register; 55 | } 56 | else if (val == 0x1) 57 | { 58 | ioapic->window_register = ioapic->ver_register; 59 | } 60 | else if (val == 0x2) 61 | { 62 | ioapic->window_register = ioapic->arb_register; 63 | } 64 | return; 65 | } 66 | /* Writing on window register. */ 67 | if (offset == 0x10) 68 | { 69 | if (ioapic->select_register >= 0x10) 70 | { 71 | uint8_t rdr_tbl_index = ioapic->select_register - 0x10; 72 | ioapic->redirect_tbl[rdr_tbl_index] = val; 73 | } 74 | return; 75 | } 76 | } 77 | 78 | uint32_t ioapic_read_reg(uint32_t addr) 79 | { 80 | uint8_t offset = addr - IOAPIC_DEFAULT_BASE; 81 | if (offset == 0x10) 82 | { 83 | return ioapic->window_register; 84 | } 85 | return 0; 86 | } 87 | 88 | void dump_ioapic() 89 | { 90 | printf("\n", (void *)ioapic); 91 | printf("IOREGSEL: %08x IOWIN: %08x IOAPICID: %08x\n", ioapic->select_register, ioapic->window_register, ioapic->id_register); 92 | printf("Redirection Tables: "); 93 | uint8_t i; 94 | for (i = 0; i < 48; i += 2) 95 | { 96 | if (ioapic->redirect_tbl[i] > 0) 97 | { 98 | printf("[IRQ: %08x DESTID: %08x] ", ioapic->redirect_tbl[i], ioapic->redirect_tbl[i + 1]); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /ioapic.h: -------------------------------------------------------------------------------- 1 | #ifndef IOAPIC_H_ 2 | #define IOAPIC_H_ 3 | 4 | #include 5 | 6 | #include "lapic.h" 7 | 8 | #define IOAPIC_DEFAULT_BASE 0xFEC00000 9 | #define IOAPIC_ID = 0x0; 10 | 11 | /* 12 | * 13 | * 14 | * - IOREGSEL 15 | * I/O REGISTER SELECT REGISTER: RW 16 | * 0xFEC0 xy00 (xy=See APICBASE Register in the PIIX3) 17 | * |31_____________8|7____________________0| 18 | * |____Reserved____|_APIC_Register_Offset_| 19 | * 20 | * - IOWIN 21 | * I/O WINDOW REGISTER: RW 22 | * 0xFEC0 xy10 (xy=See APICBASE Register in PIIX3) 23 | * |31__________________________________0| 24 | * |_________APIC_Register_Data__________| 25 | * 26 | * 27 | * 28 | * - IOAPICID: RW 29 | * Offset: 0x0 30 | * |31________28|27___24|23_____________0| 31 | * |__Reserved__|APIC_ID|____Reserved____| 32 | * 33 | * - IOAPICVER: RO 34 | * Offset: 0x1 35 | * |31_24|23___________________16|15_8|7_______0| 36 | * |Rsvd_|_Max_Redirection_Entry_|Rsvd|_Version_| 37 | * 38 | * - IOAPICARB: RO 39 | * Arbitration priority of for bus ownershipt (rotating priority scheme: 15 wins) 40 | * Offset: 0x2 41 | * |31________28|27__________24|23_____________0| 42 | * |__Reserved__|Arbitration_ID|____Reserved____| 43 | * 44 | * - IOREDTBL[23:0] 64-bit entries (2 x 32-bit registers): RW 45 | * Offset: 46 | * 0x10-0x11 (IOREDTBL0) 47 | * 0x12-0x13 (IOREDTBL1) 48 | * ... 49 | * 0x3E-0x3F (IOREDTBL23) 50 | * 51 | * |63___________56|55________________________32| 52 | * |__Destination__|_________Reserved___________| 53 | * 54 | * Destination Field: 55 | * APIC ID in physical destination mode *xv6 uses this with APIC ID (cpunum) 56 | * Set of processors in logical mode 57 | * 58 | * |31______17|16__|15_|14_|13_|12__|11__|10_8|7____________0| 59 | * | Reserved ||Msk|Trg|IRR|Pol|DelS|DesM|DelM|__Int_Vector__| 60 | * 61 | * Msk = Interrupt mask: 1: masked 62 | * Trg = Trigger mode: 1: level sensitive / 0: edge sensitive 63 | * IRR = Remote IRR: APIC Ack in level-sensitive mode: 1: ack in local APIC -> 0: EOI from local APIC 64 | * Pol = Interrupt Pin Polarity: 0: high active / 1: low active 65 | * DelS = Delivery Status: 0: idle / 1: pending to send 66 | * DesM = Destination Mode: 67 | * 0: physical mode (Destination APIC is by ID) 68 | * 1: logical mode (Destination Format Register and Logical Destination Register in each Local APIC) 69 | * DelM = Delivery Mode: 70 | * 0: Fixed (Signal on INTR to all destinations. Both edge/level.) 71 | * 1: Lowest Priority (To processor with lowest priority. Both edge/level.) 72 | * 2: SMI (System management interrrupt. Vector is ignored.) 73 | * 3: Reserved 74 | * 4: NMI (NMI to all destinations. Vector is ignored. Only edge.) 75 | * 5: INIT (INIT to all destinations. Only edge.) 76 | * 6: Reserved 77 | * 7: ExtINT (INTR signal from external connection like 8259A to all destinations. Only edge.) 78 | * Int Vector: 8-bit field containing the interrupt (10h to FEh). 79 | */ 80 | 81 | typedef struct 82 | { 83 | uint32_t select_register; 84 | uint32_t window_register; 85 | uint32_t id_register; 86 | uint32_t ver_register; 87 | uint32_t arb_register; 88 | uint32_t redirect_tbl[48]; 89 | LAPIC *lapic[8]; 90 | } IOAPIC; 91 | 92 | extern IOAPIC *ioapic; 93 | 94 | void init_ioapic(); 95 | 96 | void add_lapic(uint8_t index, LAPIC *lapic); 97 | void ioapic_int_to_lapic(uint8_t irq); 98 | 99 | void ioapic_write_reg(uint32_t addr, uint32_t val); 100 | uint32_t ioapic_read_reg(uint32_t addr); 101 | 102 | void dump_ioapic(); 103 | #endif -------------------------------------------------------------------------------- /kbd.h: -------------------------------------------------------------------------------- 1 | #ifndef KBD_H_ 2 | #define KBD_H_ 3 | 4 | #include 5 | 6 | #include "ioapic.h" 7 | 8 | #define KBD_BUF_SIZE 255 9 | #define KBD_STATUS_IN 2 10 | 11 | #define NO 0 12 | /* 13 | * Status Register 14 | * |_b_|_meaning________________________________________| 15 | * | 0 | Output Buffer: 0=empty / 1=full *a | 16 | * | 1 | Input Buffer: 0=empty / 1=full *b | 17 | * | 2 | System Flag: 0 on reset / 1 after passing POST | 18 | * | 3 | Command/Data: 0=data 1=command for device | 19 | * | 4 | Chipset specific | 20 | * | 5 | Chipset specific | 21 | * | 6 | Time-out Error: 0=noerror / 1=error | 22 | * | 7 | Parity Error: 0=noerror / 1=error | 23 | * |____________________________________________________| 24 | * a. must be set before attempting to read data from IO port 0x60 25 | * b. must be clear before attempting to write data to IO port 0x60 or IO port 0x64 26 | */ 27 | typedef struct 28 | { 29 | uint8_t status; 30 | IOAPIC *ioapic; 31 | unsigned int buf[256]; 32 | uint8_t buf_index; 33 | uint8_t buf_out_index; 34 | uint8_t buf_index_reset; 35 | } KBD; 36 | 37 | void init_kbd(IOAPIC *ioapic); 38 | uint8_t get_kbd_status(); 39 | uint8_t get_kbd_data(); 40 | void write_ps2_output_port(uint8_t value); 41 | void write_ps2_config_byte(uint8_t value); 42 | 43 | #endif -------------------------------------------------------------------------------- /lapic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "lapic.h" 9 | #include "interrupt.h" 10 | 11 | #define IRR_L 32 12 | 13 | LAPIC *create_lapic(Emulator *emu) 14 | { 15 | LAPIC *lapic = malloc(sizeof(LAPIC)); 16 | memset(lapic->registers, 0, sizeof(lapic->registers)); 17 | lapic->emu = emu; 18 | pthread_t timer_thread; 19 | lapic->timer_thread = &timer_thread; 20 | return lapic; 21 | } 22 | 23 | void lapic_send_intr(LAPIC *lapic) 24 | { 25 | if (!lapic->int_enabled || !lapic->unit_enabled || !lapic->emu->int_enabled || lapic->registers[EOI >> 4] != 0) 26 | { 27 | return; 28 | } 29 | pthread_mutex_lock(&lapic->lock); 30 | uint8_t i; 31 | for (i = 0; i < IRR_L; i++) 32 | { 33 | if (lapic->irr[i] > 0) 34 | { 35 | lapic->isr[i] = lapic->irr[i]; 36 | lapic->isr_index = i; 37 | lapic->emu->int_r = lapic->irr[i]; 38 | lapic->registers[EOI >> 4] = 1; 39 | lapic->irr[i] = 0; 40 | break; 41 | } 42 | } 43 | pthread_mutex_unlock(&lapic->lock); 44 | } 45 | 46 | static void lapic_eoi(LAPIC *lapic) 47 | { 48 | pthread_mutex_lock(&lapic->lock); 49 | lapic->isr[lapic->isr_index] = 0; 50 | lapic->registers[EOI >> 4] = 0; 51 | pthread_mutex_unlock(&lapic->lock); 52 | lapic_send_intr(lapic); 53 | } 54 | 55 | void lapic_write_to_irr(LAPIC *lapic, uint8_t irq) 56 | { 57 | if (!lapic->unit_enabled || !lapic->int_enabled) 58 | { 59 | return; 60 | } 61 | pthread_mutex_lock(&lapic->lock); 62 | uint8_t i; 63 | for (i = 0; i < IRR_L; i++) 64 | { 65 | if (lapic->irr[i] == 0) 66 | { 67 | lapic->irr[i] = irq; 68 | pthread_mutex_unlock(&lapic->lock); 69 | lapic_send_intr(lapic); 70 | return; 71 | } 72 | } 73 | pthread_mutex_unlock(&lapic->lock); 74 | } 75 | 76 | /* 77 | * Timer interrupt 78 | * Decrement Rate: bus frequency / DCR (divide configuration register) 79 | * ICR (Initial Count Register) - 1 at decrement rate above 80 | * Interrupt is generated at ICR:0 and counter is reset to ICR. 81 | * For xv6 it's aimed to be 100 times/sec, so the loop below just waits 10ms. 82 | */ 83 | static void *timer_loop(void *ptr) 84 | { 85 | LAPIC *lapic = (LAPIC *)ptr; 86 | while (1) 87 | { 88 | lapic_write_to_irr(lapic, T_IRQ0 + IRQ_TIMER); 89 | usleep(10 * 1000); 90 | } 91 | return NULL; 92 | } 93 | 94 | static void check_int_enabled(LAPIC *lapic) 95 | { 96 | if (lapic->registers[LINT0 >> 4] == MASKED && lapic->registers[LINT1 >> 4] == MASKED) 97 | { 98 | lapic->int_enabled = 1; 99 | } 100 | else 101 | { 102 | lapic->int_enabled = 0; 103 | } 104 | } 105 | 106 | void lapic_write_reg(LAPIC *lapic, uint32_t addr, uint32_t val) 107 | { 108 | uint32_t offset = (addr - LAPIC_DEFAULT_BASE); 109 | uint8_t index = offset >> 4; 110 | lapic->registers[index] = val; 111 | if (offset == SVR) 112 | { 113 | if (val & 0x100) 114 | { 115 | lapic->unit_enabled = 1; 116 | } 117 | return; 118 | } 119 | else if (offset == TICR) 120 | { 121 | pthread_create(lapic->timer_thread, NULL, timer_loop, (void *)lapic); 122 | } 123 | else if (offset == TPR) 124 | { 125 | check_int_enabled(lapic); 126 | } 127 | else if (offset == EOI && val == 0) 128 | { 129 | check_int_enabled(lapic); 130 | lapic_eoi(lapic); 131 | } 132 | } 133 | 134 | uint32_t lapic_read_reg(LAPIC *lapic, uint32_t addr) 135 | { 136 | uint8_t index = (addr - LAPIC_DEFAULT_BASE) >> 4; 137 | return lapic->registers[index]; 138 | } 139 | 140 | void dump_lapic(LAPIC *lapic) 141 | { 142 | printf("\n", (void *)lapic); 143 | printf("TPR: %08x EOI: %08x SVR: %08x\n", lapic->registers[TPR >> 4], lapic->registers[EOI >> 4], lapic->registers[SVR >> 4]); 144 | printf("TIMER: %08x TICR: %08x\n", lapic->registers[TIMER >> 4], lapic->registers[TICR >> 4]); 145 | printf("LINT0: %08x LINT1: %08x\n", lapic->registers[LINT0 >> 4], lapic->registers[LINT1 >> 4]); 146 | } -------------------------------------------------------------------------------- /lapic.h: -------------------------------------------------------------------------------- 1 | #ifndef LAPIC_H_ 2 | #define LAPIC_H_ 3 | 4 | /* 5 | * 6 | * The default base address 0xFEE00000. 7 | * (0x0 - 0x10: Reserved) 8 | * 0x20: RW: LAPIC ID Register 9 | * 0x30: R : LAPIC Version Register 10 | * (0x40 - 0x70: Reserved) 11 | * 0x80: RW: TPR (Task Priority Register) 12 | * 0x90: R : APR (Arbitration Priority Register) 13 | * 0xA0: R : PPR (Processor Pritority Register) 14 | * 0xB0: W : EOI Register 15 | * 0xC0: R : RRD (Remote Read Register) 16 | * 0xD0: RW: Logical Destination Register 17 | * 0xE0: RW: Destination Format Register 18 | * 0xF0: RW: Spurious Interrupt Vector Register 19 | * 0x100 - 0x170: R: ISR (In-service Register) 20 | * 0x180 - 0x1F0: R: TMR (Trigger Mode Register) 21 | * 0x200 - 0x270: R: IRR (Interrupt Request Register) 22 | * 0x280: R: Error Status Register 23 | * (0x290 - 0x2E0: Reserved) 24 | * 0x2F0: RW: CMCI (LVT Corrected Machine Check Interrupt Register) 25 | * 0x300 - 0x310: RW: ICR (Interrupt Command Register) *described below 26 | * 0x320: RW: LVT Timer Register *described below 27 | * 0x330: RW: LVT Thermal Sensor Register 28 | * 0x340: RW: LVT Performance Monitoring Counters Register 29 | * 0x350: RW: LVT LINT0 Register 30 | * 0x360: RW: LVT LINT1 Register 31 | * 0x370: RW: LVT Error Register 32 | * 0x380: RW: Initial Count Register (for Timer) 33 | * 0x390: R : Current Count Register (for Timer) 34 | * (0x3A0 - 0x3D0: Reserved) 35 | * 0x3E0: RW: Devide Configuration Register (for Timer) 36 | * (0x3F0: Reserved) 37 | * 38 | * 39 | * 0 - 7: Vector Number 40 | * 8 - 11: 100b if NMI (for timer) 41 | * 12: Set if interrupt pending 42 | * 13: Polarity. Set for low trigger. 43 | * 14: Remote IRR 44 | * 15: Trigger Mode. Set for level trigger. 45 | * 16: Set for mask. 46 | * 17 - 31: Reserved 47 | * 48 | * 49 | * 0 - 7: Vector Number / Start page number of SIPI (Start IPI) 50 | * 8 - 10: Destination Mode (0: normal, 1: lowest, 2: SMI, 4: NMI, 5: INIT, 6: SIPI) 51 | * 11: Destination Mode (0: physical destination, 1: logical destination) 52 | * 12: Delivery Status (0: accepted, 1: pending) 53 | * (13: Reserved) 54 | * 14: 0: INIT level de-assert 55 | * 15: 1: INIT level de-assert 56 | * 18 - 19: Destination type (0: 0x310 will be ignored, 1: to self, 2: to all processors, 3: to all but self) 57 | * (20: 31: Reserved) 58 | */ 59 | 60 | #include 61 | #include 62 | 63 | #include "emulator.h" 64 | 65 | #define LAPIC_DEFAULT_BASE 0xFEE00000 66 | 67 | #define TPR 0x0080 // Task Priority 68 | #define EOI 0x00B0 // EOI 69 | #define SVR 0x00F0 // Spurious Interrupt Vector 70 | #define TIMER 0x0320 // Local Vector Table 0 (TIMER) 71 | #define TICR 0x0380 // Timer Initial Count 72 | #define LINT0 0x0350 // Local Vector Table 1 (LINT0) 73 | #define LINT1 0x0360 // Local Vector Table 2 (LINT1) 74 | #define ERROR 0x0370 // Local Vector Table 3 (ERROR) 75 | #define MASKED 0x00010000 // Interrupt masked 76 | 77 | LAPIC *create_lapic(Emulator *emu); 78 | 79 | void lapic_send_intr(LAPIC *lapic); 80 | void lapic_write_to_irr(LAPIC *lapic, uint8_t irq); 81 | 82 | void lapic_write_reg(LAPIC *lapic, uint32_t addr, uint32_t val); 83 | uint32_t lapic_read_reg(LAPIC *lapic, uint32_t addr); 84 | 85 | void dump_lapic(LAPIC *lapic); 86 | 87 | #endif -------------------------------------------------------------------------------- /modrm.h: -------------------------------------------------------------------------------- 1 | #ifndef MODRM_H_ 2 | #define MODRM_H_ 3 | 4 | #include 5 | 6 | #include "emulator.h" 7 | 8 | typedef struct 9 | { 10 | uint8_t scale; // 2 bits 11 | uint8_t index; // 3 bits 12 | uint8_t base; // 3 bits 13 | } SIB; 14 | 15 | typedef struct 16 | { 17 | /* Mod: 2 bits */ 18 | uint8_t mod; 19 | /* REG: 3 bits */ 20 | union { // union: different data at the same location 21 | uint8_t opcode; // used to extend opcode (e.g. inc: ff + 000 and dec: ff + 001) 22 | uint8_t reg_index; // used to specify register (target or source) 23 | }; 24 | uint8_t rm; // 3 bits 25 | SIB sib; // 1 byte 26 | union { 27 | int8_t disp8; 28 | int16_t disp16; 29 | uint32_t disp32; 30 | }; 31 | } ModRM; 32 | 33 | ModRM create_modrm(); 34 | 35 | /* 36 | * Parses ModR/M, SIB and Displacement. 37 | * EIP of Emulator needs to be pointing ModR/M Byte. 38 | */ 39 | void parse_modrm(Emulator *emu, ModRM *modrm); 40 | 41 | /* Calcurates the memory address. Exposed for LEA instruction. */ 42 | uint32_t calc_memory_address(Emulator *emu, ModRM *modrm); 43 | 44 | /* Sets 8-bit value to register or memory depending on Mod of ModR/M byte. */ 45 | void set_rm8(Emulator *emu, ModRM *modrm, uint8_t value); 46 | 47 | /* Gets 8-bit value from register or memory depending on Mod of ModR/M byte. */ 48 | uint8_t get_rm8(Emulator *emu, ModRM *modrm); 49 | 50 | void set_rm16(Emulator *emu, ModRM *modrm, uint16_t value); 51 | uint16_t get_rm16(Emulator *emu, ModRM *modrm); 52 | 53 | void set_rm32(Emulator *emu, ModRM *modrm, uint32_t value); 54 | uint32_t get_rm32(Emulator *emu, ModRM *modrm); 55 | 56 | /* Sets 8-bit value on the register specified by REG of ModR/M. */ 57 | void set_r8(Emulator *emu, ModRM *modrm, uint8_t value); 58 | 59 | /* Get 8-bit value from the register specified by REG of ModR/M. */ 60 | uint8_t get_r8(Emulator *emu, ModRM *modrm); 61 | 62 | void set_r16(Emulator *emu, ModRM *modrm, uint16_t value); 63 | uint16_t get_r16(Emulator *emu, ModRM *modrm); 64 | 65 | void set_r32(Emulator *emu, ModRM *modrm, uint32_t value); 66 | uint32_t get_r32(Emulator *emu, ModRM *modrm); 67 | 68 | /* Sets 16-bit value on the segment register specified by REG of ModR/M. */ 69 | void set_seg_r(Emulator *emu, ModRM *modrm, uint16_t value); 70 | 71 | /* Get 16-bit value from the segment register specified by REG of ModR/M. */ 72 | uint16_t get_seg_r(Emulator *emu, ModRM *modrm); 73 | 74 | #endif -------------------------------------------------------------------------------- /mp.h: -------------------------------------------------------------------------------- 1 | #ifndef MP_H_ 2 | #define MP_H_ 3 | 4 | #include "emulator.h" 5 | 6 | void set_mp_config(Emulator *emu); 7 | 8 | #endif -------------------------------------------------------------------------------- /paging.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "paging.h" 9 | #include "emulator_functions.h" 10 | 11 | void check_paging(Emulator *emu) 12 | { 13 | if (emu->is_pg) 14 | return; 15 | if ((emu->control_registers[CR0] & CR0_PG) != 0) 16 | emu->is_pg = 1; 17 | } 18 | 19 | /* 20 | * Page Directory Entry 21 | * 31_____________________________12_11_____9____________________________________0 22 | * | Page table 4kb-aligned address | Avail. | G | S | 0 | A | D | W | U | R | P | 23 | * |_____________________________________________________________________________| 24 | * P: Present 25 | * R: Read/write 26 | * U: User/supervisor 27 | * W: Write-through / write-back 28 | * D: cache-Disabled 29 | * A: Accessed 30 | * S: page Size 31 | * 32 | * Page Table Entry 33 | * 31_____________________________12_11_____9_______________________________________0 34 | * | Page table 4kb-aligned address | Avail. | G* | 0 | D* | A | C* | W | U | R | P | 35 | * |________________________________________________________________________________| 36 | * C: Same as Cache-disabled above 37 | * G: Global. 1: prevents TLB cache update on CR3 reset. (CR4 global enable needs to be on.) 38 | * D: Dirty flag (written) 39 | * 0: memory type when PAT is enabled. 40 | * 41 | * Address in 3-level Scheme 42 | * 43 | * 44 | * Add 45 | */ 46 | uint32_t get_phys_addr(Emulator *emu, uint32_t linear_addr, uint8_t write, uint8_t exec) 47 | { 48 | uint32_t pde_index = linear_addr >> 22; 49 | uint32_t pde = _get_memory32(emu, emu->control_registers[CR3] + (pde_index * 4)); 50 | uint8_t cr4_pse = emu->control_registers[CR4] & CR4_PSE; 51 | uint8_t pde_ps = pde & PDE_PS; 52 | /* 53 | * Page size extension enabled. 54 | * [10 bits]: Page directory entry index 55 | * [22 bits]: Offset from page directory entry base 56 | */ 57 | if ((cr4_pse != 0) && (pde_ps != 0)) 58 | { 59 | uint32_t phys_base = pde & 0xFFFFF000; 60 | uint32_t phys_offset = linear_addr & 0x3FFFFF; 61 | return phys_base + phys_offset; 62 | } 63 | /* 64 | * Page directory + page table 65 | * [10 bits]: Page directory entry index 66 | * [10 bits]: Page table entry index 67 | * [12 bits]: Offset from page table entry base 68 | */ 69 | else 70 | { 71 | uint32_t pt_base = pde & 0xFFFFF000; 72 | uint32_t pte_index = (linear_addr >> 12) & 0x3FF; 73 | uint32_t pte = _get_memory32(emu, pt_base + (pte_index * 4)); 74 | uint32_t phys_base = pte & 0xFFFFF000; 75 | uint32_t phys_offset = linear_addr & 0xFFF; 76 | return phys_base + phys_offset; 77 | } 78 | } -------------------------------------------------------------------------------- /paging.h: -------------------------------------------------------------------------------- 1 | #ifndef PAGING_H_ 2 | #define PAGING_H_ 3 | 4 | #include "emulator.h" 5 | 6 | #define CR0_PG (1 << 31) 7 | #define CR4_PSE (1 << 4) 8 | 9 | #define PDE_PS (1 << 7) 10 | 11 | void check_paging(Emulator *emu); 12 | 13 | uint32_t get_phys_addr(Emulator *emu, uint32_t linear_addr, uint8_t write, uint8_t exec); 14 | 15 | #endif -------------------------------------------------------------------------------- /shift.h: -------------------------------------------------------------------------------- 1 | #ifndef SHIFT_H_ 2 | #define SHIFT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "instruction_defs.h" 11 | #include "emulator_functions.h" 12 | #include "modrm.h" 13 | #include "io.h" 14 | 15 | typedef struct 16 | { 17 | uint8_t result; 18 | uint8_t carry; 19 | } ShiftRes8; 20 | 21 | typedef struct 22 | { 23 | uint32_t result; 24 | uint8_t carry; 25 | } ShiftRes32; 26 | 27 | uint8_t rol8(uint8_t val, uint8_t n); 28 | uint8_t ror8(uint8_t val, uint8_t n); 29 | ShiftRes8 rcl8(uint8_t val, uint8_t n, uint8_t carry); 30 | ShiftRes8 rcr8(uint8_t val, uint8_t n, uint8_t carry); 31 | ShiftRes8 shl8(uint8_t val, uint8_t n); 32 | ShiftRes8 shr8(uint8_t val, uint8_t n, uint8_t carry); 33 | ShiftRes8 sar8(uint8_t val, uint8_t n, uint8_t carry); 34 | 35 | uint32_t rol32(uint32_t val, uint8_t n); 36 | uint32_t ror32(uint32_t val, uint8_t n); 37 | ShiftRes32 rcl32(uint32_t val, uint8_t n, uint8_t carry); 38 | ShiftRes32 rcr32(uint32_t val, uint8_t n, uint8_t carry); 39 | ShiftRes32 shl32(uint32_t val, uint8_t n); 40 | ShiftRes32 shr32(uint32_t val, uint8_t n, uint8_t carry); 41 | ShiftRes32 sar32(uint32_t val, uint8_t n, uint8_t carry); 42 | 43 | #endif -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | # Execution Tests with Binary Files 2 | 3 | function echo_ndisasm() { 4 | echo "ndisasm -b 32 $1" 5 | echo 6 | ndisasm -b 32 $1 7 | echo 8 | } 9 | 10 | function echo_output() { 11 | echo "./dax86 $1" 12 | echo 13 | echo "$2" 14 | echo 15 | } 16 | 17 | function run_test() { 18 | test_dir="./tests/exec/$1" 19 | test_path="$test_dir/$1.bin" 20 | expected_path="$test_dir/expected.txt" 21 | verbose=false 22 | 23 | if [ "$2" == "-v" ]; then 24 | verbose=true 25 | fi 26 | # start of test 27 | echo "------------------------------------------------" 28 | echo "Building test binary $1..." 29 | build_output=$(make -C $test_dir) 30 | if [ "$verbose" = true ]; then 31 | echo 32 | echo "$build_output" 33 | echo 34 | fi 35 | echo "Running test with $1..." 36 | output=$(./dax86 $test_path test -v) 37 | if [[ $output == *"End of program :)"* ]]; then 38 | echo "[Run: SUCCESS]" 39 | if [ "$verbose" = true ]; then 40 | echo 41 | echo_ndisasm "$test_path" 42 | echo_output "$test_path" "$output" 43 | fi 44 | else 45 | echo "[Run: FAILURE]" 46 | echo 47 | echo_ndisasm "$test_path" 48 | echo_output "$test_path" "$output" 49 | exit 1 50 | fi 51 | if [ -f "${expected_path}" ] 52 | then 53 | echo "[Assertion]" 54 | line_num=0 55 | while IFS= read -r line; do 56 | if [[ $output == *"$line"* ]]; then 57 | if [ "$verbose" = true ]; then 58 | echo "Line ${line_num}: Pass" 59 | fi 60 | else 61 | echo "Line ${line_num}: Fail" 62 | echo 63 | echo_ndisasm "$test_path" 64 | echo_output "$test_path" "$output" 65 | exit 1 66 | fi 67 | line_num=$((line_num+1)) 68 | done < "${expected_path}" 69 | echo "All check passed." 70 | else 71 | echo "expected.txt Not Found" 72 | fi 73 | echo 74 | } 75 | 76 | # Files below do not run after 0x7c00 offset: 77 | # tests/mov_jmp/mov_jmp.bin 78 | # 79 | # Files below require input: 80 | # tests/io/in.bin 81 | # tests/io/in_display.bin 82 | # tests/rep/rep.bin 83 | # 84 | # Binary is more than 512 bytes (1 sector): 85 | # tests/mp/mp.bin (prints "c" "i" "m" "p"): requires 1024 bytes. 86 | # tests/console/console.bin (prints "test123"): requires 2048 bytes. 87 | 88 | function test_all() { 89 | for i in \ 90 | "modrm"\ 91 | "org_jmp"\ 92 | "call"\ 93 | "main_func"\ 94 | "args"\ 95 | "if"\ 96 | "flags_set"\ 97 | "flags_clear"\ 98 | "if"\ 99 | "jmp_c"\ 100 | "io_out"\ 101 | "seg"\ 102 | "or"\ 103 | "sub"\ 104 | "and"\ 105 | "xor"\ 106 | "pusha"\ 107 | "code_80"\ 108 | "test"\ 109 | "xchg"\ 110 | "mov"\ 111 | "pop"\ 112 | "code_c0"\ 113 | "loop"\ 114 | "jmp_far"\ 115 | "jmp_far16"\ 116 | "call_far"\ 117 | "call_far16"\ 118 | "moffs"\ 119 | "str_8"\ 120 | "str_32"\ 121 | "gdt"\ 122 | "mul"\ 123 | "div"\ 124 | "disk"\ 125 | "movzx"\ 126 | "lapic"\ 127 | "ioapic" 128 | do 129 | run_test $i 130 | done 131 | } 132 | 133 | function main() { 134 | if [ -z "$1" ]; then 135 | test_all 136 | else 137 | run_test $1 "-v" 138 | fi 139 | } 140 | 141 | main $1 142 | -------------------------------------------------------------------------------- /tests/exec/and/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = and.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/and/and.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | sub esp, 16 ; 7BF0 4 | mov ebp, esp ; EBP: 7BF0 5 | 6 | mov eax, 0x3 ; EAX: 1 7 | and al, 0x2 ; 24 ; EAX: 2 8 | push eax ; ESP -> 7BEC: 0x2 9 | 10 | or byte [ebp], al ; 7BF0: 0x2 11 | and byte [ebp], al ; 20 ; 7BF0: 0x2 12 | 13 | mov eax, 0x7 ; EAX: 7 14 | and byte al, [ebp] ; 22 ; EAX: 0x2 15 | push eax ; ESP -> 7BE8: 0x2 16 | 17 | or dword [ebp+4], 0x7 ; 7BF4: 0x7 (0111) 18 | and dword [ebp+4], 0x5 ; 83 ; 7BF4: 0x5 (0101) 19 | mov eax, [ebp+4] 20 | push eax ; 7BE4: 0x5 21 | 22 | mov eax, 0x1 23 | and dword [ebp+4], eax ; 21 ; 7BF4: 0x1 24 | 25 | mov eax, 0x4 26 | and dword eax, [ebp+4] ; 23 ; EAX: 0x0 27 | push eax ; ESP -> 7BE0: 0x0 28 | 29 | mov eax, 0x1001 30 | and dword eax, 0x1000 ; 25 ; EAX: 0x1000 31 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/and/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00001000 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007be0 6 | EBP: 00007bf0 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 00 00 00 00 05 00 00 00 02 00 00 00 02 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 24 | 00007C00: 83 EC 10 89 E5 B8 03 00 00 00 24 02 50 08 45 00 20 45 00 B8 07 00 00 00 22 45 00 50 83 4D 04 07 25 | 00007C20: 83 65 04 05 8B 45 04 50 B8 01 00 00 00 21 45 04 B8 04 00 00 00 23 45 04 50 B8 01 10 00 00 25 00 26 | 00007C40: 10 00 00 E9 B8 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 | -------------------------------------------------------------------------------- /tests/exec/args/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = args.bin 2 | OBJS = crt0.o args.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/args/args.c: -------------------------------------------------------------------------------- 1 | int add(int a, int b) 2 | { 3 | return a + b; 4 | } 5 | 6 | int main(void) 7 | { 8 | return add(2, 5); 9 | } 10 | 11 | /* 12 | * 00000000 E812000000 call dword 0x17 ; pushes ret addr ; ESP 0x7C00 - 4 = 0x7BFC: 7C05 (EIP: 7C00 + 5) ; 13 | * 00000005 E9F683FFFF jmp dword 0xffff8400 14 | * 0000000A 55 push ebp ; add() ; 7BE8: 7BF8 from EBP 15 | * 0000000B 89E5 mov ebp,esp ; EBP: 7BE8 16 | * 0000000D 8B5508 mov edx,[ebp+0x8] ; 7BE8 + 0x8 = 7BF0: 0x2 -> EDX 17 | * 00000010 8B450C mov eax,[ebp+0xc] ; 7BE8 + 0xC = 7BF4: 0x5 -> EAX 18 | * 00000013 01D0 add eax,edx ; EAX: 0x7 19 | * 00000015 5D pop ebp ; EBP: 7BF8 (ESP: 7BEC) 20 | * 00000016 C3 ret ; Jmp to 7C23 (from ESP: 7BEC) -> ESP: 7BF0 21 | * 00000017 55 push ebp ; main() ; 0x7BF8: 0x00 22 | * 00000018 89E5 mov ebp,esp ; EBP: 7BF8 23 | * 0000001A 6A05 push byte +0x5 ; 7BF4: 0x05 24 | * 0000001C 6A02 push byte +0x2 ; 7BF0: 0x02 25 | * 0000001E E8E7FFFFFF call dword 0xa ; 7BEC: 7C23 (EIP: 7C1E + 5) 26 | * 00000023 83C408 add esp,byte +0x8 ; ESP: 7BF8 27 | * 00000026 C9 leave ; updates ESP with current EBP: ESP: 0x7BF0 -> 0x7BF8 and pops old EBP to EBP: 0x0000 & ESP: 0x7BFC 28 | * 00000027 C3 ret ; pops return address from ESP: 0x7BFC -> 7C05 ESP: 0x7C00 29 | */ -------------------------------------------------------------------------------- /tests/exec/args/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 7 | -------------------------------------------------------------------------------- /tests/exec/args/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000007 2 | ECX: 00000000 3 | EDX: 00000002 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | CS: 00000000 11 | DS: 00000000 12 | ES: 00000000 13 | SS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007B00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007B20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 | 00007B40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 25 | 00007B60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 26 | 00007B80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 | 00007BA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 29 | 00007BE0: 00 00 00 00 00 00 00 00 F8 7B 00 00 23 7C 00 00 02 00 00 00 05 00 00 00 00 00 00 00 05 7C 00 00 30 | 00007C00: E8 12 00 00 00 E9 F6 83 FF FF 55 89 E5 8B 55 08 8B 45 0C 01 D0 5D C3 55 89 E5 6A 05 6A 02 E8 E7 31 | 00007C20: FF FF FF 83 C4 08 C9 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/call/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = call.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/call/call.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | start: 4 | mov eax, 0x00f1 5 | mov ebx, 0x0029 6 | call add_routine 7 | jmp 0 8 | add_routine: 9 | mov ecx, eax 10 | add ecx, ebx 11 | ret -------------------------------------------------------------------------------- /tests/exec/call/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 000000f1 2 | ECX: 0000011a 3 | EDX: 00000000 4 | EBX: 00000029 5 | ESP: 00007c00 6 | -------------------------------------------------------------------------------- /tests/exec/call_far/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = call_far.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/call_far/call_far.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | org 0x7c00 3 | 4 | load_gdt: 5 | lgdt [GDT_DESC] 6 | ; Enable Protected Mode: PE bit on CR0 7 | mov eax, cr0 8 | or eax, 1 9 | mov cr0, eax 10 | jmp 8:pe_enter ; 1000b 11 | 12 | BITS 32 13 | pe_enter: 14 | ; Set data and stack segements. 15 | mov eax, 0x10 ; 10000b 16 | mov ds, eax 17 | mov ss, eax 18 | 19 | mov eax, 0 20 | mov ebx, 0x10 21 | mov ecx, 0x11 22 | call 0x8:0x7C4D ; eax: 0x10 after addEbx 23 | mov edx, 0x12 24 | call [indirect] ; eax: 0x21 after addEcx 25 | add eax, edx ; eax: 0x33 26 | call far [farAddr] ; eax: 43 after addEbx 27 | jmp 0:0 28 | addEbx: 29 | add eax, ebx 30 | retf 31 | addEcx: 32 | add eax, ecx 33 | ret 34 | indirect: 35 | dd addEcx 36 | farAddr: 37 | dw 0x8 ; Seg 38 | dd 0x7C4D ; Offset 39 | GDT: 40 | ; null segment descriptor 41 | dw 0 42 | dw 0 43 | db 0 44 | db 0 45 | db 0 46 | db 0 47 | ; code segment descriptor 48 | ; 0000 FFFF 49 | ; 00CF 9800 50 | dw 0xFFFF ; limit low 51 | dw 0 ; base low 52 | db 0 ; base middle 53 | db 10011000b ; access 54 | db 11001111b ; limit + flags 55 | db 0 ; base high 56 | ; data segment descriptor 57 | ; 0000 FFFF 58 | ; 00CF 9200 59 | dw 0xFFFF ; limit low 60 | dw 0 ; base low 61 | db 0 ; base middle 62 | db 10010010b ; access 63 | db 11001111b ; limit + flags 64 | db 0 ; base high 65 | GDT_DESC: 66 | dw (GDT_DESC - GDT - 1) 67 | dd GDT -------------------------------------------------------------------------------- /tests/exec/call_far/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000043 2 | ECX: 00000011 3 | EDX: 00000012 4 | EBX: 00000010 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000010 13 | DS: 00000010 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000001 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0017 00007c5d 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 46 7C 00 00 08 00 00 00 24 | 00007C00: 0F 01 16 75 7C 0F 20 C0 66 83 C8 01 0F 22 C0 EA 14 7C 08 00 B8 10 00 00 00 8E D8 8E D0 B8 00 00 25 | 00007C20: 00 00 BB 10 00 00 00 B9 11 00 00 00 9A 4D 7C 00 00 08 00 BA 12 00 00 00 FF 15 53 7C 00 00 01 D0 26 | 00007C40: FF 1D 57 7C 00 00 EA 00 00 00 00 00 00 01 D8 CB 01 C8 C3 50 7C 00 00 08 00 4D 7C 00 00 00 00 00 27 | 00007C60: 00 00 00 00 00 FF FF 00 00 00 98 CF 00 FF FF 00 00 00 92 CF 00 17 00 5D 7C 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/call_far16/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = call_far16.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/call_far16/call_far16.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | org 0x7c00 3 | start: 4 | mov eax, 0 5 | mov ebx, 0x10 6 | mov ecx, 0x11 7 | call 0x7C0:0x2D ; eax: 0x10 after addEbx 8 | mov edx, 0x12 9 | call [indirect] ; eax: 0x21 after addEcx 10 | add eax, edx ; eax: 0x33 11 | call far [farAddr] ; eax: 43 after addEbx 12 | jmp 0:0 13 | addEbx: 14 | add eax, ebx 15 | retf 16 | addEcx: 17 | add eax, ecx 18 | ret 19 | indirect: 20 | dd addEcx 21 | farAddr: 22 | dw 0x7C0 ; Seg 23 | dd 0x2D ; Offset -------------------------------------------------------------------------------- /tests/exec/call_far16/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000043 2 | ECX: 00000011 3 | EDX: 00000012 4 | EBX: 00000010 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 7C 00 00 00 00 24 | 00007C00: 66 B8 00 00 00 00 66 BB 10 00 00 00 66 B9 11 00 00 00 9A 2D 00 C0 07 66 BA 12 00 00 00 FF 16 35 25 | 00007C20: 7C 66 01 D0 FF 1E 39 7C EA 00 00 00 00 66 01 D8 CB 66 01 C8 C3 31 7C 00 00 C0 07 2D 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/code_80/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = code_80.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/code_80/code_80.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | ; code: 80 4 | push 0 5 | mov dword eax, esp 6 | add byte [eax], 3 ; EBP(0x7BFC): 3 7 | or byte [eax], 4 ; EBP(0x7BFC): 7 8 | adc byte [eax], 1 ; EBP(0x7BFC): 8 9 | sbb byte [eax], 1 ; EBP(0x7BFC): 7 10 | and byte [eax], 15 ; EBP(0x7BFC): 7 11 | sub byte [eax], 1 ; EBP(0x7BFC): 6 (0110) xor (0100) 12 | xor byte [eax], 4 ; EBP(0x7BFC): 2 13 | cmp byte [eax], 3 14 | 15 | ; code: 83 16 | push 0 17 | mov dword eax, esp 18 | add dword [eax], 0x3000 ; EBP(0x7BF8): 0x3000 19 | or dword [eax], 0x4000 ; EBP(0x7BF8): 0x7000 20 | adc dword [eax], 0x1000 ; EBP(0x7BF8): 0x8000 21 | sbb dword [eax], 0x1000 ; EBP(0x7BF8): 0x7000 22 | and dword [eax], 0xF000 ; EBP(0x7BF8): 0x5000(0110 0000 x 3) and 0xF000(1111 0000 x 3) = 0x7000 23 | sub dword [eax], 0x1000 ; EBP(0x7BF8): 0x6000 24 | xor dword [eax], 0x4000 ; EBP(0x7BF8): 0x7000(0110 0000 x 3) xor 0x6000(0100 0000 x 3) = 0x2000 25 | cmp dword [eax], 0x3000 26 | 27 | ; code: 83 28 | push 0 29 | mov dword eax, esp 30 | add dword [eax], 3 ; EBP(0x7BF4): 3 31 | or dword [eax], 4 ; EBP(0x7BF4): 7 32 | adc dword [eax], 1 ; EBP(0x7BF4): 8 33 | sbb dword [eax], 1 ; EBP(0x7BF4): 7 34 | and dword [eax], 15 ; EBP(0x7BF4): 7 35 | sub dword [eax], 1 ; EBP(0x7BF4): 6 (0110) xor (0100) 36 | xor dword [eax], 4 ; EBP(0x7BF4): 2 37 | cmp dword [eax], 3 38 | 39 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/code_80/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00007bf4 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bf4 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 10000001 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 20 00 00 02 00 00 00 24 | 00007C00: 6A 00 89 E0 80 00 03 80 08 04 80 10 01 80 18 01 80 20 0F 80 28 01 80 30 04 80 38 03 6A 00 89 E0 25 | 00007C20: 81 00 00 30 00 00 81 08 00 40 00 00 81 10 00 10 00 00 81 18 00 10 00 00 81 20 00 F0 00 00 81 28 26 | 00007C40: 00 10 00 00 81 30 00 40 00 00 81 38 00 30 00 00 6A 00 89 E0 83 00 03 83 08 04 83 10 01 83 18 01 27 | 00007C60: 83 20 0F 83 28 01 83 30 04 83 38 03 E9 8F 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 | 00007C80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/code_c0/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = code_c0.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/code_c0/code_c0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | push 131 ; 0x7BFC: 0x83: 1000 0011 (CF: 0) 4 | mov eax, esp 5 | rol byte [eax], 0x2 ; C0 /0 rotate rm8 left imm8 times ; 0000 1110 (0x0E) 6 | pushfd ; 0x7BF8: 0x0 7 | 8 | push 131 ; 0x7BF4: 1000 0011 (CF: 0) 9 | mov eax, esp 10 | rol byte [eax], 0xA ; C0 /0 rotate rm8 left imm8 times ; 0000 1110 (0x0E) 11 | pushfd ; 0x7BF0: 0x0 12 | 13 | push 131 ; 0x7BEC: 1000 0011 (CF: 0) 14 | mov eax, esp 15 | ror byte [eax], 0x2 ; C0 /1 rotate rm8 right imm8 times ; 1110 0000 (0xE0) 16 | pushfd ; 0x7BE8: 0 17 | 18 | push 163 ; 0x7BE4: 1010 0011 (CF: 0) 19 | mov eax, esp 20 | rcl byte [eax], 0x3 ; C0 /2 rotate rm8 left imm8 times including CF ; 0001 1010 (0x1A) 21 | pushfd ; 0x7BE0: 0x1 22 | 23 | push 131 ; 0x7BDC: 1 1000 0011 (CF: 1) 24 | mov eax, esp 25 | rcr byte [eax], 0x3 ; C0 /3 rotate rm8 right imm8 times including CF ; 1111 0000 (0xF0) 26 | pushfd ; 0x7BD8: 0x0 27 | 28 | push 131; 0x7BD4: 1000 0011 (CF: 0) 29 | mov eax, esp 30 | shl byte [eax], 0x2 ; C0 /4 logical shift rm8 left imm8 times ; 0000 1100 (0x0C) 31 | pushfd ; 0x7BD0: 0x0 32 | 33 | push 131; 0x7BCC: 1000 0011 (CF: 0) 34 | mov eax, esp 35 | shr byte [eax], 0x2 ; C0 /5 logical shift rm8 right imm8 times ; 0010 0000 (0x20) 36 | pushfd ; 0x7BC8: 0x1 37 | 38 | push 131; 0x7BC4: 1000 0011 (CF: 1) 39 | mov eax, esp 40 | sar byte [eax], 0x2 ; C0 /7 arithmetic shift rm8 left imm8 times ; 1110 0000 (0xE0) 41 | pushfd ; 0x7BC0: 0x1 42 | 43 | ; code_c1 ; 44 | 45 | push 131 ; 0x7BBC: 0x83: 0x0 0x0 0x0 1000 0011 (CF: 1) 46 | mov eax, esp 47 | rol dword [eax], 25 ; C1/0 ; 0000 0110 0x0 0x0 0000 0001 (0x6000001) 48 | pushfd ; 0x7BB8: 0x1 (from previous condition) 49 | 50 | push 131 ; 0x7BB4: 0x0 0x0 0x0 1000 0011 (CF: 1) 51 | mov eax, esp 52 | rol dword [eax], 34 ; C1/0 ; 0x0 0x0 0000 0010 0000 1100 (0x20C) 53 | pushfd ; 0x7BB0: 0x1 (from previous condition) 54 | 55 | push 131 ; 0x7BAC: 0x0 0x0 0x0 1000 0011 (CF: 1) 56 | mov eax, esp 57 | ror dword [eax], 34 ; C1/ 1 ; 1100 0000 0x0 0x0 0010 0000 (0xC0000020) 58 | pushfd ; 0x7BA8: 0x1 (from previous condition) 59 | 60 | push 0xA3000000 ; 0x7BA4: 1010 0011 0x0 0x0 0x0 (CF: 1) 61 | mov eax, esp 62 | rcl dword [eax], 3 ; C1/2 ; 0001 1000 0x0 0x0 0000 1100 (0x18000006) 63 | pushfd ; 0x7BA0: 0x1 64 | 65 | push 131 ; 0x7B9C: 0x0 0x0 0x0 1000 0011 (CF: 1) 66 | mov eax, esp 67 | rcr dword [eax], 3 ; C1/3 ; 1110 0000 0x0 0x0 0001 0000 (0xE0000010) 68 | pushfd ; 0x7B98: 0x0 69 | 70 | push 131; 0x7B94: 0x0 0x0 0x0 1000 0011 (CF: 0) 71 | mov eax, esp 72 | shl dword [eax], 25 ; C1/4 ; 0000 0110 0x0 0x0 0x0 (0x6000000) 73 | pushfd ; 0x7B90: 0x1 74 | 75 | push 0x83000000; 0x7B8C: 1000 0011 0x0 0x0 0x0 (CF: 1) 76 | mov eax, esp 77 | shr dword [eax], 25 ; C1/5 ; 0x0 0x0 0x0 0100 0001 (0x41) 78 | pushfd ; 0x7B88: 0x1 79 | 80 | push 0x83000000; 0x7B84: 1000 0011 0x0 0x0 0x0 (CF: 1) 81 | mov eax, esp 82 | sar dword [eax], 25 ; C1/7 ; 0xFF 0xFF 0xFF 1100 0001 (0xFFFFFFC1) 83 | pushfd ; 0x7B80: 0x1 84 | 85 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/code_c0/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00007b84 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007b80 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000001 22 | 00007B60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007B80: 01 00 00 00 C1 FF FF FF 01 00 00 00 41 00 00 00 01 00 00 00 00 00 00 06 00 00 00 00 10 00 00 E0 24 | 00007BA0: 01 00 00 00 06 00 00 18 01 00 00 00 20 00 00 C0 01 00 00 00 0C 02 00 00 01 00 00 00 01 00 00 06 25 | 00007BC0: 01 00 00 00 E0 00 00 00 01 00 00 00 20 00 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 F0 00 00 00 26 | 00007BE0: 01 00 00 00 1A 00 00 00 00 00 00 00 E0 00 00 00 00 00 00 00 0E 00 00 00 00 00 00 00 0E 00 00 00 27 | 00007C00: 68 83 00 00 00 89 E0 C0 00 02 9C 68 83 00 00 00 89 E0 C0 00 0A 9C 68 83 00 00 00 89 E0 C0 08 02 28 | 00007C20: 9C 68 A3 00 00 00 89 E0 C0 10 03 9C 68 83 00 00 00 89 E0 C0 18 03 9C 68 83 00 00 00 89 E0 C0 20 29 | 00007C40: 02 9C 68 83 00 00 00 89 E0 C0 28 02 9C 68 83 00 00 00 89 E0 C0 38 02 9C 68 83 00 00 00 89 E0 C1 30 | 00007C60: 00 19 9C 68 83 00 00 00 89 E0 C1 00 22 9C 68 83 00 00 00 89 E0 C1 08 22 9C 68 00 00 00 A3 89 E0 31 | 00007C80: C1 10 03 9C 68 83 00 00 00 89 E0 C1 18 03 9C 68 83 00 00 00 89 E0 C1 20 19 9C 68 00 00 00 83 89 32 | 00007CA0: E0 C1 28 19 9C 68 00 00 00 83 89 E0 C1 38 19 9C E9 4B 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 33 | -------------------------------------------------------------------------------- /tests/exec/code_f6/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = code_f6.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/code_f6/code_f6.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | push 0xFF ; 5 | mov dword eax, esp 6 | test byte [eax], 0x0 7 | pushfd ; 01000000 (0x40) (zero flag) 8 | 9 | push 0xFF ; 10 | mov dword eax, esp 11 | test byte [eax], 0x80 12 | pushfd ; 10000000 (0x80) (sign flag) 13 | 14 | push 5 ; 0000 0101 15 | mov dword eax, esp 16 | not byte [eax] ; F6 2 not rm8 ; 1111 1010 (0xFA) 17 | 18 | push 5 ; 0000 0101 19 | mov dword eax, esp 20 | neg byte [eax] ; F6 3 neg rm8 ; 1111 1011 (0xFB): -128 + 123 (0111 1011) = 5 21 | 22 | push -5 ; 1111 1011 23 | mov dword eax, esp 24 | neg byte [eax] ; 0x05 25 | 26 | ; code F7 ; 27 | 28 | push 0xFF ; 29 | mov dword eax, esp 30 | test dword [eax], 0x0 31 | pushfd ; 01000000 (0x40) (zero flag) 32 | 33 | push 0xFF ; 34 | mov dword eax, esp 35 | test dword [eax], 0x80 36 | pushfd ; 10000000 (0x80) (sign flag) 37 | 38 | push 5 ; 0x00 0x00 0x00 0000 0101 39 | mov dword eax, esp 40 | not dword [eax] ; F6 2 not rm8 ; 0xFF 0xFF 0xFF 1111 1010 (0xFA) 41 | 42 | push 5 ; 0x00 0x00 0x00 0000 0101 43 | mov dword eax, esp 44 | neg dword [eax] ; F6 3 neg rm8 ; 0xFF 0xFF 0xFF 1111 1011 (0xFB): -128 + 123 (0111 1011) = 5 45 | 46 | push dword 0xFAFFFFFB ; -83886085: 1111 1010 0xFF 0xFF 1111 1011 47 | mov dword eax, esp 48 | neg dword [eax] ; 83886085: 0x05 00 00 05 49 | 50 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/console/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = console.bin 2 | OBJS = crt0.o main.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/console/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | extern main 3 | global start 4 | start: 5 | lgdt [GDT_DESC] 6 | mov eax, cr0 7 | or eax, 1 8 | mov cr0, eax 9 | jmp 8:pe_enter ; 1000b 10 | 11 | BITS 32 12 | pe_enter: 13 | mov dword eax, 0x10 ; 10000b 14 | mov ss, ax 15 | mov ds, ax 16 | call main 17 | jmp 0:0 ; E9 (F4 83 FF FF) 18 | 19 | ; FF FF 00 00 00 92 CF 00 20 | GDT: 21 | ; null segment descriptor 22 | dw 0 23 | dw 0 24 | db 0 25 | db 0 26 | db 0 27 | db 0 28 | ; code segment descriptor 29 | ; 0000 FFFF 30 | ; 00CF 9800 31 | dw 0xFFFF ; limit low 32 | dw 0 ; base low 33 | db 0 ; base middle 34 | db 10011000b ; access 35 | db 11001111b ; limit + flags 36 | db 0 ; base high 37 | ; data segment descriptor 38 | ; 0000 FFFF 39 | ; 00CF 9200 40 | dw 0xFFFF ; limit low 41 | dw 0 ; base low 42 | db 0 ; base middle 43 | db 10010010b ; access 44 | db 11001111b ; limit + flags 45 | db 0 ; base high 46 | ; staci segment descriptor 47 | ; 0000 FFFF 48 | ; 00CF 9200 49 | dw 0xFFFF ; limit low 50 | dw 0 ; base low 51 | db 0 ; base middle 52 | db 10010010b ; access 53 | db 11001111b ; limit + flags 54 | db 0 ; base high 55 | 56 | ; 07 00 0C 7C 00 00 57 | GDT_DESC: 58 | dw (GDT_DESC - GDT - 1) 59 | dd GDT -------------------------------------------------------------------------------- /tests/exec/console/main.c: -------------------------------------------------------------------------------- 1 | #define BACKSPACE 0x100 2 | #define CRTPORT 0x3d4 3 | 4 | typedef unsigned int uint; 5 | typedef unsigned short ushort; 6 | typedef unsigned char uchar; 7 | typedef uint pde_t; 8 | 9 | static ushort *crt = (ushort *)0xb8000; // CGA memory 10 | 11 | static void consputc(int); 12 | 13 | static inline void 14 | outb(ushort port, uchar data) 15 | { 16 | asm volatile("out %0,%1" 17 | : 18 | : "a"(data), "d"(port)); 19 | } 20 | 21 | static inline uchar 22 | inb(ushort port) 23 | { 24 | uchar data; 25 | 26 | asm volatile("in %1,%0" 27 | : "=a"(data) 28 | : "d"(port)); 29 | return data; 30 | } 31 | 32 | static void 33 | printint(int xx, int base, int sign) 34 | { 35 | static char digits[] = "0123456789abcdef"; 36 | char buf[16]; 37 | int i; 38 | uint x; 39 | 40 | if (sign && (sign = xx < 0)) 41 | x = -xx; 42 | else 43 | x = xx; 44 | 45 | i = 0; 46 | do 47 | { 48 | buf[i++] = digits[x % base]; 49 | } while ((x /= base) != 0); 50 | 51 | if (sign) 52 | buf[i++] = '-'; 53 | 54 | while (--i >= 0) 55 | consputc(buf[i]); 56 | } 57 | 58 | static void 59 | cgaputc(int c) 60 | { 61 | int pos; 62 | 63 | // Cursor position: col + 80*row. 64 | outb(CRTPORT, 14); 65 | pos = inb(CRTPORT + 1) << 8; 66 | outb(CRTPORT, 15); 67 | pos |= inb(CRTPORT + 1); 68 | 69 | if (c == '\n') 70 | pos += 80 - pos % 80; 71 | else if (c == BACKSPACE) 72 | { 73 | if (pos > 0) 74 | --pos; 75 | } 76 | else 77 | crt[pos++] = (c & 0xff) | 0x0700; // black on white 78 | 79 | // if (pos < 0 || pos > 25 * 80) 80 | // panic("pos under/overflow"); 81 | 82 | if ((pos / 80) >= 24) 83 | { // Scroll up. 84 | // memmove(crt, crt + 80, sizeof(crt[0]) * 23 * 80); 85 | pos -= 80; 86 | // memset(crt + pos, 0, sizeof(crt[0]) * (24 * 80 - pos)); 87 | } 88 | 89 | outb(CRTPORT, 14); 90 | outb(CRTPORT + 1, pos >> 8); 91 | outb(CRTPORT, 15); 92 | outb(CRTPORT + 1, pos); 93 | crt[pos] = ' ' | 0x0700; 94 | } 95 | 96 | #define COM1 0x3f8 97 | 98 | void microdelay(int us) 99 | { 100 | } 101 | 102 | void uartputc(int c) 103 | { 104 | int i; 105 | 106 | for (i = 0; i < 128 && !(inb(COM1 + 5) & 0x20); i++) 107 | microdelay(10); 108 | outb(COM1 + 0, c); 109 | } 110 | 111 | void consputc(int c) 112 | { 113 | if (c == BACKSPACE) 114 | { 115 | uartputc('\b'); 116 | uartputc(' '); 117 | uartputc('\b'); 118 | } 119 | else 120 | uartputc(c); 121 | cgaputc(c); 122 | } 123 | 124 | void cprintf(char *fmt, ...) 125 | { 126 | int i, c, locking; 127 | uint *argp; 128 | char *s; 129 | 130 | // if (fmt == 0) 131 | // panic("null fmt"); 132 | 133 | argp = (uint *)(void *)(&fmt + 1); 134 | for (i = 0; (c = fmt[i] & 0xff) != 0; i++) 135 | { 136 | if (c != '%') 137 | { 138 | consputc(c); 139 | continue; 140 | } 141 | c = fmt[++i] & 0xff; 142 | if (c == 0) 143 | break; 144 | switch (c) 145 | { 146 | case 'd': 147 | printint(*argp++, 10, 1); 148 | break; 149 | case 'x': 150 | case 'p': 151 | printint(*argp++, 16, 0); 152 | break; 153 | case 's': 154 | if ((s = (char *)*argp++) == 0) 155 | s = "(null)"; 156 | for (; *s; s++) 157 | consputc(*s); 158 | break; 159 | case '%': 160 | consputc('%'); 161 | break; 162 | default: 163 | // Print unknown % sequence to draw attention. 164 | consputc('%'); 165 | consputc(c); 166 | break; 167 | } 168 | } 169 | } 170 | 171 | int main(void) 172 | { 173 | cprintf("test 123\n"); 174 | } -------------------------------------------------------------------------------- /tests/exec/cwd/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = cwd.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/cwd/cwd.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | ; mov word ax, 3 4 | ; cwde 5 | ; push eax 6 | 7 | ; mov word ax, -3 8 | ; cwde 9 | ; push eax 10 | 11 | mov dword eax, 3 12 | cdq 13 | push edx 14 | push eax 15 | 16 | mov dword eax, -3 17 | cdq 18 | push edx 19 | push eax 20 | 21 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/disk/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = disk.bin 2 | OBJS = crt0.o main_func.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/disk/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/disk/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00008000 2 | ECX: 00000000 3 | EDX: 000001f0 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 01000000 23 | 00007B60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 | 00007B80: 00 00 00 00 00 00 00 00 00 00 00 00 F7 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 25 | 00007BA0: B4 7B 00 00 23 7D 00 00 F0 01 00 00 00 80 00 00 00 00 00 00 D4 7B 00 00 5C 7D 00 00 00 7E 00 00 26 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 F8 7B 00 00 90 7D 00 00 00 80 00 00 27 | 00007BE0: 00 02 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7E 00 00 00 00 00 00 05 7C 00 00 28 | 00007C00: E8 6F 01 00 00 E9 F6 83 FF FF 55 89 E5 83 EC 08 8B 55 08 8B 45 0C 66 89 55 FC 88 45 F8 0F B6 45 29 | 00007C20: F8 0F B7 55 FC EE C9 C3 55 89 E5 83 EC 14 8B 45 08 66 89 45 EC 0F B7 45 EC 89 C2 EC 88 45 FF 0F 30 | 00007C40: B6 45 FF C9 C3 55 89 E5 57 53 8B 55 08 8B 4D 0C 8B 45 10 89 CB 89 DF 89 C1 FC F3 6D 89 C8 89 FB 31 | 00007C60: 89 5D 0C 89 45 10 5B 5F 5D C3 55 89 E5 90 68 F7 01 00 00 E8 B0 FF FF FF 83 C4 04 0F B6 C0 25 C0 32 | 00007C80: 00 00 00 83 F8 40 75 E6 C9 C3 55 89 E5 E8 D8 FF FF FF 6A 01 68 F2 01 00 00 E8 6C FF FF FF 83 C4 33 | 00007CA0: 08 8B 45 0C 0F B6 C0 50 68 F3 01 00 00 E8 58 FF FF FF 83 C4 08 8B 45 0C C1 E8 08 0F B6 C0 50 68 34 | 00007CC0: F4 01 00 00 E8 41 FF FF FF 83 C4 08 8B 45 0C C1 E8 10 0F B6 C0 50 68 F5 01 00 00 E8 2A FF FF FF 35 | 00007CE0: 83 C4 08 8B 45 0C C1 E8 18 83 C8 E0 0F B6 C0 50 68 F6 01 00 00 E8 10 FF FF FF 83 C4 08 6A 20 68 36 | 00007D00: F7 01 00 00 E8 01 FF FF FF 83 C4 08 E8 59 FF FF FF 68 80 00 00 00 FF 75 08 68 F0 01 00 00 E8 22 37 | 00007D20: FF FF FF 83 C4 0C C9 C3 55 89 E5 83 EC 10 8B 55 08 8B 45 0C 01 D0 89 45 FC 8B 45 10 25 FF 01 00 38 | 00007D40: 00 F7 D8 01 45 08 8B 45 10 C1 E8 09 89 45 10 EB 19 FF 75 10 FF 75 08 E8 2E FF FF FF 83 C4 08 81 39 | 00007D60: 45 08 00 02 00 00 83 45 10 01 8B 45 08 3B 45 FC 72 DF C9 C3 55 89 E5 83 EC 10 C7 45 FC 00 7E 00 40 | 00007D80: 00 6A 00 68 00 02 00 00 FF 75 FC E8 98 FF FF FF 83 C4 0C C9 C3 00 00 00 00 00 00 00 00 00 00 00 41 | 00007DA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 | 00007DC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 | 00007DE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 44 | 00007E00: E8 6F 01 00 00 E9 F6 83 FF FF 55 89 E5 83 EC 08 8B 55 08 8B 45 0C 66 89 55 FC 88 45 F8 0F B6 45 45 | 00007E20: F8 0F B7 55 FC EE C9 C3 55 89 E5 83 EC 14 8B 45 08 66 89 45 EC 0F B7 45 EC 89 C2 EC 88 45 FF 0F 46 | 00007E40: B6 45 FF C9 C3 55 89 E5 57 53 8B 55 08 8B 4D 0C 8B 45 10 89 CB 89 DF 89 C1 FC F3 6D 89 C8 89 FB 47 | 00007E60: 89 5D 0C 89 45 10 5B 5F 5D C3 55 89 E5 90 68 F7 01 00 00 E8 B0 FF FF FF 83 C4 04 0F B6 C0 25 C0 48 | 00007E80: 00 00 00 83 F8 40 75 E6 C9 C3 55 89 E5 E8 D8 FF FF FF 6A 01 68 F2 01 00 00 E8 6C FF FF FF 83 C4 49 | 00007EA0: 08 8B 45 0C 0F B6 C0 50 68 F3 01 00 00 E8 58 FF FF FF 83 C4 08 8B 45 0C C1 E8 08 0F B6 C0 50 68 50 | 00007EC0: F4 01 00 00 E8 41 FF FF FF 83 C4 08 8B 45 0C C1 E8 10 0F B6 C0 50 68 F5 01 00 00 E8 2A FF FF FF 51 | 00007EE0: 83 C4 08 8B 45 0C C1 E8 18 83 C8 E0 0F B6 C0 50 68 F6 01 00 00 E8 10 FF FF FF 83 C4 08 6A 20 68 -------------------------------------------------------------------------------- /tests/exec/disk/main_func.c: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned char uchar; 3 | typedef unsigned short ushort; 4 | 5 | #define SECTSIZE 512 6 | 7 | static inline void 8 | outb(ushort port, uchar data) 9 | { 10 | asm volatile("out %0,%1" 11 | : 12 | : "a"(data), "d"(port)); 13 | } 14 | 15 | static inline uchar 16 | inb(ushort port) 17 | { 18 | uchar data; 19 | 20 | asm volatile("in %1,%0" 21 | : "=a"(data) 22 | : "d"(port)); 23 | return data; 24 | } 25 | 26 | static inline void 27 | insl(int port, void *addr, int cnt) 28 | { 29 | asm volatile("cld; rep insl" 30 | : "=D"(addr), "=c"(cnt) 31 | : "d"(port), "0"(addr), "1"(cnt) 32 | : "memory", "cc"); 33 | } 34 | 35 | void waitdisk(void) 36 | { 37 | // Wait for disk ready. 38 | while ((inb(0x1F7) & 0xC0) != 0x40) 39 | ; 40 | } 41 | 42 | // Read a single sector at offset into dst. 43 | void readsect(void *dst, uint offset) 44 | { 45 | // Issue command. 46 | waitdisk(); 47 | outb(0x1F2, 1); // count = 1 48 | outb(0x1F3, offset); 49 | outb(0x1F4, offset >> 8); 50 | outb(0x1F5, offset >> 16); 51 | outb(0x1F6, (offset >> 24) | 0xE0); 52 | outb(0x1F7, 0x20); // cmd 0x20 - read sectors 53 | 54 | // Read data. 55 | waitdisk(); 56 | insl(0x1F0, dst, SECTSIZE / 4); 57 | } 58 | 59 | // Read 'count' bytes at 'offset' from kernel into physical address 'pa'. 60 | // Might copy more than asked. 61 | void readseg(uchar *pa, uint count, uint offset) 62 | { 63 | uchar *epa; 64 | 65 | epa = pa + count; 66 | 67 | // Round down to sector boundary. 68 | pa -= offset % SECTSIZE; 69 | 70 | // Convert to sector number 71 | offset = (offset / SECTSIZE); 72 | 73 | // If this is too slow, we could read lots of sectors at a time. 74 | // We'd write more to memory than asked, but it doesn't matter -- 75 | // we load in increasing order. 76 | for (; pa < epa; pa += SECTSIZE, offset++) 77 | readsect(pa, offset); 78 | } 79 | 80 | int main(void) 81 | { 82 | uchar *dst = (uchar *)0x7E00; 83 | readseg(dst, 512, 0); 84 | } -------------------------------------------------------------------------------- /tests/exec/div/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = div.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/div/div.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | ; div rm8 ; 5 | 6 | sub esp, 16 ; ESP: 7BF0 7 | mov ebp, esp ; EBP: 7BF0 8 | 9 | mov byte [ebp], 0xF 10 | mov al, 0xF 11 | div byte [ebp] 12 | push eax ; 7BEC: 0x01 13 | 14 | mov byte [ebp], 0x2 15 | mov al, 0x7 16 | div byte [ebp] 17 | push eax ; 7BE8: 00 00 01 03 18 | 19 | ; div rm32 ; 20 | 21 | mov dword [ebp], 0xFFFFFFFE ; 4294967294 22 | mov edx, 0x1 23 | mov eax, 0x11111111 ; 4581298449 24 | div dword [ebp] 25 | push edx ; 7BE4: 0x1F ; 0x11111113(rem: 286331155) 26 | push eax ; 7BE0: 0x1 27 | 28 | mov dword [ebp], 0xFFFFFFFF ; 4294967295 29 | mov edx, 0x0 ; 30 | mov eax, 0xFFFFFFFF 31 | div dword [ebp] 32 | push edx ; 7BDC: 0x0 33 | push eax ; 7BD8: 0x1 34 | 35 | ; idiv rm8 ; 36 | 37 | mov byte [ebp], 0xF 38 | mov al, 0xF 39 | idiv byte [ebp] 40 | push eax ; 7BD4: 0x01 41 | 42 | mov byte [ebp], -2 43 | mov al, 7 44 | idiv byte [ebp] 45 | push eax ; 7BD0: 00 00 01(1: same sign as dividend) FD(1111 1101 = -3) 46 | 47 | ; idiv rm32 ; 48 | 49 | mov eax, 0 50 | mov dword [ebp], 0 51 | 52 | mov dword [ebp], 3 53 | mov edx, -1 54 | mov eax, -1 55 | idiv dword [ebp] 56 | push eax ; 7BCC: 0x0 57 | push edx ; 7BC8: -1 (0xFFFFFFFF) 58 | 59 | mov dword [ebp], 0x7FFFFFFF ; 2147483647 60 | mov edx, 0x7FFF 61 | mov eax, 0xFFFFFFFF ; 0x7FFF FFFF FFFF: 140737488355327 62 | idiv dword [ebp] 63 | push eax ; 7BC4: 0x10000 (65536) 64 | push edx ; 7BC0: 0xFFFF (65535) 65 | 66 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/div/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00010000 2 | ECX: 00000000 3 | EDX: 0000ffff 4 | EBX: 00000000 5 | ESP: 00007bc0 6 | EBP: 00007bf0 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BC0: FF FF 00 00 00 00 01 00 FF FF FF FF 00 00 00 00 FD 01 00 00 01 00 00 00 01 00 00 00 00 00 00 00 24 | 00007BE0: 01 00 00 00 13 11 11 11 03 01 00 00 01 00 00 00 FF FF FF 7F 00 00 00 00 00 00 00 00 00 00 00 00 25 | 00007C00: 83 EC 10 89 E5 C6 45 00 0F B0 0F F6 75 00 50 C6 45 00 02 B0 07 F6 75 00 50 C7 45 00 FE FF FF FF 26 | 00007C20: BA 01 00 00 00 B8 11 11 11 11 F7 75 00 52 50 C7 45 00 FF FF FF FF BA 00 00 00 00 B8 FF FF FF FF 27 | 00007C40: F7 75 00 52 50 C6 45 00 0F B0 0F F6 7D 00 50 C6 45 00 FE B0 07 F6 7D 00 50 B8 00 00 00 00 C7 45 28 | 00007C60: 00 00 00 00 00 C7 45 00 03 00 00 00 BA FF FF FF FF B8 FF FF FF FF F7 7D 00 50 52 C7 45 00 FF FF 29 | 00007C80: FF 7F BA FF 7F 00 00 B8 FF FF FF FF F7 7D 00 50 52 E9 6A 83 FF FF 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/flags_clear/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = flags_clear.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/flags_clear/expected.txt: -------------------------------------------------------------------------------- 1 | eflags:00000000 00000000 00000000 00000000 2 | -------------------------------------------------------------------------------- /tests/exec/flags_clear/flags_clear.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | stc 4 | sti 5 | std 6 | clc 7 | cli 8 | cld 9 | jmp 0 10 | -------------------------------------------------------------------------------- /tests/exec/flags_set/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = flags_set.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/flags_set/expected.txt: -------------------------------------------------------------------------------- 1 | eflags:00000000 00000000 00000110 00000001 2 | -------------------------------------------------------------------------------- /tests/exec/flags_set/flags_set.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | sti 4 | std 5 | cmc 6 | jmp 0 7 | -------------------------------------------------------------------------------- /tests/exec/gdt/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = gdt.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/gdt/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000010 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bfc 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000008 12 | SS: 00000010 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000001 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0017 00007c25 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 24 | 00007C00: 0F 01 16 3D 7C 0F 20 C0 66 83 C8 01 0F 22 C0 EA 14 7C 08 00 B8 10 00 00 00 8E D0 68 FF FF 00 00 25 | 00007C20: E9 DB 83 FF FF 00 00 00 00 00 00 00 00 FF FF 00 00 00 98 CF 00 FF FF 00 00 00 92 CF 00 17 00 25 26 | -------------------------------------------------------------------------------- /tests/exec/gdt/gdt.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | org 0x7c00 3 | 4 | load_gdt: 5 | lgdt [GDT_DESC] ; 0F 01 15 (14 7C 00 00): 15=21: 000 10(op) 101(r/m) 6 | ; xgetbv ; 0F 01 D0: D0(so): 110 10(op) 000(r/m) 7 | ; xsetbv ; 0F 01 D1: D1(so): 110 10(op) 001(r/m) 8 | ; monitor ; 0F 01 C8: C8(so): 110 01(op) 000(r/m) 9 | ; mwait ; 0F 01 C9: C9=201: 110 01(op) 001(r/m) 10 | 11 | ; Enable Protected Mode: PE bit on CR0 12 | mov eax, cr0 13 | or eax, 1 14 | mov cr0, eax 15 | 16 | jmp 8:pe_enter ; 1000b 17 | 18 | BITS 32 19 | pe_enter: 20 | mov dword eax, 0x10 ; 10000b 21 | mov ss, ax 22 | push 0xFFFF 23 | jmp 0 ; E9 (F4 83 FF FF) 24 | 25 | ; FF FF 00 00 00 92 CF 00 26 | GDT: 27 | ; null segment descriptor 28 | dw 0 29 | dw 0 30 | db 0 31 | db 0 32 | db 0 33 | db 0 34 | ; code segment descriptor 35 | ; 0000 FFFF 36 | ; 00CF 9800 37 | dw 0xFFFF ; limit low 38 | dw 0 ; base low 39 | db 0 ; base middle 40 | db 10011000b ; access 41 | db 11001111b ; limit + flags 42 | db 0 ; base high 43 | ; data segment descriptor 44 | ; 0000 FFFF 45 | ; 00CF 9200 46 | dw 0xFFFF ; limit low 47 | dw 0 ; base low 48 | db 0 ; base middle 49 | db 10010010b ; access 50 | db 11001111b ; limit + flags 51 | db 0 ; base high 52 | 53 | ; 07 00 0C 7C 00 00 54 | GDT_DESC: 55 | dw (GDT_DESC - GDT - 1) 56 | dd GDT 57 | 58 | GDT_TEST: 59 | dw 0xFFFF ; limit low 60 | dw 0x5678 ; base low 61 | db 0x34 ; base middle 62 | db 10010010b ; access 63 | db 11001111b ; limit + flags 64 | db 0x12 ; base high -------------------------------------------------------------------------------- /tests/exec/if/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = if.bin 2 | OBJS = crt0.o if.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 -O0 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/if/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/if/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000003 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | CS: 00000000 11 | DS: 00000000 12 | ES: 00000000 13 | SS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 7C 00 00 23 | 00007C00: E8 1A 00 00 00 E9 F6 83 FF FF 55 89 E5 83 7D 08 00 78 05 8B 45 08 EB 05 8B 45 08 F7 D8 5D C3 55 24 | -------------------------------------------------------------------------------- /tests/exec/if/if.c: -------------------------------------------------------------------------------- 1 | int abs(int i) 2 | { 3 | if (i >= 0) 4 | { 5 | return i; 6 | } 7 | else 8 | { 9 | return -i; 10 | } 11 | } 12 | 13 | int main(void) 14 | { 15 | return abs(-3); 16 | } 17 | 18 | /* 19 | * LDFLAG: -Ttext 0x7c00: 31744 20 | * 00000000 E81A000000 call dword 0x1f ; 0x0000001A: 26 ; 0 + 0x1A + 5 = 1F ; Push 7c05 to ESP: 7CFC ; 21 | * 00000005 E9F683FFFF jmp dword 0xF683FFFF ; FFFF83F6: -31754 -> 31749(this EIP) +5(instruction) - 31754 = 0: jump to 0 22 | * 0000000A 55 push ebp ; OPTIMIZED~ 23 | * 0000000B 89E5 mov ebp,esp 24 | * 0000000D 837D0800 cmp dword [ebp+0x8],byte +0x0 25 | * 00000011 7805 js 0x18 26 | * 00000013 8B4508 mov eax,[ebp+0x8] 27 | * 00000016 EB05 jmp short 0x1d 28 | * 00000018 8B4508 mov eax,[ebp+0x8] 29 | * 0000001B F7D8 neg eax 30 | * 0000001D 5D pop ebp 31 | * 0000001E C3 ret ; ~OPTIMIZED 32 | * 0000001F 55 push ebp ; main() ; ESP: 7BF8: 0000 33 | * 00000020 89E5 mov ebp,esp ; EBP: 7BF8 34 | * 00000022 B803000000 mov eax,0x3 ; EAX: 3 35 | * 00000027 5D pop ebp ; EBP: 0000 & ESP: 7BFC 36 | * 00000028 C3 ret ; Pops 7BFC: 7c05 and jumps to it. ESP: 7C00 ; 37 | */ -------------------------------------------------------------------------------- /tests/exec/inst_list/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = list.bin mov_rel8.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/inst_list/mov_rel8.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | str1: 5 | db 'Hello', 10, 0 6 | mov eax, str1 7 | -------------------------------------------------------------------------------- /tests/exec/io/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = in.bin in_display.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector -m32 8 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.o : %.asm Makefile 18 | $(AS) -f elf $< 19 | 20 | %.bin : %.o Makefile 21 | $(LD) $(LDFLAGS) -o $@ $< 22 | 23 | %.bin : %.asm Makefile 24 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/io/in.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | mov edx, 0x03f8 4 | in al, dx 5 | in al, 0x64 6 | jmp 0 7 | -------------------------------------------------------------------------------- /tests/exec/io/in_display.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | start: 4 | mov edx, 0x03f8 5 | mainloop: 6 | mov al, '>' 7 | out dx, al 8 | input: 9 | in al, dx 10 | cmp al, 'h' 11 | je puthello 12 | cmp al, 'w' 13 | je putworld 14 | cmp al, 'q' 15 | je fin 16 | jmp input 17 | puthello: 18 | mov esi, msghello 19 | call puts 20 | jmp mainloop 21 | putworld: 22 | mov esi, msgworld 23 | call puts 24 | jmp mainloop 25 | fin: 26 | jmp 0 27 | puts: 28 | mov al, [esi] 29 | inc esi 30 | cmp al, 0 31 | je putsend 32 | out dx, al 33 | jmp puts 34 | putsend: 35 | ret 36 | msghello: 37 | db "hello", 0x0d, 0x0a, 0 38 | msgworld: 39 | db "world", 0x0d, 0x0a, 0 40 | -------------------------------------------------------------------------------- /tests/exec/io_out/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = io_out.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector -m32 8 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.o : %.asm Makefile 18 | $(AS) -f elf $< 19 | 20 | %.bin : %.o Makefile 21 | $(LD) $(LDFLAGS) -o $@ $< 22 | 23 | %.bin : %.asm Makefile 24 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/io_out/expected.txt: -------------------------------------------------------------------------------- 1 | CS: 0000 EIP: 00007C00 Op: BA 2 | CS: 0000 EIP: 00007C05 Op: B8 3 | CS: 0000 EIP: 00007C0A Op: EE 4 | ACS: 0000 EIP: 00007C0B Op: EF 5 | ACS: 0000 EIP: 00007C0C Op: E9 6 | End of program :) 7 | EAX: 00000041 8 | ECX: 00000000 9 | EDX: 000003f8 10 | EBX: 00000000 11 | ESP: 00007c00 12 | EBP: 00000000 13 | ESI: 00000000 14 | EDI: 00000000 15 | EIP: 00000000 16 | ES: 00000000 17 | CS: 00000000 18 | SS: 00000000 19 | DS: 00000000 20 | FS: 00000000 21 | GS: 00000000 22 | CR0: 00000000 23 | CR1: 00000000 24 | CR2: 00000000 25 | CR3: 00000000 26 | CR4: 00000000 27 | eflags:00000000 00000000 00000000 00000000 28 | -------------------------------------------------------------------------------- /tests/exec/io_out/io_out.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | mov edx, 0x03f8 4 | mov eax, 0x41 5 | out dx, al 6 | out dx, eax 7 | jmp 0 8 | -------------------------------------------------------------------------------- /tests/exec/ioapic/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = ioapic.bin 2 | OBJS = crt0.o ioapic.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/ioapic/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/ioapic/expected.txt: -------------------------------------------------------------------------------- 1 | IOREGSEL: 00000001 IOWIN: 00170011 IOAPICID: 00000000 2 | Redirection Tables: [IRQ: 00000023 DESTID: 00000003] 3 | -------------------------------------------------------------------------------- /tests/exec/ioapic/ioapic.c: -------------------------------------------------------------------------------- 1 | #define IOAPIC 0xFEC00000 // Default physical address of IO APIC 2 | #define REG_TABLE 0x10 // Redirection table base 3 | 4 | struct ioapic 5 | { 6 | unsigned int reg; 7 | unsigned int pad[3]; 8 | unsigned int data; 9 | }; 10 | 11 | static unsigned int 12 | ioapicread(int reg) 13 | { 14 | volatile struct ioapic *ioapic = (volatile struct ioapic *)IOAPIC; 15 | ioapic->reg = reg; 16 | return ioapic->data; 17 | } 18 | 19 | static void 20 | ioapicwrite(int reg, unsigned int data) 21 | { 22 | volatile struct ioapic *ioapic = (volatile struct ioapic *)IOAPIC; 23 | ioapic->reg = reg; 24 | ioapic->data = data; 25 | } 26 | 27 | int main(void) 28 | { 29 | int i, id, maxintr; 30 | 31 | id = ioapicread(0x0) >> 24; 32 | 33 | ioapicwrite(REG_TABLE + 2 * 1, (32 + 3)); 34 | ioapicwrite(REG_TABLE + 2 * 1 + 1, 3); 35 | 36 | maxintr = (ioapicread(0x01) >> 16) & 0xFF; 37 | } -------------------------------------------------------------------------------- /tests/exec/jmp_c/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = jmp_c.bin 2 | OBJS = crt0.o jmp_c.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/jmp_c/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/jmp_c/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000037 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | CS: 00000000 11 | DS: 00000000 12 | ES: 00000000 13 | SS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 | 00007BE0: 00 00 00 00 37 00 00 00 F8 7B 00 00 3C 7C 00 00 0B 00 00 00 0A 00 00 00 00 00 00 00 05 7C 00 00 23 | 00007C00: E8 2B 00 00 00 E9 F6 83 FF FF 55 89 E5 83 EC 10 C7 45 FC 00 00 00 00 EB 0A 8B 45 08 01 45 FC 83 24 | 00007C20: 45 08 01 8B 45 08 3B 45 0C 7E EE 8B 45 FC C9 C3 55 89 E5 6A 0A 6A 01 E8 CE FF FF FF 83 C4 08 C9 25 | 00007C40: C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 26 | -------------------------------------------------------------------------------- /tests/exec/jmp_c/jmp_c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 0x37 (55) 3 | */ 4 | int sum(int a, int b) 5 | { 6 | int sum; 7 | sum = 0; 8 | while (a <= b) 9 | { 10 | sum += a; 11 | a++; 12 | } 13 | return sum; 14 | } 15 | 16 | int main(void) 17 | { 18 | return sum(1, 10); 19 | } 20 | 21 | /* 22 | * 00000000 E82B000000 call dword 0x30 ; 0 + 43(0x2B) + 5 = 48(0x30) ; ESP: 7BFC = 7C05 23 | * 00000005 E9F683FFFF jmp dword 0xffff8400 ; jmp to 0 ; 24 | * 0000000A 55 push ebp ; sum() ; 7BE8 = 7BF8 ; <> 25 | * 0000000B 89E5 mov ebp,esp ; EBP: 7BE8 ; <> 26 | * 0000000D 83EC10 sub esp,byte +0x10 ; ESP = 7BE8 - 16 = 7BDC ; 27 | * 00000010 C745FC00000000 mov dword [ebp-0x4],0x0 ; sum = 0; 7BE4: 0x0 ; 28 | * 00000017 EB0A jmp short 0x23 ; EIP = 0x7C17 + 2 + 0x0A(10) = 0x7C23 ; 29 | * 00000019 8B4508 mov eax,[ebp+0x8] ; EAX: 0x1 from EBP+0x8:7BF0 30 | * 0000001C 0145FC add [ebp-0x4],eax ; EBP-0x4: 0 from (EIP:0x10) ; adds a to sum ; 31 | * 0000001F 83450801 add dword [ebp+0x8],byte +0x1 ; EBP+0x8:7BF0 ; adds 1 to a ; 32 | * 00000023 8B4508 mov eax,[ebp+0x8] ; EAX: EBP:7BE8 + 8 = 7BF0: 0x1 ; jumps here from 0x7C17 ; 33 | * 00000026 3B450C cmp eax,[ebp+0xc] ; EBP:7BF0 + 12 = 7BF4: 0x10 ; EAX - 7BF4:0x10 34 | * 00000029 7EEE jng 0x19 ; jump if not greater (jle) ; 0x29 + 0x2 + 0xEE(-18) = 0x19 35 | * 0000002B 8B45FC mov eax,[ebp-0x4] ; EAX: result from 7BE4 36 | * 0000002E C9 leave ; moves current EBP to ESP and pops old EBP to EBP ; ESP: 7BE8 -> EBP: 7BF8 from 7BE8 -> ESP: 7BEC; 37 | * 0000002F C3 ret ; EIP = 7C3C from 7BEC -> ESP: 7BF0 38 | * 00000030 55 push ebp ; main() ; <> ESP: 7BF8 = 0x0 ; 39 | * 00000031 89E5 mov ebp,esp ; <> 40 | * 00000033 6A0A push byte +0xa ; ESP: 7BF4 = 0xA(10) 41 | * 00000035 6A01 push byte +0x1 ; ESP: 7BF0 = 0x1 42 | * 00000037 E8CEFFFFFF call dword 0xa ; EIP: 7C37(31799) + 5 + FFFFFFCE(-50) = 7C0A ; ESP:7BEC = 7C3C 43 | * 0000003C 83C408 add esp,byte +0x8 ; ESP: 7BF0 + 8 = 7BF8 44 | * 0000003F C9 leave ; ESP: 7BF8 & EBP: 0x0 from 7BF8 -> ESP: 7BFC; 45 | * 00000040 C3 ret ; EIP: 7C05 from 7BFC -> ESP: 7c00 46 | */ -------------------------------------------------------------------------------- /tests/exec/jmp_far/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = jmp_far.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/jmp_far/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000010 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bf4 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000010 13 | DS: 00000010 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000001 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0017 00007c50 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 08 00 00 00 08 00 00 00 24 | 00007C00: 0F 01 16 68 7C 0F 20 C0 66 83 C8 01 0F 22 C0 EA 14 7C 08 00 B8 10 00 00 00 8E D8 8E D0 FF 25 74 25 | 00007C20: 7C 00 00 EA BC 9A 78 56 34 12 0E EA 39 7C 00 00 08 00 EA CD AB 89 67 45 23 0E FF 2D 6E 7C 00 00 26 | 00007C40: 0E EA DE BC 9A 78 56 34 0E EA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 00 98 CF 00 27 | 00007C60: FF FF 00 00 00 92 CF 00 17 00 50 7C 00 00 08 00 48 7C 00 00 2A 7C 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/jmp_far/jmp_far.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | org 0x7c00 3 | 4 | load_gdt: 5 | lgdt [GDT_DESC] ; 0F 01 15 (14 7C 00 00): 15=21: 000 10(op) 101(r/m) 6 | ; xgetbv ; 0F 01 D0: D0(so): 110 10(op) 000(r/m) 7 | ; xsetbv ; 0F 01 D1: D1(so): 110 10(op) 001(r/m) 8 | ; monitor ; 0F 01 C8: C8(so): 110 01(op) 000(r/m) 9 | ; mwait ; 0F 01 C9: C9=201: 110 01(op) 001(r/m) 10 | 11 | ; Enable Protected Mode: PE bit on CR0 12 | mov eax, cr0 13 | or eax, 1 14 | mov cr0, eax 15 | 16 | jmp 8:pe_enter ; 1000b 17 | 18 | BITS 32 19 | pe_enter: 20 | mov eax, 0x10 ; 10000b 21 | mov ds, eax 22 | mov ss, eax 23 | jmp [NEAR_ADDR1] 24 | jmp 0x1234:0x56789ABC ; Will be skipped. 25 | push cs 26 | 27 | jmp 0x8:0x7C39 ; EA 04 00 00 00 7C 00 ; 0x7C00 + 0xE = 0x7C0E 28 | jmp 0x2345:0x6789ABCD ; EA jmp ptr16:16/32 ; EA BC 9A 78 56 34 12 ; Will be skipped. 29 | push cs 30 | 31 | jmp far [FAR_ADDR1] ; FF 2D (same as [0x7C25]) ; FF 2D (0010 1011) 23 7C 00 00 ; 32 | push cs ; Will be skipped. 33 | jmp 0x3456:0x789ABCDE ; Will be skipped. 34 | push cs 35 | 36 | jmp 0:0 37 | 38 | ; FF FF 00 00 00 92 CF 00 39 | GDT: 40 | ; null segment descriptor 41 | dw 0 42 | dw 0 43 | db 0 44 | db 0 45 | db 0 46 | db 0 47 | ; code segment descriptor 48 | ; 0000 FFFF 49 | ; 00CF 9800 50 | dw 0xFFFF ; limit low 51 | dw 0 ; base low 52 | db 0 ; base middle 53 | db 10011000b ; access 54 | db 11001111b ; limit + flags 55 | db 0 ; base high 56 | ; data segment descriptor 57 | ; 0000 FFFF 58 | ; 00CF 9200 59 | dw 0xFFFF ; limit low 60 | dw 0 ; base low 61 | db 0 ; base middle 62 | db 10010010b ; access 63 | db 11001111b ; limit + flags 64 | db 0 ; base high 65 | 66 | ; 07 00 0C 7C 00 00 67 | GDT_DESC: 68 | dw (GDT_DESC - GDT - 1) 69 | dd GDT 70 | 71 | FAR_ADDR1: 72 | dw 0x8 ; Seg 73 | dd 0x7C48 ; Offset 74 | 75 | NEAR_ADDR1: 76 | dd 0x7C2A -------------------------------------------------------------------------------- /tests/exec/jmp_far16/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = jmp_far16.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/jmp_far16/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000000 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bfa 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 07 C1 07 00 00 24 | 00007C00: FF 26 29 7C EA 78 56 34 12 0E EA 04 00 C1 07 EA 89 67 45 23 0E FF 2E 25 7C 0E EA 9A 78 56 34 0E 25 | 00007C20: EA 00 00 00 00 C0 07 1F 00 09 7C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 26 | -------------------------------------------------------------------------------- /tests/exec/jmp_far16/jmp_far16.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | org 0x7c00 3 | ; jmp 4 | ; EB: jmp rel8 short, displacement relative to next instruction 5 | ; E9: jmp rel8/16 near, displacement relative to next instruction 6 | ; FF/4: jmp r/m16/32 near, absolute 7 | ; EA: jmp ptr16/32 far, absolute from operand 8 | ; FF/5: jmp m16/32 far, absolute indirect 9 | 10 | ; near: within current code segment 11 | ; far in real mode: code seg + offset (ptr16:16/32 or m16:16/32) 12 | ; (far address is loaded directly into CS & EIP) 13 | 14 | ; absolute: absoslute offset from current from base of CS 15 | ; usually register or r/m16/32 16 | ; relative: signed offset from currrent EIP 17 | ; usually a label in asm -> signed value after linking 18 | 19 | ; direct: address in operand 20 | ; indirect: memory location of 4/6 byte far address (m16:16/32) 21 | 22 | ; not sure SEG:OFFSET or OFFSET:SEG on memory ; 23 | ; push SEG -> push OFFSET & 24 | ; pop EIP -> pop SEG according to far return instruction (CB) 25 | 26 | jmp [NEAR_ADDR1] 27 | jmp 0x1234:0x5678 ; Will be skipped. 28 | push cs ; Address: 7C0D 29 | 30 | jmp 0x7C1:0x4 ; EA 04 00 00 00 7C 00 ; 0x7C00 + 0xE = 0x7C0E 31 | jmp 0x2345:0x6789 ; EA jmp ptr16:16/32 ; EA BC 9A 78 56 34 12 ; Will be skipped. 32 | push cs ; ADDRESS: 0x7C14 33 | 34 | jmp far [FAR_ADDR1] ; FF 2D (same as [0x7C25]) ; FF 2D (0010 1011) 23 7C 00 00 ; 35 | push cs ; Will be skipped. 36 | jmp 0x3456:0x789A ; Will be skipped. 37 | push cs ; ADDRESS: 0x7C2B 38 | 39 | jmp 0:0 40 | 41 | FAR_ADDR1: 42 | dw 0x7C0 ; Seg 43 | dw 0x1F ; Offset 44 | 45 | NEAR_ADDR1: 46 | dd 0x7C09 -------------------------------------------------------------------------------- /tests/exec/lapic/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = lapic.bin 2 | OBJS = crt0.o lapic.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/lapic/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/lapic/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00989680 2 | ECX: 00000000 3 | EDX: 00000380 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 FE F8 7B 00 00 D1 7C 00 00 24 | 00007BE0: E0 00 00 00 80 96 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 FE 00 00 00 00 05 7C 00 00 25 | 00007C00: E8 39 00 00 00 E9 F6 83 FF FF 55 89 E5 83 EC 10 C7 45 FC 00 00 E0 FE 8B 45 08 8D 14 85 00 00 00 26 | 00007C20: 00 8B 45 FC 01 C2 8B 45 0C 89 02 8B 45 08 8D 14 85 00 00 00 00 8B 45 FC 01 D0 8B 00 C9 C3 55 89 27 | 00007C40: E5 83 EC 10 68 00 00 01 00 68 D4 00 00 00 E8 B7 FF FF FF 83 C4 08 68 00 00 01 00 68 D8 00 00 00 28 | 00007C60: E8 A5 FF FF FF 83 C4 08 6A 00 68 C4 00 00 00 E8 96 FF FF FF 83 C4 08 68 00 85 08 00 68 C0 00 00 29 | 00007C80: 00 E8 84 FF FF FF 83 C4 08 C7 45 FC 00 00 E0 FE 90 8B 45 FC 05 00 03 00 00 8B 00 25 00 10 00 00 30 | 00007CA0: 85 C0 75 ED 6A 00 6A 20 E8 5D FF FF FF 83 C4 08 68 20 00 02 00 68 C8 00 00 00 E8 4B FF FF FF 83 31 | 00007CC0: C4 08 68 80 96 98 00 68 E0 00 00 00 E8 39 FF FF FF 83 C4 08 C9 C3 00 00 00 00 00 00 00 00 00 00 32 | TPR: 00000000 EOI: 00000000 SVR: 00000000 33 | TIMER: 00020020 TICR: 00989680 34 | LINT0: 00010000 LINT1: 00010000 -------------------------------------------------------------------------------- /tests/exec/lapic/lapic.c: -------------------------------------------------------------------------------- 1 | #define ID (0x0020 / 4) // ID 2 | #define TPR (0x0080 / 4) // Task Priority 3 | #define ICRLO (0x0300 / 4) // Interrupt Command 4 | #define INIT 0x00000500 // INIT/RESET 5 | #define STARTUP 0x00000600 // Startup IPI 6 | #define DELIVS 0x00001000 // Delivery status 7 | #define ASSERT 0x00004000 // Assert interrupt (vs deassert) 8 | #define DEASSERT 0x00000000 9 | #define LEVEL 0x00008000 // Level triggered 10 | #define BCAST 0x00080000 // Send to all APICs, including self. 11 | #define BUSY 0x00001000 12 | #define FIXED 0x00000000 13 | #define ICRHI (0x0310 / 4) // Interrupt Command [63:32] 14 | #define TIMER (0x0320 / 4) // Local Vector Table 0 (TIMER) 15 | #define PCINT (0x0340 / 4) // Performance Counter LVT 16 | #define LINT0 (0x0350 / 4) // Local Vector Table 1 (LINT0) 17 | #define LINT1 (0x0360 / 4) // Local Vector Table 2 (LINT1) 18 | #define ERROR (0x0370 / 4) // Local Vector Table 3 (ERROR) 19 | #define TICR (0x0380 / 4) // Timer Initial Count 20 | #define MASKED 0x00010000 // Interrupt masked 21 | #define PERIODIC 0x00020000 // Periodic 22 | 23 | #define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ 24 | #define IRQ_TIMER 0 25 | 26 | #define LAPIC_DEFAULT_BASE 0xFEE00000 27 | 28 | // volatile unsigned int *lapic = (unsigned int *)LAPIC_DEFAULT_BASE; // Initialized in mp.c 29 | 30 | static unsigned int 31 | lapicw(int index, int value) 32 | { 33 | volatile unsigned int *lapic = (unsigned int *)LAPIC_DEFAULT_BASE; 34 | lapic[index] = value; 35 | return lapic[index]; 36 | } 37 | 38 | int main(void) 39 | { 40 | lapicw(LINT0, MASKED); 41 | lapicw(LINT1, MASKED); 42 | lapicw(ICRHI, 0); 43 | lapicw(ICRLO, BCAST | INIT | LEVEL); 44 | volatile unsigned int *lapic = (unsigned int *)LAPIC_DEFAULT_BASE; 45 | while (lapic[ICRLO] & DELIVS) 46 | ; 47 | lapicw(TPR, 0); 48 | lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER)); 49 | lapicw(TICR, 10000000); 50 | } -------------------------------------------------------------------------------- /tests/exec/les/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = les.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/les/les.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | label0: 3 | org 0x7c00 4 | les dword eax, [ebx] ; les ModRM -------------------------------------------------------------------------------- /tests/exec/loop/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = loop.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/loop/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000004 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007b74 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 01000000 22 | 00007B60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 23 | 00007B80: 04 00 00 00 01 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 04 00 00 00 24 | 00007BA0: 00 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 25 | 00007BC0: 04 00 00 00 01 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 04 00 00 00 26 | 00007BE0: 00 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 04 00 00 00 27 | 00007C00: B8 04 00 00 00 B9 04 00 00 00 E1 FE 48 51 50 E0 F9 B9 04 00 00 00 E0 FE 40 51 50 E1 F9 B9 04 00 28 | 00007C20: 00 00 48 51 50 E2 FB B9 04 00 00 00 40 51 50 E2 FB 51 B9 01 00 00 00 E3 0E 6A 01 B9 00 00 00 00 29 | 00007C40: E3 05 68 FF 00 00 00 6A 02 E9 B2 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/loop/loop.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | mov eax, 4 4 | mov ecx, 4 5 | 6 | ; ZF: 0 ; 7 | label1: 8 | loopz label1 9 | dec eax 10 | push ecx ; 4 -> 3 -> 2 -> 1 -> 0 11 | push eax ; 3 -> 2 -> 1 -> 0 (ZF: 1) -> next 12 | loopnz label1 13 | 14 | ; ZF: 1 ; 15 | mov ecx, 4 16 | label2: 17 | loopnz label2 18 | inc eax 19 | push ecx ; 4 -> 3 -> 2 -> 1 -> 0 20 | push eax ; 1 -> 2 -> 3 -> 4 -> next 21 | loopz label2 22 | 23 | mov ecx, 4 24 | label3: 25 | dec eax 26 | push ecx ; 4 -> 3 -> 2 -> 1 -> 0 27 | push eax ; 3 -> 2 -> 1 -> 0 -> next 28 | loop label3 29 | 30 | mov ecx, 4 31 | label4: 32 | inc eax 33 | push ecx ; 4 -> 3 -> 2 -> 1 -> 0 34 | push eax ; 1 -> 2 -> 3 -> 4 -> next 35 | loop label4 36 | push ecx ; 0 37 | 38 | mov ecx, 1 39 | jecxz label5 40 | push 0x1 ; comes here as ecx: 1 41 | mov ecx, 0 42 | jecxz label5 43 | push 0xFF ; should not come here with ecx: 0 44 | label5: 45 | push 0x2 ; comes here from jecxz: 2 46 | jmp 0 47 | -------------------------------------------------------------------------------- /tests/exec/main_func/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = main_func.bin 2 | OBJS = crt0.o main_func.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/main_func/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/main_func/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000004 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | CS: 00000000 11 | DS: 00000000 12 | ES: 00000000 13 | SS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 05 7C 00 00 23 | 00007C00: E8 05 00 00 00 E9 F6 83 FF FF 55 89 E5 83 EC 10 C7 45 FC 03 00 00 00 83 45 FC 01 8B 45 FC C9 C3 24 | -------------------------------------------------------------------------------- /tests/exec/main_func/main_func.c: -------------------------------------------------------------------------------- 1 | int main(void) 2 | { 3 | int val = 3; 4 | val++; 5 | return val; 6 | } 7 | /* 8 | * 00000000 E805000000 call dword 0xa ; pushes ret addr ; ESP 0x7C00 - 4 = 0x7BFC: 7C05 (7C00 + 5) 9 | * 00000005 E9F683FFFF jmp dword 0xffff8400 (-31744) <-0x7C00: 31744 10 | * 0000000A 55 push ebp ; pushes current EBP ; ESP 0x7BFC - 4 = 0x7BF8: 0x0000 11 | * 0000000B 89E5 mov ebp,esp ; brings current ESP to EBP ; EBP: 0x7BF8 12 | * 0000000D 83EC10 sub esp,byte +0x10 ; moves ESP down by 16 ; ESP: 0x7BF8 - 16 = 7BE8 13 | * 00000010 C745FC03000000 mov dword [ebp-0x4],0x3 ; EBP: 0x7BF8 - 4 = 0x7BF4: 3 14 | * 00000017 8345FC01 add dword [ebp-0x4],byte +0x1 ; 0x7BF4: 4 15 | * 0000001B 8B45FC mov eax,[ebp-0x4] ; EAX: 4 16 | * 0000001E C9 leave ; updates ESP with current EBP: ESP: 0x7BE8 -> 0x7BF8 and pops old EBP to EBP: 0x0000 & ESP: 0x7BFC 17 | * 0000001F C3 ret ; pops return address from ESP: 0x7BFC 18 | */ -------------------------------------------------------------------------------- /tests/exec/modrm/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = modrm.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/modrm/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 0000100d 2 | ECX: 0000000a 3 | EDX: 00000002 4 | EBX: 00007bf0 5 | ESP: 00007be4 6 | EBP: 00000000 7 | ESI: 00000009 8 | EDI: 0000000a 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BE0: 00 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 0A 00 00 00 0A 00 00 00 00 00 00 00 23 | 00007C00: 83 EC 10 89 E3 B8 00 00 00 00 04 02 00 03 02 03 C7 43 04 05 00 00 00 01 43 04 03 43 04 8B 73 04 24 | 00007C20: FF 43 04 8B 7B 04 BA 02 00 00 00 89 3C 93 89 BC 93 00 10 00 00 8B 8C 93 00 10 00 00 05 00 10 00 25 | 00007C40: 00 FE 43 FC FE 43 FC FE 4B FC FF 43 F8 FF 43 F8 FF 4B F8 83 EC 08 FF 73 F8 E9 A2 83 FF FF 00 00 -------------------------------------------------------------------------------- /tests/exec/modrm/modrm.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | sub esp, 16 ; 7BF0 4 | mov ebx, esp ; EBP: 7BF0 5 | mov eax, 0 ; EAX: 0 6 | add al, 2 ; EAX: 1 7 | add byte [ebx], al ; op: 00 ; 7BF0: 2 8 | add byte al, [ebx] ; op: 02 ; EAX: 4 9 | mov dword [ebx+4], 5 ; 7BF4: 5 10 | add dword [ebx+4], eax ; 7BF4: 9 11 | add dword eax, [ebx+4] ; EAX : 13 12 | mov esi, [ebx+4] ; ESI: 9 13 | inc dword [ebx+4] ; 7BF4: 10 14 | mov edi, [ebx+4] ; EDI: 10 15 | ; ModRM: 7C (01: Mod-01 111: Reg-EDI 100: SIB indicator) ; 16 | ; SIB: 95 (10: *4, 010: EDX, 101: EBP) ; 17 | mov edx, 2 ; EDX: 2 18 | mov [ebx + edx * 4], edi ; op: 89 ; 7BF0(EBP) + 2(EDX) * 4 = 7BF8: 10 ; 19 | mov [ebx + edx * 4 + 0x1000], edi ; 8BF0: 10 ; 20 | mov ecx, [ebx + edx * 4 + 0x1000] ; ECX: 10 ; 21 | add dword eax, 0x1000 ; EAX: 1 22 | 23 | 24 | inc byte [ebx - 4] ; 7BF0(EBP) - 4 = 7BEC: 01 25 | inc byte [ebx - 4] 26 | dec byte [ebx - 4] 27 | 28 | inc dword [ebx - 8] ; 7BF0 (EBP)-8 = 7BE8: 01 29 | inc dword [ebx - 8] 30 | dec dword [ebx - 8] 31 | 32 | sub esp, 8 ; 7BF0 (EBP) - 8 = 7BE8 33 | push dword [ebx - 8] ; FF/6 ; 7BE4: 01 34 | 35 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/moffs/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = moffs.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/moffs/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: eeeeeeee 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bf0 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 000007ba 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BA0: FF 00 EE EE EE EE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EE EE EE EE 11 11 11 11 FF 00 00 00 11 00 00 00 25 | 00007C00: B8 BA 07 00 00 8E D8 B8 00 00 00 00 B0 FF A2 00 00 00 00 B0 11 50 A0 00 00 00 00 50 B8 EE EE EE 26 | 00007C20: EE A3 02 00 00 00 B8 11 11 11 11 50 A1 02 00 00 00 50 E9 C9 83 FF FF 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/moffs/moffs.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | ; moffs8 4 | mov eax, 0x7BA 5 | mov ds, eax 6 | mov eax, 0 7 | mov al, 0xFF 8 | mov byte [0x0], al 9 | mov byte al, 0x11 ; to be overwritten 10 | push eax 11 | mov byte al, [0x0] 12 | push eax ; 0x7BFC: 0xFF 13 | 14 | ; moff32 15 | 16 | mov eax, 0xEEEEEEEE 17 | mov dword [0x2], eax 18 | mov dword eax, 0x11111111 19 | push eax 20 | mov dword eax, [0x2] 21 | push eax 22 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/mov/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = mov.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/mov/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 000000ff 2 | ECX: 00000000 3 | EDX: 0000000f 4 | EBX: 00000000 5 | ESP: 00007bf8 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 000000ff 17 | CR1: 00000000 18 | CR2: 00000001 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 13 00 00 00 3C 7C 00 00 24 | 00007C00: 89 E0 BA 0F 00 00 00 8D 04 90 50 89 E0 BA 0F 00 00 00 8D 42 04 50 0D FF 00 00 00 0F 22 C0 83 E0 25 | 00007C20: 01 0F 22 D0 0F 20 C0 E9 D4 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/mov/mov.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | ; mov eax, ds ; Tested in seg ; 4 | ; mov ebp, esp ; required for 66 tests below 5 | mov dword eax, esp 6 | mov dword edx, 0xF 7 | ; 7C00 + 0xF * 4 = 7C3C 8 | lea eax, [eax + edx * 4] ; R: EAX ModRM: 0490 04: [-][-] SIB: 90 = 1001 0000: scale: 2 index: EDX base: EAX 9 | push eax 10 | mov dword eax, esp 11 | mov dword edx, 0xF 12 | lea eax, [edx + 4] ; ModRM: C2: RM: EDX R: EAX 13 | push eax 14 | ; mov eax, cr0 ; 0F 20 C0 (1100 0000: Reg:000) 15 | ; mov eax, cr3 ; 0F 20 D8 (1101 1000: Reg:011) 16 | ; mov eax, cr4 ; 0F 20 E0 (1110 0000: Reg:100) 17 | or eax, 0xFF 18 | mov cr0, eax 19 | and eax, 0x1 20 | mov cr2, eax 21 | mov eax, cr0 22 | ; mov es, edx ; Tested in seg ; 23 | 24 | ; 66: operand prefix (needs to be tested in protected mode) 25 | ; mov [ebp - 10], dx ; 66 89 5424FC 26 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/mov_jmp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = mov_jmp.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/mov_jmp/mov_jmp.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | start: 3 | mov eax, 41 4 | jmp short start -------------------------------------------------------------------------------- /tests/exec/movzx/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = movzx.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/movzx/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 000000ff 2 | ECX: 00000000 3 | EDX: 00001111 4 | EBX: 00000000 5 | ESP: 00007c00 6 | EBP: 00007c00 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00000000 00000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF 11 11 11 11 24 | 00007C00: 89 E5 C7 45 F8 FF FF FF FF 0F B6 45 F8 C7 45 FC 11 11 11 11 0F B7 55 FC E9 E3 83 FF FF 00 00 00 25 | -------------------------------------------------------------------------------- /tests/exec/movzx/movzx.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | mov ebp, esp 4 | mov dword [ebp-0x8], 0xFFFFFFFF 5 | movzx eax, byte [ebp-0x8] ; eax should have 0xFF 6 | mov dword [ebp-0x4], 0x11111111 7 | movzx edx, word [ebp-0x4] ; edx should have 0x1111 8 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/mp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = mp.bin 2 | OBJS = crt0.o mp.o 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector -m32 9 | LDFLAGS += -m elf_i386 --entry=start --oformat=binary -Ttext 0x7c00 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.o : %.asm Makefile 19 | $(AS) -f elf $< 20 | 21 | $(TARGET) : $(OBJS) Makefile 22 | $(LD) $(LDFLAGS) -o $@ $(OBJS) -------------------------------------------------------------------------------- /tests/exec/mp/crt0.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | extern main 3 | global start 4 | start: 5 | call main 6 | jmp 0 7 | -------------------------------------------------------------------------------- /tests/exec/mp/expected.txt: -------------------------------------------------------------------------------- 1 | mCS: 0000 EIP: 00007C26 Op: C9 2 | pCS: 0000 EIP: 00007C26 Op: C9 3 | -------------------------------------------------------------------------------- /tests/exec/mul/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = mul.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/mul/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: fffffff7 2 | ECX: 00000000 3 | EDX: f8000000 4 | EBX: 00000000 5 | ESP: 00007b94 6 | EBP: 00007bf0 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | GDTR: 0000 00000000 22 | eflags:00000000 00000000 00001000 00000001 23 | 00007B80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 08 00 00 F7 FF FF FF 01 08 00 00 24 | 00007BA0: FD FF FF FF 01 08 00 00 00 00 00 80 00 00 00 F8 00 00 00 00 01 00 00 00 00 00 00 00 01 08 00 00 25 | 00007BC0: 80 F8 00 00 00 00 00 00 06 00 00 00 01 08 00 00 01 00 00 00 FE FF FF FF 00 00 00 00 01 FE 00 00 26 | 00007BE0: 01 08 00 00 01 FE 00 00 00 00 00 00 E1 00 00 00 FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 27 | 00007C00: 83 EC 10 89 E5 C6 45 00 0F B0 0F F6 65 00 50 9C C6 45 00 FF B0 FF F6 65 00 50 9C C7 45 00 FF 00 28 | 00007C20: 00 00 B8 FF 00 00 00 F7 65 00 50 9C C7 45 00 FF FF FF FF B8 FF FF FF FF F7 65 00 52 50 9C C6 45 29 | 00007C40: 00 03 B0 02 F6 6D 00 50 9C C6 45 00 80 B0 0F F6 6D 00 50 9C C7 45 00 FF FF FF FF B8 FF FF FF FF 30 | 00007C60: F7 6D 00 52 50 9C C7 45 00 00 00 00 80 B8 FF FF FF 0F F7 6D 00 52 50 9C C7 45 00 FF FF FF FF 6B 31 | 00007C80: 45 00 03 50 9C 6B C0 03 50 9C E9 71 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/mul/mul.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | ; mul ; 5 | 6 | sub esp, 16 ; ESP: 7BF0 7 | mov ebp, esp ; EBP: 7BF0 8 | 9 | mov byte [ebp], 0xF 10 | mov al, 0xF 11 | mul byte [ebp] 12 | push eax ; 7BEC: 0xE1(255) 13 | pushf ; 7BE8: 0x0 14 | 15 | mov byte [ebp], 0xFF ; 255 16 | mov al, 0xFF 17 | mul byte [ebp] 18 | push eax ; 7BE4: 0xFE01(65025) 19 | pushf ; 7BE0: 0x801: 0x0 0x0 00 00 1(OF)0 00 | 00 00 00 01(CF) 20 | 21 | mov dword [ebp], 0xFF 22 | mov eax, 0xFF 23 | mul dword [ebp] 24 | push eax ; 7BDC: 0xFE01 25 | pushf ; 7BD8: 0x0 26 | 27 | mov dword [ebp], 0xFFFFFFFF ; 4294967295 28 | mov eax, 0xFFFFFFFF 29 | mul dword [ebp] 30 | push edx ; 7BD4: 0xFFFFFFFE 31 | push eax ; 7BD0: 0x1 (0xFFFFFFFE 00000001: 18446744065119617025) 32 | pushf ; 7BCC: 0x801 33 | 34 | ; imul ; 35 | 36 | mov byte [ebp], 0x3 37 | mov al, 0x2 38 | imul byte [ebp] 39 | push eax ; 7BC8: 0x6 40 | pushf ; 7BC4: 0x0 41 | 42 | mov byte [ebp], 0x80 ; -128 43 | mov al, 0xF 44 | imul byte [ebp] 45 | push eax ; 7BC0: 0xF880(-1920) 46 | pushf ; 7BBC: 0x0801 47 | 48 | mov dword [ebp], 0xFFFFFFFF ; -1 49 | mov eax, 0xFFFFFFFF ; -1 50 | imul dword [ebp] 51 | push edx ; 7BB8: 0x0 52 | push eax ; 7BB4: 0x1 53 | pushf ; 7BB0: 0x0 54 | 55 | mov dword [ebp], 0x80000000 ; -2147483648 56 | mov eax, 0x0FFFFFFF ; 268435455 57 | imul dword [ebp] 58 | push edx ; 7BAC: 0xF8000000 59 | push eax ; 7BA8: 0x80000000 (-576460750155939840) 60 | pushf ; 7BA4: 0x0801 61 | 62 | mov dword [ebp], 0xFFFFFFFF ; -1 63 | imul eax, [ebp], byte 3 64 | push eax ; 7BA0: 0xFFFFFFFD (-3) 65 | pushf ; 7B9C: 0x0801 66 | 67 | imul eax, byte 3 ; 6B C0 03; C0: 11 000 000: eax 68 | push eax ; 7B98: 0xFFFFFFF7 (-9) 69 | pushf ; 7B94: 0x0801 70 | 71 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/or/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = or.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/or/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00001007 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007be4 6 | EBP: 00007bf0 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 00 00 00 00 07 00 00 00 0B 00 00 00 09 00 00 00 09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 24 | 00007C00: 83 EC 10 89 E5 B8 01 00 00 00 0C 08 50 08 45 00 B8 02 00 00 00 0A 45 00 50 83 4D 04 01 B8 02 00 25 | 00007C20: 00 00 09 45 04 B8 04 00 00 00 0B 45 04 50 0D 00 10 00 00 E9 C8 83 FF FF 00 00 00 00 00 00 00 00 26 | 00007C40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 | -------------------------------------------------------------------------------- /tests/exec/or/or.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | sub esp, 16 ; 7BF0 4 | mov ebp, esp ; EBP: 7BF0 5 | 6 | mov eax, 0x1 ; EAX: 1 7 | or al, 0x8 ; op: 0C EAX: 9 8 | push eax ; ESP -> 7BEC: 0x9 9 | 10 | or byte [ebp], al ; op: 08 ; 7BF0: 0x9 11 | 12 | mov eax, 0x2 ; EAX: 2 13 | or byte al, [ebp] ; op: 0A ; EAX: 0xB 14 | push eax ; ESP -> 7BE8: 0xB 15 | 16 | or dword [ebp+4], 0x1 ; op: 83 ; 7BF4: 0x1 17 | 18 | mov eax, 0x2 19 | or dword [ebp+4], eax ; op: 09 ; 7BF4: 0x3 20 | 21 | mov eax, 0x4 22 | or dword eax, [ebp+4] ; op: 0B ; EAX: 0x7 23 | push eax ; ESP -> 7BE4: 0x7 24 | 25 | or dword eax, 0x1000 ; op: 0D ; EAX: 0x1007 26 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/org_jmp/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = org_jmp.bin 2 | I386_ELF_GCC = /usr/local/Cellar/i386-elf-gcc/8.2.0/lib/gcc/i386-elf/8.2.0/include 3 | 4 | CC = gcc 5 | LD = ld 6 | AS = nasm 7 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 8 | -g -fno-stack-protector 9 | LDFLAGS += --entry=func --oformat=binary 10 | 11 | .PHONY: all 12 | all : 13 | make $(TARGET) 14 | 15 | %.o : %.c Makefile 16 | $(CC) $(CFLAGS) -c $< 17 | 18 | %.bin : %.o Makefile 19 | $(LD) $(LDFLAGS) -o $@ $< 20 | 21 | %.bin : %.asm Makefile 22 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/org_jmp/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000029 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007c00 6 | -------------------------------------------------------------------------------- /tests/exec/org_jmp/org_jmp.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | mov eax, 41 4 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/paging/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = paging.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/paging/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000010 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bfc 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000010 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 80010001 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00007c68 20 | CR4: 00000010 21 | GDTR: 0017 00007c4a 22 | eflags:00000000 00000000 00000000 10000000 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 24 | 00007C00: 0F 01 16 62 7C 0F 20 C0 66 83 C8 01 0F 22 C0 EA 14 7C 08 00 0F 20 E0 83 C8 10 0F 22 E0 B8 68 7C 25 | 00007C20: 00 00 0F 22 D8 0F 20 C0 0D 00 00 01 80 0F 22 C0 EA 02 00 40 00 08 00 B8 10 00 00 00 8E D0 68 FF 26 | 00007C40: FF 00 00 EA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF 00 00 00 98 CF 00 FF FF 00 00 00 92 27 | 00007C60: CF 00 17 00 4A 7C 00 00 8F 00 00 00 0F 00 C7 07 0F 50 C3 07 00 00 00 00 00 00 00 00 00 00 00 00 28 | -------------------------------------------------------------------------------- /tests/exec/paging/paging.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | org 0x7c00 3 | 4 | load_gdt: 5 | lgdt [GDT_DESC] ; 0F 01 15 (14 7C 00 00): 15=21: 000 10(op) 101(r/m) 6 | 7 | ; Enable Protected Mode: PE bit on CR0 8 | mov eax, cr0 9 | or eax, 1 10 | mov cr0, eax 11 | 12 | jmp 8:pe_enter ; GDT index: 1 << 3 = 1000b 13 | 14 | BITS 32 15 | pe_enter: 16 | ; Turn on page size extension for 4Mbyte pages 17 | mov eax, cr4 18 | or eax, 0x00000010 19 | mov cr4, eax 20 | ; Set page directory 21 | mov eax, PDE1 22 | mov cr3, eax 23 | ; Turn on paging. 24 | mov eax, cr0 25 | or eax, 0x80010000 26 | mov cr0, eax 27 | ; From here EIP will be translated. So we need 2 mappings: 28 | ; Before jmp (using PSE): PDE[10]: 0 | Offset[22]: 0 = 0x0 + EIP: 0x7C33 => 0x7C33 29 | ; After jmp (regular paging): PDE[10]: 1 | PTE[10]: 0 | Offset[12]: 2 30 | ; (0000 0000 0100 0000 0000 0000 0000 0010) = 0x400002 31 | jmp 8:0x400002 32 | 33 | pg_enter: 34 | mov dword eax, 0x10 ; 10000b 35 | mov ss, ax 36 | push 0xFFFF ; ESP: 0x7c00 => identical mapping (PDE1) 37 | jmp 0:0 ; E9 (F4 83 FF FF) 38 | 39 | ; FF FF 00 00 00 92 CF 00 40 | GDT: 41 | ; null segment descriptor 42 | dw 0 43 | dw 0 44 | db 0 45 | db 0 46 | db 0 47 | db 0 48 | ; code segment descriptor 49 | ; 0000 FFFF 50 | ; 00CF 9800 51 | dw 0xFFFF ; limit low 52 | dw 0 ; base low 53 | db 0 ; base middle 54 | db 10011000b ; access 55 | db 11001111b ; limit + flags 56 | db 0 ; base high 57 | ; data segment descriptor 58 | ; 0000 FFFF 59 | ; 00CF 9200 60 | dw 0xFFFF ; limit low 61 | dw 0 ; base low 62 | db 0 ; base middle 63 | db 10010010b ; access 64 | db 11001111b ; limit + flags 65 | db 0 ; base high 66 | 67 | GDT_DESC: 68 | dw (GDT_DESC - GDT - 1) 69 | dd GDT 70 | 71 | PDE1: 72 | ; 31_____________________________12_11_____9____________________________________0 73 | ; | Page table 4kb-aligned address | Avail. | G | S | 0 | A | D | W | U | R | P | 74 | ; |_____________________________________________________________________________| 75 | ; *Identical Mapping 76 | ; 0x0000 008F 77 | dw 0x8F 78 | dw 0x0 79 | 80 | PDE2: 81 | ; Pointing to PGT 82 | ; 0x07C7 300F 83 | dw 0x000F 84 | dw 0x7C7 85 | 86 | ; 0x7C73 87 | PGT: 88 | ; 31_____________________________12_11_____9____________________________________0 89 | ; | Page table 4kb-aligned address | Avail. | G | 0 | D | A | C | W | U | R | P | 90 | ; |_____________________________________________________________________________| 91 | dw 0x500F 92 | dw 0x7C3 ; 7C35 + 2 = pg_enter (0x7c37) 93 | ; on memory: 0f80 c307 94 | ; get_memory32 at 0x7c73: 07C3 800F 95 | -------------------------------------------------------------------------------- /tests/exec/pop/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = pop.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/pop/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: ffffd5ff 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bf8 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 11010101 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 03 00 00 00 24 | 00007C00: 6A 03 89 E0 8F 40 FC 83 EC 04 B8 03 00 00 00 83 E8 03 9C B8 03 00 00 00 83 E8 04 9D 9C B4 FF 9E 25 | 00007C20: 9F E9 DA 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/pop/pop.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | push 3 4 | mov dword eax, esp 5 | pop dword [eax - 4] ; 0x7CFC: 3 6 | sub esp, 4 7 | 8 | mov dword eax, 3 9 | sub dword eax, 3 ; EFLAGS: 0000 0000 0100 0000 10 | pushfd ; 9C ; 0x7CF8: 0x40 11 | mov dword eax, 3 12 | sub dword eax, 4 ; EFLAGS: 1000 0001 ; EAX: 0xFFFF FFFF 13 | popfd ; 9D ; EFLAGS: 0000 0000 0100 0000 14 | pushfd ; 0x7CF4: 0x40 15 | 16 | mov byte ah, 0xFF 17 | sahf ; EFLAGS: 0000 0000 1101 0101 18 | lahf ; EAX: 0xFFFFD5FF (D5FF: 1101 0101 1111 1111) 19 | 20 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/pusha/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = pusha.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/pusha/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000001 2 | ECX: 00000002 3 | EDX: 00000003 4 | EBX: 00000004 5 | ESP: 00007c00 6 | EBP: 00000006 7 | ESI: 00000007 8 | EDI: 00000008 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 08 00 00 00 07 00 00 00 06 00 00 00 00 7C 00 00 04 00 00 00 03 00 00 00 02 00 00 00 01 00 00 00 24 | 00007C00: B8 01 00 00 00 B9 02 00 00 00 BA 03 00 00 00 BB 04 00 00 00 BD 06 00 00 00 BE 07 00 00 00 BF 08 25 | 00007C20: 00 00 00 60 B8 08 00 00 00 B9 07 00 00 00 BA 06 00 00 00 BB 05 00 00 00 BD 03 00 00 00 BE 02 00 26 | 00007C40: 00 00 BF 01 00 00 00 61 E9 B3 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 | 00007C60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 | -------------------------------------------------------------------------------- /tests/exec/pusha/pusha.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | mov eax, 0x1 5 | mov ecx, 0x2 6 | mov edx, 0x3 7 | mov ebx, 0x4 8 | ; mov esp, 0x5 9 | mov ebp, 0x6 10 | mov esi, 0x7 11 | mov edi, 0x8 12 | pusha 13 | mov eax, 0x8 14 | mov ecx, 0x7 15 | mov edx, 0x6 16 | mov ebx, 0x5 17 | ; mov esp, 0x4 18 | mov ebp, 0x3 19 | mov esi, 0x2 20 | mov edi, 0x1 21 | popa 22 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/rep/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = rep.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/rep/rep.asm: -------------------------------------------------------------------------------- 1 | ; only for test at moment. 2 | ; rep doesn't work with in al, dx (EC) instruction 3 | ; todo: replace with supported instructions. 4 | BITS 32 5 | org 0x7c00 6 | mov ecx, 5 7 | mov edx, 0x03f8 8 | rep in al, dx 9 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/seg/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = seg.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/seg/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00001001 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00000000 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00001004 11 | CS: 00000000 12 | SS: 00001001 13 | DS: 000007be 14 | FS: 00001005 15 | GS: 00001006 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 10 BE 07 01 10 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 | 00007C00: BC 00 00 00 00 B8 01 10 10 00 8E C0 B8 BE 07 00 00 8E D0 B8 04 10 00 00 8E D8 B8 05 10 00 00 8E 25 | 00007C20: E0 B8 06 10 00 00 8E E8 06 16 1E 07 1F 17 8C D0 E9 CB 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/seg/seg.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | mov esp, 0 4 | mov eax, 0x101001 5 | mov es, ax ; 8EC0 ; ModRM:1100 0000 -> reg_index:000 6 | 7 | ; mov eax, 0x1002 8 | ; mov cs, ax ; 8EC8 ; ModRM:1100 1000 -> reg_index:001 9 | 10 | ; changes SS to 0x7BE0 11 | mov eax, 0x7BE 12 | mov ss, ax ; 8ED0 ; ModRM:1101 0000 -> reg_index:010 13 | 14 | mov eax, 0x1004 15 | mov ds, ax ; 8ED8 ; ModRM:1101 1000 -> reg_index:011 16 | 17 | mov eax, 0x1005 18 | mov fs, ax ; 8EE0 ; ModRM:1110 0000 -> reg_index:100 19 | 20 | mov eax, 0x1006 21 | mov gs, ax ; 8EE8 ; ModRM:1110 1000 -> reg_index:101 22 | 23 | push es 24 | ; push cs 25 | push ss 26 | push ds 27 | 28 | pop es ; ES: 0x1004 from DS 29 | ; no pop cs ; CS: 0x1002 30 | pop ds ; DS: 0x7BE from SS 31 | pop ss ; SS: 0x1001 from ES 32 | 33 | mov eax, ss ; EAX: 0x1001 from ES 34 | 35 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/sib/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = sib.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/sib/sib.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | label0: 3 | org 0x7c00 4 | ; 03 add r32, rm32 ; 5 | ; 0C mod: 00 rm: 100 r32: 001 ; [-][-][ECX] ; 6 | ; BB ; 10: 4 (scale) 111: EDI(index) 011: EBX(base) 7 | mov eax, 0 8 | mov ebx, esp 9 | mov edi, 4 10 | mov dword [ebx + edi * 8], 5 11 | add dword eax, [ebx + edi * 8] ; 03 0C BB 12 | jmp 0; 13 | hlt ; F4 hlt ; -------------------------------------------------------------------------------- /tests/exec/str_32/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = str_32.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/str_32/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00707563 2 | ECX: 00000000 3 | EDX: 00000003 4 | EBX: 00000000 5 | ESP: 00007bf4 6 | EBP: 00000000 7 | ESI: 00007c79 8 | EDI: 00007c81 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 10000001 22 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 03 00 00 00 23 | 00007C00: BA 20 00 00 00 89 D1 BF 5D 7C 00 00 F2 AF 29 CA 42 52 89 D1 BF 5D 7C 00 00 BE 5D 7C 00 00 F3 A7 24 | 00007C20: 51 89 D1 BF 5D 7C 00 00 BE 69 7C 00 00 F3 A7 51 B9 01 00 00 00 BE 75 7C 00 00 BF 79 7C 00 00 F3 25 | 00007C40: A5 B8 FF FF FF FF BF 7D 7C 00 00 B9 01 00 00 00 F3 AB BE 75 7C 00 00 AD E9 A3 83 FF FF 6D 61 72 26 | 00007C60: 69 6C 79 6E 0A 00 00 00 00 6D 61 72 69 61 68 0A 0A 00 00 00 00 63 75 70 00 63 75 70 00 FF FF FF 27 | 00007C80: FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/str_32/str_32.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | ; strncomp ; 5 | 6 | ; check the length of msghello 7 | mov edx, 32 8 | mov ecx, edx 9 | mov edi, str_marilyn 10 | repne scasd ; EAX - ES:EDI -> update flags 11 | sub edx, ecx 12 | inc edx 13 | push edx ; 0x02 (length of marilyn by 4 bytes) 14 | 15 | ; compare same chars 16 | mov ecx, edx 17 | mov edi, str_marilyn 18 | mov esi, str_marilyn 19 | rep cmpsd ; DS:ESI - ES:EDI -> update flags 20 | push ecx ; 0x00 (rep went through all letters: equal) 21 | 22 | ; compare diff chars 23 | mov ecx, edx 24 | mov edi, str_marilyn 25 | mov esi, str_mariah 26 | rep cmpsd 27 | push ecx ; 0x01 (rep stops at difference: not equal) 28 | 29 | ; write strings ; 30 | 31 | mov ecx, 1 32 | mov esi, str_cup 33 | mov edi, str_abc 34 | rep movsd ; DS:ESI to ES:EDI 35 | 36 | ; initialize buffer ; 37 | 38 | mov eax, 0xFFFFFFFF 39 | mov edi, str_def 40 | mov ecx, 1 41 | rep stosd ; AL to ES:DI/EDI 42 | 43 | ; load a letter to AL ; 44 | 45 | mov esi, str_cup 46 | lodsd ; DS:SI/ESI to AL ; EAX: 0x68 47 | 48 | jmp 0 49 | 50 | str_marilyn: 51 | db "marilyn", 0x0a, 0, 0, 0, 0; 7C5D: 6d 61 72 69 6c 79 6e 0a 00 00 00 00 52 | 53 | str_mariah: 54 | db "mariah", 0x0a, 0x0a, 0, 0, 0, 0 ; 7C69: 6d 61 72 69 61 68 0a 0a 00 00 00 00 55 | 56 | str_cup: 57 | db "cup", 0 ; 7C75: 63 75 70 00 58 | 59 | str_abc: 60 | db "abc", 0 ; 7C79: 61 62 63 00 -> 63 75 70 00 61 | 62 | str_def: 63 | db "def", 0 ; 7C7D: 64 65 66 00 -> 01 01 01 00 -------------------------------------------------------------------------------- /tests/exec/str_8/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = str_8.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/str_8/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000068 2 | ECX: 00000000 3 | EDX: 00000008 4 | EBX: 00000000 5 | ESP: 00007bf4 6 | EBP: 00000000 7 | ESI: 00007c68 8 | EDI: 00007c75 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 10000001 22 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 08 00 00 00 23 | 00007C00: BA 20 00 00 00 89 D1 C4 3D 76 7C 00 00 F2 AE 29 CA 42 52 89 D1 C4 3D 76 7C 00 00 C5 35 76 7C 00 24 | 00007C20: 00 F3 A6 51 89 D1 C4 3D 76 7C 00 00 C5 35 7C 7C 00 00 F3 A6 51 B9 04 00 00 00 BE 67 7C 00 00 BF 25 | 00007C40: 6C 7C 00 00 F3 A4 B0 01 BF 71 7C 00 00 B9 04 00 00 00 F3 AA BE 67 7C 00 00 AC E9 A1 83 FF FF 68 26 | 00007C60: 65 6C 6C 6F 0D 0A 00 68 65 6C 6C 00 68 65 6C 6C 00 01 01 01 01 00 00 00 5F 7C 00 00 00 00 67 7C 27 | 00007C80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/str_8/str_8.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | 4 | ; strncomp ; 5 | 6 | ; check the length of msghello 7 | mov edx, 32 8 | mov ecx, edx 9 | les dword edi, [addr_to_str_hello] 10 | repne scasb ; AL - ES:EDI -> update flags 11 | sub edx, ecx 12 | inc edx 13 | push edx ; 0x08 (length of str_hello) 14 | 15 | ; compare same chars 16 | mov ecx, edx 17 | les dword edi, [addr_to_str_hello] 18 | lds dword esi, [addr_to_str_hello] 19 | rep cmpsb ; DS:ESI - ES:EDI -> update flags 20 | push ecx ; 0x00 (rep went through all letters: equal) 21 | 22 | ; compare diff chars 23 | mov ecx, edx 24 | les dword edi, [addr_to_str_hello] 25 | lds dword esi, [addr_to_str_hell] 26 | rep cmpsb 27 | push ecx ; 0x04 (rep stops at difference: not equal) 28 | 29 | ; write strings ; 30 | 31 | mov ecx, 4 32 | mov esi, str_hell 33 | mov edi, str_abcd 34 | rep movsb ; DS:ESI to ES:EDI 35 | 36 | ; initialize buffer ; 37 | 38 | mov al, 1 39 | mov edi, str_defg 40 | mov ecx, 4 41 | rep stosb ; AL to ES:DI/EDI 42 | 43 | ; load a letter to AL ; 44 | 45 | mov esi, str_hell 46 | lodsb ; DS:SI/ESI to AL ; EAX: 0x68 47 | 48 | jmp 0 49 | 50 | str_hello: 51 | db "hello", 0x0d, 0x0a, 0 ; 7C57: 68 65 6C 6C 6F 0D 0A 00 52 | 53 | str_hell: 54 | db "hell", 0 ; 7C67: 68 65 6c 6c 00 55 | 56 | str_abcd: 57 | db "abcd", 0 ; 7C6C: 61 62 63 64 00 -> 68 65 6c 6c 00 58 | 59 | str_defg: 60 | db "defg", 0 ; 7C71: 64 65 66 67 00 -> 01 01 01 01 00 61 | 62 | addr_to_str_hello: 63 | dw 0x0 ; Seg 64 | dd 0x7C5F ; Offset 65 | 66 | addr_to_str_hell: 67 | dw 0x0 ; Seg 68 | dd 0x7C67 ; Offset -------------------------------------------------------------------------------- /tests/exec/sub/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = sub.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/sub/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: fffff002 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007bec 6 | EBP: 00007bf0 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 10000001 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 02 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 24 | 00007C00: 83 EC 10 89 E5 B8 0A 00 00 00 2C 02 C6 45 00 0A 28 45 00 2A 45 00 50 C7 45 04 0A 00 00 00 29 45 25 | 00007C20: 04 2B 45 04 2D 00 10 00 00 E9 D2 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 26 | -------------------------------------------------------------------------------- /tests/exec/sub/sub.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | sub esp, 16 ; 83 ; ESP: 7BF0 4 | mov ebp, esp ; EBP: 7BF0 5 | mov eax, 10 ; EAX: 10 6 | sub al, 2 ; 2C ; EAX: 8 7 | mov byte [ebp], 10 8 | sub byte [ebp], al ; 28 ; 7BF0: 2 9 | sub byte al, [ebp] ; 2A ; EAX: 6 10 | push eax ; 7BEC: 6 11 | mov dword [ebp+4], 10 ; 7BF4: 10 12 | sub dword [ebp+4], eax ; 29 ; 7BF4: 4 13 | sub dword eax, [ebp+4] ; 2B ; EAX : 2 14 | sub dword eax, 0x1000 ; 2D ; 2 - 0x1000 = 4096 ; EAX: -4094 15 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/test/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = test.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/test/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000000 2 | ECX: 00000000 3 | EDX: 00007bf4 4 | EBX: 00000000 5 | ESP: 00007be0 6 | EBP: 00000000 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 01000000 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 40 00 00 00 80 00 00 00 40 00 00 00 80 00 00 00 40 00 00 00 FF 00 00 00 80 00 00 00 FF 00 00 00 24 | 00007C00: 68 FF 00 00 00 B8 80 00 00 00 89 E2 84 02 9C 68 FF 00 00 00 B8 00 00 00 00 89 E2 85 02 9C B8 FF 25 | 00007C20: 00 00 00 A8 80 9C B8 00 00 00 00 A8 80 9C B8 00 00 00 F0 A9 00 00 00 80 9C B8 00 00 00 00 A9 FF 26 | 00007C40: FF FF FF 9C E9 B7 83 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/test/test.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | push 0xFF ; 0x7BFC: 0xFF 4 | mov dword eax, 0x80 5 | mov edx, esp 6 | test byte [edx], al 7 | pushfd ; 0x7BF8: 10000000 (0x80) (sign flag) 8 | 9 | push 0xFF ; 0x7BF4: 0xFF 10 | mov dword eax, 0 11 | mov edx, esp 12 | test dword [edx], eax 13 | pushfd ; 0x7BF0: 01000000 (0x40) (zero flag) 14 | 15 | mov dword eax, 0xFF 16 | test byte al, 0x80 17 | pushfd ; 0x7BEC: 10000000 (0x80) (sign flag) 18 | 19 | mov dword eax, 0 20 | test byte al, 0x80 21 | pushfd ; 0x7BE8: 01000000 (0x40) (zero flag) 22 | 23 | mov dword eax, 0xF0000000 24 | test dword eax, 0x80000000 25 | pushfd ; 0x7BE4: 10000000 (0x80) (sign flag) 26 | 27 | mov dword eax, 0 28 | test dword eax, 0xFFFFFFFF 29 | pushfd ; 0x7BE0: 01000000 (0x40) (zero flag) 30 | 31 | jmp 0 -------------------------------------------------------------------------------- /tests/exec/xchg/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = xchg.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/xchg/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00000018 2 | ECX: 0000000d 3 | EDX: 0000000f 4 | EBX: 0000000b 5 | ESP: 00007ba8 6 | EBP: 00000015 7 | ESI: 00000013 8 | EDI: 00000011 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007B80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BA0: 00 00 00 00 00 00 00 00 AC 7B 00 00 18 00 00 00 15 00 00 00 16 00 00 00 11 00 00 00 14 00 00 00 24 | 00007BC0: 11 00 00 00 12 00 00 00 0F 00 00 00 10 00 00 00 0D 00 00 00 0E 00 00 00 0B 00 00 00 0C 00 00 00 25 | 00007BE0: 09 00 00 00 0A 00 00 00 07 00 00 00 08 00 00 00 05 00 00 00 06 00 00 00 04 00 00 00 03 00 00 00 26 | 00007C00: B8 03 00 00 00 6A 01 89 E2 86 02 B8 04 00 00 00 6A 02 89 E2 87 02 B8 05 00 00 00 B9 06 00 00 00 27 | 00007C20: 91 50 51 B8 07 00 00 00 BA 08 00 00 00 92 50 52 B8 09 00 00 00 BB 0A 00 00 00 93 50 53 B8 0B 00 28 | 00007C40: 00 00 BB 0C 00 00 00 93 50 53 B8 0D 00 00 00 B9 0E 00 00 00 91 50 51 B8 0F 00 00 00 BA 10 00 00 29 | 00007C60: 00 92 50 52 B8 11 00 00 00 BF 12 00 00 00 97 50 57 B8 13 00 00 00 BE 14 00 00 00 96 50 57 B8 15 30 | 00007C80: 00 00 00 BD 16 00 00 00 95 50 55 B8 B0 7B 00 00 BC 18 00 00 00 94 50 54 E9 63 83 FF FF 00 00 00 31 | 00007CA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -------------------------------------------------------------------------------- /tests/exec/xchg/xchg.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7C00 3 | mov dword eax, 3 4 | push 1 5 | mov edx, esp 6 | xchg byte [edx], al ; 0x7BFC: 3 7 | 8 | mov dword eax, 4 9 | push 2 ; ESP: 0x7BFC 10 | mov edx, esp 11 | xchg dword [edx], eax ; 0x7BF8: 4 12 | 13 | mov dword eax, 5 14 | mov dword ecx, 6 15 | xchg dword ecx, eax 16 | push eax ; 0x7BF4: 6 17 | push ecx ; 0x7BF0: 5 18 | 19 | mov dword eax, 7 20 | mov dword edx, 8 21 | xchg dword edx, eax 22 | push eax ; 0x7BFC: 8 23 | push edx ; 0x7BE8: 7 24 | 25 | mov dword eax, 9 26 | mov dword ebx, 10 27 | xchg dword eax, ebx 28 | push eax ; 0x7BE4: 10 29 | push ebx ; 0x7BE0: 9 30 | 31 | ; xchg dword eax, eax ; 90: nop ; 32 | 33 | mov dword eax, 11 34 | mov dword ebx, 12 35 | xchg eax, ebx 36 | push eax ; 0x7BDC: 12 37 | push ebx ; 0x7BD8: 11 38 | 39 | mov dword eax, 13 40 | mov dword ecx, 14 41 | xchg eax, ecx 42 | push eax ; 0x7BD4: 14 43 | push ecx ; 0x7BD0: 13 44 | 45 | mov dword eax, 15 46 | mov dword edx, 16 47 | xchg eax, edx 48 | push eax ; 0x7BCC: 16 49 | push edx ; 0x7BC8: 15 50 | 51 | mov dword eax, 17 52 | mov dword edi, 18 53 | xchg eax, edi 54 | push eax ; 0x7BC4: 18 55 | push edi ; 0x7BC0: 17 56 | 57 | mov dword eax, 19 58 | mov dword esi, 20 59 | xchg eax, esi 60 | push eax ; 0x7BBC: 20 61 | push edi ; 0x7BB8: 19 62 | 63 | mov dword eax, 21 64 | mov dword ebp, 22 65 | xchg eax, ebp 66 | push eax ; 0x7BB4: 22 67 | push ebp ; 0x7BB0: 21 68 | 69 | mov dword eax, 0x7BB0 70 | mov dword esp, 24 71 | xchg eax, esp 72 | push eax ; 0x7BAC: 24 73 | push esp ; 0x7BA8: 7BAC 74 | 75 | ; mov ax, 9 ; 66 B8 76 | ; mov bx, 10 ; 66 B8 77 | ; xchg bx, ax ; 66 93 78 | ; push ax ; 66 50 79 | ; push bx ; 66 53 80 | jmp 0 81 | 82 | -------------------------------------------------------------------------------- /tests/exec/xor/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = xor.bin 2 | 3 | CC = gcc 4 | LD = ld 5 | AS = nasm 6 | CFLAGS += -nostdlib -fno-asynchronous-unwind-tables \ 7 | -g -fno-stack-protector 8 | LDFLAGS += --entry=func --oformat=binary 9 | 10 | .PHONY: all 11 | all : 12 | make $(TARGET) 13 | 14 | %.o : %.c Makefile 15 | $(CC) $(CFLAGS) -c $< 16 | 17 | %.bin : %.o Makefile 18 | $(LD) $(LDFLAGS) -o $@ $< 19 | 20 | %.bin : %.asm Makefile 21 | $(AS) -f bin -o $@ $< -------------------------------------------------------------------------------- /tests/exec/xor/expected.txt: -------------------------------------------------------------------------------- 1 | EAX: 00001000 2 | ECX: 00000000 3 | EDX: 00000000 4 | EBX: 00000000 5 | ESP: 00007be4 6 | EBP: 00007bf0 7 | ESI: 00000000 8 | EDI: 00000000 9 | EIP: 00000000 10 | ES: 00000000 11 | CS: 00000000 12 | SS: 00000000 13 | DS: 00000000 14 | FS: 00000000 15 | GS: 00000000 16 | CR0: 00000000 17 | CR1: 00000000 18 | CR2: 00000000 19 | CR3: 00000000 20 | CR4: 00000000 21 | eflags:00000000 00000000 00000000 00000000 22 | 00007BC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 | 00007BE0: 00 00 00 00 04 00 00 00 05 00 00 00 08 00 00 00 07 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 24 | 00007C00: 83 EC 10 89 E5 B8 01 00 00 00 34 09 50 C6 45 00 0F 30 45 00 B8 02 00 00 00 32 45 00 50 C6 45 04 25 | 00007C20: 03 83 75 04 01 B8 03 00 00 00 31 45 04 B8 05 00 00 00 33 45 04 50 35 04 10 00 00 E9 C0 83 FF FF 26 | 00007C40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 | -------------------------------------------------------------------------------- /tests/exec/xor/xor.asm: -------------------------------------------------------------------------------- 1 | BITS 32 2 | org 0x7c00 3 | sub esp, 16 ; 7BF0 4 | mov ebp, esp ; EBP: 7BF0 5 | 6 | mov eax, 0x1 ; EAX: 1 7 | xor al, 0x9 ; op: 34 EAX: 8 8 | push eax ; ESP -> 7BEC: 0x8 9 | 10 | mov byte [ebp], 0xF 11 | xor byte [ebp], al ; op: 30 ; 7BF0: 0x7 12 | 13 | mov eax, 0x2 ; EAX: 2 14 | xor byte al, [ebp] ; op: 32 ; EAX: 0x5 15 | push eax ; ESP -> 7BE8: 0x5 16 | 17 | mov byte [ebp+4], 0x3 18 | xor dword [ebp+4], 0x1 ; op: 83 ; 7BF4: 0x2 19 | 20 | mov eax, 0x3 21 | xor dword [ebp+4], eax ; op: 31 ; 7BF4: 0x1 22 | 23 | mov eax, 0x5 24 | xor dword eax, [ebp+4] ; op: 33 ; EAX: 0x4 25 | push eax ; ESP -> 7BE4: 0x4 26 | 27 | xor dword eax, 0x1004 ; op: 35 ; EAX: 0x1000 28 | jmp 0 -------------------------------------------------------------------------------- /twos_complement.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "twos_complement.h" 4 | 5 | int8_t to_int8(uint8_t raw) 6 | { 7 | if (raw > 127) 8 | { 9 | return (int8_t)(raw - 0xFF) + 0xFF; 10 | } 11 | else 12 | { 13 | return (int8_t)raw; 14 | } 15 | } 16 | 17 | int16_t to_int16(uint16_t raw) 18 | { 19 | if (raw > 32767) 20 | { 21 | return (int16_t)(raw - 0xFFFF) + 0xFFFF; 22 | } 23 | else 24 | { 25 | return (int16_t)raw; 26 | } 27 | } 28 | 29 | int32_t to_int32(uint32_t raw) 30 | { 31 | if (raw > 2147483647) 32 | { 33 | return (int32_t)(raw - 0xFFFFFFFF) + 0xFFFFFFFF; 34 | } 35 | else 36 | { 37 | return (int32_t)raw; 38 | } 39 | } 40 | 41 | int64_t to_int64(uint64_t raw) 42 | { 43 | if (raw > 9223372036854775807) 44 | { 45 | return (int64_t)(raw - 0xFFFFFFFFFFFFFFFF) + 0xFFFFFFFFFFFFFFFF; 46 | } 47 | else 48 | { 49 | return (int64_t)raw; 50 | } 51 | } -------------------------------------------------------------------------------- /twos_complement.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int8_t to_int8(uint8_t raw); 4 | int16_t to_int16(uint16_t raw); 5 | int32_t to_int32(uint32_t raw); 6 | int64_t to_int64(uint64_t raw); -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "util.h" 5 | #include "emulator.h" 6 | #include "lapic.h" 7 | #include "ioapic.h" 8 | 9 | #include 10 | 11 | #define DEBUG_SIZE 256 12 | 13 | Config config; 14 | int debug_i = 0; 15 | int debug_cs[DEBUG_SIZE]; 16 | int debug_eips[DEBUG_SIZE]; 17 | int debug_ops[DEBUG_SIZE]; 18 | int debug_ss[DEBUG_SIZE]; 19 | int debug_esp[DEBUG_SIZE]; 20 | 21 | void init_config(int verbose, int test) 22 | { 23 | config.verbose = verbose; 24 | config.test = test; 25 | } 26 | 27 | void debug_append(uint16_t cs, uint32_t eip, uint8_t op, uint16_t ss, uint32_t esp_val) 28 | { 29 | debug_cs[debug_i] = cs; 30 | debug_eips[debug_i] = eip; 31 | debug_ops[debug_i] = op; 32 | debug_ss[debug_i] = ss; 33 | debug_esp[debug_i] = esp_val; 34 | debug_i = (debug_i + 1) % DEBUG_SIZE; 35 | } 36 | 37 | void debug_print() 38 | { 39 | printf("Last %d instructions:\n", DEBUG_SIZE); 40 | int i; 41 | for (i = debug_i; i < 256; i++) 42 | { 43 | printf("CS: %04x EIP: %08x Op: %02x SS: %04x ESP: %08x\n", debug_cs[i], debug_eips[i], debug_ops[i], debug_ss[i], debug_esp[i]); 44 | } 45 | for (i = 0; i < debug_i; i++) 46 | { 47 | printf("CS: %04x EIP: %08x Op: %02x SS: %04x ESP: %08x\n", debug_cs[i], debug_eips[i], debug_ops[i], debug_ss[i], debug_esp[i]); 48 | } 49 | } 50 | 51 | void print_emu(Emulator *emu) 52 | { 53 | dump_registers(emu); 54 | dump_eflags(emu); 55 | dump_memory(emu, 0x7b00, 1024); 56 | dump_lapic(emu->lapic); 57 | dump_ioapic(); 58 | } 59 | 60 | void add_canon_echo() 61 | { 62 | static struct termios oldt, newt; 63 | tcgetattr(STDIN_FILENO, &oldt); 64 | newt = oldt; 65 | newt.c_lflag |= (ICANON | ECHO); 66 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 67 | } 68 | 69 | void remove_canon_echo() 70 | { 71 | static struct termios oldt, newt; 72 | tcgetattr(STDIN_FILENO, &oldt); 73 | newt = oldt; 74 | newt.c_lflag &= ~(ICANON | ECHO); 75 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 76 | } 77 | 78 | void panic() 79 | { 80 | add_canon_echo(); 81 | exit(1); 82 | } 83 | 84 | void panic_exit(Emulator *emu) 85 | { 86 | add_canon_echo(); 87 | debug_print(); 88 | print_emu(emu); 89 | exit(1); 90 | } 91 | 92 | void sig_exit(Emulator *emu) 93 | { 94 | add_canon_echo(); 95 | debug_print(); 96 | print_emu(emu); 97 | exit(0); 98 | } 99 | 100 | void normal_exit() 101 | { 102 | add_canon_echo(); 103 | exit(0); 104 | } -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H_ 2 | #define UTIL_H_ 3 | 4 | #include 5 | 6 | #include "emulator.h" 7 | 8 | typedef struct 9 | { 10 | int verbose; 11 | int test; 12 | } Config; 13 | 14 | extern Config config; 15 | 16 | void init_config(int verbose, int test); 17 | void debug_append(uint16_t cs, uint32_t eip, uint8_t op, uint16_t ss, uint32_t esp_val); 18 | void debug_print(); 19 | void print_emu(Emulator *emu); 20 | 21 | void add_canon_echo(); 22 | void remove_canon_echo(); 23 | 24 | void panic() __attribute__((noreturn)); 25 | void panic_exit(Emulator *emu) __attribute__((noreturn)); 26 | void sig_exit(Emulator *emu) __attribute__((noreturn)); 27 | void normal_exit(); 28 | 29 | #endif -------------------------------------------------------------------------------- /xv6memfs.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ykskb/dax86/d7c90afb4a306f04bd840da2b32faedec01bef93/xv6memfs.img --------------------------------------------------------------------------------