├── tests ├── __init__.py └── test_gen_py_merge_procs_.py ├── asmTests ├── included.inc ├── file1.txt ├── addr.as ├── snake.lst ├── errorlvl.com ├── true.asm ├── build.sh ├── _config.sh ├── include.asm ├── hello.map ├── twopass.asm ├── rol.asm ├── _tests.sh ├── popf.asm ├── _singletest.sh ├── hello.asm_disabled ├── loop.asm ├── lodsb.asm ├── LICENSE ├── cmp.asm ├── inc.asm ├── snake.map ├── datadup.asm ├── cmpsb.asm ├── errorlvl.asm ├── xor.asm ├── pushpop.asm ├── dataoff.asm ├── shlshr.asm ├── addsub.asm ├── proc.asm ├── build_mingw.sh ├── equ.asm ├── array.asm ├── macro.as ├── test.asm ├── file.asm ├── mem2.asm ├── struct.asm ├── mov.asm ├── movsb.asm ├── neg.asm └── data.asm ├── docs ├── authors.rst ├── changelog.rst ├── license.rst ├── Makefile └── index.rst ├── masm2c ├── __init__.py ├── enumeration.py ├── Macro.py ├── Token.py └── symbol_table.py ├── pytest.ini ├── requirements.txt ├── CHANGELOG.md ├── CONTRIBUTING.md ├── examples ├── IPLAY.CFG ├── IPLAY.EXE ├── ISETUP.EXE ├── intro.exe ├── iplay.asm ├── iplay.idc ├── iplay.pct ├── iplay.png ├── iplay_m_.asm ├── iplay_m_.cpp ├── iplay_masm.asm ├── iplay_nasm.asm ├── build_tasm.bat ├── build_nasm.bat ├── build_masm.bat ├── build_t2.bat ├── intro.h ├── iplay_nasm_override.patch ├── _ida_to_tasm.sh ├── intro.asm └── snake.h ├── qemu_tests ├── test-i386.exe ├── README ├── _test.sh ├── convert_llvm.sh ├── test-i386-code16.S ├── test-i386-muldiv.h ├── Makefile.target └── test-i386.h ├── vikings ├── vikings.exe_seg000.cpp ├── vikings.exe_seg002.cpp ├── vikings.exe_seg003.cpp ├── init.h ├── init.cpp ├── build.sh └── vikings.exe_default_seg.cpp ├── install-dev.sh ├── .gitattributes ├── AUTHORS.md ├── runtests.sh ├── install-test.sh ├── .workflow ├── _binarytests.sh ├── instr_test ├── _config.sh └── build.sh ├── asm_emu ├── Makefile ├── x86_sahf.h ├── x86_push.h ├── x86_pop.h ├── x86_shrd.h ├── x86_shld.h ├── x86_cmp.h ├── _gen_emu_wrapper._sh_ ├── x86_or.h ├── x86_and.h ├── x86_xor.h ├── x86_test.h ├── x86_div.h ├── x86_neg.h ├── x86_shr.h ├── x86_dec.h ├── x86_inc.h ├── x86_stos.h ├── x86_sar.h ├── x86_shl.h ├── x86_sub.h ├── x86_add.h ├── 2.h ├── x86_sbb.h ├── x86_adc.h └── x86_imul.h ├── win.cpp ├── outdated ├── build_bc.bat ├── ulink.cfg ├── iprintf.cpp ├── _tasm_to_nasm.sh ├── iprintf.asm └── .circleci │ └── config.yml ├── .pycrunch-config.yaml ├── MANIFEST.in ├── .github ├── workflows │ ├── c-cpp.yml │ └── python-app.yml └── ISSUE_TEMPLATE │ └── bug_report.md ├── _coverage.bat ├── .coveragerc ├── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── masm2c.py ├── pyproject.toml ├── shadowstack.h ├── asm_regs_dbx.h ├── Makefile ├── asm_32.h ├── asm_regs_decomp.h ├── LICENSE ├── lark_test.py ├── asm_regs_m2c.h ├── mcb.h ├── vgapal.h ├── error.h ├── asm_16.h └── memmgr.h /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /asmTests/included.inc: -------------------------------------------------------------------------------- 1 | MOV al,0 2 | JMP exitLabel 3 | -------------------------------------------------------------------------------- /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. _authors: 2 | .. include:: ../AUTHORS.rst 3 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. _changes: 2 | .. include:: ../CHANGELOG.rst 3 | -------------------------------------------------------------------------------- /masm2c/__init__.py: -------------------------------------------------------------------------------- 1 | dist_name = __name__ 2 | __version__ = "0.9.8" 3 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | norecursedirs = docs *.egg-info .git appdir .tox -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | lark 2 | jsonpickle 3 | pytest 4 | mock 5 | coverage 6 | -------------------------------------------------------------------------------- /asmTests/file1.txt: -------------------------------------------------------------------------------- 1 | xxTest blabla 2 | sdfsddsffdsfdsdfsfdsdfsdfsdfsfdssfd 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | Version 0.1 5 | =========== 6 | 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See [docs/about/CONTRIBUTING.md](docs/about/CONTRIBUTING.md) 2 | -------------------------------------------------------------------------------- /asmTests/addr.as: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/asmTests/addr.as -------------------------------------------------------------------------------- /asmTests/snake.lst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/asmTests/snake.lst -------------------------------------------------------------------------------- /examples/IPLAY.CFG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/IPLAY.CFG -------------------------------------------------------------------------------- /examples/IPLAY.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/IPLAY.EXE -------------------------------------------------------------------------------- /examples/ISETUP.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/ISETUP.EXE -------------------------------------------------------------------------------- /examples/intro.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/intro.exe -------------------------------------------------------------------------------- /examples/iplay.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay.asm -------------------------------------------------------------------------------- /examples/iplay.idc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay.idc -------------------------------------------------------------------------------- /examples/iplay.pct: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay.pct -------------------------------------------------------------------------------- /examples/iplay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay.png -------------------------------------------------------------------------------- /asmTests/errorlvl.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/asmTests/errorlvl.com -------------------------------------------------------------------------------- /examples/iplay_m_.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay_m_.asm -------------------------------------------------------------------------------- /examples/iplay_m_.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay_m_.cpp -------------------------------------------------------------------------------- /examples/iplay_masm.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay_masm.asm -------------------------------------------------------------------------------- /examples/iplay_nasm.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/examples/iplay_nasm.asm -------------------------------------------------------------------------------- /qemu_tests/test-i386.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/qemu_tests/test-i386.exe -------------------------------------------------------------------------------- /docs/license.rst: -------------------------------------------------------------------------------- 1 | .. _license: 2 | 3 | ======= 4 | License 5 | ======= 6 | 7 | .. include:: ../LICENSE.txt 8 | -------------------------------------------------------------------------------- /vikings/vikings.exe_seg000.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/vikings/vikings.exe_seg000.cpp -------------------------------------------------------------------------------- /vikings/vikings.exe_seg002.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/vikings/vikings.exe_seg002.cpp -------------------------------------------------------------------------------- /vikings/vikings.exe_seg003.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xor2003/masm2c/HEAD/vikings/vikings.exe_seg003.cpp -------------------------------------------------------------------------------- /install-dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pip install --upgrade pip || exit 1 4 | pip install -e .[dev] || exit 1 5 | ./install-test.sh 6 | -------------------------------------------------------------------------------- /vikings/init.h: -------------------------------------------------------------------------------- 1 | #ifndef INIT_H 2 | #define INIT_H 3 | 4 | #include "../asm.h" 5 | 6 | 7 | #include "cpu.h" 8 | #include "mem.h" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /asmTests/true.asm: -------------------------------------------------------------------------------- 1 | _TEXT segment use16 word public 'CODE' ;IGNORE 2 | assume cs:_TEXT 3 | start proc near 4 | 5 | MOV AX,4C00h 6 | INT 21h 7 | start endp 8 | 9 | _TEXT ends ;IGNORE 10 | 11 | end start ;IGNORE 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Declare files that will always have LF Only line endings on checkout. 2 | *.sh text eol=lf 3 | *.asm text eol=crlf 4 | *.cpp text eol=lf 5 | *.h text eol=lf 6 | *.py text eol=lf 7 | *.diff text eol=lf 8 | *.txt text eol=lf 9 | 10 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Development Lead 2 | ================ 3 | 4 | * x0r 5 | 6 | Contributors 7 | ============ 8 | 9 | For a full list of contributors and their activity 10 | see [here](https://github.com/igordejanovic/parglare/graphs/contributors). 11 | -------------------------------------------------------------------------------- /masm2c/enumeration.py: -------------------------------------------------------------------------------- 1 | """ 2 | Defines enumerations for different types of data and addressing modes used in the translation process. 3 | """ 4 | from enum import Enum 5 | 6 | 7 | class IndirectionType(Enum): 8 | OFFSET = -1 9 | VALUE = 0 10 | POINTER = 1 11 | -------------------------------------------------------------------------------- /runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # Run all tests and generate coverage report 3 | 4 | coverage run --source masm2c -m pytest tests/ 5 | #coverage report --fail-under 90 || exit 1 6 | # Run this to generate html report 7 | # coverage html --directory=coverage 8 | #flake8 || exit 1 9 | -------------------------------------------------------------------------------- /install-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -exv 2 | 3 | pip install --upgrade pip 4 | pip install pytest coverage 5 | pip install -r requirements.txt 6 | 7 | #git clone https://github.com/igordejanovic/parglare.git parglaredev 8 | #pip install parglaredev/ 9 | 10 | pip install -e .[test] 11 | -------------------------------------------------------------------------------- /.workflow: -------------------------------------------------------------------------------- 1 | workflow "Example Workflow" { 2 | on = "push" 3 | resolves = ["autopep8", "python-lint"] 4 | } 5 | 6 | action "python-lint" { 7 | uses = "CyberZHG/github-action-python-lint@0.0.2" 8 | } 9 | action "autopep8" { 10 | uses = "peter-evans/autopep8@v1.0.0" 11 | } 12 | -------------------------------------------------------------------------------- /_binarytests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | #git clone https://github.com/igordejanovic/parglare.git parglaredev 4 | #pip install parglaredev/ 5 | #rm -rf parglaredev/ 6 | pip install -r requirements.txt 7 | 8 | cd asmTests 9 | 10 | ./_tests.sh 11 | 12 | cd ../qemu_tests 13 | 14 | ./_test.sh 15 | -------------------------------------------------------------------------------- /instr_test/_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | 3 | export SDL="-DNOSDL" 4 | export CURSES="-DNOCURSES $(pkg-config --cflags --libs ncurses)" 5 | export CURSES="-DNOCURSES" 6 | export OPT="-std=c++14 -Wno-narrowing -mno-ms-bitfields -Wno-multichar -Wno-overflow $SDL $CURSES -D_GNU_SOURCE=1 -ggdb3 -O0 -I. -I.. " 7 | -------------------------------------------------------------------------------- /asm_emu/Makefile: -------------------------------------------------------------------------------- 1 | TOPDIR=../ 2 | include $(TOPDIR)Rules.make 3 | 4 | all: 5 | 6 | test-x86.o: test-x86.c ../config.h x86*.h 7 | $(CC) test-x86.c -o $@ -c 8 | 9 | test-x86: test-x86.o 10 | $(CC) -o $@ $^ $(MATH_LIBS) 11 | 12 | clean: 13 | rm -f *.o *$(LIB_SUFFIX) test-x86 14 | 15 | install: 16 | 17 | uninstall: 18 | -------------------------------------------------------------------------------- /asmTests/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | . ./_config.sh 4 | 5 | if [ -z "$CXX" ];then 6 | export CXX=g++ 7 | fi 8 | 9 | #$CC $OPT $1.cpp -E >$1.e 10 | #$CXX $OPT $1.cpp -c 11 | #$CXX $1.o ../asm.o ../memmgr.o -o $1 $OPT 12 | $CXX _data.cpp $1.cpp ../asm.o ../memmgr.o ../shadowstack.o $OPT -o $1 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/build_tasm.bat: -------------------------------------------------------------------------------- 1 | del iplay_tasm.obj iplay_tasm.exe 2 | lzasm /q /la /w2 /c /kh32768 iplay_tasm.asm 3 | rem wlink name iplay_tasm.exe system dos file iplay_tasm.obj option verbose 4 | alink -m -oEXE iplay_tasm.obj 5 | \upx.exe --ultra-brute iplay_tasm.exe 6 | type IPLAY.PCT >> iplay_tasm.exe 7 | ren iplay_tasm.exe iplay_t.exe 8 | 9 | -------------------------------------------------------------------------------- /examples/build_nasm.bat: -------------------------------------------------------------------------------- 1 | del iplay_nasm.obj iplay_nasm.exe 2 | nasm.exe -f obj -Ox iplay_nasm.asm -l iplay_nasm.lst 3 | rem wlink name iplay_nasm.exe system dos file iplay_nasm.obj option verbose 4 | alink -m -oEXE iplay_nasm.obj 5 | \upx.exe --ultra-brute iplay_nasm.exe 6 | type IPLAY.PCT >> iplay_nasm.exe 7 | ren iplay_nasm.exe iplay_n.exe 8 | -------------------------------------------------------------------------------- /asm_emu/x86_sahf.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_sahf(struct assembler_state_t *state) 6 | { 7 | uint32_t temp = state->eflags; 8 | temp &= 0xffffff00; 9 | temp |= 2; 10 | temp |= (state->ah & 0xd5); 11 | state->eflags = temp; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /win.cpp: -------------------------------------------------------------------------------- 1 | #ifdef __MINGW32__ 2 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 3 | #include 4 | extern int main(int argc, char* argv[]); 5 | int WinMain( 6 | HINSTANCE hInstance, 7 | HINSTANCE hPrevInstance, 8 | LPSTR lpCmdLine, 9 | int nShowCmd 10 | ) 11 | {return main(0,0); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /outdated/build_bc.bat: -------------------------------------------------------------------------------- 1 | set CC=C:\inertia_player\BC5\BIN\BCC.EXE 2 | set OPT=-1- -Os -G -d -w-par -c -ml -M -IC:\inertia_player\BC5\INCLUDE -LC:\inertia_player\BC5\LIB -DDEBUG=3 3 | %CC% %OPT% asm.cpp 4 | %CC% %OPT% memmgr.cpp 5 | %CC% %OPT% %1.cpp 6 | C:\inertia_player\BC5\BIN\ulink.exe -Tde c0l.obj proc.obj asm.obj memmgr.obj,proc.exe,,gen.lib pdcurses.lib mathl.lib cl.lib -------------------------------------------------------------------------------- /instr_test/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | . ./_config.sh 4 | 5 | if [ -z "$CXX" ];then 6 | export CXX=g++ 7 | fi 8 | 9 | ( 10 | cd .. 11 | #$CXX $OPT asm.cpp -c 12 | #$CXX $OPT memmgr.cpp -c 13 | #$CXX $OPT shadowstack.cpp -c 14 | ) 15 | # ../asm.o ../memmgr.o ../shadowstack.o 16 | $CXX test_insn_tests.cpp $OPT -lgtest -lgtest_main -o test_insn_tests 17 | 18 | -------------------------------------------------------------------------------- /examples/build_masm.bat: -------------------------------------------------------------------------------- 1 | del iplay_m.obj iplay_m.exe 2 | rem JWasm.exe -Fl -Zd -Zi3 iplay_m.asm 3 | ml.exe /Zi /c /Fl /Sa iplay_m.asm 4 | rem wlink name iplay_nasm.exe system dos file iplay_nasm.obj option verbose 5 | rem alink -m -oEXE iplay_m.obj 6 | LINK.EXE /nopackcode /co iplay_m.obj 7 | rem \upx.exe --ultra-brute iplay_m.exe 8 | rem type IPLAY.PCT >> iplay_m.exe 9 | rem ren iplay_m.exe iplay_m.exe 10 | -------------------------------------------------------------------------------- /.pycrunch-config.yaml: -------------------------------------------------------------------------------- 1 | # documentation https://pycrunch.com/docs/configuration-file 2 | engine: 3 | runtime: pytest 4 | timeout: 5000 5 | cpu-cores: 1 6 | 7 | discovery: 8 | exclusions: 9 | # (example) do not search tests in 'ignored_folder' folder 10 | #- ignored_folder/ 11 | # do not search tests in 'test_ignored.py' file 12 | - _pglr_test.py 13 | - _pglr_test_.py 14 | - _masm61_lark.py 15 | 16 | -------------------------------------------------------------------------------- /examples/build_t2.bat: -------------------------------------------------------------------------------- 1 | del iplay_t1.obj iplay_t2.obj iplay_t.exe 2 | rem lzasm /zi /q /la /w2 /c /kh32768 iplay_t.asm 3 | tasm /zi /m2 /q /la /w2 /c /kh32768 iplay_t1.asm 4 | tasm /zi /m2 /q /la /w2 /c /kh32768 iplay_t2.asm 5 | rem wlink name iplay_t.exe system dos file iplay_t.obj option verbose 6 | tlink7 /v /3 iplay_t1.obj iplay_t2.obj,iplay_t.exe 7 | rem \upx.exe --ultra-brute iplay_t.exe 8 | rem type IPLAY.PCT >> iplay_t.exe 9 | 10 | -------------------------------------------------------------------------------- /asmTests/_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ex 2 | 3 | #export CXX="g++" 4 | #SDL=$(pkg-config --cflags --libs sdl2) 5 | export SDL="-DNOSDL" 6 | export CURSES="-DNOCURSES $(pkg-config --cflags --libs ncurses)" 7 | export OPT="-std=c++11 -Wno-narrowing -mno-ms-bitfields -Wno-multichar $SDL $CURSES -D_GNU_SOURCE=1 -ggdb3 -O0 -I. -I.. -DSHADOW_STACK -DM2CDEBUG=3" 8 | #-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DCHTYPE_16 9 | # -mconsole -DSDL_MAIN_HANDLED 10 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS.md 2 | 3 | include CONTRIBUTING.md 4 | include CHANGELOG.md 5 | include LICENSE.txt 6 | include README.md 7 | 8 | recursive-include tests * 9 | recursive-exclude * __pycache__ 10 | recursive-exclude * *.py[co] 11 | recursive-exclude * *.log 12 | recursive-exclude * *.dot 13 | recursive-exclude * *.pdf 14 | recursive-exclude * *.pstats 15 | recursive-exclude * *.report 16 | recursive-exclude * *.txt 17 | 18 | recursive-include docs *.md *.png 19 | -------------------------------------------------------------------------------- /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-22.04 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: configure 15 | run: | 16 | sudo apt-get update -y 17 | sudo apt-get install -y git make gcc gcc-multilib g++-multilib libncurses-dev 18 | 19 | - name: build 20 | run: | 21 | ./_binarytests.sh 22 | -------------------------------------------------------------------------------- /_coverage.bat: -------------------------------------------------------------------------------- 1 | coverage erase 2 | coverage run -a masm2c.py asmTests/*.asm 3 | coverage run -a masm2c.py -m single asmTests/proc.asm 4 | coverage run -a masm2c.py -m persegment asmTests/proc.asm 5 | coverage run -a masm2c.py -m separate asmTests/proc.asm 6 | coverage run -a masm2c.py -m single asmTests/jxx.asm 7 | coverage run -a masm2c.py -m persegment asmTests/jxx.asm 8 | coverage run -a masm2c.py -m separate asmTests/jxx.asm 9 | coverage run -a masm2c.py -FL -d asmTests/snake.lst 10 | coverage run -a -m pytest tests 11 | coverage html 12 | cd htmlcov 13 | chrome index.html 14 | -------------------------------------------------------------------------------- /outdated/ulink.cfg: -------------------------------------------------------------------------------- 1 | ; ATTENTION: Edit this file or replace it with any file from sample.cfg\*.cfg 2 | ; 3 | ; 4 | ; 5 | ;---------------------------------------------------------------- 6 | # Set to real library search path and uncomment 7 | -LC:\inertia_player\BC5\LIB 8 | 9 | # Change and uncoment any of next strings if needed 10 | 11 | -r -O # remap import names, bind image 12 | 13 | ; -Gw # D6/BCB6 dfm-style 14 | 15 | ; -Ge # disable library exports 16 | 17 | ; -w-cmt # disable compatibility messages 18 | 19 | ; -o -Gh # Import by ordinal, strip unused PE headers 20 | -------------------------------------------------------------------------------- /asmTests/include.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _DATA ends ;IGNORE 5 | 6 | _TEXT segment use16 word public 'CODE' ;IGNORE 7 | assume cs:_TEXT,ds:_DATA 8 | start proc near 9 | 10 | 11 | mov eax,1 12 | 13 | include ; OKOK 14 | 15 | failure: 16 | exitLabel: 17 | mov ah,4ch ; AH=4Ch - Exit To DOS 18 | int 21h 19 | start endp 20 | 21 | _TEXT ends ;IGNORE 22 | 23 | stackseg segment para stack 'STACK' ;IGNORE 24 | db 1000h dup(?) 25 | stackseg ends ;IGNORE 26 | 27 | end start ;IGNORE 28 | -------------------------------------------------------------------------------- /asmTests/hello.map: -------------------------------------------------------------------------------- 1 | 2 | Start Stop Length Name Class 3 | 4 | 01000H 0A889H 0A78AH _DATA CODE 5 | 01001H 0A889H 0A78AH _TEXT CODE 6 | 01004H 0A889H 0A78AH STACKSEG CODE 7 | 8 | 9 | Address Publics by Value 10 | 11 | 0000:0100 start 12 | 0000:0C0C nullsub_1 13 | 0000:3D42 a@ 14 | 0000:3D4A aB@nf 15 | 0000:3D52 aBbFff 16 | 0000:4B52 aVwxwyzZZ_ZZZAb 17 | 0000:4BE0 a?lllllmmmmmnnn 18 | 0000:4BFE aKl 19 | 0000:4C02 aMnoopqrstuvwrs 20 | 0000:A60E aPareScoreName 21 | 22 | Program entry point at 0000:0100 23 | -------------------------------------------------------------------------------- /asm_emu/x86_push.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_pushl(struct assembler_state_t *state, const uint32_t src) 6 | { 7 | state->esp -= 4; 8 | if (state->esp & 0x00000003) 9 | { 10 | fprintf(stderr, "#AC(0) exception occured here\n"); 11 | return; 12 | } 13 | x86_write_memory(state, state->ss, state->esp, 4, src); 14 | } 15 | static inline void asm_pushw(struct assembler_state_t *state, const uint16_t src) 16 | { 17 | asm_pushl(state, src); 18 | } 19 | static inline void asm_pushb(struct assembler_state_t *state, const uint8_t src) 20 | { 21 | asm_pushl(state, src); 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | # .coveragerc to control coverage.py 2 | [run] 3 | branch = True 4 | source = masm2c 5 | # omit = bad_file.py 6 | 7 | [paths] 8 | source = 9 | masm2c/ 10 | */site-packages/ 11 | 12 | [report] 13 | # Regexes for lines to exclude from consideration 14 | exclude_lines = 15 | # Have to re-enable the standard pragma 16 | pragma: no cover 17 | 18 | # Don't complain about missing debug-only code: 19 | def __repr__ 20 | if self\.debug 21 | 22 | # Don't complain if tests don't hit defensive assertion code: 23 | raise AssertionError 24 | raise NotImplementedError 25 | 26 | # Don't complain if non-runnable code isn't run: 27 | if 0: 28 | if __name__ == .__main__.: 29 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Code review checklist 4 | 5 | - [ ] Pull request represents a single change (i.e. not fixing disparate/unrelated things in a single PR) 6 | - [ ] Title summarizes what is changing 7 | - [ ] Commit messages are meaningful (see [this][commit messages] for details) 8 | - [ ] Tests have been included and/or updated 9 | - [ ] Docstrings have been included and/or updated, as appropriate 10 | - [ ] Standalone docs have been updated accordingly 11 | - [ ] Changelog(s) has/have been updated, as needed (see `CHANGELOG.md`, no need 12 | to update for typo fixes and such). 13 | 14 | 15 | [commit messages]: https://chris.beams.io/posts/git-commit/ 16 | -------------------------------------------------------------------------------- /asmTests/twopass.asm: -------------------------------------------------------------------------------- 1 | 2 | .386p 3 | 4 | _DATA segment use16 word public 'DATA' ;IGNORE 5 | var3 dw var4 6 | var4 dw var3 7 | var5 dw lab1 8 | var6 dw lab2 9 | 10 | _DATA ends ;IGNORE 11 | 12 | _TEXT segment use16 word public 'CODE' ;IGNORE 13 | assume cs:_TEXT,ds:_DATA 14 | 15 | start proc near 16 | 17 | lab1: 18 | MOV ax, lab2 19 | MOV ax, var1 20 | MOV ax, var2 21 | MOV ax, var3 22 | MOV ax, var4 23 | MOV ax, lab1 24 | lab2: 25 | mov ax,4c00h 26 | int 21h 27 | 28 | start endp 29 | 30 | 31 | _TEXT ends ;IGNORE 32 | 33 | 34 | 35 | _DATA2 segment use16 word public 'DATA' ;IGNORE 36 | var1 dw var2 37 | var2 dw var1 38 | 39 | _DATA2 ends ;IGNORE 40 | 41 | end start ;IGNORE 42 | -------------------------------------------------------------------------------- /asm_emu/x86_pop.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_popl(struct assembler_state_t *state, uint32_t *dst) 6 | { 7 | if (state->esp & 0x00000003) 8 | { 9 | fprintf(stderr, "#AC(0) exception occured here\n"); 10 | return; 11 | } 12 | *dst = x86_read_memory(state, state->ss, state->esp, 4); 13 | state->esp += 4; 14 | } 15 | static inline void asm_popw(struct assembler_state_t *state, uint16_t *dst) 16 | { 17 | uint32_t tmp; 18 | asm_popl(state, &tmp); 19 | *dst = tmp; 20 | } 21 | static inline void asm_popb(struct assembler_state_t *state, uint8_t *dst) 22 | { 23 | uint32_t tmp; 24 | asm_popl(state, &tmp); 25 | *dst = tmp; 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /asmTests/rol.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | 5 | _DATA ends ;IGNORE 6 | 7 | _TEXT segment use16 word public 'CODE' ;IGNORE 8 | assume cs:_TEXT,ds:_DATA 9 | start proc near 10 | 11 | 12 | mov ebx,01B 13 | 14 | rol ebx,1 15 | cmp ebx,010B 16 | jne failure 17 | 18 | rol ebx,31 19 | cmp ebx,1 20 | jne failure 21 | 22 | MOV al,0 23 | JMP exitLabel 24 | failure: 25 | mov al,1 26 | exitLabel: 27 | mov ah,4ch ; AH=4Ch - Exit To DOS 28 | int 21h ; DOS INT 21h 29 | start endp 30 | 31 | _TEXT ends ;IGNORE 32 | 33 | stackseg segment para stack 'STACK' ;IGNORE 34 | db 1000h dup(?) 35 | stackseg ends ;IGNORE 36 | 37 | end start ;IGNORE 38 | -------------------------------------------------------------------------------- /outdated/iprintf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef uint32_t dd; 6 | 7 | dd iiprintf(dd stackPointer) 8 | { 9 | dd save = *(dd*)stackPointer; 10 | __asm__( ".intel_syntax;\n" 11 | "push ebp\n" //backup ebp 12 | " mov ebp,esp\n" // backup real stack 13 | 14 | " mov esp, %[stackPointer]\n" // switch to emulated stack. printf arguments are stored as cdecl in stack (not in regs) 15 | " add esp, 4\n" // remove it from stack 16 | " call _printf\n" 17 | 18 | " mov esp, ebp\n" // restore real stack 19 | " pop ebp\n" 20 | 21 | //" ret\n" 22 | ".att_syntax;" 23 | : 24 | :[stackPointer] "r" (stackPointer) 25 | ); 26 | 27 | *(dd*)stackPointer = save; 28 | return stackPointer; 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Temporary and binary files 2 | *~ 3 | *.py[cod] 4 | *.so 5 | *.bkp 6 | !.isort.cfg 7 | !setup.cfg 8 | *.orig 9 | *.log 10 | *.pot 11 | __pycache__/* 12 | .cache/* 13 | .*.swp 14 | */.ipynb_checkpoints/* 15 | .DS_Store 16 | 17 | # Project files 18 | .ropeproject 19 | .project 20 | .pydevproject 21 | .settings 22 | .idea 23 | .vscode 24 | tags 25 | 26 | # Package files 27 | *.egg 28 | *.eggs/ 29 | .installed.cfg 30 | *.egg-info 31 | 32 | # Unittest and coverage 33 | htmlcov/* 34 | .coverage 35 | .tox 36 | junit.xml 37 | coverage.xml 38 | .pytest_cache/ 39 | 40 | # Build and docs folder/files 41 | build/* 42 | dist/* 43 | sdist/* 44 | docs/api/* 45 | docs/_rst/* 46 | docs/_build/* 47 | cover/* 48 | MANIFEST 49 | 50 | # Per-project virtualenvs 51 | .venv*/ 52 | 53 | *.obj 54 | *.o 55 | .aider* 56 | -------------------------------------------------------------------------------- /asmTests/_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | if [ -z "$CXX" ];then 4 | export CXX=g++ 5 | fi 6 | 7 | filename="$1" 8 | 9 | > _result.log 10 | 11 | . ./_config.sh 12 | 13 | ( 14 | cd .. 15 | $CXX $OPT asm.cpp -c 16 | $CXX $OPT memmgr.cpp -c 17 | $CXX $OPT shadowstack.cpp -c 18 | ) 19 | 20 | result=0 21 | 22 | for name in $(ls *.asm *.lst|xargs) 23 | do 24 | echo "Testing $name:" 25 | ./_singletest.sh "$name" 2>&1 | tee -a _result.log 26 | res=${PIPESTATUS[0]} 27 | if [ $res -ne 0 ];then 28 | echo "$n failed with code $res" | tee -a _result.log 29 | result=$(( $result + 1 )) 30 | export result 31 | fi 32 | echo '-------------------------------------------------------------' 33 | echo 34 | done 35 | #cat _result.log 36 | ! grep 'error:' _result.log 37 | echo "Total result: $result" 38 | exit $result 39 | -------------------------------------------------------------------------------- /asm_emu/x86_shrd.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_shrdl(struct assembler_state_t *state, uint8_t count, const uint32_t src, uint32_t *dst) 6 | { 7 | count = count & 0x0000001f; 8 | int of = *dst&1; 9 | 10 | if (count) 11 | { 12 | int i; 13 | write_cf(state->eflags, *dst & (1<<(count))); /* the last bit to be shifted out */ 14 | // for (i=0;i>=count; 17 | *dst|=(src <<(32-i)); 18 | } 19 | } 20 | 21 | if (count==1) 22 | write_of(state->eflags, (of & ~*dst) & 1); 23 | else 24 | write_of(state->eflags, 0); 25 | 26 | write_sf(state->eflags, *dst & 1); 27 | write_zf(state->eflags, !*dst); 28 | #ifdef X86_PF 29 | asm_update_pf(state->eflags, *dst); 30 | #endif 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /asmTests/popf.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _TEXT segment use16 word public 'CODE' ;IGNORE 4 | assume cs:_TEXT,ds:_DATA 5 | start proc near 6 | 7 | push 1234h 8 | 9 | loc_15c4a: ; POPF 10 | or bh, 0 11 | sub_15c: 12 | push cs 13 | call loc_15c4a+1 14 | 15 | pushf 16 | pop ax 17 | 18 | CMP ax, 1234h 19 | JNE failure 20 | 21 | ;mov ax, (ax SHL 4) + dx 22 | ;mov ax,cs 23 | ;mov dx, offset loc_2 24 | ;push dx ; offset 25 | ;push ax ; segment 26 | ;retf 27 | ;loc_2: 28 | 29 | MOV al,0 30 | JMP exitLabel 31 | failure: 32 | ;mov al,1 33 | exitLabel: 34 | mov ah,4ch ; AH=4Ch - Exit To DOS 35 | int 21h 36 | start endp 37 | 38 | _TEXT ends ;IGNORE 39 | 40 | stackseg segment para stack 'STACK' ;IGNORE 41 | db 100h dup(?) 42 | stackseg ends ;IGNORE 43 | 44 | end start ;IGNORE 45 | -------------------------------------------------------------------------------- /asm_emu/x86_shld.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_shldl(struct assembler_state_t *state, uint8_t count, const uint32_t src, uint32_t *dst) 6 | { 7 | count = count & 0x0000001f; 8 | int of = *dst&0x80000000; 9 | 10 | if (count) 11 | { 12 | int i; 13 | write_cf(state->eflags, *dst & (1<<(32-count))); /* the last bit to be shifted out */ 14 | for (i=0;ieflags, (of & ~*dst) & 0x80000000); 23 | else 24 | write_of(state->eflags, 0); 25 | 26 | write_sf(state->eflags, *dst & 0x80000000); 27 | write_zf(state->eflags, !*dst); 28 | #ifdef X86_PF 29 | asm_update_pf(state->eflags, *dst); 30 | #endif 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /vikings/init.cpp: -------------------------------------------------------------------------------- 1 | #include "../asm.h" 2 | #include 3 | #include 4 | 5 | void init_get_fname(char *dst, char *src); 6 | 7 | //Initializer - is startet if executed file is SCHICKM.EXE/BLADEM.EXE or GEN.EXE 8 | //Returns true if the desired programm is started 9 | bool masm2c_init(char *name, unsigned short reloc, unsigned short _cs, unsigned short ip) 10 | { 11 | 12 | char fname[81]; 13 | int ver; 14 | 15 | init_get_fname(fname, name); 16 | 17 | if (strcmp(fname, "vikings.exe")) return false; 18 | 19 | return true; 20 | } 21 | 22 | 23 | namespace m2c 24 | { 25 | void load_drivers() 26 | { 27 | // fread(raddr(0x24ed,0x100),0xffff,1,fopen("DN386.HSQ","r")); 28 | // fread(raddr(0x47d8,0x100),0xffff,1,fopen("DNSBP.HSQ","r")); 29 | // fread(raddr(0x4d44,0x100),0xffff,1,fopen("DNMID.HSQ","r")); 30 | 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | include: 3 | - language: python 4 | dist: focal 5 | python: 6 | - "3.8" 7 | 8 | install: 9 | - ./install-test.sh 10 | 11 | script: 12 | - ./runtests.sh 13 | 14 | after_success: 15 | - coveralls 16 | 17 | - language: cpp 18 | dist: focal 19 | compiler: 20 | - gcc 21 | 22 | cache: 23 | apt: true 24 | 25 | addons: 26 | apt: 27 | packages: 28 | - gcc-multilib 29 | - g++-multilib 30 | - libncurses5-dev:i386 31 | - libncurses5:i386 32 | 33 | before_install: 34 | - echo 'getconf _NPROCESSORS_ONLN' 35 | - lsb_release -c 36 | - lsb_release -r 37 | 38 | script: 39 | - ./_binarytests.sh 40 | 41 | sudo: false 42 | -------------------------------------------------------------------------------- /asm_emu/x86_cmp.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_subl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst); 6 | static inline void asm_subw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst); 7 | static inline void asm_subb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst); 8 | static inline void asm_cmpl(struct assembler_state_t *state, uint32_t src, uint32_t dst) 9 | { 10 | uint32_t tmp = dst; 11 | asm_subl(state, src, &tmp); 12 | } 13 | static inline void asm_cmpw(struct assembler_state_t *state, uint16_t src, uint16_t dst) 14 | { 15 | uint16_t tmp = dst; 16 | asm_subw(state, src, &tmp); 17 | } 18 | static inline void asm_cmpb(struct assembler_state_t *state, uint8_t src, uint8_t dst) 19 | { 20 | uint8_t tmp = dst; 21 | asm_subb(state, src, &tmp); 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /asmTests/_singletest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #set -x 3 | if [ -z "$CXX" ];then 4 | export CXX=g++ 5 | fi 6 | name="$1" 7 | n="$(echo $name| perl -pe 's!(\.asm|\.lst)!!')" 8 | 9 | rm $n.cpp $n.h $n.err $n.log $n.txt $n.asm.log $n.o $n 2>/dev/null || true 10 | ##./ml /c /Fl $1.asm 11 | #uasm /c /Fl $1.asm 12 | if [ -z "$name" ];then 13 | exit 0 14 | elif [ ! -r "$name" ];then 15 | echo "No such file $name" 16 | exit 2 17 | fi 18 | 19 | 20 | ../masm2c.py -m separate "$name" > "$n.txt" 2>&1 21 | res=$? 22 | if [ "${res}" -ne 0 ];then 23 | cat "$n.txt" 24 | exit "${res}" 25 | fi 26 | 27 | 28 | ./build.sh $n > "$n.txt" 2>&1 29 | res=$? 30 | if [ "${res}" -ne 0 ];then 31 | cat "$n.txt" asm.log 32 | exit "${res}" 33 | fi 34 | rm asm.log || true 35 | 36 | ./$n > "$n.txt" 2>&1 37 | res=$? 38 | if [ "${res}" -ne 0 ];then 39 | cat "$n.txt" 40 | exit "${res}" 41 | fi 42 | #python ../_masm61.py $1.asm 43 | 44 | -------------------------------------------------------------------------------- /qemu_tests/README: -------------------------------------------------------------------------------- 1 | These are i386 specific guest programs 2 | 3 | test-i386 4 | --------- 5 | 6 | This program executes most of the 16 bit and 32 bit x86 instructions and 7 | generates a text output, for comparison with the output obtained with 8 | a real CPU or another emulator. 9 | 10 | The Linux system call modify_ldt() is used to create x86 selectors 11 | to test some 16 bit addressing and 32 bit with segmentation cases. 12 | 13 | The Linux system call vm86() is used to test vm86 emulation. 14 | 15 | Various exceptions are raised to test most of the x86 user space 16 | exception reporting. 17 | 18 | linux-test 19 | ---------- 20 | 21 | This program tests various Linux system calls. It is used to verify 22 | that the system call parameters are correctly converted between target 23 | and host CPUs. 24 | 25 | test-i386-fprem 26 | --------------- 27 | 28 | test-mmap 29 | --------- 30 | 31 | sha1 32 | ---- 33 | 34 | hello-i386 35 | ---------- 36 | -------------------------------------------------------------------------------- /vikings/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | #. ./_config.sh 4 | 5 | if [ -z "$CXX" ];then 6 | export CXX=g++ 7 | fi 8 | 9 | export SDL="$(pkg-config --cflags --libs sdl2)" 10 | export CURSES="-DNOCURSES $(pkg-config --cflags --libs ncurses)" 11 | export OPT="-Wno-narrowing -mno-ms-bitfields -Wno-multichar $SDL $CURSES -D_GNU_SOURCE=1 -ggdb3 -O0 -I. -I.. -DM2CDEBUG=3" 12 | 13 | ( 14 | cd .. 15 | $CXX $OPT asm.cpp -c 16 | $CXX $OPT memmgr.cpp -c 17 | $CXX $OPT shadowstack.cpp -c 18 | ) 19 | 20 | 21 | # 22 | 23 | $CXX -c vikings.exe.cpp $OPT 24 | $CXX -c _data.cpp $OPT 25 | $CXX -c vikings.exe_default_seg.cpp $OPT 26 | $CXX -c vikings.exe_seg000.cpp $OPT 27 | $CXX -c vikings.exe_seg002.cpp $OPT 28 | $CXX -c vikings.exe_seg003.cpp $OPT 29 | 30 | $CXX vikings.exe.o _data.o vikings.exe_default_seg.o vikings.exe_seg000.o vikings.exe_seg002.o vikings.exe_seg003.o ../asm.o ../memmgr.o ../shadowstack.o $OPT -o vikings 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /asmTests/hello.asm_disabled: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _msg db 'Hello World!',13,10,'$' 5 | 6 | _DATA ends ;IGNORE 7 | 8 | _TEXT segment use16 word public 'CODE' ;IGNORE 9 | assume cs:_TEXT,ds:_DATA 10 | start proc near 11 | 12 | 13 | 14 | push _data 15 | pop ds 16 | mov ah,9 ; AH=09h - Print DOS Message 17 | mov dx,offset _msg ; DS:EDX -> $ Terminated String 18 | int 21h ; DOS INT 21h 19 | 20 | ; weird test... 21 | mov ebx,-1 22 | mov bl,0 23 | cmp ebx,0ffffff00h 24 | jne failure 25 | 26 | xor eax,eax 27 | jmp exitLabel 28 | failure: 29 | mov al,1 30 | exitLabel: 31 | mov ah,4ch ; AH=4Ch - Exit To DOS 32 | int 21h ; DOS INT 21h ; DOS INT 21h 33 | start endp 34 | 35 | _TEXT ends ;IGNORE 36 | 37 | stackseg segment para stack 'STACK' ;IGNORE 38 | db 1000h dup(?) 39 | stackseg ends ;IGNORE 40 | 41 | end start ;IGNORE 42 | -------------------------------------------------------------------------------- /examples/intro.h: -------------------------------------------------------------------------------- 1 | #ifndef TASMRECOVER_INTRO_STUBS_H__ 2 | #define TASMRECOVER_INTRO_STUBS_H__ 3 | 4 | /* PLEASE DO NOT MODIFY THIS FILE. ALL CHANGES WILL BE LOST! LOOK FOR README FOR DETAILS */ 5 | 6 | /* 7 | * 8 | */ 9 | 10 | #include "asm.h" 11 | 12 | //namespace intro { 13 | 14 | #define kbegin 0x1001 15 | #define kmaketopoloop 0x1111 16 | #define kmainloop 0x1112 17 | #define kangleloop 0x1113 18 | #define kradiusloop 0x1114 19 | #define knowall 0x1115 20 | #define klineloop 0x1116 21 | #define kprojectloop 0x1117 22 | #define kplotloop 0x1118 23 | #define kdontdraw 0x1119 24 | 25 | struct MYPACKED Memory{ 26 | db dummy1[4096]; // protective 27 | db code[16]; // segment code 28 | 29 | db stack[STACK_SIZE]; 30 | db heap[HEAP_SIZE]; 31 | }; 32 | 33 | //class introContext { 34 | //public: 35 | // introContext() {} 36 | 37 | // void _start(); 38 | //}; 39 | 40 | //} // End of namespace DreamGen 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /qemu_tests/_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | if [ -z "$CXX" ];then 4 | export CXX=g++ 5 | fi 6 | 7 | # No need to generate reference each time 8 | #gcc -O0 -m32 -lm test-i386.c -o test-i386 2>&1 | tee result.txt 9 | #-Os -fdata-sections -ffunction-sections -static -s 10 | #./test-i386 > test-i386.txt 11 | 12 | rm test-i386_conv test-i386_conv.txt || true 13 | ##$CXX -O0 -I.. test-i386_conv.cpp -E -fpermissive > test-i386_conv.e 14 | $CXX -O0 -w -fpermissive -m32 -lm -I.. -DNOSDL -DNO_SHADOW_STACK test-i386_conv.cpp -o test-i386_conv 2>&1 | tee -a result.txt 15 | ## -ggdb3 -Og -Wa,-adhlns="test-i386_conv.lst" -fdata-sections -ffunction-sections -static -ftime-report 16 | 17 | #$CXX -O0 -ggdb3 -w -fpermissive -m32 -lm -I.. test-i386_brute.cpp -o test-i386_brute 18 | 19 | ./test-i386_conv > test-i386_conv.txt 20 | diff -diu --label real test-i386.txt --label emulated test-i386_conv.txt > test-i386.diff || true 21 | 22 | diff -diu test-i386_benchmark.diff test-i386.diff | tee -a result.txt 23 | -------------------------------------------------------------------------------- /vikings/vikings.exe_default_seg.cpp: -------------------------------------------------------------------------------- 1 | /* PLEASE DO NOT MODIFY THIS FILE. ALL CHANGES WILL BE LOST! LOOK FOR README FOR DETAILS */ 2 | 3 | /* 4 | * 5 | */ 6 | 7 | #include "vikings.exe.h" 8 | 9 | 10 | 11 | bool mainproc(m2c::_offsets _i, struct m2c::_STATE* _state){ 12 | X86_REGREF 13 | __disp = _i; 14 | 15 | if (__disp == 0) goto _begin; 16 | else goto __dispatch_call; 17 | mainproc: 18 | _begin: 19 | J(CALL(start,0)); R(RETN(0)); 20 | assert(0); 21 | __dispatch_call: 22 | #ifdef DOSBOX_CUSTOM 23 | if ((__disp >> 16) == 0xf000) 24 | {cs=0xf000;eip=__disp&0xffff;m2c::fix_segs();return false;} // Jumping to BIOS 25 | if ((__disp>>16) == 0) {__disp |= ((dd)cs) << 16;} 26 | #endif 27 | switch (__disp) { 28 | case m2c::kmainproc: goto mainproc; 29 | default: m2c::log_error("Don't know how to jump to 0x%x. See " __FILE__ " line %d\n", __disp, __LINE__);m2c::stackDump(); abort(); 30 | }; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /qemu_tests/convert_llvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set +x 3 | ~/clang8/bin/clang++ -Os -w -fpermissive -m32 -lm -I.. -DNOSDL -DNO_SHADOW_STACK -DM2CDEBUG=-1 test-i386_conv.cpp -S -emit-llvm 4 | perl -i -pe 's!^declare (i\d+) (\@llvm\.f.*)!define $1 $2 {ret $1 0}!' test-i386_conv.ll 5 | perl -i -pe 's!llvm\.f!f!g' test-i386_conv.ll 6 | exit 0 7 | perl -ni -e 'print unless / = comdat any/' test-i386_conv.ll 8 | perl -ni -e 'print unless /= global /' test-i386_conv.ll 9 | perl -ni -e 'print unless /= external hidden global /' test-i386_conv.ll 10 | perl -ni -e 'print unless /= internal global /' test-i386_conv.ll 11 | perl -ni -e 'print unless /= private unnamed_addr constant /' test-i386_conv.ll 12 | perl -ni -e 'print unless /= local_unnamed_addr global /' test-i386_conv.ll 13 | perl -ni -e 'print unless /= local_unnamed_addr constant /' test-i386_conv.ll 14 | perl -ni -e 'print unless /= appending global /' test-i386_conv.ll 15 | 16 | perl -i -pe 's!dso_local !!g; s!comdat align!align!g; s!comdat !!g; s!section "\.text\.startup"!!' test-i386_conv.ll 17 | 18 | -------------------------------------------------------------------------------- /asmTests/loop.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _DATA ends ;IGNORE 5 | 6 | _TEXT segment use16 word public 'CODE' ;IGNORE 7 | assume cs:_TEXT,ds:_DATA 8 | 9 | start proc near 10 | 11 | 12 | 13 | xor edx,edx 14 | mov ecx,10 15 | toto: 16 | INC edx 17 | loop toto 18 | 19 | cmp edx,10 20 | jne failure 21 | 22 | xor edx,edx 23 | mov ecx,10 24 | toto1: 25 | INC edx 26 | sub eax,eax 27 | loope toto1 28 | 29 | cmp edx,10 30 | jne failure 31 | 32 | xor edx,edx 33 | mov ecx,10 34 | toto2: 35 | INC edx 36 | sub eax,eax 37 | inc eax 38 | loope toto2 39 | 40 | cmp edx,1 41 | jne failure 42 | 43 | 44 | MOV al,0 45 | JMP exitLabel 46 | failure: 47 | mov al,1 48 | exitLabel: 49 | mov ah,4ch ; AH=4Ch - Exit To DOS 50 | int 21h ; DOS INT 21h 51 | 52 | start endp 53 | 54 | _TEXT ends ;IGNORE 55 | 56 | 57 | 58 | stackseg segment para stack 'STACK' ;IGNORE 59 | db 1000h dup(?) ;IGNORE 60 | stackseg ends ;IGNORE 61 | 62 | end start ;IGNORE 63 | -------------------------------------------------------------------------------- /masm2c.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # MASM x86 to C translator 3 | # 4 | # MASM2C is the legal property of its developers, whose names 5 | # are too numerous to list here. Please refer to the COPYRIGHT 6 | # file distributed with this source distribution. 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License 10 | # as published by the Free Software Foundation; either version 2 11 | # of the License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | # 22 | 23 | from masm2c.cli import main 24 | 25 | main() 26 | 27 | -------------------------------------------------------------------------------- /asmTests/lodsb.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 2,5,6 5 | var2 dw 4,6,9 6 | var3 dd 11,-11,2,4 7 | var4 db 100 dup (1) 8 | var5 db 'abcd' 9 | 10 | 11 | _DATA ends ;IGNORE 12 | 13 | _TEXT segment use16 word public 'CODE' ;IGNORE 14 | assume cs:_TEXT,ds:_DATA 15 | start proc near 16 | 17 | 18 | mov ax,_DATA 19 | mov ds,ax 20 | 21 | push ds 22 | pop es 23 | 24 | mov esi,offset var1 25 | mov edi,offset var4 26 | 27 | mov eax, 0ffffffffh 28 | lodsb 29 | cmp al,2 30 | jne failure 31 | cmp ah,0ffh 32 | jne failure 33 | cmp ah,-1 34 | jne failure 35 | 36 | mov ecx,'dcba' 37 | xor eax,eax 38 | lea esi,var5 39 | lodsd 40 | mov ebx,eax 41 | cmp ebx,'dcba' 42 | jne failure 43 | 44 | 45 | MOV al,0 46 | JMP exitLabel 47 | failure: 48 | mov al,1 49 | exitLabel: 50 | mov ah,4ch ; AH=4Ch - Exit To DOS 51 | int 21h 52 | start endp 53 | 54 | _TEXT ends ;IGNORE 55 | 56 | stackseg segment para stack 'STACK' ;IGNORE 57 | db 1000h dup(?) 58 | stackseg ends ;IGNORE 59 | 60 | end start ;IGNORE 61 | -------------------------------------------------------------------------------- /asmTests/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Franck GOTTHOLD, xor2003 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. 22 | -------------------------------------------------------------------------------- /asm_emu/_gen_emu_wrapper._sh_: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # static inline void asm_adcb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 3 | 4 | echo '#include "asm_emu/x86.h"' > 1.h 5 | echo '#include "asm_emu/2.h"' >> 1.h 6 | 7 | #echo '#include "asm_emu/1.h"' > 1.cpp 8 | echo 'static struct assembler_state_t asm_cpu_state;' >> 1.h 9 | 10 | cat 1.txt | while read line;do 11 | name=$(echo $line | cut -f4 -d' ' | cut -f1 -d'(') 12 | echo "name $name" 13 | 14 | new_sig=$(echo $line| perl -pe 's! asm! !; s![bwl]\(!(!; s!;$!!; s!struct assembler_state_t \*state(, )?!!; s!uint(8|16|32)_t \*!uint$1_t &!g;') 15 | echo "newsig $new_sig" 16 | 17 | new_def=$(echo $line| perl -pe 's! asm! !; s![bwl]\(!(!; s!;$!!; s!struct assembler_state_t \*state(, )?!!; s!$!\;\n!') 18 | echo "newdef $new_def" 19 | 20 | call=$(echo $line| perl -pe 's!static inline void!!; s!struct assembler_state_t \*!!; s!uint(8|16|32)_t \*!&!g; s!uint(8|16|32)_t ?!!g; s!const !!g; s!$!\;!; s!state!&asm_cpu_state!') 21 | echo "call $call" 22 | 23 | # echo $new_def >> 1.h 24 | 25 | echo $new_sig >> 1.h 26 | echo "{" >> 1.h 27 | echo " $call" >> 1.h 28 | echo "}" >> 1.h 29 | echo "" >> 1.h 30 | done 31 | -------------------------------------------------------------------------------- /outdated/_tasm_to_nasm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh +x 2 | cp iplay_tasm.asm iplay_tasm_.asm 3 | sed -ie 's!far_module!faar_module!g' iplay_tasm_.asm 4 | perl nomyso.pl iplay_tasm_.asm iplay_tasmn.asm 5 | 6 | grep far iplay_tasm.asm |perl -pe 's![ \t]+! !g' |cut -f2 -d' ' | grep -wFf - iplay_tasm.asm | grep 'call\|jmp' | grep -v 'near\|callsubx' \ 7 | | perl -pe 's!(call|jmp)(\s+)([A-Za-z_0-9\[\]:]+)!s/$1$2\\<$3\\>/$1 far $3/!; s!\[!\\[!g; s!\]!\\]!g' | grep -v ';' | sort | uniq > _temp.sed 8 | 9 | echo > iplay_nasm.asm 10 | 11 | cat iplay_tasmn.asm | grep -vw "model large" | \ 12 | perl -pe "s/\r//g; s!jcxz\s+short\s+!jcxz !; s!jmp short loc_11B28!jmp loc_11B28!; s!\['\+:A\+'\]!']A:['!" | sed -f _temp.sed \ 13 | >> iplay_nasm.asm 14 | 15 | cp iplay_nasm.asm iplay_nasm_or.asm 16 | patch -p0 iplay_nasm.asm iplay_nasm_override.patch 17 | 18 | #/cygdrive/c/Program\ Files/DOSBox-0.74/DOSBox.exe V.BAT 19 | ./build_nasm.bat 20 | 21 | #signatures (character constants) grep -P "'[A-Za-z0-9 \.\[\]\\\/][A-Za-z0-9 \.\[\]\\\/]+'" iplay_tasm.asm | grep -Pv "db|segment|'\s+'" > _signatures.txt 22 | 23 | #segs override 24 | #grep -n "lods\|stos\|movs" iplay_tasm.asm | grep -P "[a-z]:[a-z]" -------------------------------------------------------------------------------- /asmTests/cmp.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 1 5 | var2 dw 2 6 | var3 dd 3 7 | _DATA ends ;IGNORE 8 | 9 | _TEXT segment use16 word public 'CODE' ;IGNORE 10 | assume cs:_TEXT,ds:_DATA 11 | 12 | start proc near 13 | 14 | 15 | sti ; Set The Interrupt Flag 16 | cld ; Clear The Direction Flag 17 | 18 | cmp var1,1 19 | jne failure 20 | 21 | mov eax,1 22 | cmp var1,al 23 | jne failure 24 | 25 | cmp var2,2 26 | jne failure 27 | 28 | 29 | mov ebx,2 30 | cmp var2,bx 31 | jne failure 32 | 33 | cmp var3,3 34 | jne failure 35 | 36 | mov ecx,3 37 | cmp var3,ecx 38 | jne failure 39 | 40 | mov al,7 41 | mov ah,7 42 | cmp al,ah 43 | jne failure 44 | 45 | MOV al,0 46 | JMP exitLabel 47 | failure: 48 | mov al,1 49 | exitLabel: 50 | mov ah,4ch ; AH=4Ch - Exit To DOS 51 | int 21h ; DOS INT 21h 52 | start endp 53 | 54 | _TEXT ends ;IGNORE 55 | 56 | stackseg segment para stack 'STACK' ;IGNORE 57 | db 1000h dup(?) 58 | stackseg ends ;IGNORE 59 | 60 | end start ;IGNORE 61 | -------------------------------------------------------------------------------- /asmTests/inc.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 2 5 | var2 dw 11 6 | var3 dd 34 7 | _DATA ends ;IGNORE 8 | 9 | _TEXT segment use16 word public 'CODE' ;IGNORE 10 | assume cs:_TEXT,ds:_DATA 11 | start proc near 12 | 13 | 14 | mov ax, _data 15 | mov ds, ax 16 | xor eax,eax 17 | INC eax 18 | CMP eax,1 19 | JNE failure 20 | 21 | INC eax 22 | CMP eax,2 23 | JNE failure 24 | 25 | INC eax 26 | CMP eax,3 27 | JNE failure 28 | CMP eax,133 29 | JE failure 30 | 31 | INC [var1] 32 | CMP [var1],3 33 | JNE failure 34 | CMP [var1],111 35 | JE failure 36 | 37 | INC [var2] 38 | INC [var2] 39 | CMP [var2],13 40 | JNE failure 41 | CMP [var2],1 42 | JE failure 43 | 44 | INC [var3] 45 | CMP [var3],35 46 | JNE failure 47 | CMP [var3],37 48 | JE failure 49 | 50 | MOV al,0 51 | JMP exitLabel 52 | failure: 53 | mov al,1 54 | exitLabel: 55 | mov ah,4ch ; AH=4Ch - Exit To DOS 56 | int 21h 57 | start endp 58 | 59 | _TEXT ends ;IGNORE 60 | 61 | stackseg segment para stack 'STACK' ;IGNORE 62 | db 1000h dup(?) 63 | stackseg ends ;IGNORE 64 | 65 | end start ;IGNORE 66 | -------------------------------------------------------------------------------- /asmTests/snake.map: -------------------------------------------------------------------------------- 1 | 2 | Start Stop Length Name Class 3 | 4 | 00000H 000FFH 00100H DATA DATA 5 | 00100H 00459H 0035AH seg001 CODE 6 | 7 | 8 | Address Publics by Value 9 | 10 | 0000:0000 msg 11 | 0000:001C instructions 12 | 0000:0078 aThanksForPlayi 13 | 0000:009D gameovermsg 14 | 0000:00B9 scoremsg 15 | 0000:00C1 head 16 | 0000:00C4 body 17 | 0000:00F4 segmentcount 18 | 0000:00F5 fruitactive 19 | 0000:00F6 fruitx 20 | 0000:00F7 fruity 21 | 0000:00F8 gameover 22 | 0000:00F9 quit 23 | 0000:00FA delaytime 24 | 0010:0000 main 25 | 0010:0092 delay 26 | 0010:00A3 fruitgeneration 27 | 0010:0122 dispdigit 28 | 0010:012A dispnum 29 | 0010:0141 setcursorpos 30 | 0010:014A draw 31 | 0010:018C readchar 32 | 0010:019C keyboardfunctions 33 | 0010:01F6 shiftsnake 34 | 0010:029F printbox 35 | 0010:02CE writecharat 36 | 0010:02F9 readcharat 37 | 0010:0324 writestringat 38 | 39 | Program entry point at 0010:0000 40 | -------------------------------------------------------------------------------- /asmTests/datadup.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | dubsize EQU 13 4 | testEqu EQU 1 5 | 6 | _DATA segment use16 word public 'DATA' ;IGNORE 7 | var0 db 10 dup (?) 8 | var db 4 dup (5) 9 | var2 db 5 dup (0) 10 | var3 db 5*5 dup (0,testEqu*2,2*2,3) 11 | 12 | _DATA ends ;IGNORE 13 | 14 | _TEXT segment use16 word public 'CODE' ;IGNORE 15 | assume cs:_TEXT,ds:_DATA 16 | 17 | start proc near 18 | 19 | mov ax,_DATA 20 | mov ds,ax 21 | 22 | cmp [var],5 23 | mov al,1 24 | jne failure 25 | cmp [var2],0 26 | mov al,2 27 | jne failure 28 | cmp [var+3],5 29 | mov al,3 30 | jne failure 31 | cmp [var+4],0 32 | mov al,4 33 | jne failure 34 | cmp [var2-1],5 35 | mov al,5 36 | jne failure 37 | cmp [var0+5],0 38 | mov al,6 39 | jne failure 40 | cmp [var-1],0 41 | mov al,7 42 | jne failure 43 | 44 | MOV al,0 45 | JMP exitLabel 46 | failure: 47 | ;mov al,1 48 | exitLabel: 49 | mov ah,4ch ; AH=4Ch - Exit To DOS 50 | int 21h ; DOS INT 21h 51 | start endp 52 | 53 | _TEXT ends ;IGNORE 54 | 55 | stackseg segment para stack 'STACK' ;IGNORE 56 | db 1000h dup(?) 57 | stackseg ends ;IGNORE 58 | 59 | end start ;IGNORE 60 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | NOTE: Your code should build beforehand successfully with Masm (or UASM: http://www.terraspace.co.uk/uasm.html) 11 | the masm2c tools do not even try to support you with the complexity of the reversing (if will not work if you're not able to build your reversed code with masm) 12 | reversing a DOS program (or something) else is definitily more work then producing asm with IDA and run masm2c 13 | Please source code or part for investigation. 14 | 15 | **Describe the bug** 16 | A clear and concise description of what the bug is. 17 | 18 | **To Reproduce** 19 | Steps to reproduce the behavior: 20 | 1. Go to '...' 21 | 2. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Please complete the following information:** 27 | - Bitness [e.g. 16] 28 | - Mode [e.g. Protected or Real] 29 | - Disassembler [e.g. IDA, re2 or None] 30 | - Assembler [e.g. masm 6.1 or uasm, jwasm] 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /asmTests/cmpsb.asm: -------------------------------------------------------------------------------- 1 | 2 | _DATA segment use16 word public 'DATA' ;IGNORE 3 | var1 db 1,2,3 4 | var2 db 1,2,4 5 | _DATA ends ;IGNORE 6 | 7 | _TEXT segment use16 word public 'CODE' ;IGNORE 8 | assume cs:_TEXT,ds:_DATA 9 | 10 | start proc near 11 | 12 | mov ax,_DATA 13 | mov ds,ax 14 | mov es,ax 15 | 16 | cld ; Clear The Direction Flag 17 | 18 | mov si, offset var1 19 | mov di, offset var2 20 | mov cx,2 21 | repe cmpsb 22 | mov al,1 23 | jne failure 24 | mov al,2 25 | jc failure 26 | 27 | mov si, offset var1 28 | mov di, offset var2 29 | mov cx,3 30 | repe cmpsb 31 | mov al,3 32 | je failure 33 | mov al,4 34 | jnc failure 35 | 36 | mov di, offset var1 37 | mov cx,6 38 | mov al,1 39 | repe scasb 40 | mov al,5 41 | je failure 42 | mov al,6 43 | jnc failure 44 | 45 | MOV al,0 46 | JMP exitLabel 47 | failure: 48 | ;mov al,1 49 | exitLabel: 50 | mov ah,4ch ; AH=4Ch - Exit To DOS 51 | int 21h ; DOS INT 21h 52 | start endp 53 | 54 | _TEXT ends ;IGNORE 55 | 56 | stackseg segment para stack 'STACK' ;IGNORE 57 | db 1000h dup(?) 58 | stackseg ends ;IGNORE 59 | 60 | end start ;IGNORE 61 | -------------------------------------------------------------------------------- /asm_emu/x86_or.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_orl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst) 6 | { 7 | *dst = *dst | src; 8 | 9 | write_cf(state->eflags, 0); 10 | write_of(state->eflags, 0); 11 | 12 | write_sf(state->eflags, *dst & 0x80000000); 13 | write_zf(state->eflags, !*dst); 14 | #ifdef X86_PF 15 | asm_update_pf(state->eflags, *dst); 16 | #endif 17 | } 18 | static inline void asm_orw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 19 | { 20 | *dst = *dst | src; 21 | 22 | write_cf(state->eflags, 0); 23 | write_of(state->eflags, 0); 24 | 25 | write_sf(state->eflags, *dst & 0x8000); 26 | write_zf(state->eflags, !*dst); 27 | #ifdef X86_PF 28 | asm_update_pf(state->eflags, *dst); 29 | #endif 30 | } 31 | static inline void asm_orb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 32 | { 33 | *dst = *dst | src; 34 | 35 | write_cf(state->eflags, 0); 36 | write_of(state->eflags, 0); 37 | 38 | write_sf(state->eflags, *dst & 0x80); 39 | write_zf(state->eflags, !*dst); 40 | #ifdef X86_PF 41 | asm_update_pf(state->eflags, *dst); 42 | #endif 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /asm_emu/x86_and.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_andl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst) 6 | { 7 | *dst = *dst & src; 8 | 9 | write_cf(state->eflags, 0); 10 | write_of(state->eflags, 0); 11 | 12 | write_sf(state->eflags, *dst & 0x80000000); 13 | write_zf(state->eflags, !*dst); 14 | #ifdef X86_PF 15 | asm_update_pf(state->eflags, *dst); 16 | #endif 17 | } 18 | static inline void asm_andw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 19 | { 20 | *dst = *dst & src; 21 | 22 | write_cf(state->eflags, 0); 23 | write_of(state->eflags, 0); 24 | 25 | write_sf(state->eflags, *dst & 0x8000); 26 | write_zf(state->eflags, !*dst); 27 | #ifdef X86_PF 28 | asm_update_pf(state->eflags, *dst); 29 | #endif 30 | } 31 | static inline void asm_andb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 32 | { 33 | *dst = *dst & src; 34 | 35 | write_cf(state->eflags, 0); 36 | write_of(state->eflags, 0); 37 | 38 | write_sf(state->eflags, *dst & 0x80); 39 | write_zf(state->eflags, !*dst); 40 | #ifdef X86_PF 41 | asm_update_pf(state->eflags, *dst); 42 | #endif 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /asm_emu/x86_xor.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_xorl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst) 6 | { 7 | *dst = *dst ^ src; 8 | 9 | write_cf(state->eflags, 0); 10 | write_of(state->eflags, 0); 11 | 12 | write_sf(state->eflags, *dst & 0x80000000); 13 | write_zf(state->eflags, !*dst); 14 | #ifdef X86_PF 15 | asm_update_pf(state->eflags, *dst); 16 | #endif 17 | } 18 | static inline void asm_xorw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 19 | { 20 | *dst = *dst ^ src; 21 | 22 | write_cf(state->eflags, 0); 23 | write_of(state->eflags, 0); 24 | 25 | write_sf(state->eflags, *dst & 0x8000); 26 | write_zf(state->eflags, !*dst); 27 | #ifdef X86_PF 28 | asm_update_pf(state->eflags, *dst); 29 | #endif 30 | } 31 | static inline void asm_xorb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 32 | { 33 | *dst = *dst ^ src; 34 | 35 | write_cf(state->eflags, 0); 36 | write_of(state->eflags, 0); 37 | 38 | write_sf(state->eflags, *dst & 0x80); 39 | write_zf(state->eflags, !*dst); 40 | #ifdef X86_PF 41 | asm_update_pf(state->eflags, *dst); 42 | #endif 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /asmTests/errorlvl.asm: -------------------------------------------------------------------------------- 1 | _TEXT segment use16 word public 'CODE' ;IGNORE 2 | assume cs:_TEXT,ds:_TEXT,ss:_TEXT 3 | org 100h 4 | start proc near 5 | 6 | MOV AH,4Dh 7 | INT 21h 8 | mov ah,0 9 | 10 | mov bx,10 ;CONST 11 | xor cx,cx ;Reset counter 12 | a: xor dx,dx ;Setup for division DX:AX / BX 13 | div bx ; -> AX is Quotient, Remainder DX=[0,9] 14 | push dx ;(1) Save remainder for now 15 | inc cx ;One more digit 16 | test ax,ax ;Is quotient zero? 17 | jnz a ;No, use as next dividend 18 | b: pop dx ;(1) 19 | add dl,"0" ;Turn into character [0,9] -> ["0","9"] 20 | mov ah,02h ;DOS.DisplayCharacter 21 | int 21h ; -> AL 22 | loop b 23 | 24 | mov dl,0dh 25 | mov ah,02h ;DOS.DisplayCharacter 26 | int 21h ; -> AL 27 | mov dl,0ah 28 | mov ah,02h ;DOS.DisplayCharacter 29 | int 21h ; -> AL 30 | 31 | MOV AH,4Ch 32 | INT 21h 33 | start endp 34 | 35 | _TEXT ends ;IGNORE 36 | 37 | end start ;IGNORE 38 | -------------------------------------------------------------------------------- /examples/iplay_nasm_override.patch: -------------------------------------------------------------------------------- 1 | --- iplay_n_or.asm 2013-12-04 13:47:13.935073100 +0400 2 | +++ iplay_n.asm 2013-12-04 13:47:14.138073100 +0400 3 | @@ -2649,7 +2649,7 @@ 4 | mov di, bx 5 | mov cx, 200h 6 | cld 7 | - rep movsd 8 | + fs rep movsd 9 | pop di 10 | pop ax 11 | mov ecx, [di+24h] 12 | @@ -2702,7 +2702,7 @@ 13 | cld 14 | 15 | loc_1248B: ; CODE XREF: ems_mapmemx+1ACj 16 | - movsb 17 | + fs movsb 18 | cmp si, dx 19 | jb short loc_12493 20 | mov si, bp 21 | @@ -2717,7 +2717,7 @@ 22 | mov di, bx 23 | mov cx, 200h 24 | cld 25 | - rep movsd 26 | + fs rep movsd 27 | retn 28 | 29 | 30 | @@ -2827,7 +2827,7 @@ 31 | mov di, bx 32 | mov cx, 200h 33 | cld 34 | - rep movsd 35 | + fs rep movsd 36 | retn 37 | 38 | 39 | @@ -15052,9 +15052,9 @@ 40 | mov di, buffer_1DB6C 41 | mov dx, di 42 | cld 43 | - movsd 44 | - movsd 45 | - movsd 46 | + fs movsd 47 | + fs movsd 48 | + fs movsd 49 | mov byte [di], 0 50 | cmp byte [fs:2], 0 51 | jz short loc_194EB 52 | @@ -17813,7 +17813,7 @@ 53 | mov si, bx 54 | mov cx, 8 55 | cld 56 | - rep movsd 57 | + fs rep movsd 58 | test byte [fs:bx+3Ch], 1 59 | jnz short loc_1AC35 60 | mov si, unk_1D6C3 61 | -------------------------------------------------------------------------------- /asmTests/xor.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _DATA ends ;IGNORE 5 | 6 | _TEXT segment use16 word public 'CODE' ;IGNORE 7 | assume cs:_TEXT,ds:_DATA 8 | ;start proc near 9 | false_start: 10 | jmp failure 11 | 12 | start: 13 | mov eax,2 14 | xor eax,eax 15 | jnz failure 16 | 17 | mov eax,511 18 | mov ebx,255 19 | xor eax,ebx 20 | jz failure 21 | 22 | mov eax,511 23 | mov ebx,255 24 | xor ax,bx 25 | jz failure 26 | 27 | mov eax,511 28 | mov ebx,255 29 | xor al,bl 30 | jnz failure 31 | 32 | cmp eax,256 33 | jne failure 34 | 35 | mov ecx,0f0ffh 36 | mov ebx,00fffh 37 | 38 | xor ch,bh 39 | cmp ecx,0ffffh 40 | jne failure 41 | 42 | mov ecx,0df01h 43 | or cl,0f0h 44 | cmp ecx,0dff1h 45 | jne failure 46 | 47 | mov eax,1 48 | or eax,eax 49 | jz failure 50 | 51 | mov eax,0 52 | or eax,eax 53 | jnz failure 54 | 55 | xor eax,eax 56 | JMP exitLabel 57 | failure: 58 | mov al,1 59 | exitLabel: 60 | mov ah,4ch ; AH=4Ch - Exit To DOS 61 | int 21h 62 | ;start endp 63 | 64 | _TEXT ends ;IGNORE 65 | 66 | stackseg segment para stack 'STACK' ;IGNORE 67 | db 1000h dup(?) 68 | stackseg ends ;IGNORE 69 | 70 | end start ;IGNORE 71 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | AUTODOCDIR = api 11 | 12 | # User-friendly check for sphinx-build 13 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $?), 1) 14 | $(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/") 15 | endif 16 | 17 | .PHONY: help clean Makefile 18 | 19 | # Put it first so that "make" without argument is like "make help". 20 | help: 21 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 22 | 23 | clean: 24 | rm -rf $(BUILDDIR)/* $(AUTODOCDIR) 25 | 26 | # Catch-all target: route all unknown targets to Sphinx using the new 27 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 28 | %: Makefile 29 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 30 | -------------------------------------------------------------------------------- /asmTests/pushpop.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _DATA ends ;IGNORE 5 | 6 | _TEXT segment use16 word public 'CODE' ;IGNORE 7 | assume cs:_TEXT,ds:_DATA 8 | 9 | start proc near 10 | 11 | mov ebx,2 12 | push ebx 13 | pop eax 14 | cmp eax,2 15 | jne failure 16 | cmp ebx,2 17 | jne failure 18 | 19 | mov eax,1 20 | mov ebx,2 21 | mov ecx,3 22 | mov edx,4 23 | mov esi,6 24 | mov edi,8 25 | mov ebp,9 26 | 27 | pushad 28 | 29 | xor eax,eax 30 | xor ecx,ecx 31 | xor ebx,ebx 32 | xor edx,edx 33 | xor esi,esi 34 | xor edi,edi 35 | xor ebp,ebp 36 | 37 | cmp esi,0 38 | jne failure 39 | cmp edi,0 40 | jne failure 41 | 42 | popad 43 | 44 | ;push eax ebp ebx 45 | ;pOp ebx ebp eax 46 | 47 | cmp ebp,9 48 | jne failure 49 | 50 | 51 | xor ecx,ecx 52 | mov ecx,0a0000h 53 | mov ebx,0f222h 54 | ;push bx fs 55 | ;pop fs cx 56 | cmp ecx,0af222h 57 | ;jne exitLabel 58 | 59 | MOV al,0 60 | JMP exitLabel 61 | failure: 62 | mov al,1 63 | exitLabel: 64 | mov ah,4ch ; AH=4Ch - Exit To DOS 65 | int 21h 66 | start endp 67 | 68 | _TEXT ends ;IGNORE 69 | 70 | stackseg segment para stack 'STACK' ;IGNORE 71 | db 1000h dup(?) 72 | stackseg ends ;IGNORE 73 | 74 | end start ;IGNORE 75 | 76 | -------------------------------------------------------------------------------- /asm_emu/x86_test.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_testl(struct assembler_state_t *state, uint32_t src1, uint32_t src2) 6 | { 7 | uint32_t tmp = src1 & src2; 8 | 9 | write_zf(state->eflags, !tmp); 10 | write_sf(state->eflags, tmp & 0x80000000); 11 | 12 | write_of(state->eflags, 0); 13 | write_cf(state->eflags, 0); 14 | #ifdef X86_PF 15 | asm_update_pf(state->eflags, tmp); 16 | #endif 17 | /* LEAVE AF alone */ 18 | } 19 | static inline void asm_testw(struct assembler_state_t *state, uint16_t src1, uint16_t src2) 20 | { 21 | uint16_t tmp = src1 & src2; 22 | 23 | write_zf(state->eflags, !tmp); 24 | write_sf(state->eflags, tmp & 0x8000); 25 | 26 | write_of(state->eflags, 0); 27 | write_cf(state->eflags, 0); 28 | #ifdef X86_PF 29 | asm_update_pf(state->eflags, tmp); 30 | #endif 31 | /* LEAVE AF alone */ 32 | } 33 | static inline void asm_testb(struct assembler_state_t *state, uint8_t src1, uint8_t src2) 34 | { 35 | uint8_t tmp = src1 & src2; 36 | 37 | write_zf(state->eflags, !tmp); 38 | write_sf(state->eflags, tmp & 0x80); 39 | 40 | write_of(state->eflags, 0); 41 | write_cf(state->eflags, 0); 42 | #ifdef X86_PF 43 | asm_update_pf(state->eflags, tmp); 44 | #endif 45 | /* LEAVE AF alone */ 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /outdated/iprintf.asm: -------------------------------------------------------------------------------- 1 | ; printf1.asm call printf by replacing real stack with emulated stack 2 | ; Assemble: nasm -f coff -g -l iprintf.lst iprintf.asm 3 | ; uasm64 -coff -Fl iprintf.asm 4 | ; Link: gcc -o printf1 printf1.o 5 | ; Run: printf1 6 | ; Output: a=5, eax=7 7 | 8 | ; Equivalent C code 9 | ; /* printf1.c print an int and an expression */ 10 | ; #include 11 | ; int main() 12 | ; { 13 | ; int a=5; 14 | ; printf("a=%d, eax=%d\n", a, a+2); 15 | ; return 0; 16 | ; } 17 | 18 | ; Declare some external functions 19 | ; 20 | .386 21 | EXTRN _printf:dword ; the C function, to be called 22 | 23 | ; SECTION .text ; Code section. 24 | 25 | public _iiprintf ; the standard gcc entry point 26 | ;extern stackPointer 27 | code segment use32 28 | _iiprintf proc ; the program label for the entry point 29 | push ebp ; set up stack frame 30 | mov ebp,esp 31 | 32 | mov esp, [ebp+8] 33 | add esp, 4 34 | call _printf ; Call C function 35 | 36 | mov eax,esp 37 | 38 | mov esp, ebp ; takedown stack frame 39 | pop ebp ; same as "leave" op 40 | 41 | ; mov eax,0 ; normal, no error, return value 42 | ret ; return 43 | _iiprintf endp 44 | code ends 45 | end 46 | -------------------------------------------------------------------------------- /asmTests/dataoff.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 2,5,6 5 | var2 dw 4,6,9 6 | var3 dd 11,-11,2,4 7 | _DATA ends ;IGNORE 8 | 9 | _TEXT segment use16 word public 'CODE' ;IGNORE 10 | assume cs:_TEXT,ds:_DATA 11 | 12 | start proc near 13 | 14 | MOV ax, _data 15 | MOV ds, ax 16 | 17 | MOV al,1 18 | mov edi,offset var1 19 | mov dl,byte ptr [edi] 20 | cmp dl,2 21 | jne failure 22 | 23 | MOV al,2 24 | mov cl,2 25 | mov ds:[edi],cl 26 | mov dl,byte ptr [edi] 27 | cmp dl,2 28 | jne failure 29 | 30 | MOV al,3 31 | mov edi,offset var1 32 | mov dl,[edi+1] 33 | cmp dl,5 34 | jne failure 35 | 36 | MOV al,4 37 | inc byte ptr [edi+1] 38 | cmp byte ptr [edi+1],6 39 | jne failure 40 | 41 | 42 | MOV al,5 43 | mov edi,offset var2 44 | mov dl,[edi] 45 | cmp dl,4 46 | jne failure 47 | 48 | MOV al,6 49 | lea esi,var2 50 | cmp edi,esi 51 | jne failure 52 | 53 | MOV al,0 54 | 55 | JMP exitLabel 56 | failure: 57 | ;mov al,1 58 | exitLabel: 59 | mov ah,4ch ; AH=4Ch - Exit To DOS 60 | int 21h ; DOS INT 21h 61 | start endp 62 | 63 | _TEXT ends ;IGNORE 64 | 65 | stackseg segment para stack 'STACK' ;IGNORE 66 | db 1000h dup(?) 67 | stackseg ends ;IGNORE 68 | 69 | end start ;IGNORE 70 | -------------------------------------------------------------------------------- /asm_emu/x86_div.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_divl(struct assembler_state_t *state, const uint32_t src) 6 | { 7 | if (src <= state->edx) 8 | { 9 | fprintf(stderr, "#DE exception occured here (0x%08x%08x / 0x%08x )\n", state->edx, state->eax, src); 10 | state->edx = 0xffffffff; 11 | state->eax = 0; 12 | 13 | } else { 14 | uint64_t temp1 = ((uint64_t)state->edx << 32) | (state->eax); 15 | uint32_t temp2 = temp1 / src; 16 | state->edx = temp1 % src; 17 | state->eax = temp2; 18 | } 19 | } 20 | static inline void asm_divw(struct assembler_state_t *state, const uint16_t src) 21 | { 22 | if (src <= state->dx) 23 | { 24 | fprintf(stderr, "#DE exception occured here\n"); 25 | state->edx = 0xffff; 26 | state->eax = 0; 27 | 28 | } else { 29 | uint32_t temp1 = ((uint32_t)state->dx << 16) | (state->ax); 30 | uint16_t temp2 = temp1 / src; 31 | state->dx = temp1 % src; 32 | state->ax = temp2; 33 | } 34 | } 35 | static inline void asm_divb(struct assembler_state_t *state, const uint8_t src) 36 | { 37 | if (src <= state->ah) 38 | { 39 | fprintf(stderr, "#DE exception occured here\n"); 40 | state->edx = 0xff; 41 | state->eax = 0; 42 | 43 | } else { 44 | uint32_t temp2 = state->ax / src; 45 | state->ah = state->ax % src; 46 | state->al = temp2; 47 | } 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python application 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Set up Python 3.10 23 | uses: actions/setup-python@v3 24 | with: 25 | python-version: "3.10" 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | pip install flake8 pytest coverage mock 30 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 31 | # - name: Lint with flake8 32 | # run: | 33 | # stop the build if there are Python syntax errors or undefined names 34 | # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 35 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 36 | # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 37 | - name: Test with pytest 38 | run: | 39 | pytest 40 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.2.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "masm2c" 7 | version = "0.9.8" 8 | description = "Masm2c is a 16-bit assembly to C++ translator" 9 | authors = [ 10 | {name = "xor2003", email = "xor2003@gmx.com"}, 11 | ] 12 | dependencies = [ 13 | "jsonpickle>=3.4.2", 14 | "lark>=1.2.2", 15 | ] 16 | requires-python = ">=3.9" 17 | readme = "README.md" 18 | license = {text = "GPL"} 19 | keywords = ["masm", "assembly", "reverse engineering"] 20 | classifiers = [ 21 | "Development Status :: 4 - Beta", 22 | "Intended Audience :: Developers", 23 | "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", 24 | "Programming Language :: Python :: 3", 25 | "Programming Language :: Python :: 3.10", 26 | "Programming Language :: Python :: 3.11", 27 | "Programming Language :: Python :: 3.12", 28 | "Programming Language :: Python :: 3.9", 29 | "Programming Language :: Assembly", 30 | "Programming Language :: C++", 31 | "Operating System :: OS Independent" 32 | ] 33 | 34 | [project.optional-dependencies] 35 | dev = [ 36 | "coverage>=7.6.4", 37 | "mock>=5.1.0", 38 | "pytest>=8.3.3", 39 | ] 40 | 41 | [project.urls] 42 | Homepage = "https://github.com/xor2003/masm2c" 43 | 44 | [project.scripts] 45 | masm2c = "masm2c.cli:main" 46 | 47 | -------------------------------------------------------------------------------- /asmTests/shlshr.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 2,5,6 5 | var2 dw 4,6,9 6 | var3 dd 11,-11,2,4 7 | var4 db 100 dup (1) 8 | _DATA ends ;IGNORE 9 | 10 | _TEXT segment use16 word public 'CODE' ;IGNORE 11 | assume cs:_TEXT,ds:_DATA 12 | start proc near 13 | 14 | 15 | mov eax,10B 16 | cmp eax,2 17 | jne failure 18 | 19 | SHR eax,1 20 | cmp eax,1 21 | jne failure 22 | 23 | mov ebx,0ffffffffh 24 | mov bl,011111111B 25 | SHR bl,1 26 | 27 | cmp bl,001111111B 28 | jne failure 29 | 30 | mov ecx,0ffffffffh 31 | mov ch,011111111B 32 | SHR ch,1 33 | cmp ch,001111111B 34 | jne failure 35 | 36 | SHL ch,2 37 | cmp ch,011111100B 38 | jne failure 39 | 40 | mov eax,4 41 | sar eax,1 42 | cmp eax,2 43 | jne failure 44 | 45 | mov eax,-4 46 | sar eax,1 47 | cmp eax,-2 48 | jne failure 49 | 50 | mov eax,-8 51 | sar eax,2 52 | cmp eax,-2 53 | jne failure 54 | 55 | mov edx,0abcdef77h 56 | mov eax,012345678h 57 | shrd eax, edx, 8 58 | cmp eax,077123456h 59 | jne failure 60 | cmp edx,0abcdef77h 61 | jne failure 62 | 63 | 64 | MOV al,0 65 | JMP exitLabel 66 | failure: 67 | mov al,1 68 | exitLabel: 69 | mov ah,4ch ; AH=4Ch - Exit To DOS 70 | int 21h 71 | start endp 72 | 73 | _TEXT ends ;IGNORE 74 | 75 | stackseg segment para stack 'STACK' ;IGNORE 76 | db 1000h dup(?) 77 | stackseg ends ;IGNORE 78 | 79 | end start ;IGNORE 80 | -------------------------------------------------------------------------------- /asmTests/addsub.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 2,5,6 5 | var2 dw 4,6,9 6 | var3 dd 11,-11,2,4 7 | var4 db 100 dup (1) 8 | var5 dd 10 dup (?) 9 | 10 | _DATA ends ;IGNORE 11 | 12 | _TEXT segment use16 word public 'CODE' ;IGNORE 13 | assume cs:_TEXT,ds:_DATA 14 | start: 15 | 16 | add word ptr [var5+2],50 17 | cmp word ptr [var5+2],50 18 | jne failure 19 | 20 | sub word ptr [var5+2],25 21 | cmp word ptr [var5+2],25 22 | jne failure 23 | 24 | cmp word ptr var5,0 25 | jne failure 26 | 27 | ;sub word ptr [liste_bombe+ebp+4+5*4+xy_adder],ou 28 | 29 | mov eax,3 30 | mov ebx,2 31 | sub ebx,eax 32 | JA failure 33 | 34 | mov eax,2 35 | mov ebx,3 36 | sub ebx,eax 37 | JB failure 38 | cmp ebx,1 39 | jne failure 40 | 41 | cmp ebx,2 42 | JA failure 43 | cmp ebx,0 44 | JB failure 45 | cmp ebx,1 46 | JB failure 47 | JA failure 48 | 49 | mov eax,-1b-(-2h+3o) 50 | cmp eax,-2 51 | jne failure 52 | 53 | mov ebx,2 54 | cmp eax,ebx 55 | jb failure 56 | 57 | mov dl,'c' 58 | sub dl,'a' 59 | cmp dl,2 60 | jne failure 61 | 62 | xor edi,edi 63 | add edi,14*320 64 | 65 | MOV al,0 66 | JMP exitLabel 67 | failure: 68 | mov al,1 69 | exitLabel: 70 | mov ah,4ch ; AH=4Ch - Exit To DOS 71 | int 21h 72 | 73 | 74 | _TEXT ends ;IGNORE 75 | 76 | stackseg segment para stack 'STACK' ;IGNORE 77 | db 1000h dup(?) 78 | stackseg ends ;IGNORE 79 | 80 | end start ;IGNORE 81 | -------------------------------------------------------------------------------- /asm_emu/x86_neg.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_negl(struct assembler_state_t *state, uint32_t *dst) 6 | { 7 | uint32_t tmp = 0 - *dst; 8 | 9 | write_of(state->eflags, tmp > *dst); 10 | write_sf(state->eflags, tmp & 0x80000000); 11 | write_zf(state->eflags, !tmp); 12 | write_cf(state->eflags, !*dst); 13 | #ifdef X86_PF 14 | asm_update_pf(state->eflags, tmp); 15 | #endif 16 | #ifdef X86_AF 17 | asm_update_af(state->eflags, tmp, *dst); 18 | #endif 19 | 20 | *dst = tmp; 21 | } 22 | static inline void asm_negw(struct assembler_state_t *state, uint16_t *dst) 23 | { 24 | uint16_t tmp = 0 - *dst; 25 | 26 | write_of(state->eflags, tmp > *dst); 27 | write_sf(state->eflags, tmp & 0x8000); 28 | write_zf(state->eflags, !tmp); 29 | write_cf(state->eflags, !*dst); 30 | #ifdef X86_PF 31 | asm_update_pf(state->eflags, tmp); 32 | #endif 33 | #ifdef X86_AF 34 | asm_update_af(state->eflags, tmp, *dst); 35 | #endif 36 | 37 | *dst = tmp; 38 | } 39 | static inline void asm_negb(struct assembler_state_t *state, uint8_t *dst) 40 | { 41 | uint8_t tmp = 0 - *dst; 42 | 43 | write_of(state->eflags, tmp > *dst); 44 | write_sf(state->eflags, tmp & 0x80); 45 | write_zf(state->eflags, !tmp); 46 | write_cf(state->eflags, !*dst); 47 | #ifdef X86_PF 48 | asm_update_pf(state->eflags, tmp); 49 | #endif 50 | #ifdef X86_AF 51 | asm_updae_af(state->eflags, tmp, *dst); 52 | #endif 53 | 54 | *dst = tmp; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /asmTests/proc.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _DATA ends ;IGNORE 5 | 6 | _TEXT segment use16 word public 'CODE' ;IGNORE 7 | assume cs:_TEXT,ds:_DATA 8 | start proc near 9 | 10 | xor eax,eax 11 | xor edx,edx 12 | xor ebx,ebx 13 | xor ecx,ecx 14 | 15 | inc ebx 16 | call incebx 17 | inc ecx 18 | inc ecx 19 | call aincecx 20 | 21 | mov al,1 22 | cmp edx,1 23 | jne failure 24 | 25 | mov al,2 26 | cmp ecx,3 27 | jne failure 28 | 29 | mov al,3 30 | cmp ebx,3 31 | jne failure 32 | 33 | mov al,4 34 | call [aaofs] 35 | cmp ebx,4 36 | jne failure 37 | 38 | 39 | mov al,0 40 | JMP exitLabel 41 | ;mov edx,offset exitLabel 42 | 43 | MOV al,0 44 | JMP exitLabel 45 | failure: 46 | ;mov al,1 47 | exitLabel: 48 | mov ah,4ch ; AH=4Ch - Exit To DOS 49 | int 21h 50 | start endp 51 | 52 | incebx proc near 53 | inc ebx 54 | cmp ebx,TWO 55 | je ok 56 | ret 57 | ok: 58 | inc ebx 59 | ret 60 | inceBX endp 61 | 62 | aincecx proc near 63 | inc ecx 64 | call aincedx 65 | tWO equ 2 66 | ret 67 | aincecx endp 68 | 69 | aincedx proc near 70 | inc edx 71 | ret 72 | aincedx endp 73 | 74 | aa proc near 75 | mov ebx,555 76 | aa endp 77 | 78 | bb proc near 79 | mov ebx,4 80 | ret 81 | bb endp 82 | 83 | aaofs dw offset aa 84 | 85 | _TEXT ends ;IGNORE 86 | 87 | stackseg segment para stack 'STACK' ;IGNORE 88 | db 1000h dup(?) ;IGNORE 89 | stackseg ends ;IGNORE 90 | 91 | end start ;IGNORE 92 | -------------------------------------------------------------------------------- /asmTests/build_mingw.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | #export OPT="-mno-ms-bitfields -Wno-multichar -I/MinGW/include/ -L/MinGW/lib -I../ -L../ ../pdcurses.a -lmingw32 -lSDL2main -lSDL2 -ggdb" 4 | #export OPT="-Og -m32 -mno-ms-bitfields -Wno-multichar -Wno-narrowing -I../ -L../ -I/mingw32/include/pdcurses -L/mingw32/lib -I. -L. -ggdb3 -lSDL -lSDLmain" 5 | #export OPT="-Og -mno-ms-bitfields -Wno-multichar -Wno-address-of-packed-member -I. -I.. -L. -lmingw32 -mconsole -ggdb3 -lSDL -lSDLmain -DDEBUG=3" 6 | 7 | #export PKG_CONFIG_PATH=/c/msys64/mingw32/lib/pkgconfig 8 | export CXX="g++" 9 | #SDL=$(pkg-config --cflags --libs sdl) 10 | SDL="-DNOSDL" 11 | #SDL="-D_GNU_SOURCE=1 -Dmain=SDL_main -I/mingw/include/SDL -L/mingw/lib -lmingw32 -lSDLmain -lSDL -lmingw32 -lSDLmain -lSDL -lm -luser32 -lgdi32 -lwinmm -ldxguid" 12 | CURSES="-I/mingw/include/pdcurses -L/mingw/lib " 13 | export OPT="-m32 -Wno-narrowing -mno-ms-bitfields -Wno-multichar $SDL $CURSES -D_GNU_SOURCE=1 -ggdb3 -O0 -I. -I.. -DDEBUG=3" 14 | #-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DCHTYPE_16 15 | #echo $OPT 16 | 17 | #pkg-config --cflags --libs ncurses 18 | # -mconsole -DSDL_MAIN_HANDLED 19 | # -DDEBUG=3 20 | #export CC="/Mingw/bin/g++" 21 | 22 | #cd .. 23 | #$CC $OPT asm.cpp -c 24 | #$CC $OPT memmgr.cpp -c 25 | #cd asmTests 26 | 27 | #$CC $OPT $1.cpp -E >$1.e 28 | $CXX $OPT $1.cpp -c 29 | $CXX $OPT data.cpp -c 30 | #$CXX data.o $1.o ../asm.o ../memmgr.o /MinGW/lib/pdcurses.a -o $1 $OPT 31 | $CXX data.o $1.o ../asm.o ../memmgr.o C:\\MinGW\\lib\\pdcurses.a -o $1 $OPT 32 | 33 | 34 | -------------------------------------------------------------------------------- /masm2c/Macro.py: -------------------------------------------------------------------------------- 1 | """ 2 | Deals with macro definitions and expansions. 3 | The Macro class stores information about each macro and its parameters. 4 | """ 5 | from masm2c.op import baseop 6 | 7 | 8 | # Masm2c S2S translator (initially based on SCUMMVM tasmrecover) 9 | # 10 | # Masm2c is the legal property of its developers, whose names 11 | # are too numerous to list here. Please refer to the COPYRIGHT 12 | # file distributed with this source distribution. 13 | # 14 | # This program is free software; you can redistribute it and/or 15 | # modify it under the terms of the GNU General Public License 16 | # as published by the Free Software Foundation; either version 2 17 | # of the License, or (at your option) any later version. 18 | # 19 | # This program is distributed in the hope that it will be useful, 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | # GNU General Public License for more details. 23 | # 24 | # You should have received a copy of the GNU General Public License 25 | # along with this program; if not, write to the Free Software 26 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 27 | # 28 | 29 | class Macro: 30 | def __init__(self, name, parameters, repeat=1) -> None: 31 | self.__name = name 32 | self.__parameters = parameters 33 | self.instructions: list[baseop] = [] 34 | self.__repeat = repeat 35 | 36 | def getparameters(self): 37 | return self.__parameters 38 | -------------------------------------------------------------------------------- /examples/_ida_to_tasm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh +x 2 | echo Ideal > iplay_tasm.asm 3 | TOREMOVE='useless|gravis|wss|proaud|sbpro|sb' 4 | #TOREMOVE='useless|mouse|midi|stereo|covox|adlib|wss|pcspeaker|proaud|sbpro|sb|gravis|inr|far|ult|psm|_669|e669' 5 | 6 | cat IPLAY.asm | grep -vw "nop\|xchg bx, bx\|Ideal\|p286n\|intel_syntax\|align [248]" | \ 7 | #cat IPLAY.asm | grep -vw "Ideal\|p286n\|intel_syntax" | \ 8 | perl -pe 's!seg dseg!dseg!; s!,\s+seg\s+!, !;s! seg ! !;s!argc\s*=\s*word\s+ptr!_argc = word ptr!;s!argv\s*=\s*dword\s+ptr!_argv = dword ptr!; s!\[(bp+[^\[]*)(var|arg)(_[0-9A-F]+)([^\]]*)\]!\[ss:($1$2$3$4)\]!;s!\[((dword|word|byte) ptr bp+[^\[]*)(var|arg)(_[0-9A-F]+)([^\]]*)\]!\[ss:($1$3$4$5)\]!' \ 9 | | grep -vP "call\s+(useless|gravis_)|dw offset (${TOREMOVE})_|jnz\s+short gravis_13A6A" \ 10 | | perl -pe "BEGIN{undef $/;} s/proc\s+(${TOREMOVE})_.*?(endp)\s+(${TOREMOVE})_[_A-Za-z0-9]+//smg" \ 11 | | perl -pe 's!jmp\s+\[snd_([a-z]+)_offs\+bx\]!jmp sb16_$1!; s!\[sndcards_text_tbl\+si\]!offset sb16_txt!;' \ 12 | >> iplay_tasm.asm 13 | #| grep -vP "call\s+(useless|gravis_|mouse_)|dw offset (${TOREMOVE})_|jnz\s+short gravis_13A6A" \ 14 | #| perl -pe "BEGIN{undef $/;} s/(midi_init:).*?(retn)//smg" \ 15 | #| perl -pe "BEGIN{undef $/;} s!(dw offset mod_mk_module?)!off_25326 dw offset mod_mk_module!" \ 16 | 17 | 18 | 19 | #cat iplay.asm | perl -pe 's!short !!;s! near!!;s!ret[nf]!retcode!;s!call !call proc !' > iplay_tasm.asm 20 | #cat iplay.asm | perl -pe 's!short !!;s!__dosretax near!__dosretax far!;s!_abs near!_abs far!' > iplay_tasm.asm 21 | 22 | #/cygdrive/c/Program\ Files/DOSBox-0.74/DOSBox.exe V.BAT 23 | ./build_tasm.bat 24 | -------------------------------------------------------------------------------- /shadowstack.h: -------------------------------------------------------------------------------- 1 | class _STATE; 2 | 3 | class ShadowStack { 4 | struct Frame { 5 | bool init=false; 6 | const char *file; 7 | size_t line; 8 | dd sp; 9 | dw cs; 10 | dd ip; 11 | dd value; 12 | dw *pointer_; 13 | size_t addcounter; 14 | size_t remcounter; 15 | bool itwascall; 16 | size_t call_deep; 17 | }; 18 | 19 | std::vector m_ss; 20 | size_t m_current=0; 21 | bool m_itiscall=false; 22 | bool m_itisret=false; 23 | size_t m_deep=1; 24 | public: 25 | ShadowStack() : m_ss(0x10000) 26 | {} 27 | 28 | int m_needtoskipcall=0; 29 | bool m_active=true; 30 | bool m_forceactive=false; 31 | 32 | size_t m_currentdeep=0; 33 | 34 | void enable() {m_active=true;} 35 | void disable() {m_active=false;} 36 | void forceenable() {m_forceactive=true;} 37 | void forcedisable() {m_forceactive=false;} 38 | 39 | void push(_STATE *_state, dd value); 40 | 41 | void pop(_STATE *_state); 42 | 43 | void print(_STATE *_state); 44 | void print_frame(const Frame& f); 45 | 46 | void itiscall() {m_itiscall=true;} 47 | void itisret() {m_itisret=true;} 48 | bool itwascall(_STATE* _state); 49 | 50 | void decreasedeep(); 51 | bool needtoskipcalls(); 52 | size_t getneedtoskipcallndclean(){int ret = m_needtoskipcall; m_needtoskipcall = 0; return ret;} 53 | void noneedreturn(){--m_needtoskipcall;} 54 | }; 55 | 56 | -------------------------------------------------------------------------------- /asm_emu/x86_shr.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_shrl(struct assembler_state_t *state, uint8_t count, uint32_t *dst) 6 | { 7 | count = count & 0x0000001f; 8 | int of = *dst&0x80000000; 9 | 10 | if (count) 11 | { 12 | write_cf(state->eflags, *dst & 1<<(count-1)); 13 | *dst>>=count; 14 | } 15 | 16 | if (count==1) 17 | write_of(state->eflags, of); 18 | 19 | write_sf(state->eflags, *dst & 0x80000000); 20 | write_zf(state->eflags, !*dst); 21 | #ifdef X86_PF 22 | asm_update_pf(state->eflags, *dst); 23 | #endif 24 | } 25 | static inline void asm_shrw(struct assembler_state_t *state, uint8_t count, uint16_t *dst) 26 | { 27 | count = count & 0x0000001f; 28 | int of = *dst&0x8000; 29 | 30 | if (count) 31 | { 32 | write_cf(state->eflags, *dst & 1<<(count-1)); 33 | *dst>>=count; 34 | } 35 | 36 | if (count==1) 37 | write_of(state->eflags, of); 38 | 39 | write_sf(state->eflags, *dst & 0x80000000); 40 | write_zf(state->eflags, !*dst); 41 | #ifdef X86_PF 42 | asm_update_pf(state->eflags, *dst); 43 | #endif 44 | } 45 | static inline void asm_shrb(struct assembler_state_t *state, uint8_t count, uint8_t *dst) 46 | { 47 | count = count & 0x0000001f; 48 | int of = *dst&0x80; 49 | 50 | if (count) 51 | { 52 | write_cf(state->eflags, *dst & 1<<(count-1)); 53 | *dst>>=count; 54 | } 55 | 56 | if (count==1) 57 | write_of(state->eflags, of); 58 | 59 | write_cf(state->eflags, 0); 60 | write_sf(state->eflags, *dst & 0x80); 61 | write_zf(state->eflags, !*dst); 62 | #ifdef X86_PF 63 | asm_update_pf(state->eflags, *dst); 64 | #endif 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /qemu_tests/test-i386-code16.S: -------------------------------------------------------------------------------- 1 | .code16 2 | .globl code16_start 3 | .globl code16_end 4 | 5 | CS_SEG = 0xf 6 | 7 | code16_start: 8 | 9 | .globl code16_func1 10 | 11 | /* basic test */ 12 | code16_func1 = . - code16_start 13 | mov $1, %eax 14 | data32 lret 15 | 16 | /* test push/pop in 16 bit mode */ 17 | .globl code16_func2 18 | code16_func2 = . - code16_start 19 | xor %eax, %eax 20 | mov $0x12345678, %ebx 21 | movl %esp, %ecx 22 | push %bx 23 | subl %esp, %ecx 24 | pop %ax 25 | data32 lret 26 | 27 | /* test various jmp opcodes */ 28 | .globl code16_func3 29 | code16_func3 = . - code16_start 30 | jmp 1f 31 | nop 32 | 1: 33 | mov $4, %eax 34 | mov $0x12345678, %ebx 35 | xor %bx, %bx 36 | jz 2f 37 | add $2, %ax 38 | 2: 39 | 40 | call myfunc 41 | 42 | lcall $CS_SEG, $(myfunc2 - code16_start) 43 | 44 | ljmp $CS_SEG, $(myjmp1 - code16_start) 45 | myjmp1_next: 46 | 47 | cs lcall *myfunc2_addr - code16_start 48 | 49 | cs ljmp *myjmp2_addr - code16_start 50 | myjmp2_next: 51 | 52 | data32 lret 53 | 54 | myfunc2_addr: 55 | .short myfunc2 - code16_start 56 | .short CS_SEG 57 | 58 | myjmp2_addr: 59 | .short myjmp2 - code16_start 60 | .short CS_SEG 61 | 62 | myjmp1: 63 | add $8, %ax 64 | jmp myjmp1_next 65 | 66 | myjmp2: 67 | add $16, %ax 68 | jmp myjmp2_next 69 | 70 | myfunc: 71 | add $1, %ax 72 | ret 73 | 74 | myfunc2: 75 | add $4, %ax 76 | lret 77 | 78 | 79 | code16_end: 80 | -------------------------------------------------------------------------------- /asm_emu/x86_dec.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_decl(struct assembler_state_t *state, uint32_t *dst) 6 | { 7 | uint32_t tmp = *dst - 1; 8 | 9 | if ((*dst & 0x80000000) != 0) 10 | write_of(state->eflags, 0 == (tmp & 0x80000000)); /* signed overflow */ 11 | else 12 | write_of(state->eflags, 0); 13 | 14 | write_sf(state->eflags, tmp & 0x80000000); 15 | write_zf(state->eflags, !tmp); 16 | #ifdef X86_PF 17 | asm_update_pf(state->eflags, tmp); 18 | #endif 19 | #ifdef X86_AF 20 | asm_updae_af(state->eflags, tmp, *dst); 21 | #endif 22 | 23 | *dst = tmp; 24 | } 25 | static inline void asm_decw(struct assembler_state_t *state, uint16_t *dst) 26 | { 27 | uint16_t tmp = *dst - 1; 28 | 29 | if ((*dst & 0x8000) != 0) 30 | write_of(state->eflags, 0 == (tmp & 0x8000)); /* signed overflow */ 31 | else 32 | write_of(state->eflags, 0); 33 | 34 | write_sf(state->eflags, tmp & 0x8000); 35 | write_zf(state->eflags, !tmp); 36 | #ifdef X86_PF 37 | asm_update_pf(state->eflags, tmp); 38 | #endif 39 | #ifdef X86_AF 40 | asm_update_af(state->eflags, tmp, *dst); 41 | #endif 42 | 43 | *dst = tmp; 44 | } 45 | static inline void asm_decb(struct assembler_state_t *state, uint8_t *dst) 46 | { 47 | uint8_t tmp = *dst - 1; 48 | 49 | if ((*dst & 0x80) != 0) 50 | write_of(state->eflags, 0 == (tmp & 0x80)); /* signed overflow */ 51 | else 52 | write_of(state->eflags, 0); 53 | 54 | write_sf(state->eflags, tmp & 0x80); 55 | write_zf(state->eflags, !tmp); 56 | #ifdef X86_PF 57 | asm_update_pf(state->eflags, tmp); 58 | #endif 59 | #ifdef X86_AF 60 | asm_update_af(state->eflags, tmp, *dst); 61 | #endif 62 | 63 | *dst = tmp; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /asm_emu/x86_inc.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_incl(struct assembler_state_t *state, uint32_t *dst) 6 | { 7 | uint32_t tmp = *dst + 1; 8 | 9 | if ((*dst & 0x80000000) == 0) 10 | write_of(state->eflags, 0 != (tmp & 0x80000000)); /* signed overflow */ 11 | else 12 | write_of(state->eflags, 0); 13 | 14 | write_sf(state->eflags, tmp & 0x80000000); 15 | write_zf(state->eflags, !tmp); 16 | #ifdef X86_PF 17 | asm_update_pf(state->eflags, tmp); 18 | #endif 19 | #ifdef X86_AF 20 | asm_updae_af(state->eflags, tmp, *dst); 21 | #endif 22 | 23 | *dst = tmp; 24 | } 25 | static inline void asm_incw(struct assembler_state_t *state, uint16_t *dst) 26 | { 27 | uint16_t tmp = *dst + 1; 28 | 29 | if ((*dst & 0x8000) == 0) 30 | write_of(state->eflags, 0 != (tmp & 0x8000)); /* signed overflow */ 31 | else 32 | write_of(state->eflags, 0); 33 | 34 | write_sf(state->eflags, tmp & 0x8000); 35 | write_zf(state->eflags, !tmp); 36 | #ifdef X86_PF 37 | asm_update_pf(state->eflags, tmp); 38 | #endif 39 | #ifdef X86_AF 40 | asm_update_af(state->eflags, tmp, *dst); 41 | #endif 42 | 43 | *dst = tmp; 44 | } 45 | static inline void asm_incb(struct assembler_state_t *state, uint8_t *dst) 46 | { 47 | uint8_t tmp = *dst + 1; 48 | 49 | if ((*dst & 0x80) == 0) 50 | write_of(state->eflags, 0 != (tmp & 0x80)); /* signed overflow */ 51 | else 52 | write_of(state->eflags, 0); 53 | 54 | write_sf(state->eflags, tmp & 0x80); 55 | write_zf(state->eflags, !tmp); 56 | #ifdef X86_PF 57 | asm_update_pf(state->eflags, tmp); 58 | #endif 59 | #ifdef X86_AF 60 | asm_update_af(state->eflags, tmp, *dst); 61 | #endif 62 | 63 | *dst = tmp; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /asm_emu/x86_stos.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_stosb(struct assembler_state_t *state) 6 | { 7 | x86_write_memory(state, state->es, state->edi, 1, state->al); 8 | if (read_df(state->eflags)) 9 | state->edi--; 10 | else 11 | state->edi++; 12 | } 13 | static inline void asm_stosw(struct assembler_state_t *state) 14 | { 15 | x86_write_memory(state, state->es, state->edi, 2, state->ax); 16 | if (read_df(state->eflags)) 17 | state->edi-=2; 18 | else 19 | state->edi+=2; 20 | } 21 | static inline void asm_stosl(struct assembler_state_t *state) 22 | { 23 | x86_write_memory(state, state->es, state->edi, 4, state->eax); 24 | if (read_df(state->eflags)) 25 | state->edi-=4; 26 | else 27 | state->edi+=4; 28 | } 29 | 30 | static inline void asm_rep_stosb(struct assembler_state_t *state) 31 | { 32 | while (state->ecx) 33 | { 34 | x86_write_memory(state, state->es, state->edi, 1, state->al); 35 | if (read_df(state->eflags)) 36 | state->edi--; 37 | else 38 | state->edi++; 39 | 40 | state->ecx--; 41 | } 42 | } 43 | static inline void asm_rep_stosw(struct assembler_state_t *state) 44 | { 45 | while (state->ecx) 46 | { 47 | x86_write_memory(state, state->es, state->edi, 2, state->ax); 48 | if (read_df(state->eflags)) 49 | state->edi-=2; 50 | else 51 | state->edi+=2; 52 | 53 | state->ecx--; 54 | } 55 | } 56 | static inline void asm_rep_stosl(struct assembler_state_t *state) 57 | { 58 | while (state->ecx) 59 | { 60 | x86_write_memory(state, state->es, state->edi, 4, state->eax); 61 | if (read_df(state->eflags)) 62 | state->edi-=2; 63 | else 64 | state->edi+=2; 65 | 66 | state->ecx--; 67 | } 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /asm_emu/x86_sar.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_sarl(struct assembler_state_t *state, uint8_t count, uint32_t *dst) 6 | { 7 | count = count & 0x0000001f; 8 | int of = *dst&0x80000000; 9 | int i; 10 | 11 | if (count) 12 | { 13 | write_cf(state->eflags, *dst & 1<<(count-1)); 14 | } 15 | 16 | for (i = 0; i < count; i++) 17 | { 18 | *dst>>=1; 19 | *dst|=of; 20 | } 21 | 22 | if (count==1) 23 | write_of(state->eflags, 0); 24 | 25 | write_sf(state->eflags, *dst & 0x80000000); 26 | write_zf(state->eflags, !*dst); 27 | #ifdef X86_PF 28 | asm_update_pf(state->eflags, *dst); 29 | #endif 30 | } 31 | static inline void asm_sarw(struct assembler_state_t *state, uint8_t count, uint16_t *dst) 32 | { 33 | count = count & 0x0000001f; 34 | int of = *dst&0x8000; 35 | int i; 36 | 37 | if (count) 38 | { 39 | write_cf(state->eflags, *dst & 1<<(count-1)); 40 | } 41 | 42 | for (i = 0; i < count; i++) 43 | { 44 | *dst>>=1; 45 | *dst|=of; 46 | } 47 | 48 | if (count==1) 49 | write_of(state->eflags, 0); 50 | write_sf(state->eflags, *dst & 0x80000000); 51 | write_zf(state->eflags, !*dst); 52 | #ifdef X86_PF 53 | asm_update_pf(state->eflags, *dst); 54 | #endif 55 | } 56 | static inline void asm_sarb(struct assembler_state_t *state, uint8_t count, uint8_t *dst) 57 | { 58 | count = count & 0x0000001f; 59 | int of = *dst&0x80; 60 | int i; 61 | 62 | if (count) 63 | { 64 | write_cf(state->eflags, *dst & 1<<(count-1)); 65 | } 66 | 67 | for (i = 0; i < count; i++) 68 | { 69 | *dst>>=1; 70 | *dst|=of; 71 | } 72 | 73 | if (count==1) 74 | write_of(state->eflags, 0); 75 | write_sf(state->eflags, *dst & 0x80); 76 | write_zf(state->eflags, !*dst); 77 | #ifdef X86_PF 78 | asm_update_pf(state->eflags, *dst); 79 | #endif 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /asmTests/equ.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 dw 4 5 | db 12 6 | _DATA ends ;IGNORE 7 | 8 | _TEXT segment use16 word public 'CODE' ;IGNORE 9 | assume cs:_TEXT,ds:_DATA 10 | start proc near 11 | 12 | ;mov eax, E TODO implement several passes 13 | ;cmp eax,1 14 | ;mov al,1 15 | ;jne failure 16 | ;E = 1 17 | 18 | F equ bx 19 | G = byte ptr -2 20 | H equ word ptr 1+2 21 | ;I = word + 5 ;TODO 22 | ;J equ word + 5 ; word here means 2 23 | ;JJ equ dw -5 ; text = "dw -5" 24 | ;error JJ = dw -5 ; word here means 2 25 | 26 | push seg _DATA 27 | pop ds 28 | 29 | ;mov ax, word ptr +5 ; result to just 5 30 | ;mov ax, word ptr [5] ; [5] 31 | ;mov ax, word ptr ds:[5] ; [5] 32 | ;mov ax, word [byte] 33 | ;mov ax,2 34 | ;mov ax,[2] 35 | ;mov ax,word [2] 36 | ;mov ax,word ptr ds:[2] 37 | 38 | ;mov eax, I 39 | cmp eax, 7 40 | mov al,7 41 | ;jne failure 42 | 43 | ;mov eax, J 44 | cmp eax, 7 45 | mov al,6 46 | ;jne failure 47 | 48 | BBB = 2 49 | mov eax, BBB 50 | cmp eax,2 51 | mov al,2 52 | jne failure 53 | 54 | mov eax, CC 55 | cmp eax,4 56 | mov al,3 57 | jne failure 58 | BBB = 1 59 | 60 | call incebx 61 | jne failure 62 | 63 | DDD = var1 ; actually it is address of var1 64 | mov ax, DDD 65 | cmp ax, var1 66 | mov al,4 67 | jne failure 68 | 69 | MOV al,0 70 | JMP exitLabel 71 | failure:: 72 | 73 | exitLabel: 74 | mov ah,4ch ; AH=4Ch - Exit To DOS 75 | int 21h 76 | start endp 77 | 78 | incebx proc near 79 | 80 | BBB = 3 81 | mov eax, BBB 82 | cmp eax,3 83 | mov al,5 84 | 85 | CC equ 4 86 | 87 | ret 88 | inceBX endp 89 | 90 | 91 | _TEXT ends ;IGNORE 92 | 93 | stackseg segment para stack 'STACK' ;IGNORE 94 | db 1000h dup(?) ;IGNORE 95 | stackseg ends ;IGNORE 96 | 97 | end start ;IGNORE 98 | -------------------------------------------------------------------------------- /asm_emu/x86_shl.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_shll(struct assembler_state_t *state, uint8_t count, uint32_t *dst) 6 | { 7 | count = count & 0x0000001f; 8 | 9 | if (count) 10 | { 11 | write_cf(state->eflags, *dst & (1<<(32-count))); /* the last bit to be shifted out */ 12 | *dst<<=count; 13 | } 14 | 15 | if (count==1) 16 | write_of(state->eflags, read_cf(state->eflags) ^ (!!(*dst & 0x80000000))); 17 | 18 | write_sf(state->eflags, *dst & 0x80000000); 19 | write_zf(state->eflags, !*dst); 20 | #ifdef X86_PF 21 | asm_update_pf(state->eflags, *dst); 22 | #endif 23 | } 24 | static inline void asm_shlw(struct assembler_state_t *state, uint8_t count, uint16_t *dst) 25 | { 26 | count = count & 0x0000001f; 27 | 28 | if (count) 29 | { 30 | write_cf(state->eflags, *dst & (1<<(16-count))); /* the last bit to be shifted out */ 31 | *dst<<=count; 32 | } 33 | 34 | if (count==1) 35 | write_of(state->eflags, read_cf(state->eflags) ^ (!!(*dst & 0x8000))); 36 | 37 | write_sf(state->eflags, *dst & 0x80000000); 38 | write_zf(state->eflags, !*dst); 39 | #ifdef X86_PF 40 | asm_update_pf(state->eflags, *dst); 41 | #endif 42 | } 43 | static inline void asm_shlb(struct assembler_state_t *state, uint8_t count, uint8_t *dst) 44 | { 45 | count = count & 0x0000001f; 46 | 47 | if (count) 48 | { 49 | write_cf(state->eflags, *dst & (1<<(8-count))); /* the last bit to be shifted out */ 50 | *dst<<=count; 51 | } 52 | 53 | if (count==1) 54 | write_of(state->eflags, read_cf(state->eflags) ^ (!!(*dst & 0x80))); 55 | 56 | write_sf(state->eflags, *dst & 0x80); 57 | write_zf(state->eflags, !*dst); 58 | #ifdef X86_PF 59 | asm_update_pf(state->eflags, *dst); 60 | #endif 61 | } 62 | #define asm_sall(count,dst) asm_shll(count,dst) 63 | #define asm_salw(count,dst) asm_shlw(count,dst) 64 | #define asm_salb(count,dst) asm_shlb(count,dst) 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /asmTests/array.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var4 db 1 5 | var1 db 2,5,6 6 | var2 dw 4,6,9 7 | var3 dd 11,-11,2,4000000 8 | _DATA ends ;IGNORE 9 | 10 | _TEXT segment use16 word public 'CODE' ;IGNORE 11 | assume cs:_TEXT,ds:_DATA 12 | start proc near 13 | 14 | 15 | sti ; Set The Interrupt Flag 16 | cld ; Clear The Direction Flag 17 | 18 | MOV ax, _data 19 | MOV ds, ax 20 | mov bx,1 21 | mov si,1 22 | 23 | mov al,13 24 | cmp var4[2],5 25 | jne failure 26 | 27 | mov al,12 28 | cmp var1[1],5 29 | jne failure 30 | 31 | mov al,11 32 | cmp var1[bx],5 33 | jne failure 34 | 35 | mov al,10 36 | cmp var1[bx+si],6 37 | jne failure 38 | 39 | mov al,1 40 | cmp var1,2 41 | jne failure 42 | 43 | mov al,2 44 | cmp [var1],2 45 | jne failure 46 | 47 | ;JMP exitLabel 48 | 49 | 50 | mov al,3 51 | cmp [var1+1],5 52 | jne failure 53 | 54 | 55 | mov al,4 56 | cmp [var2],4 57 | jne failure 58 | 59 | mov al,5 60 | cmp [var2+2],6 61 | jne failure 62 | 63 | mov al,6 64 | cmp [var3],11 65 | jne failure 66 | 67 | mov al,7 68 | cmp [var3+3*4],4000000 69 | jne failure 70 | 71 | mov al,8 72 | cmp var3+3*4,4000000 73 | jne failure 74 | 75 | mov al,9 76 | mov ebp,3*4 77 | cmp ds:[var3+ebp],4000000 78 | jne failure 79 | 80 | ;mov al,10 81 | ;cmp ds:var3+ebp,4000000 82 | ;jne failure 83 | 84 | MOV al,0 85 | JMP exitLabel 86 | failure: 87 | ;mov al,1 88 | exitLabel: 89 | mov ah,4ch ; AH=4Ch - Exit To DOS 90 | int 21h ; DOS INT 21h 91 | start endp 92 | 93 | _TEXT ends ;IGNORE 94 | 95 | 96 | 97 | stackseg segment para stack 'STACK' ;IGNORE 98 | db 1000h dup(?) 99 | stackseg ends ;IGNORE 100 | 101 | end start ;IGNORE 102 | -------------------------------------------------------------------------------- /asm_emu/x86_sub.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_subl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst) 6 | { 7 | uint32_t tmp = *dst - src; 8 | 9 | write_cf(state->eflags, tmp > *dst); 10 | 11 | if ((*dst & 0x80000000) != (src & 0x80000000)) 12 | write_of(state->eflags, (src & 0x80000000) == (tmp & 0x80000000)); /* signed overflow */ 13 | else 14 | write_of(state->eflags, 0); 15 | 16 | write_sf(state->eflags, tmp & 0x80000000); 17 | write_zf(state->eflags, !tmp); 18 | #ifdef X86_PF 19 | asm_update_pf(state->eflags, tmp); 20 | #endif 21 | #ifdef X86_AF 22 | asm_updae_af(state->eflags, tmp, *dst); 23 | #endif 24 | 25 | *dst = tmp; 26 | } 27 | static inline void asm_subw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 28 | { 29 | uint16_t tmp = *dst - src; 30 | 31 | write_cf(state->eflags, tmp > *dst); 32 | 33 | if ((*dst & 0x8000) != (src & 0x8000)) 34 | write_of(state->eflags, (src & 0x8000) == (tmp & 0x8000)); /* signed overflow */ 35 | else 36 | write_of(state->eflags, 0); 37 | 38 | write_sf(state->eflags, tmp & 0x8000); 39 | write_zf(state->eflags, !tmp); 40 | #ifdef X86_PF 41 | asm_update_pf(state->eflags, tmp); 42 | #endif 43 | #ifdef X86_AF 44 | asm_updae_af(state->eflags, tmp, *dst); 45 | #endif 46 | 47 | *dst = tmp; 48 | } 49 | static inline void asm_subb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 50 | { 51 | uint8_t tmp = *dst - src; 52 | 53 | write_cf(state->eflags, tmp > *dst); 54 | 55 | if ((*dst & 0x80) != (src & 0x80)) 56 | write_of(state->eflags, (src & 0x80) == (tmp & 0x80)); /* signed overflow */ 57 | else 58 | write_of(state->eflags, 0); 59 | 60 | write_sf(state->eflags, tmp & 0x80); 61 | write_zf(state->eflags, !tmp); 62 | #ifdef X86_PF 63 | asm_update_pf(state->eflags, tmp); 64 | #endif 65 | #ifdef X86_AF 66 | asm_updae_af(state->eflags, tmp, *dst); 67 | #endif 68 | 69 | *dst = tmp; 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /asm_emu/x86_add.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_addl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst) 6 | { 7 | uint32_t tmp = *dst + src; 8 | 9 | write_cf(state->eflags, tmp < *dst); /* unsigned overflow */ 10 | if ((*dst & 0x80000000) == (src & 0x80000000)) 11 | write_of(state->eflags, (src & 0x80000000) != (tmp & 0x80000000)); /* signed overflow */ 12 | else 13 | write_of(state->eflags, 0); 14 | 15 | write_sf(state->eflags, tmp & 0x80000000); 16 | write_zf(state->eflags, !tmp); 17 | #ifdef X86_PF 18 | asm_update_pf(state->eflags, tmp); 19 | #endif 20 | #ifdef X86_AF 21 | asm_updae_af(state->eflags, tmp, *dst); 22 | #endif 23 | 24 | *dst = tmp; 25 | } 26 | static inline void asm_addw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 27 | { 28 | uint16_t tmp = *dst + src; 29 | 30 | write_cf(state->eflags, tmp < *dst); /* unsigned overflow */ 31 | if ((*dst & 0x8000) == (src & 0x8000)) 32 | write_of(state->eflags, (src & 0x8000) != (tmp & 0x8000)); /* signed overflow */ 33 | else 34 | write_of(state->eflags, 0); 35 | 36 | write_sf(state->eflags, tmp & 0x8000); 37 | write_zf(state->eflags, !tmp); 38 | #ifdef X86_PF 39 | asm_update_pf(state->eflags, tmp); 40 | #endif 41 | #ifdef X86_AF 42 | asm_update_af(state->eflags, tmp, *dst); 43 | #endif 44 | 45 | *dst = tmp; 46 | } 47 | static inline void asm_addb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 48 | { 49 | uint8_t tmp = *dst + src; 50 | 51 | write_cf(state->eflags, tmp < *dst); /* unsigned overflow */ 52 | if ((*dst & 0x80) == (src & 0x80)) 53 | write_of(state->eflags, (src & 0x80) != (tmp & 0x80)); /* signed overflow */ 54 | else 55 | write_of(state->eflags, 0); 56 | 57 | write_sf(state->eflags, tmp & 0x80); 58 | write_zf(state->eflags, !tmp); 59 | #ifdef X86_PF 60 | asm_update_pf(state->eflags, tmp); 61 | #endif 62 | #ifdef X86_AF 63 | asm_update_af(state->eflags, tmp, *dst); 64 | #endif 65 | 66 | *dst = tmp; 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /asmTests/macro.as: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | varMAC1 db 10 dup (5) 5 | db 10 dup (6) 6 | last_voice db 1 7 | changement dd 2 8 | fx dw 14 dup (0) 9 | 10 | 11 | _DATA ends ;IGNORE 12 | 13 | _TEXT segment use16 word public 'CODE' ;IGNORE 14 | assume cs:_TEXT,ds:_DATA 15 | start proc near 16 | 17 | 18 | 19 | 20 | 21 | 22 | MAC1 MACRO 23 | mov eax,0 24 | 25 | ENDM 26 | 27 | MAC2 MACRO arg1 28 | mov eax,arg1 29 | push es 30 | push ds 31 | push eax 32 | push ebx 33 | POP ebx 34 | POP eax 35 | POP ds 36 | POP es 37 | ENDM 38 | 39 | MAC3 MACRO m,o 40 | nop 41 | mov m,o 42 | nop 43 | ENDM 44 | 45 | 46 | MAC5 MACRO arg1 47 | local cc 48 | MAC3 ecx,arg1 49 | cc: 50 | INC EDX 51 | LOOP cc 52 | ENDM 53 | 54 | MAC6 MACRO a,b 55 | lea edi,varMAC1 56 | mov al,[a+edi] 57 | ENDM 58 | 59 | bruit MACRO a,b,t 60 | local op 61 | 62 | 63 | push ebp eax 64 | mov al,a 65 | or al,01110000B 66 | mov ebp,[last_voice] 67 | add [last_voice],2 68 | cmp [last_voice],14*2 69 | jne op 70 | mov [last_voice],0 71 | op: 72 | 73 | 74 | mov byte ptr [t+ebp],al ;al ;073h ;4 bits:panning, 4 bits: sample 75 | ;0 droite. ici. F left 76 | 77 | mov eax,[changement] 78 | and eax,011B 79 | add eax,b 80 | mov byte ptr [t+ebp+1],al ;note 81 | pop eax ebp 82 | ENDM 83 | 84 | mov eax,123 85 | MAC1 86 | cmp eax,0 87 | jne failure 88 | 89 | MAC2 122 90 | cmp eax,122 91 | jne failure 92 | 93 | MAC3 ebx,45 94 | cmp ebx,45 95 | jne failure 96 | 97 | MOV edx,0 98 | MAC5 10 99 | MAC5 10 100 | CMP edx,20 101 | jne failure 102 | 103 | inc varMAC1 104 | 105 | MAC6 3,2 106 | 107 | MOV al,0 108 | JMP exitLabel 109 | failure: 110 | mov al,1 111 | exitLabel: 112 | mov ah,4ch ; AH=4Ch - Exit To DOS 113 | int 21h ; DOS INT 21h 114 | start endp 115 | 116 | _TEXT ends ;IGNORE 117 | 118 | stackseg segment para stack 'STACK' ;IGNORE 119 | db 1000h dup(?) 120 | stackseg ends ;IGNORE 121 | 122 | end start ;IGNORE 123 | -------------------------------------------------------------------------------- /asmTests/test.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | var1 db 2,5,6 5 | var2 dw 4,6,9 6 | var3 dd 11,-11,2,4 7 | var4 db 100 dup (1) 8 | _DATA ends ;IGNORE 9 | 10 | _TEXT segment use16 word public 'CODE' ;IGNORE 11 | assume cs:_TEXT,ds:_DATA 12 | start proc near 13 | 14 | 15 | 16 | mov eax,10B 17 | test eax,eax 18 | jz failure 19 | 20 | test al,0B 21 | jnz failure 22 | 23 | test al,010B 24 | jz failure 25 | 26 | mov ebx,0ffff01ffh 27 | test bh,01h 28 | jz failure 29 | 30 | test bh,02h 31 | jnz failure 32 | jb failure 33 | 34 | mov eax,0 35 | inc eax 36 | dec eax 37 | setnz al 38 | cmp eax,0 39 | jnz failure 40 | 41 | mov eax,0 42 | mov ebx,0 43 | inc eax 44 | setnz bh 45 | cmp ebx,100h 46 | jnz failure 47 | 48 | mov eax,0 49 | inc eax 50 | dec eax 51 | setz al 52 | cmp eax,1 53 | jnz failure 54 | 55 | mov eax,0 56 | mov ebx,0 57 | inc eax 58 | setz bh 59 | cmp ebx,0 60 | jnz failure 61 | 62 | clc 63 | mov eax,0 64 | setb al 65 | cmp eax,0 66 | jnz failure 67 | 68 | stc 69 | mov eax,0 70 | setb al 71 | cmp eax,1 72 | jnz failure 73 | 74 | mov eax,0100b 75 | bt eax,2 76 | jnc failure 77 | bt eax,0 78 | jc failure 79 | 80 | mov eax,0100b 81 | btc eax,2 82 | jnc failure 83 | btc eax,0 84 | jc failure 85 | cmp eax,1 86 | jne failure 87 | 88 | mov eax,0100b 89 | btr eax,2 90 | jnc failure 91 | btr eax,0 92 | jc failure 93 | cmp eax,0 94 | jne failure 95 | 96 | mov eax,0100b 97 | bts eax,2 98 | jnc failure 99 | bts eax,0 100 | jc failure 101 | cmp eax,0101b 102 | jne failure 103 | 104 | MOV al,0 105 | JMP exitLabel 106 | failure: 107 | mov al,1 108 | exitLabel: 109 | mov ah,4ch ; AH=4Ch - Exit To DOS 110 | int 21h 111 | start endp 112 | 113 | _TEXT ends ;IGNORE 114 | 115 | stackseg segment para stack 'STACK' ;IGNORE 116 | db 1000h dup(?) 117 | stackseg ends ;IGNORE 118 | 119 | end start ;IGNORE 120 | -------------------------------------------------------------------------------- /asmTests/file.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | load_handle dd 0 5 | fileName db 'file1.txt',0 6 | buffer db 64000 dup(0) 7 | _DATA ends ;IGNORE 8 | 9 | _TEXT segment use16 word public 'CODE' ;IGNORE 10 | assume cs:_TEXT,ds:_DATA 11 | start proc near 12 | 13 | mov ax,_DATA 14 | mov ds,ax 15 | 16 | mov edx,0 17 | mov ecx,2 18 | lea edi,buffer 19 | mov ebx,5 20 | 21 | call load_raw 22 | cmp al,0 23 | jne failure 24 | 25 | xor eax,eax 26 | cmp dword ptr buffer,'tseT' 27 | mov al, 1 28 | jne failure 29 | mov al,0 30 | JMP exitLabel 31 | 32 | failure: 33 | ;mov al,1 34 | exitLabel: 35 | mov ah,4ch ; AH=4Ch - Exit To DOS 36 | int 21h ; DOS INT 21h 37 | start endp 38 | 39 | load_raw proc near ; ecx: offset dans le fichier. 40 | ; edi: viseur dans donn�es ou ca serra copi� (ax:) 41 | ; ebx: nombre de pixels dans le pcx 42 | 43 | pushad 44 | push es 45 | push ds 46 | 47 | lea edx,fileName 48 | xor eax,eax 49 | mov al,00h ;ouverture du fichier pour lecture. 50 | mov ah,03dh 51 | int 21h 52 | jnc noerror 53 | pop ds 54 | pop es 55 | popad 56 | mov al,2 57 | ret 58 | noerror: 59 | 60 | mov [load_handle],eax 61 | 62 | mov ebx,[load_handle] 63 | mov ah,042h 64 | mov al,00h ;debut du fichier 65 | mov dx,cx 66 | shr ecx,16 67 | int 21h 68 | 69 | mov ecx,10 70 | 71 | mov ebx,[load_handle] 72 | mov ah,03fh 73 | ; edi: viseur dans donn�es ou ca serra copi� (ax:) 74 | push ds 75 | ;push fs 76 | ;pop ds 77 | mov edx,edi 78 | int 21h 79 | 80 | ; to remove 81 | ;mov ebx,eax 82 | ;jmp failure 83 | ; 84 | 85 | pop ds 86 | 87 | mov ebx,[load_handle] 88 | mov ah,03eh 89 | int 21h 90 | 91 | pop ds 92 | pop es 93 | popad 94 | mov al,0 95 | ret 96 | load_raw endp 97 | 98 | 99 | 100 | _TEXT ends ;IGNORE 101 | 102 | stackseg segment para stack 'STACK' ;IGNORE 103 | db 1000h dup(?) 104 | stackseg ends ;IGNORE 105 | 106 | end start ;IGNORE 107 | -------------------------------------------------------------------------------- /asmTests/mem2.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | a db 1 5 | ;padding db 10241024 dup(?) 6 | 7 | b db 2 8 | cc db 3 9 | d db 4 10 | e db 5 11 | f db 6 12 | pas_de_mem db 'NOT enought memory for VGA display, controls work for network games',13,10,'$' 13 | pbs1 db 'probleme dans allocation de descriptor..',13,10,'$' 14 | pbs2 db 'probleme dans dans definition de la taille du segment',13,10,'$' 15 | ASCII DB '00000000',0Dh,0Ah,'$' ; buffer for ASCII string 16 | 17 | _DATA ends ;IGNORE 18 | 19 | _TEXT segment use16 word public 'CODE' ;IGNORE 20 | assume cs:_TEXT,ds:_DATA 21 | start proc near 22 | 23 | 24 | 25 | taille_moire equ ((((2030080+64000*26)/4096)+1)*4096)-1 26 | 27 | ;--------------------- rÇserve de la mÇmoire pour mettre les donnÇes. ---- 28 | ;2.29 - Function 0501h - Allocate Memory Block: 29 | ;In: AX = 0501h 30 | ; BX:CX = size of block in bytes (must be non-zero) 31 | ;Out: if successful: 32 | ; carry flag clear 33 | ; BX:CX = linear address of allocated memory block 34 | ; SI:DI = memory block handle (used to resize and free block) 35 | mov bx,1024*10/16 36 | mov ah,48h 37 | int 21h 38 | jc failure 39 | mov es,ax 40 | 41 | mov bx,(1024*10/16)-1 42 | mov ah,4Ah 43 | int 21h 44 | jc failure 45 | 46 | mov byte ptr es:[0],55 47 | cmp byte ptr es:[0],55 48 | jne failure 49 | 50 | mov bx,(1024*10/16)+5 51 | mov ah,4Ah 52 | int 21h 53 | jc failure 54 | 55 | inc byte ptr es:[0] 56 | cmp byte ptr es:[0],56 57 | jne failure 58 | 59 | mov ah,49h 60 | int 21h 61 | jc failure 62 | 63 | 64 | 65 | mov bx,5 66 | mov ah,4Ah 67 | int 21h 68 | jc failure 69 | push es 70 | 71 | mov bx,10 72 | mov ah,4Ah 73 | int 21h 74 | jc failure 75 | mov ah,49h 76 | int 21h 77 | jc failure 78 | 79 | pop es 80 | mov ah,49h 81 | int 21h 82 | jc failure 83 | 84 | MOV al,0 85 | JMP exitLabel 86 | failure: 87 | mov al,1 88 | exitLabel: 89 | mov ah,4ch ; AH=4Ch - Exit To DOS 90 | int 21h ; DOS INT 21h 91 | start endp 92 | 93 | _TEXT ends ;IGNORE 94 | 95 | stackseg segment para stack 'STACK' ;IGNORE 96 | db 1000h dup(?) 97 | stackseg ends ;IGNORE 98 | 99 | end start ;IGNORE 100 | -------------------------------------------------------------------------------- /tests/test_gen_py_merge_procs_.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | from masm2c.gen import Gen 4 | import masm2c.proc as proc_module 5 | from masm2c.parser import Parser 6 | 7 | class Test_MergeAllProcs: 8 | 9 | # Merges all procs that have cross jumps and are incompatible with C. 10 | def test_merge_procs_with_cross_jumps(self): 11 | context = Parser() 12 | first_proc_name = "proc1" 13 | first_proc = proc_module.Proc(first_proc_name, line_number=1) 14 | first_proc.to_group_with = set(["proc2", "proc3"]) 15 | context.symbols.set_global(first_proc_name, first_proc) 16 | proc2 = proc_module.Proc("proc2", line_number=2) 17 | proc2.to_group_with = set(["proc1", "proc3"]) 18 | context.symbols.set_global("proc2", proc2) 19 | proc3 = proc_module.Proc("proc3", line_number=3) 20 | proc3.to_group_with = set(["proc1", "proc2"]) 21 | context.symbols.set_global("proc3", proc3) 22 | 23 | gen = Gen(context=context) 24 | gen._procs = ["proc1", "proc2", "proc3"] 25 | gen.grouped = set() 26 | 27 | gen._merge_all_procs() 28 | 29 | assert gen._procs == ["_group1"] 30 | assert gen.grouped == set(["proc1", "proc2", "proc3"]) 31 | assert gen.groups == OrderedDict({'proc1': '_group1', 'proc2': '_group1', 'proc3': '_group1'}) 32 | assert first_proc.to_group_with == set(["proc2", "proc3"]) 33 | assert first_proc.provided_labels == set(["proc1", "proc2", "proc3"]) 34 | assert first_proc.stmts[0].proc == "_group1" 35 | assert first_proc.stmts[0].data == "label" 36 | assert first_proc.stmts[0].real_offset == first_proc.real_offset 37 | assert first_proc.stmts[0].real_seg == first_proc.real_seg 38 | assert gen._context.symbols.get_global("_group1") == first_proc 39 | 40 | def test_merge_two_procs_with_label_updates_groups_dictionary(self): 41 | first_proc_name = "proc1" 42 | first_proc = proc_module.Proc("proc1") 43 | next_proc_name = "proc2" 44 | next_proc = proc_module.Proc("proc2") 45 | new_group_name = "group1" 46 | 47 | context = Parser() 48 | gen = Gen(context=context) 49 | gen.merge_two_procs_with_label(first_proc_name, first_proc, next_proc_name, next_proc, new_group_name) 50 | 51 | assert gen.groups[next_proc_name] == new_group_name -------------------------------------------------------------------------------- /asmTests/struct.asm: -------------------------------------------------------------------------------- 1 | .286 2 | .model tiny 3 | 4 | e struc 5 | ddd dw ? 6 | f dw ? 7 | e ends 8 | 9 | 10 | b struc 11 | gogo e 12 | aa db ? 13 | b ends 14 | 15 | GAMEINFO struc 16 | a db ? 17 | game_opponentcarid db 4 dup (?) 18 | d b <,?> 19 | game_opponenttype dw ? 20 | GAMEINFO ends 21 | 22 | VECTOR struc 23 | vx dw ? 24 | vy dw ? 25 | vz dw ? 26 | VECTOR ends 27 | 28 | TRANSFORMEDSHAPE struc 29 | ts_shapeptr db ? 30 | ts_rotvec VECTOR 31 | ts_rectptr db ? 32 | TRANSFORMEDSHAPE ends 33 | 34 | ;var_transshape = TRANSFORMEDSHAPE ptr -50 35 | 36 | _TEXT segment public 'CODE' ;IGNORE 37 | assume ds:_TEXT 38 | start proc near 39 | 40 | 41 | gameconfig GAMEINFO < 0, <1>, <<2,3>,4>, 5> 42 | db 0ffh 43 | ts TRANSFORMEDSHAPE < 6, <7, 8, 9>, 10 > 44 | 45 | fff e <> 46 | 47 | 48 | sti ; Set The Interrupt Flag 49 | cld ; Clear The Direction Flag 50 | 51 | t equ -2 52 | 53 | mov al,1 54 | cmp gameconfig.game_opponenttype, 5 55 | jne failure 56 | 57 | mov al,2 58 | mov bx, offset gameconfig.game_opponenttype+t 59 | cmp bx, (offset gameconfig.game_opponenttype-2) 60 | jne failure 61 | 62 | mov bx,-4 63 | mov al,3 64 | ;cmp[bx + ts.ts_rotvec.vz], 8 65 | jne failure 66 | 67 | ;mov bp, -4 68 | ;mov al,4 69 | ;cmp[bp + var_transshape.ts_rotvec.vz], 3 70 | ;jne failure 71 | 72 | MOV al,0 73 | JMP exitLabel 74 | failure: 75 | exitLabel: 76 | mov ah,4ch ; AH=4Ch - Exit To DOS 77 | int 21h ; DOS INT 21h 78 | 79 | ; OPTION NOOLDSTRUCTS (the MASM 6.1 default) 80 | ;structname STRUCT 81 | ;a BYTE ? 82 | ;b WORD ? 83 | ;structname ENDS 84 | ;structinstance structname <> 85 | ;mov ax, [bx].structname.b ; Add qualifying type 86 | ;mov al, structinstance.a ; No change needed 87 | ;mov ax, [bx]+4 ; Change dot to plus 88 | ; Alternative methods in MASM 6.1 89 | ; Either this: 90 | ;ASSUME bx:PTR structname 91 | ;mov ax, [bx] 92 | ; or this: 93 | ;mov ax, (structname PTR[bx]).b 94 | 95 | start endp 96 | 97 | _TEXT ends ;IGNORE 98 | 99 | stackseg segment para stack 'STACK' ;IGNORE 100 | db 1000h dup(?) 101 | stackseg ends ;IGNORE 102 | 103 | end start ;IGNORE 104 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | masm2c 3 | ====== 4 | 5 | This is the documentation of **masm2c**. 6 | 7 | .. note:: 8 | 9 | This is the main page of your project's `Sphinx`_ documentation. 10 | It is formatted in `reStructuredText`_. Add additional pages 11 | by creating rst-files in ``docs`` and adding them to the `toctree`_ below. 12 | Use then `references`_ in order to link them from this page, e.g. 13 | :ref:`authors` and :ref:`changes`. 14 | 15 | It is also possible to refer to the documentation of other Python packages 16 | with the `Python domain syntax`_. By default you can reference the 17 | documentation of `Sphinx`_, `Python`_, `NumPy`_, `SciPy`_, `matplotlib`_, 18 | `Pandas`_, `Scikit-Learn`_. You can add more by extending the 19 | ``intersphinx_mapping`` in your Sphinx's ``conf.py``. 20 | 21 | The pretty useful extension `autodoc`_ is activated by default and lets 22 | you include documentation from docstrings. Docstrings can be written in 23 | `Google style`_ (recommended!), `NumPy style`_ and `classical style`_. 24 | 25 | 26 | Contents 27 | ======== 28 | 29 | .. toctree:: 30 | :maxdepth: 2 31 | 32 | License 33 | Authors 34 | Changelog 35 | Module Reference 36 | 37 | 38 | Indices and tables 39 | ================== 40 | 41 | * :ref:`genindex` 42 | * :ref:`modindex` 43 | * :ref:`search` 44 | 45 | .. _toctree: http://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html 46 | .. _reStructuredText: http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html 47 | .. _references: http://www.sphinx-doc.org/en/stable/markup/inline.html 48 | .. _Python domain syntax: http://sphinx-doc.org/domains.html#the-python-domain 49 | .. _Sphinx: http://www.sphinx-doc.org/ 50 | .. _Python: http://docs.python.org/ 51 | .. _Numpy: http://docs.scipy.org/doc/numpy 52 | .. _SciPy: http://docs.scipy.org/doc/scipy/reference/ 53 | .. _matplotlib: https://matplotlib.org/contents.html# 54 | .. _Pandas: http://pandas.pydata.org/pandas-docs/stable 55 | .. _Scikit-Learn: http://scikit-learn.org/stable 56 | .. _autodoc: http://www.sphinx-doc.org/en/stable/ext/autodoc.html 57 | .. _Google style: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings 58 | .. _NumPy style: https://numpydoc.readthedocs.io/en/latest/format.html 59 | .. _classical style: http://www.sphinx-doc.org/en/stable/domains.html#info-field-lists 60 | -------------------------------------------------------------------------------- /qemu_tests/test-i386-muldiv.h: -------------------------------------------------------------------------------- 1 | 2 | void glue(glue(test_, OP), b)(long op0, long op1) 3 | { 4 | long res, s1, s0, flags; 5 | s0 = op0; 6 | s1 = op1; 7 | res = s0; 8 | flags = 0; 9 | asm ("push %4\n\t" 10 | "popf\n\t" 11 | stringify(OP)"b %b2\n\t" 12 | "pushf\n\t" 13 | "pop %1\n\t" 14 | : "=a" (res), "=g" (flags) 15 | : "q" (s1), "0" (res), "1" (flags)); 16 | printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n", 17 | stringify(OP) "b", s0, s1, res, flags & CC_MASK); 18 | } 19 | 20 | void glue(glue(test_, OP), w)(long op0h, long op0, long op1) 21 | { 22 | long res, s1, flags, resh; 23 | s1 = op1; 24 | resh = op0h; 25 | res = op0; 26 | flags = 0; 27 | asm ("push %5\n\t" 28 | "popf\n\t" 29 | stringify(OP) "w %w3\n\t" 30 | "pushf\n\t" 31 | "pop %1\n\t" 32 | : "=a" (res), "=g" (flags), "=d" (resh) 33 | : "q" (s1), "0" (res), "1" (flags), "2" (resh)); 34 | printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n", 35 | stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK); 36 | } 37 | 38 | void glue(glue(test_, OP), l)(long op0h, long op0, long op1) 39 | { 40 | long res, s1, flags, resh; 41 | s1 = op1; 42 | resh = op0h; 43 | res = op0; 44 | flags = 0; 45 | asm ("push %5\n\t" 46 | "popf\n\t" 47 | stringify(OP) "l %k3\n\t" 48 | "pushf\n\t" 49 | "pop %1\n\t" 50 | : "=a" (res), "=g" (flags), "=d" (resh) 51 | : "q" (s1), "0" (res), "1" (flags), "2" (resh)); 52 | printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n", 53 | stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK); 54 | } 55 | 56 | #if defined(__x86_64__) 57 | void glue(glue(test_, OP), q)(long op0h, long op0, long op1) 58 | { 59 | long res, s1, flags, resh; 60 | s1 = op1; 61 | resh = op0h; 62 | res = op0; 63 | flags = 0; 64 | asm ("push %5\n\t" 65 | "popf\n\t" 66 | stringify(OP) "q %3\n\t" 67 | "pushf\n\t" 68 | "pop %1\n\t" 69 | : "=a" (res), "=g" (flags), "=d" (resh) 70 | : "q" (s1), "0" (res), "1" (flags), "2" (resh)); 71 | printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n", 72 | stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK); 73 | } 74 | #endif 75 | 76 | #undef OP 77 | -------------------------------------------------------------------------------- /asmTests/mov.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | a db 1 5 | b dw 2 6 | cc dd 3 7 | d db 4 8 | e db 5 9 | f db 6 10 | g dd 12345 11 | h db -1 12 | h2 db 1 13 | 14 | _DATA ends ;IGNORE 15 | 16 | _TEXT segment use16 word public 'CODE' ;IGNORE 17 | assume cs:_TEXT,ds:_DATA 18 | start proc near 19 | 20 | 21 | mov ax,_DATA 22 | mov ds,ax 23 | 24 | mov ebx,0aabbccddh 25 | cmp bl,0ddh 26 | jne failure 27 | 28 | cmp bh,0cch 29 | jne failure 30 | 31 | mov eax,256+3+65536 32 | mov a,al 33 | cmp a,3 34 | jne failure 35 | 36 | mov a,ah 37 | cmp a,1 38 | jne failure 39 | 40 | mov b,ax 41 | cmp b,256+3 42 | jne failure 43 | 44 | mov cc,eax 45 | cmp cc,256+3+65536 46 | jne failure 47 | 48 | mov byte ptr [a],5 49 | cmp byte ptr [a],5 50 | jne failure 51 | 52 | mov a,5 53 | cmp a,5 54 | jne failure 55 | 56 | mov [a],5 57 | cmp [a],5 58 | jne failure 59 | 60 | xor ebx,ebx 61 | mov bx,word ptr [d] 62 | cmp bx,4+5*256 63 | jne failure 64 | 65 | xor ebx,ebx 66 | mov bx,word ptr [e] 67 | cmp bx,6*256+5 68 | jne failure 69 | 70 | mov ecx,-1 71 | mov bx,5 72 | movzx ecx,bx 73 | cmp ecx,5 74 | jne failure 75 | 76 | xor ecx,ecx 77 | mov cx,-5 78 | movsx ecx,cx 79 | cmp ecx,-5 80 | jne failure 81 | 82 | xor ebx,ebx 83 | mov bl,-1 84 | movsx bx,bl 85 | cmp bx,-1 86 | jne failure 87 | 88 | mov ebx,0FFFFFFFFh 89 | mov bl,1 90 | movsx bx,bl 91 | cmp bx,1 92 | jne failure 93 | 94 | xor ebx,ebx 95 | movsx bx,byte ptr [h] 96 | cmp bx,-1 97 | jne failure 98 | 99 | xor ebx,ebx 100 | movsx bx,byte ptr [h2] 101 | cmp bx,1 102 | jne failure 103 | 104 | ;TOFIX: test in dosbox if this works 105 | xor ebx,ebx 106 | movsx bx,[h2] 107 | cmp bx,1 108 | jne failure 109 | 110 | mov ebx,[g] 111 | cmp ebx,12345 112 | jne failure 113 | 114 | mov ebx,g 115 | cmp ebx,12345 116 | jne failure 117 | 118 | mov eax,1 119 | mov ebx,2 120 | xchg eax,ebx 121 | cmp eax,2 122 | jne failure 123 | cmp ebx,1 124 | jne failure 125 | 126 | MOV al,0 127 | JMP exitLabel 128 | failure: 129 | mov al,1 130 | exitLabel: 131 | mov ah,4ch ; AH=4Ch - Exit To DOS 132 | int 21h ; DOS INT 21h 133 | start endp 134 | 135 | _TEXT ends ;IGNORE 136 | 137 | stackseg segment para stack 'STACK' ;IGNORE 138 | db 1000h dup(?) 139 | stackseg ends ;IGNORE 140 | 141 | end start ;IGNORE 142 | -------------------------------------------------------------------------------- /asmTests/movsb.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | _DATA segment use16 word public 'DATA' ;IGNORE 3 | db 1,2,3,4 4 | 5 | var1 db 2,5,6 6 | var2 dw 4,6,9 7 | var3 dd 11,-11,2,4 8 | var4 db 100 dup (1) 9 | testOVerlap db 1,2,3,4,5,6,7,8,9,10,11,12,13,14 10 | str1 db 'abcde' 11 | str2 db 'abcde' 12 | str3 db 'cdeab' 13 | 14 | T EQU 4 15 | 16 | 17 | _DATA ends ;IGNORE 18 | 19 | _TEXT segment use16 word public 'CODE' ;IGNORE 20 | assume cs:_TEXT,ds:_DATA 21 | start proc near 22 | 23 | push _DATA 24 | pop ds 25 | 26 | push ds 27 | pop es 28 | 29 | cld 30 | ;jmp finTest 31 | mov si,offset var1 32 | mov di,offset var4 33 | movsb 34 | cmp [var4],2 35 | mov al,1 36 | jne failure 37 | 38 | 39 | 40 | cmp si,offset var1+1 41 | mov al,2 42 | jne failure 43 | cmp di,offset var4+1 44 | mov al,3 45 | jne failure 46 | 47 | 48 | mov si,offset var3 49 | mov di,offset var4 50 | mov ecx,t 51 | rep movsb 52 | cmp dword ptr var4,11 53 | mov al,4 54 | jne failure 55 | cmp [var4+t],1 56 | mov al,5 57 | jne failure 58 | 59 | 60 | cmp si,offset var3+4 61 | mov al,6 62 | jne failure 63 | cmp di,offset var4+4 64 | mov al,7 65 | jne failure 66 | 67 | ;mov edx,offset var1 ; DS:EDX -> $ Terminated String 68 | ;cmp edx,0 69 | ;jne failure 70 | ;mov cl, byte ptr ds:[2] 71 | ;cmp cl,6 72 | ;jne failure 73 | 74 | mov si,offset str1 75 | mov di,offset str2 76 | mov ecx,5 77 | repe cmpsb 78 | mov al,8 79 | jnz failure 80 | 81 | mov si,offset str1 82 | mov di,offset str3 83 | mov ecx,5 84 | repe cmpsb 85 | mov al,9 86 | jz failure 87 | 88 | finTest: 89 | mov si,offset testOVerlap 90 | mov edi,esi 91 | inc edi 92 | mov ecx,10 93 | rep movsb 94 | lea di,testOVerlap 95 | cmp byte ptr [testOVerlap+1],1 96 | mov al,10 97 | jne failure 98 | 99 | mov byte ptr [var1+1],5 100 | cmp byte ptr [var1+1],5 101 | mov al,11 102 | jne failure 103 | 104 | mov si,offset var1 105 | mov edi,esi 106 | inc edi 107 | mov ecx,10 108 | rep movsb 109 | lea di,var1 110 | cmp byte ptr [var1+2],5 111 | mov al,12 112 | je failure ; http://blog.rewolf.pl/blog/?p=177 113 | 114 | MOV al,0 115 | JMP exitLabel 116 | failure: 117 | ;mov al,1 118 | exitLabel: 119 | mov ah,4ch ; AH=4Ch - Exit To DOS 120 | int 21h 121 | start endp 122 | 123 | _TEXT ends ;IGNORE 124 | 125 | stackseg segment para stack 'STACK' ;IGNORE 126 | db 1000h dup(?) 127 | stackseg ends ;IGNORE 128 | 129 | end start ;IGNORE 130 | -------------------------------------------------------------------------------- /asm_emu/2.h: -------------------------------------------------------------------------------- 1 | #define STACK_CHECK 2 | 3 | typedef uint8_t uint8; 4 | typedef uint16_t uint16; 5 | typedef uint32_t uint32; 6 | 7 | #define _jmp(label) asm_jmp(this,label) 8 | #define _ja(label) asm_ja(this,label) 9 | #define _jae(label) asm_jae(this,label) 10 | #define _jb(label) asm_jb(this,label) 11 | #define _jbe(label) asm_jbe(this,label) 12 | #define _jc(label) asm_jc(this,label) 13 | #define _jcxz(label) asm_jcxz(this,label) 14 | #define _jecxz(label) asm_jecxz(this,label) 15 | #define _je(label) asm_je(this,label) 16 | #define _jg(label) asm_jg(this,label) 17 | #define _jge(label) asm_jge(this,label) 18 | #define _jl(label) asm_jl(this,label) 19 | #define _jle(label) asm_jle(this,label) 20 | #define _jna(label) asm_jna(this,label) 21 | #define _jnae(label) asm_jnae(this,label) 22 | #define _jnb(label) asm_jnb(this,label) 23 | #define _jnbe(label) asm_jnbe(this,label) 24 | #define _jnc(label) asm_jnc(this,label) 25 | #define _jne(label) asm_jne(this,label) 26 | #define _jng(label) asm_jng(this,label) 27 | #define _jnge(label) asm_jnge(this,label) 28 | #define _jnl(label) asm_jnl(this,label) 29 | #define _jnle(label) asm_jnle(this,label) 30 | #define _jno(label) asm_jno(this,label) 31 | #ifdef X86_PF 32 | #define _jnp(label) asm_jnp(this,label) 33 | #endif 34 | #define _jns(label) asm_jns(this,label) 35 | #define _jnz(label) asm_jnz(this,label) 36 | #define _jo(label) asm_jo(this,label) 37 | #ifdef X86_PF 38 | #define _jp(label) asm_jp(this,label) 39 | #define _jpe(label) asm_jpe(this,label) 40 | #define _jpo(label) asm_jpo(this,label) 41 | #endif 42 | #define _js(label) asm_js(this,label) 43 | #define _jz(label) asm_jz(this,label) 44 | 45 | #define _read_cf() read_cf(this->_eflags) 46 | #define _write_cf(state) write_cf(this->_eflags, state) 47 | #ifdef X86_PF 48 | /* PARITY FLAG */ 49 | #define _read_pf() read_pf(this->_eflags) 50 | #define _write_pf(state) write_pf(this->_eflags, state) 51 | #endif 52 | #ifdef X86_AF 53 | /* ADJUST FLAG */ 54 | #define _read_af() read_af(this->_eflags) 55 | #define _write_af(state) write_af(this->_eflags, state) 56 | #endif 57 | /* ZERO FLAG */ 58 | #define _read_zf() read_zf(this->_eflags) 59 | #define _write_zf(state) write_zf(this->_eflags, state) 60 | /* SIGN FLAG */ 61 | #define _read_sf() read_sf(this->_eflags) 62 | #define _write_sf(state) write_sf(this->_eflags, state) 63 | /* DIRECTION FLAG */ 64 | #define _read_df() read_df(this->_eflags) 65 | #define _write_df(state) write_df(this->_eflags, state) 66 | /* OVERFLOW FLAG */ 67 | #define _read_of() read_of(this->_eflags) 68 | #define _write_of(state) write_of(this->_eflags, state) 69 | 70 | -------------------------------------------------------------------------------- /asmTests/neg.asm: -------------------------------------------------------------------------------- 1 | .386p 2 | 3 | _DATA segment use16 word public 'DATA' ;IGNORE 4 | _DATA ends ;IGNORE 5 | 6 | _TEXT segment use16 word public 'CODE' ;IGNORE 7 | assume cs:_TEXT,ds:_DATA 8 | start proc near 9 | 10 | 11 | 12 | mov edx,2 13 | neg edx 14 | jnC failure 15 | 16 | cmp edx,-2 17 | jne failure 18 | 19 | xor ebx,ebx 20 | neg ebx 21 | jc failure 22 | 23 | mov eax,011111111111111111111111111111111b 24 | not eax 25 | cmp eax,0 26 | jne failure 27 | 28 | mov eax,0 29 | mov ax,01111111111111111b 30 | not ax 31 | cmp eax,0 32 | jne failure 33 | 34 | mov eax,0 35 | mov ax,01010101010101010b 36 | not ax 37 | cmp eax,0101010101010101b 38 | jne failure 39 | ;;;;;; 40 | mov eax,0 41 | cbw 42 | cmp eax,0 43 | jne failure 44 | 45 | mov eax,-5 46 | cbw 47 | cmp eax,-5 48 | jne failure 49 | 50 | mov eax,0 51 | mov al,-5 52 | cbw 53 | cmp ax,-5 54 | jne failure 55 | 56 | mov eax,0ffffff03h 57 | cbw 58 | cmp eax,0ffff0003h 59 | jne failure 60 | 61 | mov eax,0ffff00f3h 62 | cbw 63 | cmp eax,0fffffff3h 64 | jne failure 65 | ;;;;;; 66 | mov eax,0 67 | mov edx,0 68 | cwd 69 | cmp eax,0 70 | jne failure 71 | cmp edx,0 72 | jne failure 73 | 74 | mov eax,-5 75 | mov edx,0 76 | cwd 77 | cmp eax,-5 78 | jne failure 79 | cmp edx,0ffffh 80 | jne failure 81 | 82 | mov eax,0ffffff03h 83 | mov edx,0 84 | cwd 85 | cmp eax,0ffffff03h 86 | jne failure 87 | cmp edx,0ffffh 88 | jne failure 89 | 90 | mov eax,0ffff00f3h 91 | mov edx,0 92 | cwd 93 | cmp eax,0ffff00f3h 94 | jne failure 95 | cmp edx,0 96 | jne failure 97 | ;;;;; 98 | mov eax,0 99 | cwde 100 | cmp eax,0 101 | jne failure 102 | 103 | mov eax,-5 104 | cwde 105 | cmp eax,-5 106 | jne failure 107 | 108 | mov eax,0ffffff03h 109 | cwde 110 | cmp eax,0ffffff03h 111 | jne failure 112 | 113 | mov eax,0ffff00f3h 114 | cwde 115 | cmp eax,000f3h 116 | jne failure 117 | ;;;;;; 118 | 119 | clc 120 | jc failure 121 | 122 | stc 123 | jnc failure 124 | 125 | clc 126 | cmc 127 | jnc failure 128 | cmc 129 | jc failure 130 | 131 | xor eax,eax 132 | JMP exitLabel 133 | failure: 134 | mov al,1 135 | exitLabel: 136 | mov ah,4ch ; AH=4Ch - Exit To DOS 137 | int 21h 138 | 139 | start endp 140 | 141 | _TEXT ends ;IGNORE 142 | 143 | stackseg segment para stack 'STACK' ;IGNORE 144 | db 1000h dup(?) 145 | stackseg ends ;IGNORE 146 | 147 | end start ;IGNORE 148 | 149 | -------------------------------------------------------------------------------- /asm_regs_dbx.h: -------------------------------------------------------------------------------- 1 | class eflags 2 | { 3 | dd& _value; 4 | 5 | public: 6 | eflags(uint32_t& flags): _value((dd&)flags) 7 | {} 8 | 9 | dd getvalue() const noexcept 10 | { return _value; } 11 | void setvalue(dd v) noexcept 12 | { _value=v; } 13 | #define REGDEF_flags(Z) \ 14 | inline bool set##Z##F(bool i) noexcept {return (reinterpret_cast(&_value)->bits._##Z##F=i);} \ 15 | inline bool get##Z##F() const noexcept {return reinterpret_cast(&_value)->bits._##Z##F;} 16 | inline void reset(){_value=0;} 17 | 18 | REGDEF_flags(C) 19 | REGDEF_flags(P) 20 | REGDEF_flags(A) 21 | REGDEF_flags(Z) 22 | REGDEF_flags(S) 23 | REGDEF_flags(T) 24 | REGDEF_flags(I) 25 | REGDEF_flags(D) 26 | REGDEF_flags(O) 27 | }; 28 | 29 | // #define m2cflags cpu_regs.flags 30 | 31 | #define X86_REGREF \ 32 | db& al = cpu_regs.regs[REGI_AX].byte[BL_INDEX]; \ 33 | db& ah = cpu_regs.regs[REGI_AX].byte[BH_INDEX]; \ 34 | dw& ax = cpu_regs.regs[REGI_AX].word[W_INDEX]; \ 35 | dd& eax = *(dd*)&cpu_regs.regs[REGI_AX].dword[DW_INDEX]; \ 36 | \ 37 | db& bl = cpu_regs.regs[REGI_BX].byte[BL_INDEX]; \ 38 | db& bh = cpu_regs.regs[REGI_BX].byte[BH_INDEX]; \ 39 | dw& bx = cpu_regs.regs[REGI_BX].word[W_INDEX]; \ 40 | dd& ebx = *(dd*)&cpu_regs.regs[REGI_BX].dword[DW_INDEX]; \ 41 | \ 42 | db& cl = cpu_regs.regs[REGI_CX].byte[BL_INDEX]; \ 43 | db& ch = cpu_regs.regs[REGI_CX].byte[BH_INDEX]; \ 44 | dw& cx = cpu_regs.regs[REGI_CX].word[W_INDEX]; \ 45 | dd& ecx = *(dd*)&cpu_regs.regs[REGI_CX].dword[DW_INDEX]; \ 46 | \ 47 | db& dl = cpu_regs.regs[REGI_DX].byte[BL_INDEX]; \ 48 | db& dh = cpu_regs.regs[REGI_DX].byte[BH_INDEX]; \ 49 | dw& dx = cpu_regs.regs[REGI_DX].word[W_INDEX]; \ 50 | dd& edx = *(dd*)&cpu_regs.regs[REGI_DX].dword[DW_INDEX]; \ 51 | \ 52 | dw& si = cpu_regs.regs[REGI_SI].word[W_INDEX]; \ 53 | dd& esi = *(dd*)&cpu_regs.regs[REGI_SI].dword[DW_INDEX]; \ 54 | \ 55 | dw& di = cpu_regs.regs[REGI_DI].word[W_INDEX]; \ 56 | dd& edi = *(dd*)&cpu_regs.regs[REGI_DI].dword[DW_INDEX]; \ 57 | \ 58 | dw& sp = cpu_regs.regs[REGI_SP].word[W_INDEX]; \ 59 | dd& esp = *(dd*)&cpu_regs.regs[REGI_SP].dword[DW_INDEX]; \ 60 | \ 61 | dw& bp = cpu_regs.regs[REGI_BP].word[W_INDEX]; \ 62 | dd& ebp = *(dd*)&cpu_regs.regs[REGI_BP].dword[DW_INDEX]; \ 63 | \ 64 | dw& ip = cpu_regs.ip.word[W_INDEX]; \ 65 | dd& eip = *(dd*)&cpu_regs.ip.dword[DW_INDEX]; \ 66 | dw& cs = Segs.val[SegNames::cs]; \ 67 | dw& ds = Segs.val[SegNames::ds]; \ 68 | dw& es = Segs.val[SegNames::es]; \ 69 | dw& fs = Segs.val[SegNames::fs]; \ 70 | dw& gs = Segs.val[SegNames::gs]; \ 71 | dw& ss = Segs.val[SegNames::ss]; \ 72 | \ 73 | m2c::eflags m2cflags(cpu_regs.flags); \ 74 | dd& stackPointer = esp;\ 75 | m2c::_offsets __disp; \ 76 | dd _source; 77 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean clean-test clean-pyc clean-build docs help lint test check 2 | .DEFAULT_GOAL := help 3 | define BROWSER_PYSCRIPT 4 | import os, webbrowser, sys 5 | try: 6 | from urllib import pathname2url 7 | except: 8 | from urllib.request import pathname2url 9 | 10 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 11 | endef 12 | export BROWSER_PYSCRIPT 13 | 14 | define PRINT_HELP_PYSCRIPT 15 | import re, sys 16 | 17 | for line in sys.stdin: 18 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 19 | if match: 20 | target, help = match.groups() 21 | print("%-20s %s" % (target, help)) 22 | endef 23 | export PRINT_HELP_PYSCRIPT 24 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 25 | 26 | help: 27 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 28 | 29 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts 30 | 31 | 32 | clean-build: ## remove build artifacts 33 | rm -fr build/ 34 | rm -fr dist/ 35 | rm -fr .eggs/ 36 | find . -name '*.egg-info' -exec rm -fr {} + 37 | find . -name '*.egg' -exec rm -f {} + 38 | 39 | clean-pyc: ## remove Python file artifacts 40 | find . -name '*.pyc' -exec rm -f {} + 41 | find . -name '*.pyo' -exec rm -f {} + 42 | find . -name '*~' -exec rm -f {} + 43 | find . -name '__pycache__' -exec rm -fr {} + 44 | 45 | clean-test: ## remove test and coverage artifacts 46 | rm -fr .tox/ 47 | rm -f .coverage 48 | rm -fr htmlcov/ 49 | 50 | lint: ## check style with flake8 51 | flake8 52 | 53 | 54 | 55 | test-all: ## run tests on every Python version with tox 56 | tox 57 | 58 | coverage: ## check code coverage quickly with the default Python 59 | coverage run --source masm2c -m pytest tests/func 60 | 61 | coverage report -m 62 | coverage html 63 | $(BROWSER) htmlcov/index.html 64 | 65 | docs: ## generate MkDocs HTML documentation 66 | mkdocs build 67 | $(BROWSER) docs/_build/html/index.html 68 | 69 | servedocs: ## compile the docs watching for changes 70 | mkdocs serve 71 | $(BROWSER) "http://localhost:8000/" 72 | 73 | release: clean ## package and upload a release 74 | python setup.py sdist upload 75 | python setup.py bdist_wheel upload 76 | 77 | dist: clean ## builds source and wheel package 78 | python setup.py sdist 79 | python setup.py bdist_wheel 80 | ls -l dist 81 | 82 | install: clean ## install the package to the active Python's site-packages 83 | python setup.py install 84 | test: $(TESTS) 85 | 86 | check: test_insn_tests 87 | ./$< 88 | 89 | TESTS = test_insn_tests 90 | 91 | test_insn_tests: test_insn_tests.cpp asm.h asm_16.h asm.cpp 92 | $(CXX) $(CXXFLAGS) -I./include -isystem /usr/local/include -Wno-overflow \ 93 | -L/usr/local/lib -lpthread -lgtest_main \ 94 | -o $@ $< 95 | -------------------------------------------------------------------------------- /qemu_tests/Makefile.target: -------------------------------------------------------------------------------- 1 | # i386 cross compile notes 2 | 3 | I386_SRC=$(SRC_PATH)/tests/tcg/i386 4 | 5 | # Set search path for all sources 6 | VPATH += $(I386_SRC) 7 | 8 | I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c)) 9 | ALL_X86_TESTS=$(I386_SRCS:.c=) 10 | SKIP_I386_TESTS=test-i386-ssse3 11 | X86_64_TESTS:=$(filter test-i386-ssse3, $(ALL_X86_TESTS)) 12 | 13 | test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse 14 | run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max 15 | run-plugin-test-i386-sse-exceptions-%: QEMU_OPTS += -cpu max 16 | 17 | test-i386-pcmpistri: CFLAGS += -msse4.2 18 | run-test-i386-pcmpistri: QEMU_OPTS += -cpu max 19 | run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max 20 | 21 | run-test-i386-bmi2: QEMU_OPTS += -cpu max 22 | run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max 23 | 24 | # 25 | # hello-i386 is a barebones app 26 | # 27 | hello-i386: CFLAGS+=-ffreestanding 28 | hello-i386: LDFLAGS+=-nostdlib 29 | 30 | # test-386 includes a couple of additional objects that need to be 31 | # linked together, we also need a no-pie capable compiler due to the 32 | # non-pic calls into 16-bit mode 33 | ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_I386_NOPIE),) 34 | test-i386: CFLAGS += -fno-pie 35 | 36 | test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S test-i386.h test-i386-shift.h test-i386-muldiv.h 37 | $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ \ 38 | $( $@,"GENREF","generating $@") 52 | 53 | run-test-i386-fprem: TIMEOUT=60 54 | run-test-i386-fprem: test-i386-fprem test-i386-fprem.ref 55 | $(call run-test,test-i386-fprem, $(QEMU) $<,"$< on $(TARGET_NAME)") 56 | $(call diff-out,test-i386-fprem, test-i386-fprem.ref) 57 | else 58 | SKIP_I386_TESTS+=test-i386-fprem 59 | endif 60 | 61 | # non-inline runs will trigger the duplicate instruction heuristics in libinsn.so 62 | run-plugin-%-with-libinsn.so: 63 | $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ 64 | -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ 65 | -d plugin -D $*-with-libinsn.so.pout $*, \ 66 | "$* (inline) on $(TARGET_NAME)") 67 | 68 | # Update TESTS 69 | I386_TESTS:=$(filter-out $(SKIP_I386_TESTS), $(ALL_X86_TESTS)) 70 | TESTS=$(MULTIARCH_TESTS) $(I386_TESTS) 71 | 72 | # On i386 and x86_64 Linux only supports 4k pages (large pages are a different hack) 73 | EXTRA_RUNS+=run-test-mmap-4096 74 | -------------------------------------------------------------------------------- /examples/intro.asm: -------------------------------------------------------------------------------- 1 | ;searchlight 2 | ;y0bi / wAMMA 3 | ;26.1.2007 4 | .486 5 | code segment use16 6 | org 100h 7 | 8 | mov al,13h 9 | int 10h 10 | 11 | push 8000h 12 | pop ds 13 | push 7000h 14 | pop fs 15 | push 6000h 16 | pop gs 17 | push 0a000h 18 | pop es 19 | ;------------------ 20 | xor bx,bx 21 | MakeTopoLoop: 22 | mov ax,bx 23 | shl ax,2 24 | and al,ah 25 | cmp al,128+64+32 26 | setb al 27 | shl al,7 28 | mov byte ptr [fs:bx],al 29 | ;------------- 30 | mov ax,bx 31 | add ax,64 32 | cbw 33 | cwd 34 | mov ax,bx 35 | shl ax,1 36 | mov di,ax 37 | imul al 38 | sub ah,64 39 | xor ax,dx 40 | sar ax,6 41 | mov [gs:di],ax 42 | inc bx 43 | jnz MakeTopoLoop 44 | 45 | ;------------------ 46 | MainLoop: 47 | lodsw 48 | 49 | 50 | mov di,512 51 | AngleLoop: 52 | mov bp,[gs:si] 53 | shl bp,6 54 | mov dx,si 55 | shl dx,7 56 | add dh,89 57 | mov ah,255 58 | mov cx,128 59 | RadiusLoop: 60 | mov bx,bp 61 | mov bl,dh 62 | mov al,cl 63 | and al,ah 64 | cmp byte ptr [fs:bx],ch 65 | jne NoWall 66 | xor ax,ax 67 | NoWall: 68 | add [bx],al 69 | shr byte ptr [bx],1 70 | add dx,[gs:di+128] 71 | add bp,[gs:di] 72 | loop RadiusLoop 73 | dec di 74 | dec di 75 | jnz AngleLoop 76 | 77 | ;---------- 78 | mov bp,320 79 | LineLoop: 80 | mov dx,[gs:si] 81 | sal dx,5 82 | add dh,16 83 | 84 | mov bl,199 85 | xor cx,cx 86 | ProjectLoop: 87 | inc cx 88 | push si 89 | push dx 90 | 91 | mov ax,si 92 | shr ax,1 93 | add al,cl 94 | mov ah,dh 95 | xchg si,ax 96 | 97 | mov al,[fs:si] 98 | cbw 99 | neg ax 100 | shl ax,5 101 | cwd 102 | idiv cx 103 | add ax,100 104 | cmp ax,199 105 | jg DontDraw 106 | cmp al,bl 107 | jae DontDraw 108 | mov dl,bl 109 | xchg bx,ax 110 | sub dl,bl 111 | imul di,bx,320 112 | mov ax,si 113 | xor al,ah 114 | shr al,2 115 | add al,[si-3] 116 | sub al,64 117 | cbw 118 | not ah 119 | and al,ah 120 | shr al,3 121 | add al,16 122 | PlotLoop: 123 | mov [es:di+bp],al 124 | not di 125 | mov [es:di+bp+65],al 126 | not di 127 | add di,320 128 | dec dl 129 | jnz PlotLoop 130 | DontDraw: 131 | 132 | pop dx 133 | pop si 134 | 135 | add dx,bp 136 | add dx,bp 137 | sub dx,320 138 | 139 | cmp ch,1 140 | jb ProjectLoop 141 | dec bp 142 | jnz LineLoop 143 | 144 | in al,60h 145 | cmp al,1 146 | jne MainLoop 147 | ret 148 | 149 | 150 | code ends -------------------------------------------------------------------------------- /asm_emu/x86_sbb.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_sbbl(struct assembler_state_t *state, uint32_t src, uint32_t *dst) 6 | { 7 | uint32_t tmp = *dst - src; 8 | int of = 0; 9 | int cf = 1; 10 | 11 | if (read_cf(state->eflags)) 12 | { 13 | tmp--; 14 | src++; 15 | if (src==0x00000000) 16 | { 17 | write_cf(state->eflags, 1); 18 | cf=0; 19 | } 20 | 21 | if (src==0x80000000) 22 | of = 1; 23 | } 24 | 25 | if (cf) 26 | write_cf(state->eflags, tmp > *dst); 27 | 28 | if ((*dst & 0x80000000) != (src & 0x80000000)) 29 | write_of(state->eflags, ((src & 0x80000000) == (tmp & 0x80000000)) ^ of); /* signed overflow */ 30 | else 31 | write_of(state->eflags, of); 32 | 33 | write_sf(state->eflags, tmp & 0x80000000); 34 | write_zf(state->eflags, !tmp); 35 | #ifdef X86_PF 36 | asm_update_pf(state->eflags, tmp); 37 | #endif 38 | #ifdef X86_AF 39 | asm_updae_af(state->eflags, tmp, *dst); 40 | #endif 41 | 42 | *dst = tmp; 43 | } 44 | static inline void asm_sbbw(struct assembler_state_t *state, uint16_t src, uint16_t *dst) 45 | { 46 | uint16_t tmp = *dst - src; 47 | int of = 0; 48 | int cf = 1; 49 | 50 | if (read_cf(state->eflags)) 51 | { 52 | tmp--; 53 | src++; 54 | if (src==0x0000) 55 | { 56 | write_cf(state->eflags, 1); 57 | cf=0; 58 | } 59 | 60 | if (src==0x8000) 61 | of = 1; 62 | } 63 | 64 | if (cf) 65 | write_cf(state->eflags, tmp > *dst); 66 | 67 | if ((*dst & 0x8000) != (src & 0x8000)) 68 | write_of(state->eflags, ((src & 0x8000) == (tmp & 0x8000)) ^ of); /* signed overflow */ 69 | else 70 | write_of(state->eflags, of); 71 | 72 | write_sf(state->eflags, tmp & 0x8000); 73 | write_zf(state->eflags, !tmp); 74 | #ifdef X86_PF 75 | asm_update_pf(state->eflags, tmp); 76 | #endif 77 | #ifdef X86_AF 78 | asm_updae_af(state->eflags, tmp, *dst); 79 | #endif 80 | 81 | *dst = tmp; 82 | } 83 | static inline void asm_sbbb(struct assembler_state_t *state, uint8_t src, uint8_t *dst) 84 | { 85 | uint8_t tmp = *dst - src; 86 | int of = 0; 87 | int cf = 1; 88 | 89 | if (read_cf(state->eflags)) 90 | { 91 | tmp--; 92 | src++; 93 | if (src==0x00) 94 | { 95 | write_cf(state->eflags, 1); 96 | cf=0; 97 | } 98 | 99 | if (src==0x80) 100 | of = 1; 101 | } 102 | 103 | if (cf) 104 | write_cf(state->eflags, tmp > *dst); 105 | 106 | if ((*dst & 0x80) != (src & 0x80)) 107 | write_of(state->eflags, ((src & 0x80) == (tmp & 0x80)) ^ of); /* signed overflow */ 108 | else 109 | write_of(state->eflags, of); 110 | 111 | write_sf(state->eflags, tmp & 0x80); 112 | write_zf(state->eflags, !tmp); 113 | #ifdef X86_PF 114 | asm_update_pf(state->eflags, tmp); 115 | #endif 116 | #ifdef X86_AF 117 | asm_updae_af(state->eflags, tmp, *dst); 118 | #endif 119 | 120 | *dst = tmp; 121 | } 122 | #endif 123 | -------------------------------------------------------------------------------- /asm_emu/x86_adc.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_adcl(struct assembler_state_t *state, const uint32_t src, uint32_t *dst) 6 | { 7 | uint32_t tmp = *dst + src; 8 | int of = 0; 9 | int cf = 1; 10 | if (read_cf(state->eflags)) 11 | { 12 | tmp++; 13 | (*dst)++; 14 | if (*dst==0x00000000) 15 | { 16 | write_cf(state->eflags, 1); 17 | cf=0; 18 | } 19 | 20 | if (*dst==0x80000000) 21 | of = 1; 22 | } 23 | 24 | if (cf) 25 | write_cf(state->eflags, tmp < *dst); /* unsigned overflow */ 26 | 27 | if ((*dst & 0x80000000) == (src & 0x80000000)) 28 | write_of(state->eflags, ((src & 0x80000000) != (tmp & 0x80000000)) ^ of); /* signed overflow */ 29 | else 30 | write_of(state->eflags, of); 31 | 32 | write_sf(state->eflags, tmp & 0x80000000); 33 | write_zf(state->eflags, !tmp); 34 | #ifdef X86_PF 35 | asm_update_pf(state->eflags, tmp); 36 | #endif 37 | #ifdef X86_AF 38 | asm_updae_af(state->eflags, tmp, *dst); 39 | #endif 40 | 41 | *dst = tmp; 42 | } 43 | static inline void asm_adcw(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 44 | { 45 | uint16_t tmp = *dst + src; 46 | int of = 0; 47 | int cf = 1; 48 | if (read_cf(state->eflags)) 49 | { 50 | tmp++; 51 | (*dst)++; 52 | if (*dst==0x0000) 53 | { 54 | write_cf(state->eflags, 1); 55 | cf=0; 56 | } 57 | 58 | if (*dst==0x8000) 59 | of = 1; 60 | } 61 | 62 | if (cf) 63 | write_cf(state->eflags, tmp < *dst); /* unsigned overflow */ 64 | 65 | if ((*dst & 0x8000) == (src & 0x8000)) 66 | write_of(state->eflags, ((src & 0x8000) != (tmp & 0x8000)) ^ of); /* signed overflow */ 67 | else 68 | write_of(state->eflags, of); 69 | 70 | write_sf(state->eflags, tmp & 0x8000); 71 | write_zf(state->eflags, !tmp); 72 | #ifdef X86_PF 73 | asm_update_pf(state->eflags, tmp); 74 | #endif 75 | #ifdef X86_AF 76 | asm_update_af(state->eflags, tmp, *dst); 77 | #endif 78 | 79 | *dst = tmp; 80 | } 81 | static inline void asm_adcb(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 82 | { 83 | uint8_t tmp = *dst + src; 84 | int of = 0; 85 | int cf = 1; 86 | if (read_cf(state->eflags)) 87 | { 88 | tmp++; 89 | (*dst)++; 90 | if (*dst==0x00) 91 | { 92 | write_cf(state->eflags, 1); 93 | cf=0; 94 | } 95 | 96 | if (*dst==0x80) 97 | of = 1; 98 | } 99 | 100 | if (cf) 101 | write_cf(state->eflags, tmp < *dst); /* unsigned overflow */ 102 | 103 | if ((*dst & 0x80) == (src & 0x80)) 104 | write_of(state->eflags, ((src & 0x80) != (tmp & 0x80)) ^ of); /* signed overflow */ 105 | else 106 | write_of(state->eflags, of); 107 | 108 | write_sf(state->eflags, tmp & 0x80); 109 | write_zf(state->eflags, !tmp); 110 | #ifdef X86_PF 111 | asm_update_pf(state->eflags, tmp); 112 | #endif 113 | #ifdef X86_AF 114 | asm_update_af(state->eflags, tmp, *dst); 115 | #endif 116 | 117 | *dst = tmp; 118 | } 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /asm_32.h: -------------------------------------------------------------------------------- 1 | #ifndef __asm_32_h__ 2 | #define __asm_32_h__ 3 | 4 | static inline db* raddr_(dw segment,dd offset) {return reinterpret_cast(offset);} 5 | 6 | typedef dd MWORDSIZE; 7 | #define offset(segment,name) ((size_t)(db*)&name) 8 | 9 | #define MOVSS(a) {void * dest;void * src;src=realAddress(esi,ds); dest=realAddress(edi,es); \ 10 | memmove(dest,src,a); edi+=(GET_DF()==0)?a:-a; esi+=(GET_DF()==0)?a:-a; } 11 | #define STOS(a,b) {memcpy (realAddress(edi,es), ((db *)&eax)+b, a); edi+=(GET_DF()==0)?a:-a;} 12 | 13 | #define REP ecx++;while (--ecx != 0) 14 | #define REPE AFFECT_ZFifz(0);ecx++;while (--ecx != 0 && GET_ZF()) 15 | #define REPNE AFFECT_ZFifz(1);ecx++;while (--ecx != 0 && !GET_ZF()) 16 | #define XLAT {al = *m2c::raddr_(ds,ebx+al);} 17 | #define CMPSB \ 18 | { \ 19 | db* src=realAddress(esi,ds); db* dest=realAddress(edi,es); \ 20 | CMP(*src, *dest); edi+=(GET_DF()==0)?1:-1; esi+=(GET_DF()==0)?1:-1; \ 21 | } 22 | #define CMPSW \ 23 | { \ 24 | dw* src=(dw*)realAddress(esi,ds); dw* dest=(dw*)realAddress(edi,es); \ 25 | CMP(*src, *dest); edi+=(GET_DF()==0)?2:-2; esi+=(GET_DF()==0)?2:-2; \ 26 | } 27 | 28 | // printf("~%08X_",*(dd*)realAddress(esi,ds)); printf("%08X~",*(dd*)realAddress(edi,es)); \ 29 | 30 | #define CMPSD \ 31 | { \ 32 | dd* src=(dd*)realAddress(esi,ds); dd* dest=(dd*)realAddress(edi,es); \ 33 | CMP(*src, *dest); edi+=(GET_DF()==0)?4:-4; esi+=(GET_DF()==0)?4:-4; \ 34 | } 35 | 36 | //printf("~%02X",al);printf("%02X~",*realAddress(edi,es)); 37 | 38 | #define SCASB \ 39 | { \ 40 | CMP(al, *(db*)realAddress(edi,es)); edi+=(GET_DF()==0)?1:-1; \ 41 | } 42 | #define SCASW \ 43 | { \ 44 | CMP(ax, *(dw*)realAddress(edi,es)); edi+=(GET_DF()==0)?2:-2; \ 45 | } 46 | #define SCASD \ 47 | { \ 48 | CMP(eax, *(dd*)realAddress(edi,es)); edi+=(GET_DF()==0)?4:-4; \ 49 | } 50 | 51 | #define LODSS(a,b) {memcpy (((db *)&eax)+b, realAddress(esi,ds), a); esi+=(GET_DF()==0)?a:-a;} 52 | 53 | #ifdef MSB_FIRST 54 | #define STOSB STOS(1,3) 55 | #define STOSW STOS(2,2) 56 | #else 57 | #define STOSB STOS(1,0) 58 | #ifdef A_NORMAL 59 | #define STOSW {if (es>=0xB800) {STOS(2,0);} else {attron(COLOR_PAIR(ah)); mvaddch(edi/160, (edi/2)%80, al); /*attroff(COLOR_PAIR(ah))*/;edi+=(GET_DF()==0)?2:-2;refresh();}} 60 | #else 61 | #define STOSW STOS(2,0) 62 | #endif 63 | #endif 64 | #define STOSD STOS(4,0) 65 | 66 | #define INSB {db averytemporary3 = asm2C_IN(dx);*realAddress(edi,es)=averytemporary3;edi+=(GET_DF()==0)?1:-1;} 67 | #define INSW {dw averytemporary3 = asm2C_INW(dx);*realAddress(edi,es)=averytemporary3;edi+=(GET_DF()==0)?2:-2;} 68 | 69 | #define LOOP(label) DEC(ecx); JNZ(label) 70 | #define LOOPE(label) --ecx; if (ecx!=0 && GET_ZF()) GOTOLABEL(label) //TODO 71 | #define LOOPNE(label) --ecx; if (ecx!=0 && !GET_ZF()) GOTOLABEL(label) //TODO 72 | 73 | #define MOVSB MOVSS(1) 74 | #define MOVSW MOVSS(2) 75 | #define MOVSD MOVSS(4) 76 | 77 | #ifdef MSB_FIRST 78 | #define LODSB LODSS(1,3) 79 | #define LODSW LODSS(2,2) 80 | #else 81 | #define LODSB LODSS(1,0) 82 | #define LODSW LODSS(2,0) 83 | #endif 84 | 85 | #define LODSD LODSS(4,0) 86 | 87 | 88 | #endif 89 | 90 | -------------------------------------------------------------------------------- /asm_regs_decomp.h: -------------------------------------------------------------------------------- 1 | #include "shadowstack.h" 2 | extern ShadowStack shadow_stack; 3 | 4 | #define REGDEF_hl(Z) \ 5 | extern uint32_t e##Z##x; \ 6 | uint16_t& Z##x = *(uint16_t *)& e##Z##x; \ 7 | uint8_t& Z##l = *(uint8_t *)& e##Z##x; \ 8 | uint8_t& Z##h = *(((uint8_t *)& e##Z##x)+1); 9 | 10 | #define REGDEF_l(Z) \ 11 | extern uint32_t e##Z; \ 12 | uint16_t& Z = *(uint16_t *)& e##Z ; \ 13 | uint8_t& Z##l = *(uint8_t *)& e##Z ; 14 | 15 | #define REGDEF_nol(Z) \ 16 | extern uint32_t e##Z; \ 17 | uint16_t& Z = *(uint16_t *)& e##Z ; 18 | 19 | extern bool CF; 20 | extern bool PF; 21 | extern bool AF; 22 | extern bool ZF; 23 | extern bool SF; 24 | extern bool DF; 25 | extern bool OF; 26 | extern bool IF; 27 | extern bool TF; 28 | extern dd other_flags; 29 | 30 | class eflags 31 | { 32 | 33 | _STATE* _state; 34 | public: 35 | explicit eflags(_STATE* _state):_state(_state) 36 | {} 37 | 38 | dd getvalue() const noexcept 39 | { flagsUnion f; 40 | f.value=other_flags & ~0x8000; // 286+ 41 | f.bits._CF=CF; 42 | f.bits._PF=PF; 43 | f.bits._AF=AF; 44 | f.bits._ZF=ZF; 45 | f.bits._SF=SF; 46 | f.bits._TF=TF; 47 | f.bits._IF=IF; 48 | f.bits._DF=DF; 49 | f.bits._OF=OF; 50 | return f.value; 51 | } 52 | void setvalue(dd v) noexcept 53 | { 54 | flagsUnion f; 55 | f.value = v; 56 | other_flags=v; 57 | CF=f.bits._CF; 58 | PF=f.bits._PF; 59 | AF=f.bits._AF; 60 | ZF=f.bits._ZF; 61 | SF=f.bits._SF; 62 | TF=f.bits._TF; 63 | IF=f.bits._IF; 64 | DF=f.bits._DF; 65 | OF=f.bits._OF; 66 | } 67 | #define REGDEF_flags(Z) \ 68 | inline bool set##Z##F(bool i) noexcept {return Z##F=i;} \ 69 | inline bool get##Z##F() const noexcept {return Z##F;} 70 | inline void reset(){ 71 | CF=false; 72 | PF=false; 73 | AF=false; 74 | ZF=false; 75 | SF=false; 76 | TF=false; 77 | IF=false; 78 | DF=false; 79 | OF=false; 80 | } 81 | 82 | REGDEF_flags(C) 83 | REGDEF_flags(P) 84 | REGDEF_flags(A) 85 | REGDEF_flags(Z) 86 | REGDEF_flags(S) 87 | REGDEF_flags(T) 88 | REGDEF_flags(I) 89 | REGDEF_flags(D) 90 | REGDEF_flags(O) 91 | }; 92 | 93 | #define X86_REGREF \ 94 | REGDEF_hl(a); \ 95 | REGDEF_hl(b); \ 96 | REGDEF_hl(c); \ 97 | REGDEF_hl(d); \ 98 | \ 99 | REGDEF_l(si); \ 100 | REGDEF_l(di); \ 101 | REGDEF_l(sp); \ 102 | REGDEF_l(bp); \ 103 | \ 104 | REGDEF_nol(ip); \ 105 | \ 106 | extern dw cs; \ 107 | extern dw ds; \ 108 | extern dw es; \ 109 | extern dw fs; \ 110 | extern dw gs; \ 111 | extern dw ss; \ 112 | \ 113 | extern bool CF; \ 114 | extern bool PF; \ 115 | extern bool AF; \ 116 | extern bool ZF; \ 117 | extern bool SF; \ 118 | extern bool DF; \ 119 | extern bool OF; \ 120 | extern bool IF; \ 121 | m2c::eflags m2cflags(_state); \ 122 | extern dd other_flags;\ 123 | dd& stackPointer = esp;\ 124 | m2c::_offsets __disp; \ 125 | dw _source; 126 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | You can assign any license to generated code 2 | 3 | Instructions emulation: 4 | MIT License 5 | 6 | Copyright (c) 2017 Franck GOTTHOLD, xor2003 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | 26 | ----------------------------------------------------------------------------- 27 | 28 | MASM 16bit assembler to C++ translator (initially based on SCUMMVM tasmrecover) 29 | Copyright (C) 2021 xor2003 30 | 31 | Masm2c is the legal property of its developers, whose names 32 | are too numerous to list here. Please refer to the COPYRIGHT 33 | file distributed with this source distribution. 34 | 35 | This program is free software; you can redistribute it and/or 36 | modify it under the terms of the GNU General Public License 37 | as published by the Free Software Foundation; either version 2 38 | of the License, or (at your option) any later version. 39 | 40 | This program is distributed in the hope that it will be useful, 41 | but WITHOUT ANY WARRANTY; without even the implied warranty of 42 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43 | GNU General Public License for more details. 44 | 45 | You should have received a copy of the GNU General Public License 46 | along with this program; if not, write to the Free Software 47 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 48 | 49 | ----------------------------------------------------------------------------- 50 | x86 CPU test 51 | 52 | Copyright (c) 2003 Fabrice Bellard 53 | 54 | This program is free software; you can redistribute it and/or modify 55 | it under the terms of the GNU General Public License as published by 56 | the Free Software Foundation; either version 2 of the License, or 57 | (at your option) any later version. 58 | 59 | This program is distributed in the hope that it will be useful, 60 | but WITHOUT ANY WARRANTY; without even the implied warranty of 61 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 62 | GNU General Public License for more details. 63 | 64 | You should have received a copy of the GNU General Public License 65 | along with this program; if not, see . 66 | -------------------------------------------------------------------------------- /lark_test.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Iterator 2 | 3 | import jsonpickle 4 | from lark import Lark, Transformer, Tree, lark, v_args 5 | 6 | from masm2c.Token import Token 7 | 8 | 9 | class MatchTag: 10 | always_accept = "LABEL", "STRUCTHDR" 11 | 12 | def __init__(self) -> None: 13 | self.last_type = None 14 | self.last = None 15 | 16 | def process(self, stream: Iterator[lark.Token]) -> Iterator[lark.Token]: 17 | for t in stream: 18 | if t.type == "LABEL": 19 | if t.value == "struc": 20 | t.type = "STRUCTHDR" 21 | elif t.value == "ends": 22 | t.type = "endsdir" 23 | #if t.type == "STRUCTHDR": 24 | if self.last_type == "LABEL" and t.type == "LABEL" and t.value == "VECTOR": 25 | t.type = "STRUCTNAME" 26 | self.last_type = t.type 27 | self.last = t.value 28 | yield t 29 | 30 | with open("masm2c/_masm61.lark") as g: 31 | l = Lark(g, parser="lalr", propagate_positions=True, debug=True, 32 | postlex=MatchTag()) # , keep_all_tokens=True) 33 | 34 | """ 35 | VECTOR struc 36 | vx dw ? 37 | VECTOR ends 38 | 39 | TRANSFORMEDSHAPE struc 40 | ts_shapeptr dw ? 41 | ts_rectptr dw ? 42 | ;ts_rOTvec VECTOR <> 43 | ;ts_vec VECTOR 3 dup (<>) 44 | TRANSFORMEDSHAPE ends 45 | var_transshape = TRANSFORMEDSHAPE ptr -50 46 | 47 | GAMEINFO struc 48 | game_opponenttype dw ? 49 | game_opponentmaterial dd ? 50 | game_opponentcarid db 4 dup (?) 51 | GAMEINFO ends 52 | extrn gameconfig:GAMEINFO 53 | 54 | _DATA segment use16 word public 'DATA' ;IGNORE 55 | head db '^',10,10 56 | var3 db 5*5 dup (0) 57 | var3 db 5*5 dup (0,testEqu*2,2*2*3,3) 58 | db 88h,3 dup(0),87h 59 | _dword_1DCEC dd 10524E49h ; DATA XREF: _loadcfg+1Ar 60 | var1 db 2.3E+4 61 | ASCII DB '00000000',0Dh,0Ah,'$' ; buffer for ASCII string 62 | _a070295122642\tdb '07/02/95 12:26:42',0 ; DATA XREF: seg003:off_2462E\x19o 63 | _DATA ends ;IGNORE 64 | 65 | var_transshape = TRANSFORMEDSHAPE ptr -50 66 | """ 67 | t = l.parse(""".386p 68 | a = byte ptr -50 69 | b = -50 70 | d equ 8 71 | 72 | 73 | _TEXT segment use16 word public 'CODE' ;IGNORE 74 | assume cs:_TEXT,ds:_DATA 75 | start: 76 | call dword ptr [ebx-4] 77 | shr dx, cl 78 | mov ax,'Z' - 'A' + 1 ;coment 79 | ;inc bx 80 | ;lahf 81 | add word ptr [var1-2],3h+5o*5 82 | add eax, large ds:4000h 83 | mov bl,-3 84 | mov cl,+5 85 | 86 | _TEXT ends ;IGNORE 87 | 88 | end start ;IGNORE 89 | """) 90 | 91 | 92 | class ExprRemover(Transformer): 93 | @v_args(meta=True) 94 | def expr(self, meta, children): 95 | children = Token.remove_tokens(children, "expr") 96 | 97 | return Tree("expr", children, meta) 98 | 99 | 100 | e = ExprRemover() 101 | t = e.transform(t) 102 | 103 | print(t) 104 | print(t.pretty()) 105 | 106 | 107 | class Tr(Transformer): 108 | 109 | def asminstruction(self, nodes): 110 | print(jsonpickle.dumps(nodes, indent=2)) 111 | return nodes 112 | 113 | # def expr(self, nodes): 114 | 115 | 116 | print(Tr().transform(t)) 117 | -------------------------------------------------------------------------------- /asm_regs_m2c.h: -------------------------------------------------------------------------------- 1 | #include "shadowstack.h" 2 | extern ShadowStack shadow_stack; 3 | 4 | #define REGDEF_hl(Z) \ 5 | uint32_t& e##Z##x = _state->e##Z##x; \ 6 | uint16_t& Z##x = *(uint16_t *)& e##Z##x; \ 7 | uint8_t& Z##l = *(uint8_t *)& e##Z##x; \ 8 | uint8_t& Z##h = *(((uint8_t *)& e##Z##x)+1); 9 | 10 | #define REGDEF_l(Z) \ 11 | uint32_t& e##Z = _state->e##Z; \ 12 | uint16_t& Z = *(uint16_t *)& e##Z ; \ 13 | uint8_t& Z##l = *(uint8_t *)& e##Z ; 14 | 15 | #define REGDEF_nol(Z) \ 16 | uint32_t& e##Z = _state->e##Z; \ 17 | uint16_t& Z = *(uint16_t *)& e##Z ; 18 | 19 | class eflags 20 | { 21 | 22 | _STATE* _state; 23 | public: 24 | explicit eflags(_STATE* _state):_state(_state) 25 | {} 26 | 27 | dd getvalue() const noexcept 28 | { flagsUnion f; 29 | f.value=_state->other_flags & ~0x8000; // 286+ 30 | f.bits._CF=_state->CF; 31 | f.bits._PF=_state->PF; 32 | f.bits._AF=_state->AF; 33 | f.bits._ZF=_state->ZF; 34 | f.bits._SF=_state->SF; 35 | f.bits._TF=_state->TF; 36 | f.bits._IF=_state->IF; 37 | f.bits._DF=_state->DF; 38 | f.bits._OF=_state->OF; 39 | return f.value; 40 | } 41 | void setvalue(dd v) noexcept 42 | { 43 | flagsUnion f; 44 | f.value = v; 45 | _state->other_flags=v; 46 | _state->CF=f.bits._CF; 47 | _state->PF=f.bits._PF; 48 | _state->AF=f.bits._AF; 49 | _state->ZF=f.bits._ZF; 50 | _state->SF=f.bits._SF; 51 | _state->TF=f.bits._TF; 52 | _state->IF=f.bits._IF; 53 | _state->DF=f.bits._DF; 54 | _state->OF=f.bits._OF; 55 | } 56 | #define REGDEF_flags(Z) \ 57 | inline bool set##Z##F(bool i) noexcept {return _state-> Z##F=i;} \ 58 | inline bool get##Z##F() const noexcept {return _state-> Z##F;} 59 | inline void reset(){ 60 | _state->CF=false; 61 | _state->PF=false; 62 | _state->AF=false; 63 | _state->ZF=false; 64 | _state->SF=false; 65 | _state->TF=false; 66 | _state->IF=false; 67 | _state->DF=false; 68 | _state->OF=false; 69 | } 70 | 71 | REGDEF_flags(C) 72 | REGDEF_flags(P) 73 | REGDEF_flags(A) 74 | REGDEF_flags(Z) 75 | REGDEF_flags(S) 76 | REGDEF_flags(T) 77 | REGDEF_flags(I) 78 | REGDEF_flags(D) 79 | REGDEF_flags(O) 80 | }; 81 | 82 | #define X86_REGREF \ 83 | REGDEF_hl(a); \ 84 | REGDEF_hl(b); \ 85 | REGDEF_hl(c); \ 86 | REGDEF_hl(d); \ 87 | \ 88 | REGDEF_l(si); \ 89 | REGDEF_l(di); \ 90 | REGDEF_l(sp); \ 91 | REGDEF_l(bp); \ 92 | \ 93 | REGDEF_nol(ip); \ 94 | \ 95 | dw& cs = _state->cs; \ 96 | dw& ds = _state->ds; \ 97 | dw& es = _state->es; \ 98 | dw& fs = _state->fs; \ 99 | dw& gs = _state->gs; \ 100 | dw& ss = _state->ss; \ 101 | \ 102 | bool& CF = _state->CF; \ 103 | bool& PF = _state->PF; \ 104 | bool& AF = _state->AF; \ 105 | bool& ZF = _state->ZF; \ 106 | bool& SF = _state->SF; \ 107 | bool& DF = _state->DF; \ 108 | bool& OF = _state->OF; \ 109 | bool& IF = _state->IF; \ 110 | m2c::eflags m2cflags(_state); \ 111 | dd& stackPointer = _state->esp;\ 112 | m2c::_offsets __disp; \ 113 | dw _source; 114 | -------------------------------------------------------------------------------- /asmTests/data.asm: -------------------------------------------------------------------------------- 1 | test1 EQU (00+38*3)*320+1/2+33*(3-1) 2 | test3 EQU 1500 ; 8*2*3 ;+1 +19*13*2*4 3 | TEST2 EQU -13 4 | testEqu equ 3 5 | 6 | .386p 7 | 8 | _DATA segment use16 word public 'DATA' ;IGNORE 9 | beginningdata db 4 10 | var1 db 2 11 | var2 dw 11 12 | var3 dd test2 13 | var4 db 131 14 | db 141 15 | var5 dw 2,5,0 16 | var6 dd 9,8,7,1 17 | dd 111,1 18 | dw 223,22 19 | db 'OKOKOKOK',10,13 20 | db 4 dup (5) 21 | db 'OKOKOKOK' 22 | db 'ABC',0 23 | dd offset var5 24 | align 2 25 | ASCII DB '00000000',0Dh,0Ah,'$' ; buffer for ASCII string 26 | doublequote db 'ab''cd',"e" 27 | var7 db 5*5 dup (0,testEqu*2,2*2,3) 28 | 29 | enddata db 4 30 | 31 | _DATA ends ;IGNORE 32 | 33 | _TEXT segment use16 word public 'CODE' ;IGNORE 34 | assume cs:_TEXT,ds:_DATA 35 | 36 | start proc near 37 | 38 | MOV ax, _data 39 | MOV ds, ax 40 | 41 | mov al, 'Z' - 'A' +1 42 | 43 | lea ebx,beginningdata 44 | lea eax,enddata 45 | sub eax,ebx 46 | inc eax 47 | call printeax 48 | 49 | ;TOFIX: 50 | cmp [doublequote+4],'d' 51 | ;jne failure 52 | 53 | mov eax,teST2 54 | cmp eax,-13 55 | jne failure 56 | 57 | cmp var3,-13 58 | jne failure 59 | 60 | inc var3 61 | cmp var3,-12 62 | jne failure 63 | 64 | mov dl,var1 65 | cmp dl,2 66 | jne failure 67 | 68 | mov edi,offset var1 69 | mov esi,offset var2 70 | mov dl, byte ptr [edi] 71 | cmp dl,2 72 | jne failure 73 | 74 | mov edi,offset var1 75 | mov dx,[edi+1] 76 | cmp dx,11 77 | jne failure 78 | 79 | inc byte ptr [edi+7] 80 | cmp byte ptr [edi+7],132 81 | jne failure 82 | 83 | MOV al,0 84 | JMP exitLabel 85 | failure: 86 | mov al,1 87 | exitLabel: 88 | mov ah,4ch ; AH=4Ch - Exit To DOS 89 | int 21h ; DOS INT 21h 90 | start endp 91 | 92 | 93 | 94 | printeax proc near 95 | 96 | ;----------------------- 97 | ; convert the value in EAX to hexadecimal ASCIIs 98 | ;----------------------- 99 | mov edi,OFFSET AsCii ; get the offset address 100 | mov cl,8 ; number of ASCII 101 | P1: rol eax,4 ; 1 Nibble (start with highest byte) 102 | mov bl,al 103 | and bl,0Fh ; only low-Nibble 104 | add bl,30h ; convert to ASCII 105 | cmp bl,39h ; above 9? 106 | jna short P2 107 | add bl,7 ; "A" to "F" 108 | P2: mov [edi],bl ; store ASCII in buffer 109 | inc edi ; increase target address 110 | dec cl ; decrease loop counter 111 | jnz P1 ; jump if cl is not equal 0 (zeroflag is not set) 112 | ;----------------------- 113 | ; Print string 114 | ;----------------------- 115 | mov edx,OFFSET ASCiI ; DOS 1+ WRITE STRING TO STANDARD OUTPUT 116 | mov ah,9 ; DS:DX->'$'-terminated string 117 | int 21h ; maybe redirected under DOS 2+ for output to file 118 | ; (using pipe character">") or output to printer 119 | ret 120 | printeax endp 121 | 122 | 123 | _TEXT ends ;IGNORE 124 | 125 | 126 | 127 | stackseg segment para stack 'STACK' ;IGNORE 128 | db 1000h dup(?) 129 | stackseg ends ;IGNORE 130 | 131 | end start ;IGNORE 132 | -------------------------------------------------------------------------------- /examples/snake.h: -------------------------------------------------------------------------------- 1 | /* THIS IS GENERATED FILE */ 2 | 3 | 4 | #ifndef __M2C_SNAKE_STUBS_H__ 5 | #define __M2C_SNAKE_STUBS_H__ 6 | 7 | #include "asm.h" 8 | 9 | 10 | 11 | extern db& default_seg; 12 | extern db& data; 13 | extern char (& msg)[28]; 14 | extern char (& instructions)[92]; 15 | extern char (& quitmsg)[37]; 16 | extern char (& gameovermsg)[28]; 17 | extern char (& scoremsg)[8]; 18 | extern char (& head)[3]; 19 | extern db (& body)[48]; 20 | extern db& segmentcount; 21 | extern db& fruitactive; 22 | extern db& fruitx; 23 | extern db& fruity; 24 | extern db& gameover; 25 | extern db& quit; 26 | extern db& delaytime; 27 | extern db& text; 28 | 29 | namespace m2c{ 30 | void Initializer(); 31 | static const dd kbegin = 0x1001; 32 | static const dd kmainproc = 0x1002; 33 | static const dd kmain = 0x1003; 34 | static const dd kmainloop = 0x1004; 35 | static const dd kgameover_mainloop = 0x1005; 36 | static const dd kquitpressed_mainloop = 0x1006; 37 | static const dd kquit_mainloop = 0x1007; 38 | static const dd kdelay = 0x1008; 39 | static const dd kjmp_delay = 0x1009; 40 | static const dd kfruitgeneration = 0x100a; 41 | static const dd kregenerate = 0x100b; 42 | static const dd knevermind = 0x100c; 43 | static const dd kret_fruitactive = 0x100d; 44 | static const dd kdispdigit = 0x100e; 45 | static const dd kdispnum = 0x100f; 46 | static const dd kretz = 0x1010; 47 | static const dd ksetcursorpos = 0x1011; 48 | static const dd kdraw = 0x1012; 49 | static const dd kdraw_loop = 0x1013; 50 | static const dd kout_draw = 0x1014; 51 | static const dd kreadchar = 0x1015; 52 | static const dd kkeybdpressed = 0x1016; 53 | static const dd kkeyboardfunctions = 0x1017; 54 | static const dd knext_11 = 0x1018; 55 | static const dd knext_12 = 0x1019; 56 | static const dd knext_13 = 0x101a; 57 | static const dd knext_14 = 0x101b; 58 | static const dd kquit_keyboardfunctions = 0x101c; 59 | static const dd kshiftsnake = 0x101d; 60 | static const dd kl = 0x101e; 61 | static const dd koutside = 0x101f; 62 | static const dd knext_1 = 0x1020; 63 | static const dd knext_2 = 0x1021; 64 | static const dd knext_3 = 0x1022; 65 | static const dd kdone_checking_the_head = 0x1023; 66 | static const dd kgame_over = 0x1024; 67 | static const dd ki_ate_fruit = 0x1025; 68 | static const dd kprintbox = 0x1026; 69 | static const dd kl1 = 0x1027; 70 | static const dd kl2 = 0x1028; 71 | static const dd kl3 = 0x1029; 72 | static const dd kl4 = 0x102a; 73 | static const dd kwritecharat = 0x102b; 74 | static const dd kreadcharat = 0x102c; 75 | static const dd kwritestringat = 0x102d; 76 | static const dd kloop_writestringat = 0x102e; 77 | static const dd kexit_writestringat = 0x102f; 78 | } 79 | 80 | bool delay(m2c::_offsets, struct m2c::_STATE*); 81 | bool dispdigit(m2c::_offsets, struct m2c::_STATE*); 82 | bool dispnum(m2c::_offsets, struct m2c::_STATE*); 83 | bool draw(m2c::_offsets, struct m2c::_STATE*); 84 | bool fruitgeneration(m2c::_offsets, struct m2c::_STATE*); 85 | bool keyboardfunctions(m2c::_offsets, struct m2c::_STATE*); 86 | bool asmmain(m2c::_offsets, struct m2c::_STATE*); 87 | static bool mainproc(m2c::_offsets, struct m2c::_STATE*); 88 | bool printbox(m2c::_offsets, struct m2c::_STATE*); 89 | bool readchar(m2c::_offsets, struct m2c::_STATE*); 90 | bool readcharat(m2c::_offsets, struct m2c::_STATE*); 91 | bool setcursorpos(m2c::_offsets, struct m2c::_STATE*); 92 | bool shiftsnake(m2c::_offsets, struct m2c::_STATE*); 93 | bool writecharat(m2c::_offsets, struct m2c::_STATE*); 94 | bool writestringat(m2c::_offsets, struct m2c::_STATE*); 95 | 96 | bool __dispatch_call(m2c::_offsets __disp, struct m2c::_STATE* _state); 97 | 98 | 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /mcb.h: -------------------------------------------------------------------------------- 1 | /****************************************************************/ 2 | /* */ 3 | /* mcb.h */ 4 | /* */ 5 | /* Memory Control Block data structures and declarations */ 6 | /* */ 7 | /* November 23, 1991 */ 8 | /* */ 9 | /* Copyright (c) 1995 */ 10 | /* Pasquale J. Villani */ 11 | /* All Rights Reserved */ 12 | /* */ 13 | /* This file is part of DOS-C. */ 14 | /* */ 15 | /* DOS-C is free software; you can redistribute it and/or */ 16 | /* modify it under the terms of the GNU General Public License */ 17 | /* as published by the Free Software Foundation; either version */ 18 | /* 2, or (at your option) any later version. */ 19 | /* */ 20 | /* DOS-C is distributed in the hope that it will be useful, but */ 21 | /* WITHOUT ANY WARRANTY; without even the implied warranty of */ 22 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 23 | /* the GNU General Public License for more details. */ 24 | /* */ 25 | /* You should have received a copy of the GNU General Public */ 26 | /* License along with DOS-C; see the file COPYING. If not, */ 27 | /* write to the Free Software Foundation, 675 Mass Ave, */ 28 | /* Cambridge, MA 02139, USA. */ 29 | /****************************************************************/ 30 | 31 | #ifndef __MCB_H__ 32 | #define __MCB_H__ 33 | 34 | #ifndef __BORLANDC__ 35 | #include 36 | #define MYPACKED __attribute__((__packed__)) 37 | #else 38 | #define MYPACKED 39 | typedef unsigned long uint32_t; 40 | typedef unsigned short int uint16_t; 41 | typedef short int int16_t; 42 | typedef unsigned char uint8_t; 43 | #endif 44 | 45 | typedef unsigned char BYTE; 46 | typedef uint16_t UWORD; 47 | 48 | #ifdef MAIN 49 | #ifdef VERSION_STRINGS 50 | static BYTE *mcb_hRcsId = 51 | "$Id: mcb.h 822 2004-03-25 00:20:20Z bartoldeman $"; 52 | #endif 53 | #endif 54 | 55 | #define LARGEST -1 56 | #define FIRST_FIT 0 57 | #define BEST_FIT 1 58 | #define LAST_FIT 2 59 | #define FIRST_FIT_UO 0x40 60 | #define BEST_FIT_UO 0x41 61 | #define LAST_FIT_UO 0x42 62 | #define FIRST_FIT_U 0x80 63 | #define BEST_FIT_U 0x81 64 | #define LAST_FIT_U 0x82 65 | #define FIT_U_MASK 0xc0 66 | #define FIT_MASK 0x3f 67 | 68 | #define MCB_NORMAL 0x4d 69 | #define MCB_LAST 0x5a 70 | 71 | #define DOS_PSP 0x0060 /* 0x0008 What? seg 8 =0:0080 */ 72 | #define FREE_PSP 0 73 | 74 | #define MCB_SIZE(x) ((((LONG)(x))<<4)+sizeof(mcb)) 75 | 76 | typedef UWORD seg; 77 | typedef UWORD offset; 78 | 79 | #pragma pack(push, 1) 80 | struct mcb { 81 | BYTE m_type; /* mcb type - chain or end */ 82 | UWORD m_psp; /* owner id via psp segment */ 83 | UWORD m_size; /* size of segment in paragraphs */ 84 | BYTE m_fill[3]; 85 | BYTE m_name[8]; /* owner name limited to 8 bytes */ 86 | }; 87 | #pragma pack(pop) 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /outdated/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Use the latest 2.1 version of CircleCI pipeline process engine. 2 | # See: https://circleci.com/docs/2.0/configuration-reference 3 | version: 2.1 4 | 5 | # Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects. 6 | # See: https://circleci.com/docs/2.0/orb-intro/ 7 | orbs: 8 | # The python orb contains a set of prepackaged CircleCI configuration you can use repeatedly in your configuration files 9 | # Orb commands and jobs help you with common scripting around a language/tool 10 | # so you dont have to copy and paste it everywhere. 11 | # See the orb documentation here: https://circleci.com/developer/orbs/orb/circleci/python 12 | python: circleci/python@1.5.0 13 | 14 | # Define a job to be invoked later in a workflow. 15 | # See: https://circleci.com/docs/2.0/configuration-reference/#jobs 16 | jobs: 17 | build-and-test: # This is the name of the job, feel free to change it to better match what you're trying to do! 18 | # These next lines defines a Docker executors: https://circleci.com/docs/2.0/executor-types/ 19 | # You can specify an image from Dockerhub or use one of the convenience images from CircleCI's Developer Hub 20 | # A list of available CircleCI Docker convenience images are available here: https://circleci.com/developer/images/image/cimg/python 21 | # The executor is the environment in which the steps below will be executed - below will use a python 3.10.2 container 22 | # Change the version below to your required version of python 23 | docker: 24 | - image: cimg/python:3.10.2 25 | # Checkout the code as the first step. This is a dedicated CircleCI step. 26 | # The python orb's install-packages step will install the dependencies from a Pipfile via Pipenv by default. 27 | # Here we're making sure we use just use the system-wide pip. By default it uses the project root's requirements.txt. 28 | # Then run your tests! 29 | # CircleCI will report the results back to your VCS provider. 30 | steps: 31 | - checkout 32 | - python/install-packages: 33 | pkg-manager: pip 34 | # app-dir: ~/project/package-directory/ # If you're requirements.txt isn't in the root directory. 35 | pip-dependency-file: testrequirements.txt # if you have a different name for your requirements file, maybe one that combines your runtime and test requirements. 36 | - run: 37 | name: Run tests 38 | # This assumes pytest is installed via the install-package step above 39 | command: pytest tests/ 40 | binary-tests: 41 | # Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. 42 | # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor 43 | docker: 44 | - image: ubuntu-2004:202111-02 45 | # Add steps to the job 46 | # See: https://circleci.com/docs/2.0/configuration-reference/#steps 47 | steps: 48 | - checkout 49 | - run: sudo apt install gcc-multilib g++-multilib libncurses5-dev:i386 libncurses5:i386 python 50 | 51 | - run: 52 | name: "Binary tests" 53 | command: ./_binarytests.sh 54 | 55 | # Invoke jobs via workflows 56 | # See: https://circleci.com/docs/2.0/configuration-reference/#workflows 57 | workflows: 58 | python_workflow: # This is the name of the workflow, feel free to change it to better match your workflow. 59 | # Inside the workflow, you define the jobs you want to run. 60 | jobs: 61 | - build-and-test 62 | binary-workflow: 63 | jobs: 64 | - binary-tests 65 | -------------------------------------------------------------------------------- /qemu_tests/test-i386.h: -------------------------------------------------------------------------------- 1 | 2 | #define exec_op glue(exec_, OP) 3 | #define exec_opq glue(glue(exec_, OP), q) 4 | #define exec_opl glue(glue(exec_, OP), l) 5 | #define exec_opw glue(glue(exec_, OP), w) 6 | #define exec_opb glue(glue(exec_, OP), b) 7 | 8 | #define EXECOP2(size, rsize, res, s1, flags) \ 9 | asm ("push %4\n\t"\ 10 | "popf\n\t"\ 11 | stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \ 12 | "pushf\n\t"\ 13 | "pop %1\n\t"\ 14 | : "=q" (res), "=g" (flags)\ 15 | : "q" (s1), "0" (res), "1" (flags)); \ 16 | printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \ 17 | stringify(OP) size, s0, s1, res, iflags, flags & CC_MASK); 18 | 19 | #define EXECOP1(size, rsize, res, flags) \ 20 | asm ("push %3\n\t"\ 21 | "popf\n\t"\ 22 | stringify(OP) size " %" rsize "0\n\t" \ 23 | "pushf\n\t"\ 24 | "pop %1\n\t"\ 25 | : "=q" (res), "=g" (flags)\ 26 | : "0" (res), "1" (flags)); \ 27 | printf("%-10s A=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \ 28 | stringify(OP) size, s0, res, iflags, flags & CC_MASK); 29 | 30 | #ifdef OP1 31 | #if defined(__x86_64__) 32 | void exec_opq(long s0, long s1, long iflags) 33 | { 34 | long res, flags; 35 | res = s0; 36 | flags = iflags; 37 | EXECOP1("q", "", res, flags); 38 | } 39 | #endif 40 | 41 | void exec_opl(long s0, long s1, long iflags) 42 | { 43 | long res, flags; 44 | res = s0; 45 | flags = iflags; 46 | EXECOP1("l", "k", res, flags); 47 | } 48 | 49 | void exec_opw(long s0, long s1, long iflags) 50 | { 51 | long res, flags; 52 | res = s0; 53 | flags = iflags; 54 | EXECOP1("w", "w", res, flags); 55 | } 56 | 57 | void exec_opb(long s0, long s1, long iflags) 58 | { 59 | long res, flags; 60 | res = s0; 61 | flags = iflags; 62 | EXECOP1("b", "b", res, flags); 63 | } 64 | #else 65 | #if defined(__x86_64__) 66 | void exec_opq(long s0, long s1, long iflags) 67 | { 68 | long res, flags; 69 | res = s0; 70 | flags = iflags; 71 | EXECOP2("q", "", res, s1, flags); 72 | } 73 | #endif 74 | 75 | void exec_opl(long s0, long s1, long iflags) 76 | { 77 | long res, flags; 78 | res = s0; 79 | flags = iflags; 80 | EXECOP2("l", "k", res, s1, flags); 81 | } 82 | 83 | void exec_opw(long s0, long s1, long iflags) 84 | { 85 | long res, flags; 86 | res = s0; 87 | flags = iflags; 88 | EXECOP2("w", "w", res, s1, flags); 89 | } 90 | 91 | void exec_opb(long s0, long s1, long iflags) 92 | { 93 | long res, flags; 94 | res = s0; 95 | flags = iflags; 96 | EXECOP2("b", "b", res, s1, flags); 97 | } 98 | #endif 99 | 100 | void exec_op(long s0, long s1) 101 | { 102 | s0 = i2l(s0); 103 | s1 = i2l(s1); 104 | #if defined(__x86_64__) 105 | exec_opq(s0, s1, 0); 106 | #endif 107 | exec_opl(s0, s1, 0); 108 | exec_opw(s0, s1, 0); 109 | exec_opb(s0, s1, 0); 110 | #ifdef OP_CC 111 | #if defined(__x86_64__) 112 | exec_opq(s0, s1, CC_C); 113 | #endif 114 | exec_opl(s0, s1, CC_C); 115 | exec_opw(s0, s1, CC_C); 116 | exec_opb(s0, s1, CC_C); 117 | #endif 118 | } 119 | 120 | void glue(test_, OP)(void) 121 | { 122 | exec_op(0x12345678, 0x812FADA); 123 | exec_op(0x12341, 0x12341); 124 | exec_op(0x12341, -0x12341); 125 | exec_op(0xffffffff, 0); 126 | exec_op(0xffffffff, -1); 127 | exec_op(0xffffffff, 1); 128 | exec_op(0xffffffff, 2); 129 | exec_op(0x7fffffff, 0); 130 | exec_op(0x7fffffff, 1); 131 | exec_op(0x7fffffff, -1); 132 | exec_op(0x80000000, -1); 133 | exec_op(0x80000000, 1); 134 | exec_op(0x80000000, -2); 135 | exec_op(0x12347fff, 0); 136 | exec_op(0x12347fff, 1); 137 | exec_op(0x12347fff, -1); 138 | exec_op(0x12348000, -1); 139 | exec_op(0x12348000, 1); 140 | exec_op(0x12348000, -2); 141 | exec_op(0x12347f7f, 0); 142 | exec_op(0x12347f7f, 1); 143 | exec_op(0x12347f7f, -1); 144 | exec_op(0x12348080, -1); 145 | exec_op(0x12348080, 1); 146 | exec_op(0x12348080, -2); 147 | } 148 | 149 | void *glue(_test_, OP) __init_call = glue(test_, OP); 150 | 151 | #undef OP 152 | #undef OP_CC 153 | -------------------------------------------------------------------------------- /vgapal.h: -------------------------------------------------------------------------------- 1 | db vgaPalette[256*3] = { 2 | 0, 0, 0, 0, 0, 170, 0, 170, 0, 0, 170, 170, 3 | 170, 0, 0, 170, 0, 170, 170, 85, 0, 170, 170, 170, 4 | 85, 85, 85, 85, 85, 255, 85, 255, 85, 85, 255, 255, 5 | 255, 85, 85, 255, 85, 255, 255, 255, 85, 255, 255, 255, 6 | 0, 0, 0, 20, 20, 20, 32, 32, 32, 44, 44, 44, 7 | 56, 56, 56, 69, 69, 69, 81, 81, 81, 97, 97, 97, 8 | 113, 113, 113, 130, 130, 130, 146, 146, 146, 162, 162, 162, 9 | 182, 182, 182, 203, 203, 203, 227, 227, 227, 255, 255, 255, 10 | 0, 0, 255, 65, 0, 255, 125, 0, 255, 190, 0, 255, 11 | 255, 0, 255, 255, 0, 190, 255, 0, 125, 255, 0, 65, 12 | 255, 0, 0, 255, 65, 0, 255, 125, 0, 255, 190, 0, 13 | 255, 255, 0, 190, 255, 0, 125, 255, 0, 65, 255, 0, 14 | 0, 255, 0, 0, 255, 65, 0, 255, 125, 0, 255, 190, 15 | 0, 255, 255, 0, 190, 255, 0, 125, 255, 0, 65, 255, 16 | 125, 125, 255, 158, 125, 255, 190, 125, 255, 223, 125, 255, 17 | 255, 125, 255, 255, 125, 223, 255, 125, 190, 255, 125, 158, 18 | 255, 125, 125, 255, 158, 125, 255, 190, 125, 255, 223, 125, 19 | 255, 255, 125, 223, 255, 125, 190, 255, 125, 158, 255, 125, 20 | 125, 255, 125, 125, 255, 158, 125, 255, 190, 125, 255, 223, 21 | 125, 255, 255, 125, 223, 255, 125, 190, 255, 125, 158, 255, 22 | 182, 182, 255, 199, 182, 255, 219, 182, 255, 235, 182, 255, 23 | 255, 182, 255, 255, 182, 235, 255, 182, 219, 255, 182, 199, 24 | 255, 182, 182, 255, 199, 182, 255, 219, 182, 255, 235, 182, 25 | 255, 255, 182, 235, 255, 182, 219, 255, 182, 199, 255, 182, 26 | 182, 255, 182, 182, 255, 199, 182, 255, 219, 182, 255, 235, 27 | 182, 255, 255, 182, 235, 255, 182, 219, 255, 182, 199, 255, 28 | 0, 0, 113, 28, 0, 113, 56, 0, 113, 85, 0, 113, 29 | 113, 0, 113, 113, 0, 85, 113, 0, 56, 113, 0, 28, 30 | 113, 0, 0, 113, 28, 0, 113, 56, 0, 113, 85, 0, 31 | 113, 113, 0, 85, 113, 0, 56, 113, 0, 28, 113, 0, 32 | 0, 113, 0, 0, 113, 28, 0, 113, 56, 0, 113, 85, 33 | 0, 113, 113, 0, 85, 113, 0, 56, 113, 0, 28, 113, 34 | 56, 56, 113, 69, 56, 113, 85, 56, 113, 97, 56, 113, 35 | 113, 56, 113, 113, 56, 97, 113, 56, 85, 113, 56, 69, 36 | 113, 56, 56, 113, 69, 56, 113, 85, 56, 113, 97, 56, 37 | 113, 113, 56, 97, 113, 56, 85, 113, 56, 69, 113, 56, 38 | 56, 113, 56, 56, 113, 69, 56, 113, 85, 56, 113, 97, 39 | 56, 113, 113, 56, 97, 113, 56, 85, 113, 56, 69, 113, 40 | 81, 81, 113, 89, 81, 113, 97, 81, 113, 105, 81, 113, 41 | 113, 81, 113, 113, 81, 105, 113, 81, 97, 113, 81, 89, 42 | 113, 81, 81, 113, 89, 81, 113, 97, 81, 113, 105, 81, 43 | 113, 113, 81, 105, 113, 81, 97, 113, 81, 89, 113, 81, 44 | 81, 113, 81, 81, 113, 89, 81, 113, 97, 81, 113, 105, 45 | 81, 113, 113, 81, 105, 113, 81, 97, 113, 81, 89, 113, 46 | 0, 0, 65, 16, 0, 65, 32, 0, 65, 48, 0, 65, 47 | 65, 0, 65, 65, 0, 48, 65, 0, 32, 65, 0, 16, 48 | 65, 0, 0, 65, 16, 0, 65, 32, 0, 65, 48, 0, 49 | 65, 65, 0, 48, 65, 0, 32, 65, 0, 16, 65, 0, 50 | 0, 65, 0, 0, 65, 16, 0, 65, 32, 0, 65, 48, 51 | 0, 65, 65, 0, 48, 65, 0, 32, 65, 0, 16, 65, 52 | 32, 32, 65, 40, 32, 65, 48, 32, 65, 56, 32, 65, 53 | 65, 32, 65, 65, 32, 56, 65, 32, 48, 65, 32, 40, 54 | 65, 32, 32, 65, 40, 32, 65, 48, 32, 65, 56, 32, 55 | 65, 65, 32, 56, 65, 32, 48, 65, 32, 40, 65, 32, 56 | 32, 65, 32, 32, 65, 40, 32, 65, 48, 32, 65, 56, 57 | 32, 65, 65, 32, 56, 65, 32, 48, 65, 32, 40, 65, 58 | 44, 44, 65, 48, 44, 65, 52, 44, 65, 60, 44, 65, 59 | 65, 44, 65, 65, 44, 60, 65, 44, 52, 65, 44, 48, 60 | 65, 44, 44, 65, 48, 44, 65, 52, 44, 65, 60, 44, 61 | 65, 65, 44, 60, 65, 44, 52, 65, 44, 48, 65, 44, 62 | 44, 65, 44, 44, 65, 48, 44, 65, 52, 44, 65, 60, 63 | 44, 65, 65, 44, 60, 65, 44, 52, 65, 44, 48, 65, 64 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 66 | }; -------------------------------------------------------------------------------- /masm2c/Token.py: -------------------------------------------------------------------------------- 1 | # Masm2c S2S translator (initially based on SCUMMVM tasmrecover) 2 | # 3 | # Masm2c is the legal property of its developers, whose names 4 | # are too numerous to list here. Please refer to the COPYRIGHT 5 | # file distributed with this source distribution. 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | # 21 | from typing import Any, Union 22 | 23 | import lark 24 | import lark.tree 25 | from lark import Tree 26 | 27 | SQEXPR = "sqexpr" 28 | 29 | 30 | class Token(lark.Tree): 31 | __slots__ = ("data", "children") 32 | 33 | def __init__(self, type, value) -> None: 34 | raise Exception("Dead code") 35 | 36 | 37 | # def __str__(self): 38 | 39 | # def __repr__(self): 40 | 41 | @staticmethod 42 | def find_tokens(expr: Any, lookfor: str) -> Union[list[str], list[lark.Tree], None]: 43 | l = [] 44 | if isinstance(expr, Tree): 45 | if expr.data == lookfor: 46 | if len(expr.children) == 1: 47 | l.append(expr.children[0]) 48 | else: 49 | l.append(expr.children) 50 | result = ( 51 | None 52 | if isinstance(expr.children, str) 53 | else Token.find_tokens(expr.children, lookfor) 54 | ) 55 | if result: 56 | l += result 57 | elif isinstance(expr, lark.Token): 58 | if expr.type == lookfor: 59 | l.append(expr.value) 60 | elif isinstance(expr, list): 61 | for i in range(len(expr)): 62 | if result := Token.find_tokens(expr[i], lookfor): 63 | l += result 64 | if not l: 65 | return None 66 | return l 67 | 68 | 69 | @staticmethod 70 | def remove_tokens(expr: Any, lookfor: list) -> Any: 71 | if isinstance(expr, Tree): 72 | if expr.data in lookfor: 73 | #if len(expr.children) == 1 and isinstance(expr.children[0], str): 74 | expr = expr.children 75 | expr = Token.remove_tokens(expr, lookfor) 76 | else: 77 | expr.children = Token.remove_tokens(expr.children, lookfor) 78 | return expr 79 | elif isinstance(expr, list): 80 | l = [] 81 | for i in range(len(expr)): 82 | result = Token.remove_tokens(expr[i], lookfor) 83 | if result is not None: 84 | if isinstance(result, list): 85 | l.extend(result) 86 | else: 87 | l.append(result) 88 | # if not l: 89 | return l 90 | return expr 91 | 92 | 93 | 94 | class Expression(lark.Tree): 95 | 96 | def __init__(self, *args, **kwargs) -> None: 97 | if not args: 98 | args = "expr", [] 99 | super().__init__(*args, **kwargs) 100 | from masm2c.enumeration import IndirectionType 101 | self.data = "expr" 102 | self.indirection: IndirectionType = IndirectionType.VALUE 103 | self.element_size = 0 104 | self.element_number = 1 105 | self.element_size_guess = 0 106 | self.ptr_size = 0 107 | self.mods: set[str] = set() 108 | self.registers: set[str] = set() 109 | self.segment_register = "ds" 110 | self.segment_overriden = False 111 | self.original_type = "" 112 | 113 | def size(self) -> int: 114 | from masm2c.enumeration import IndirectionType 115 | if self.indirection == IndirectionType.POINTER: 116 | return self.ptr_size 117 | else: 118 | return self.element_size * self.element_number 119 | 120 | -------------------------------------------------------------------------------- /asm_emu/x86_imul.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_X86_INTERNAL_H 2 | #warning Do not include this file directly 3 | #else 4 | 5 | static inline void asm_imul_1_l(struct assembler_state_t *state, uint32_t src) 6 | { 7 | uint64_t result = (uint64_t)((int64_t)((int32_t)src) * (int32_t)state->eax); 8 | uint32_t low_result = result; 9 | uint32_t high_result = result>>32; 10 | /* 11 | uint32_t low_result = 0; 12 | uint32_t high_result = 0; 13 | uint32_t low_src; 14 | uint32_t high_src; 15 | uint32_t tmp; 16 | uint_fast32_t mask=1; 17 | int i; 18 | 19 | int invert_result = (state->eax ^ src) & 0x80000000; 20 | 21 | if (src & 0x80000000) 22 | src = ~src; 23 | if (state->eax & 0x80000000) 24 | state->eax = ~state->eax; 25 | 26 | low_src = state->eax; 27 | high_src = 0; 28 | 29 | for (i=0;i<32;i++) 30 | { 31 | if (src & mask) 32 | { 33 | tmp = low_result + low_src; 34 | if (tmp < low_result) 35 | high_result++; 36 | low_result = tmp; 37 | 38 | high_result += high_src; 39 | } 40 | 41 | mask <<= 1; 42 | high_src <<= 1; 43 | if (low_src & 0x80000000) 44 | high_src|=1; 45 | low_src <<= 1; 46 | } 47 | 48 | if (invert_result) 49 | { 50 | low_result = ~low_result; 51 | high_result = ~high_result; 52 | }*/ 53 | if ((high_result == 0xffffffff) || (high_result == 0x00000000)) 54 | { 55 | write_of(state->eflags, 0); 56 | write_cf(state->eflags, 0); 57 | } else { 58 | write_of(state->eflags, 1); 59 | write_cf(state->eflags, 1); 60 | } 61 | state->edx = high_result; 62 | state->eax = low_result; 63 | } 64 | 65 | static inline void asm_imul_1_w(struct assembler_state_t *state, const uint16_t src) 66 | { 67 | uint32_t result = (uint32_t)((int32_t)((int16_t)src) * (int16_t)state->ax); 68 | 69 | state->dx = (result >> 16); 70 | if ((state->dx == 0xffff) || (state->dx == 0x0000)) 71 | { 72 | write_of(state->eflags, 0); 73 | write_cf(state->eflags, 0); 74 | } else { 75 | write_of(state->eflags, 1); 76 | write_cf(state->eflags, 1); 77 | } 78 | state->ax = result & 0xffff; 79 | } 80 | 81 | static inline void asm_imul_1_b(struct assembler_state_t *state, const uint8_t src) 82 | { 83 | state->ax = (uint16_t)((int16_t)((int8_t)src) * (int8_t)state->ax); 84 | 85 | if ((state->ah == 0xff) || (state->ah == 0x00)) 86 | { 87 | write_of(state->eflags, 0); 88 | write_cf(state->eflags, 0); 89 | } else { 90 | write_of(state->eflags, 1); 91 | write_cf(state->eflags, 1); 92 | } 93 | } 94 | 95 | static inline void asm_imul_2_l(struct assembler_state_t *state, uint32_t src, uint32_t *dst) 96 | { 97 | uint64_t result = (uint64_t)((int64_t)((int32_t)src) * (int32_t)*dst); 98 | uint32_t low_result = result; 99 | uint32_t high_result = result>>32; 100 | 101 | /* 102 | uint32_t low_result = 0; 103 | uint32_t high_result = 0; 104 | uint32_t low_src; 105 | uint32_t high_src; 106 | uint32_t tmp; 107 | uint_fast32_t mask=1; 108 | int i; 109 | 110 | int invert_result = (*dst ^ src) & 0x80000000; 111 | 112 | if (src & 0x80000000) 113 | src = ~src; 114 | if (*dst & 0x80000000) 115 | *dst = ~*dst; 116 | 117 | low_src = *dst; 118 | high_src = 0; 119 | 120 | for (i=0;i<32;i++) 121 | { 122 | if (src & mask) 123 | { 124 | tmp = low_result + low_src; 125 | if (tmp < low_result) 126 | high_result++; 127 | low_result = tmp; 128 | 129 | high_result += high_src; 130 | } 131 | 132 | mask <<= 1; 133 | high_src <<= 1; 134 | if (low_src & 0x80000000) 135 | high_src|=1; 136 | low_src <<= 1; 137 | } 138 | 139 | if (invert_result) 140 | { 141 | low_result = ~low_result; 142 | high_result = ~high_result; 143 | }*/ 144 | if (!high_result) /* x86 is dirty as hell here! */ 145 | { 146 | write_of(state->eflags, 0); 147 | write_cf(state->eflags, 0); 148 | } else { 149 | write_of(state->eflags, 1); 150 | write_cf(state->eflags, 1); 151 | } 152 | *dst = low_result; 153 | } 154 | 155 | static inline void asm_imul_2_w(struct assembler_state_t *state, const uint16_t src, uint16_t *dst) 156 | { 157 | uint32_t result = (uint32_t)((int32_t)((int16_t)src) * (int16_t)*dst); 158 | 159 | if (!(result & 0xffff0000)) /* x86 is dirty as hell here! */ 160 | { 161 | write_of(state->eflags, 0); 162 | write_cf(state->eflags, 0); 163 | } else { 164 | write_of(state->eflags, 1); 165 | write_cf(state->eflags, 1); 166 | } 167 | *dst = result & 0xffff; 168 | } 169 | static inline void asm_imul_2_b(struct assembler_state_t *state, const uint8_t src, uint8_t *dst) 170 | { 171 | uint16_t result = (uint16_t)((int16_t)((int8_t)src) * (int8_t)*dst); 172 | 173 | if (!(result & 0xff00)) /* x86 is dirty as hell here! */ 174 | { 175 | write_of(state->eflags, 0); 176 | write_cf(state->eflags, 0); 177 | } else { 178 | write_of(state->eflags, 1); 179 | write_cf(state->eflags, 1); 180 | } 181 | *dst = result & 0xff; 182 | } 183 | #endif 184 | -------------------------------------------------------------------------------- /masm2c/symbol_table.py: -------------------------------------------------------------------------------- 1 | """Symbol Table for managing global symbols in masm2c.""" 2 | 3 | import logging 4 | from collections import OrderedDict 5 | from typing import Any, TYPE_CHECKING, Union 6 | 7 | # Avoid circular imports for type hints 8 | if TYPE_CHECKING: 9 | from masm2c.op import Struct, label, var, _equ, _assignment 10 | from masm2c.proc import Proc 11 | from lark.lexer import Token 12 | 13 | # Define the type alias for possible symbol values 14 | SymbolValue = Union['Struct', 'label', 'Proc', 'var', '_equ', '_assignment'] 15 | 16 | def _format_object(value: SymbolValue) -> str: 17 | """Helper to represent object as string (copied from parser.py).""" 18 | import re 19 | if not hasattr(value, "__dict__"): 20 | return "" 21 | stuff = str(vars(value)) 22 | replacements = ( 23 | (r"\n", " "), 24 | (r"[{}]", ""), 25 | (r"'([A-Za-z_0-9]+)'\s*:\s*", r"\g<1>="), 26 | ) 27 | for old, new in replacements: 28 | stuff = re.sub(old, new, stuff) 29 | stuff = f"{value.__class__.__name__}({stuff})" 30 | return stuff 31 | 32 | class SymbolTable: 33 | """Manages global symbols for the MASM parser.""" 34 | 35 | def __init__(self) -> None: 36 | self.symbols: OrderedDict[str, SymbolValue] = OrderedDict() 37 | self.pass_number = 0 # Track pass number for definition checks 38 | self.test_mode = False # To allow redefinition in tests 39 | 40 | def set_pass_info(self, pass_number: int, test_mode: bool) -> None: 41 | """Set pass number and test mode from the main parser.""" 42 | self.pass_number = pass_number 43 | self.test_mode = test_mode 44 | 45 | def set_global(self, name: str, value: SymbolValue) -> None: 46 | """Adds or updates a global symbol.""" 47 | if not name: 48 | raise NameError("empty name is not allowed") 49 | value.original_name = name # Keep track of original casing/name 50 | name = name.lower() 51 | 52 | logging.debug("SymbolTable.set_global(name='%s', value=%s)", name, _format_object(value)) 53 | if name in self.symbols and self.pass_number == 1 and not self.test_mode: 54 | # Allow redefinition in later passes or test mode 55 | raise LookupError(f"global {name} was already defined in pass 1") 56 | value.used = False # Mark as unused initially 57 | self.symbols[name] = value 58 | 59 | def reset_global(self, name: str, value: SymbolValue) -> None: 60 | """Forcefully overwrite a global symbol, bypassing normal checks. 61 | 62 | Use this method only when intentionally replacing an existing symbol, 63 | such as during procedure merging or other advanced transformations. 64 | 65 | Args: 66 | name: Original symbol name 67 | value: New symbol value 68 | """ 69 | if not name: 70 | raise NameError("empty name is not allowed") 71 | value.original_name = name 72 | name = name.lower() 73 | logging.debug("SymbolTable.reset_global(name='%s', value=%s)", name, value) 74 | self.symbols[name] = value 75 | 76 | def get_global(self, name: Union['Token', str]) -> Any: 77 | """Retrieve a global symbol without marking it as used. 78 | 79 | Args: 80 | name: Symbol name (either as string or Token) 81 | 82 | Returns: 83 | The symbol object if found, otherwise None 84 | """ 85 | name_str = str(name).lower() 86 | logging.debug("SymbolTable.get_global(%s)", name_str) 87 | return self.symbols.get(name_str) 88 | 89 | def get_and_mark_global(self, name: Union['Token', str]) -> Any: 90 | """Retrieve a global symbol and mark it as used in the current context. 91 | 92 | This method both fetches the symbol and updates its 'used' flag, 93 | which helps track which symbols are actually referenced in the code. 94 | 95 | Args: 96 | name: Symbol name (either as string or Token) 97 | 98 | Returns: 99 | The symbol object if found, otherwise None 100 | """ 101 | name_str = str(name).lower() 102 | logging.debug("SymbolTable.get_and_mark_global(%s)", name_str) 103 | symbol = self.symbols.get(name_str) 104 | logging.debug("Found type: %s", type(symbol)) 105 | if symbol is None: 106 | logging.debug("SymbolTable KeyError: %s", name_str) 107 | return None 108 | symbol.used = True 109 | return symbol 110 | 111 | def get_globals(self) -> OrderedDict[str, SymbolValue]: 112 | """Returns the entire dictionary of global symbols.""" 113 | return self.symbols 114 | 115 | def __contains__(self, name: str) -> bool: 116 | """Allows checking 'if name in symbol_table'.""" 117 | return name.lower() in self.symbols -------------------------------------------------------------------------------- /error.h: -------------------------------------------------------------------------------- 1 | /****************************************************************/ 2 | /* */ 3 | /* error.h */ 4 | /* */ 5 | /* DOS-C error return codes */ 6 | /* */ 7 | /* December 1, 1991 */ 8 | /* */ 9 | /* Copyright (c) 1995 */ 10 | /* Pasquale J. Villani */ 11 | /* All Rights Reserved */ 12 | /* */ 13 | /* This file is part of DOS-C. */ 14 | /* */ 15 | /* DOS-C is free software; you can redistribute it and/or */ 16 | /* modify it under the terms of the GNU General Public License */ 17 | /* as published by the Free Software Foundation; either version */ 18 | /* 2, or (at your option) any later version. */ 19 | /* */ 20 | /* DOS-C is distributed in the hope that it will be useful, but */ 21 | /* WITHOUT ANY WARRANTY; without even the implied warranty of */ 22 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 23 | /* the GNU General Public License for more details. */ 24 | /* */ 25 | /* You should have received a copy of the GNU General Public */ 26 | /* License along with DOS-C; see the file COPYING. If not, */ 27 | /* write to the Free Software Foundation, 675 Mass Ave, */ 28 | /* Cambridge, MA 02139, USA. */ 29 | /****************************************************************/ 30 | 31 | #ifdef MAIN 32 | #ifdef VERSION_STRINGS 33 | static BYTE *error_hRcsId = 34 | "$Id: error.h 485 2002-12-09 00:17:15Z bartoldeman $"; 35 | #endif 36 | #endif 37 | 38 | /* Internal system error returns */ 39 | #define SUCCESS 0 /* Function was successful */ 40 | #define DE_INVLDFUNC -1 /* Invalid function number */ 41 | #define DE_FILENOTFND -2 /* File not found */ 42 | #define DE_PATHNOTFND -3 /* Path not found */ 43 | #define DE_TOOMANY -4 /* Too many open files */ 44 | #define DE_ACCESS -5 /* Access denied */ 45 | #define DE_INVLDHNDL -6 /* Invalid handle */ 46 | #define DE_MCBDESTRY -7 /* Memory control blocks shot */ 47 | #define DE_NOMEM -8 /* Insufficient memory */ 48 | #define DE_INVLDMCB -9 /* Invalid memory control block */ 49 | #define DE_INVLDENV -10 /* Invalid enviornement */ 50 | #define DE_INVLDFMT -11 /* Invalid format */ 51 | #define DE_INVLDACC -12 /* Invalid access */ 52 | #define DE_INVLDDATA -13 /* Invalid data */ 53 | #define DE_INVLDDRV -15 /* Invalid drive */ 54 | #define DE_RMVCUDIR -16 /* Attempt remove current dir */ 55 | #define DE_DEVICE -17 /* Not same device */ 56 | #define DE_NFILES -18 /* No more files */ 57 | #define DE_WRTPRTCT -19 /* No more files */ 58 | #define DE_BLKINVLD -20 /* invalid block */ 59 | #define DE_INVLDBUF -24 /* invalid buffer size, ext fnc */ 60 | #define DE_SEEK -25 /* error on file seek */ 61 | #define DE_HNDLDSKFULL -28 /* handle disk full (?) */ 62 | 63 | #define DE_INVLDPARM -0x57 /* invalid parameter */ 64 | 65 | #define DE_DEADLOCK -36 66 | #define DE_LOCK -39 67 | 68 | #define DE_FILEEXISTS -80 /* File exists */ 69 | 70 | /* Critical error flags */ 71 | #define EFLG_READ 0x00 /* Read error */ 72 | #define EFLG_WRITE 0x01 /* Write error */ 73 | #define EFLG_RSVRD 0x00 /* Error in rserved area */ 74 | #define EFLG_FAT 0x02 /* Error in FAT area */ 75 | #define EFLG_DIR 0x04 /* Error in dir area */ 76 | #define EFLG_DATA 0x06 /* Error in data area */ 77 | #define EFLG_ABORT 0x08 /* Handler can abort */ 78 | #define EFLG_RETRY 0x10 /* Handler can retry */ 79 | #define EFLG_IGNORE 0x20 /* Handler can ignore */ 80 | #define EFLG_CHAR 0x80 /* Error in char or FAT image */ 81 | 82 | /* error results returned after asking user */ 83 | /* MS-DOS compatible -- returned by CriticalError */ 84 | #define CONTINUE 0 85 | #define RETRY 1 86 | #define ABORT 2 87 | #define FAIL 3 88 | 89 | -------------------------------------------------------------------------------- /asm_16.h: -------------------------------------------------------------------------------- 1 | #ifndef __asm_16_h__ 2 | #define __asm_16_h__ 3 | 4 | typedef dw MWORDSIZE; 5 | 6 | #if defined(_PROTECTED_MODE) 7 | // #define raddr(segment,offset) ((db *)&m2c::m+(db)(offset)+selectors[segment]) 8 | static inline db* raddr_(dw segment,dw offset) {return ((db *)&m+(dw)(offset)+selectors[segment]);} 9 | #else 10 | //#define raddr(segment,offset) (((db *)&m2c::m + ((segment)<<4) + (offset) )) 11 | static inline db* raddr_(dw segment,dw offset) {return (db *)&m + (segment<<4) + offset;} 12 | #endif 13 | 14 | #define offset(segment,name) ((db*)(&name)-(db*)(&segment)) 15 | #define far_offset(segment,name) (offset(segment,name)+(seg_offset(segment)<<16)) 16 | #define MOVSS(a) {void * dest;void * src;src=realAddress(si,ds); dest=realAddress(di,es); \ 17 | memmove(dest,src,a); di+=(GET_DF()==0)?a:-a; si+=(GET_DF()==0)?a:-a; } 18 | #define STOS(a,b) {memcpy (realAddress(di,es), ((db *)&eax)+b, a); di+=(GET_DF()==0)?a:-a;} 19 | 20 | #define REP cx++;while (--cx != 0) 21 | #define REPE if (cx) {AFFECT_ZFifz(0);};cx++;while (--cx != 0 && GET_ZF()) 22 | #define REPNE if (cx) {AFFECT_ZFifz(1);};cx++;while (--cx != 0 && !GET_ZF()) 23 | #define XLAT {al = *m2c::raddr_(ds,bx+al);} 24 | #define CMPSB \ 25 | { \ 26 | db* src=realAddress(si,ds); db* dest=realAddress(di,es); \ 27 | CMP(*src, *dest); di+=(GET_DF()==0)?1:-1; si+=(GET_DF()==0)?1:-1; \ 28 | } 29 | #define CMPSW \ 30 | { \ 31 | dw* src=(dw*)realAddress(si,ds); dw* dest=(dw*)realAddress(di,es); \ 32 | CMP(*src, *dest); di+=(GET_DF()==0)?2:-2; si+=(GET_DF()==0)?2:-2; \ 33 | } 34 | #define CMPSD \ 35 | { \ 36 | dd* src=(dd*)realAddress(si,ds); dd* dest=(dd*)realAddress(di,es); \ 37 | CMP(*src, *dest); di+=(GET_DF()==0)?4:-4; si+=(GET_DF()==0)?4:-4; \ 38 | } 39 | 40 | #define SCASB \ 41 | { \ 42 | CMP(al, *realAddress(di,es)); di+=(GET_DF()==0)?1:-1; \ 43 | } 44 | #define SCASW \ 45 | { \ 46 | CMP(ax, *(dw*)realAddress(di,es)); di+=(GET_DF()==0)?2:-2; \ 47 | } 48 | #define SCASD \ 49 | { \ 50 | CMP(eax, *(dd*)realAddress(di,es)); di+=(GET_DF()==0)?4:-4; \ 51 | } 52 | 53 | /* 54 | #define LODS(addr,destreg,s) {memcpy (((db *)&eax), &(addr), s);; destreg+=(GET_DF()==0)?s:-s;} 55 | #define LODSS(a,b) {memcpy (((db *)&eax)+b, realAddress(si,ds), a); si+=(GET_DF()==0)?a:-a;} 56 | 57 | #ifdef MSB_FIRST 58 | #define STOSB STOS(1,3) 59 | #define STOSW STOS(2,2) 60 | #else 61 | 62 | //SDL2 VGA 63 | #if SDL_MAJOR_VERSION == 2 && !defined(NOSDL) 64 | #define STOSB { \ 65 | if (es==0xa000)\ 66 | { \ 67 | SDL_SetRenderDrawColor(renderer, vgaPalette[3*al+2], vgaPalette[3*al+1], vgaPalette[3*al], 255); \ 68 | SDL_RenderDrawPoint(renderer, di%320, di/320); \ 69 | SDL_RenderPresent(renderer); \ 70 | di+=(GET_DF()==0)?1:-1;} \ 71 | else \ 72 | {STOS(1,0);} \ 73 | } 74 | #else 75 | #define STOSB STOS(1,0) 76 | #endif 77 | 78 | #ifdef A_NORMAL 79 | #define STOSW { \ 80 | if (es==0xB800) \ 81 | {dd averytemporary=(di>>1);attrset(COLOR_PAIR(ah)); mvaddch(averytemporary/80, averytemporary%80, al); di+=(GET_DF()==0)?2:-2;refresh();} \ 82 | else \ 83 | {STOS(2,0);} \ 84 | } 85 | #else 86 | #define STOSW STOS(2,0) 87 | #endif 88 | #endif 89 | #define STOSD STOS(4,0) 90 | */ 91 | 92 | #define LODSB {al = m2c::getdata(*(db*)m2c::raddr_(ds,si)); si+=(GET_DF()==0)?1:-1;} 93 | #define LODSW {ax = m2c::getdata(*(dw*)m2c::raddr_(ds,si)); si+=(GET_DF()==0)?2:-2;} 94 | #define LODSD {eax = m2c::getdata(*(dd*)m2c::raddr_(ds,si)); si+=(GET_DF()==0)?4:-4;} 95 | 96 | #define OUTSB {OUT(dx,(db)m2c::getdata(*(db*)m2c::raddr_(ds,si))); si+=(GET_DF()==0)?1:-1;} 97 | #define OUTSW {OUT(dx,(dw)m2c::getdata(*(dw*)m2c::raddr_(ds,si))); si+=(GET_DF()==0)?2:-2;} 98 | 99 | #define MOVSB {m2c::setdata( (db*)m2c::raddr_(es,di), m2c::getdata(*(db*)m2c::raddr_(ds,si)) );si+=(GET_DF()==0)?1:-1;di+=(GET_DF()==0)?1:-1;} {if (m2c::repForMov) AFFECT_ZF(m2c::oldZF); m2c::repForMov=false;} 100 | #define MOVSW {m2c::setdata( (dw*)m2c::raddr_(es,di), m2c::getdata(*(dw*)m2c::raddr_(ds,si)) );si+=(GET_DF()==0)?2:-2;di+=(GET_DF()==0)?2:-2;} {if (m2c::repForMov) AFFECT_ZF(m2c::oldZF); m2c::repForMov=false;} 101 | #define MOVSD {m2c::setdata( (dd*)m2c::raddr_(es,di), m2c::getdata(*(dd*)m2c::raddr_(ds,si)) );si+=(GET_DF()==0)?4:-4;di+=(GET_DF()==0)?4:-4;} {if (m2c::repForMov) AFFECT_ZF(m2c::oldZF); m2c::repForMov=false;} 102 | 103 | #define STOSB {m2c::setdata( (db*)m2c::raddr_(es,di), al);di+=(GET_DF()==0)?1:-1;} {m2c::repForMov=false;} 104 | #define STOSW {m2c::setdata( (dw*)m2c::raddr_(es,di), ax);di+=(GET_DF()==0)?2:-2;} {m2c::repForMov=false;} 105 | #define STOSD {m2c::setdata( (dd*)m2c::raddr_(es,di), eax);di+=(GET_DF()==0)?4:-4;} {m2c::repForMov=false;} 106 | 107 | 108 | #define INSB {db averytemporary3 = asm2C_IN(dx);*realAddress(di,es)=averytemporary3;di+=(GET_DF()==0)?1:-1;} 109 | #define INSW {dw averytemporary3 = asm2C_INW(dx);*realAddress(di,es)=averytemporary3;di+=(GET_DF()==0)?2:-2;} 110 | 111 | #define LOOP(label) if (--cx) GOTOLABEL(label) 112 | #define LOOPE(label) if (--cx && GET_ZF()) GOTOLABEL(label) 113 | #define LOOPNE(label) if (--cx && !GET_ZF()) GOTOLABEL(label) 114 | 115 | 116 | #endif 117 | 118 | -------------------------------------------------------------------------------- /memmgr.h: -------------------------------------------------------------------------------- 1 | /****************************************************************/ 2 | /* */ 3 | /* memmgr.h */ 4 | /* */ 5 | /* Memory Manager for Core Allocation */ 6 | /* */ 7 | /* Copyright (c) 1995 */ 8 | /* Pasquale J. Villani */ 9 | /* All Rights Reserved */ 10 | /* */ 11 | /* This file is part of DOS-C. */ 12 | /* */ 13 | /* DOS-C is free software; you can redistribute it and/or */ 14 | /* modify it under the terms of the GNU General Public License */ 15 | /* as published by the Free Software Foundation; either version */ 16 | /* 2, or (at your option) any later version. */ 17 | /* */ 18 | /* DOS-C is distributed in the hope that it will be useful, but */ 19 | /* WITHOUT ANY WARRANTY; without even the implied warranty of */ 20 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 21 | /* the GNU General Public License for more details. */ 22 | /* */ 23 | /* You should have received a copy of the GNU General Public */ 24 | /* License along with DOS-C; see the file COPYING. If not, */ 25 | /* write to the Free Software Foundation, 675 Mass Ave, */ 26 | /* Cambridge, MA 02139, USA. */ 27 | /****************************************************************/ 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include "mcb.h" 34 | 35 | namespace m2c { 36 | 37 | typedef uint8_t db; 38 | typedef uint16_t dw; 39 | 40 | // !struct Memory; 41 | // !extern struct Memory m; 42 | 43 | 44 | //#define MK_FP(seg,ofs) (&(raddr(seg,ofs))) // ( (ULONG(seg)<<4)+(UWORD)(ofs) ) 45 | #define FP_SEG(fp) ( ( ((uint8_t*)(fp)) - ((uint8_t*)(&m2c::m)) )>>4) 46 | //#define FP_OFF(fp) ( (UWORD) (fp) ) 47 | #define SUCCESS 0 48 | //#define NULL 0 49 | 50 | extern uint16_t first_mcb; /* Start of user memory */ 51 | extern db mem_access_mode; 52 | 53 | #define nxtMCBsize(mcbp,size) ((mcb*)(((db*)mcbp) + (size<<4) + 0x10)) 54 | #define nxtMCB(mcbp) nxtMCBsize((mcbp), (mcbp)->m_size) 55 | 56 | #define mcbFree(mcbp) ((mcbp)->m_psp == FREE_PSP) 57 | #define mcbValid(mcbp) ( ((mcbp)->m_size != 0xffff) && \ 58 | ((mcbp)->m_type == MCB_NORMAL || (mcbp)->m_type == MCB_LAST) ) 59 | #define mcbFreeable(mcbp) \ 60 | ((mcbp)->m_type == MCB_NORMAL || (mcbp)->m_type == MCB_LAST) 61 | 62 | #define para2far(seg) ( (mcb *)((db *)&m2c::m + ((seg)<<4)) ) //(seg<<4) 63 | 64 | typedef mcb * mcb_p; 65 | 66 | /* 67 | * Join any following unused MCBs to MCB 'p'. 68 | * Return: 69 | * SUCCESS: on success 70 | * else: error number <> 71 | */ 72 | static int joinMCBs(seg para); 73 | 74 | /* Allocate a new memory area. *para is assigned to the segment of the 75 | MCB rather then the segment of the data portion */ 76 | /* If mode == LARGEST, asize MUST be != NULL and will always recieve the 77 | largest available block, which is allocated. 78 | If mode != LARGEST, asize maybe NULL, but if not, it is assigned to the 79 | size of the largest available block only on failure. 80 | size is the minimum size of the block to search for, 81 | even if mode == LARGEST. 82 | */ 83 | int DosMemAlloc(UWORD size, int mode, seg *para, UWORD *asize); 84 | 85 | /* 86 | * Unlike the name and the original prototype could suggest, this function 87 | * is used to return the _size_ of the largest available block rather than 88 | * the block itself. 89 | * 90 | * Known bug: a memory area with a size of the data area of 0 (zero) is 91 | * not considered a "largest" block. <> 92 | */ 93 | int DosMemLargest(UWORD *size); 94 | 95 | /* 96 | * Deallocate a memory block. para is the segment of the MCB itself 97 | * This function can be called with para == 0, which eases other parts 98 | * of the kernel. 99 | */ 100 | int DosMemFree(UWORD para); 101 | 102 | /* 103 | * Resize an allocated memory block. 104 | * para is the segment of the data portion of the block rather than 105 | * the segment of the MCB itself. 106 | * 107 | * If the block shall grow, it is resized to the maximal size less than 108 | * or equal to size. This is the way MS DOS is reported to work. 109 | */ 110 | int DosMemChange(UWORD para, UWORD size, UWORD * maxSize); 111 | 112 | /* 113 | * Check the MCB chain for allocation corruption 114 | */ 115 | int DosMemCheck(void); 116 | 117 | 118 | #ifdef DEBUG3 119 | void show_chain(void); 120 | 121 | void mcb_print(mcb_p mcbp); 122 | #endif 123 | 124 | static void mcb_init_copy(dw seg, dw size, mcb *near_mcb); 125 | 126 | void mcb_init(dw seg, dw size, BYTE type); 127 | 128 | } 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | --------------------------------------------------------------------------------