Frequently Asked Questions v0.00.0033 Q. When will Softx86 become a full-fledged PC emulator? A. It won't. It will however become a full-fledged Intel 80x86 CPU clone that you can tie into your PC emulation software. Q. Where are the sample DOS binaries used to test the emulator? A. Prebuilt binaries are now distributed separately from the source tarball. The source code is still provided, so you can assemble them yourself if you have NASM (Netwide Assembler) installed on your system. Q. How do I use softx86dbg? A. Bring up the command prompt (Windows or Linux), change to the root directory of the source tree and type "bin/softx86dbg" followed by a path to a DOS .COM executable. For example, to run samples/test11.com in the emulator, type: bin/softx86dbg samples/test11.com Linux users may benefit from running the statically linked version (especially if they cannot "su root" and "make install") because a previous version of the library installed in /usr/local/lib might be incompatible with the latest version of softx86dbg. You can run the statically linked version by typing: bin/softx86dbg-static samples/test11.com softx86dbg will let you know if it couldn't load the file. Q. Softx86dbg is running and it found the COM file I want to run. Now what? Softx86dbg more or less follows the DOS DEBUG.COM style interface. For each step, the values of the registers are shown. Commands are parsed one line at a time and each command is entered as one or more letters. The commands are: r [REGISTER] Change a register value r Show the register contents t Single-step (execute one instruction) q Quit d [[seg:]offset] Dump memory at given address. If no address is given, ds:0x0000 is assumed. If no segment value is given, the offset is assumed to be within the current data (DS) segment. u [[seg:]offset] Unassemble (disassemble) instructions at given address. If no address is given, disassembly starts at the current location of the instruction pointer (CS:IP). If no segment value is given, the offset is assumed to be within the current code (CS) segment. ? print help. Softx86dbg also recognizes commands that the original DOS DEBUG.COM never had: t [x] Single-step times. In other words, execute instructions then return. UPDATE: It turns out DEBUG.COM for Windows XP has this feature after all !reset Resets the virtual CPU. !ramdump Dumps the virtual RAM to a file named 1MB_MEM.BIN Q. What kind of environment does Softx86dbg emulate? A. Softx86dbg emulates a very simple DOS-style environment. An INT 21h interface is provided for the program to terminate by, and A simple PSP structure is built for the program. Softx86dbg also demonstrates the I/O port callback functions by emulating hypothetical hardware that takes input and performs a simple calculation with it. When the program terminates through INT 21h, softx86dbg prints a notice on the screen indicating that the program terminated. Q. How do I talk to the hypothetical hardware? A. Currently (as of v0.00.0020) there are two I/O ports that the hardware exists on. Port 0x1234 is a simple register. Every time it is read, the value is incremented by 0x22 or 0x2222 (depending on how much is read) and then returned to the CPU. When written, the value is copied verbatim to the register. Port 0x9A is a byte-sized register. When written, the value is incremented by 1 and then stored in the register. Then read, the value of the register is returned as-is. Since this can change in the future (not to mention conflicts with actual PC hardware) do not rely on these I/O ports being emulated. They are used only by samples/test04.com to test the I/O port emulation of Softx86. Q. I wrote a program that uses Softx86. How do I make it execute instructions? Is there a call that starts a background thread? A. Softx86 does not execute or decompile anything by itself. It expects your program to execute instructions one at a time using softx86_step(). Q. What is this "context structure" that every API function requires? A. The context structure represents one CPU and it's current state. All registers, modes, caches, and such are stored in that state. The design favors this over the use of static variables so that one copy of libsoftx86 can potentially emulate several CPUs at once. To "create" a CPU, allocate memory in your program for one context structure and call softx86_init(). /* example of C code creating and initializing softx86 context structure */ softx86_ctx* cpu; cpu = (softx86_ctx*)malloc(sizeof(softx86_ctx)); memset(cpu,0,sizeof(softx86_ctx)); /* recommended, not strictly necessary */ softx86_init(cpu); /* example of C++ code creating and initializing softx86 context structure */ softx86_ctx* cpu; cpu = new softx86_ctx; memset(cpu,0,sizeof(softx86_ctx)); /* recommended, not strictly necessary */ softx86_init(cpu); /* example of C++ code pushing softx86 to the extreme by creating 32 separate CPUs */ softx86_ctx* cpu; int x; cpu = new softx86_ctx[32]; memset(cpu,0,sizeof(softx86_ctx)*32); /* recommended, not strictly necessary */ for (x=0;x < 32;x++) /* 32 brains are better than one! */ softx86_init(&cpu[x]); The Softx86 API functions require this context structure so that they know what CPU to perform the operation on and so that they have access to the CPU state. To execute an instruction on cpu0 and decompile something on cpu1, for example, you would write: char cpu1_output[256]; softx86_step(&cpu0); softx86_decompile(&cpu1,cpu1_output); To delete a CPU and free the resources associated with it (including caches stored in the context structure), pass the context structure one last time to soft86_free(). Once it has been freed by softx86_free() you may free the memory used by the context structure itself (or do whatever you want to it). /* example of C code freeing a CPU */ softx86_free(cpu); free(cpu); cpu=NULL; /* example of C++ code freeing a CPU */ softx86_free(cpu); delete cpu; cpu=NULL; /* example of hot-shot C++ code (above) freeing all 32 CPUs he created */ int x; for (x=0;x < 32;x++) softx86_free(&cpu[x]); delete cpu; cpu=NULL; /* example of C code creating, freeing a CPU, then dancing on it's grave */ char *ptr; softx86_ctx* cpu; ptr = malloc(sizeof(softx86_ctx)); cpu = (softx86_ctx*)ptr; softx86_init(cpu); /* create CPU */ softx86_step(cpu); /* execute something */ softx86_free(cpu); /* you've served your purpose now get outta here! */ strcpy(ptr, /* alright yeah! Now I can safely use the same area of memory */ "Blah Blah Yadda Yadda"); /* to store funny weird ASCIIZ strings! Whoo! */ free(ptr); /* but I have better things to do... */ Q. I get strange errors from make or Bash even though the scripts and Makefiles look perfectly fine. A. The install.sh script may have gotten munged with DOS-style CR LF line breaks. This seems to happen when I pack the source code into a .tar.gz tarball then copy the tarball to my Windows machine and unpack it using WinZIP or 7-Zip. It doesn't immediately seem broken because Notepad and Wordpad show it perfectly, but when the extracted files are tar and gzip'd and moved back to the Linux box to be tested, the problems show up almost immediately. Bash expects to see only LF line breaks, which is why it panics the way it does. GNU Make as far as I know is generally tolerant of DOS CR/LF sequences so perhaps the Makefile is corrupt in some way. A quick fix can be done by changing to the directory containing Makefile and install.sh and typing: dos2unix install.sh; dos2unix Makefile Bash shouldn't have any more problems. NOTE: I've also found that WinZIP can't extract tar files properly if they contain symlinks. 7-Zip does just fine. Q. There are all these makefiles to make a static library and a DLL. There are also two makefiles to produce the same program: Softx86dbg. What's the point? why are you doing this? A. Producing Softx86 as a static library AND a DLL allows software developers to incorporate it into their programs in whatever flavor they like. Some people especially those producting standalone programs, like statically linked versions so that they don't have to deal with messy DLL dependencies or carry extra luggage around with the main executable. Other developers, especially those working on large projects, like modular designs so that DLLs and resources can be loaded and unloaded dynamically (imagine a large project that uses Softx86 as one of many emulation engines to simulate everything ranging from a PC to a Z-80 to a Super-NES, for example). For these large projects, Softx86 in DLL form is the best choice.