flat assembler
Message board for the users of flat assembler.
Index
> DOS > How do I set FASM to compile to 16bit realmode code? |
Author |
|
Tomasz Grysztar 01 Oct 2018, 07:36
In case of fasm it is the source text that determines the format of generated output (including the bitness of generated code). If you assemble a source that produces 16-bit MZ .EXE, it is going to produce such file no matter whether you assemble it with DOS, Win32 or Linux version of fasm.
Keeping that in mind, you can find examples of 16-bit MZ .EXE, .COM and even 16-bit .SYS for DOS in the "flat assembler for DOS" package. You do not have to run that version of fasm to assemble them, you can just extract the example sources from the package and assemble them with Win32 or Linux version of fasm for the same result. |
|||
01 Oct 2018, 07:36 |
|
Ben321 01 Oct 2018, 07:47
Just curious. Is it also possible to output NZ (16bit Windows EXE such as programs for Windows 3.1), using FASM?
|
|||
01 Oct 2018, 07:47 |
|
Tomasz Grysztar 01 Oct 2018, 08:08
No, there was never much interested in NE to make it worth it implementing it in fasm.
Nowadays it should be possible to make some macro sets for fasmg that would produce NE. I might one day do this (and also OMF and LE formats), but first I want to finish writing about the formats that are more relevant now. |
|||
01 Oct 2018, 08:08 |
|
Ben321 01 Oct 2018, 18:39
Tomasz Grysztar wrote: No, there was never much interested in NE to make it worth it implementing it in fasm. There are basically 3 main OSs in the main (Microsoft) line of OSs. These are DOS, Windows 16bit, and Windows 32/64bit. DOS used MZ. Windows 16bit used NE. Windows 32/64bit uses PE. So why did the makers of NASM allow it to compile MZ and PE EXEs, but completely skip NE EXEs? That seems like a pretty big omission. It would make sense if they only wanted to compile PE, as that's the latest version. Or if they wanted it to compile PE or NE, as those are all the Windows types of EXE files. It would even make sense if the assembler compiled MZ or NE EXE files, if the maker of the assembler was targeting the retro computing crowd. But to make it intentionally skip the capability to compile NE EXE files, seems just so random, and wrong. |
|||
01 Oct 2018, 18:39 |
|
DimonSoft 01 Oct 2018, 19:42
This forum is the wrong place to ask about decisions made by NASM developers.
Little intereset to NE EXEs may come from the fact that it hasn’t been around long enough. PE EXE is a must have feature these days, and MZ EXE and COM files support might be quite easy to implement. |
|||
01 Oct 2018, 19:42 |
|
Ben321 02 Oct 2018, 05:33
Ok, as it turns out, the latest version of Bochs, already is compiled with the needed options to use the debugger, and even the GUI based debugger. You just need to setup the settings file correctly to use the GUI based debugger.
Ok, good, now i have the debugger running. Now I just need to make sure that it pauses execution at the EXACT instant that the program that I want to debug actually starts executing. I don't want to debug DOS itself. I want to debug the program that I'm running from DOS, and do so starting with its FIRST opcode (to make sure I don't miss any potential bugs in the program). Can you tell me how to make sure the debugger pauses execution for debugging, only when the program itself first executes (and not in the DOS prompt)? I have tried inserting an INT3 opcode into the ASM itself, and made that the first instruction in my program, because it's industry standard to break at INT3. But it didn't break. Can you recommend another technique to accomplish this? |
|||
02 Oct 2018, 05:33 |
|
rugxulo 02 Oct 2018, 07:11
Ben321 wrote: Can you tell me how to make sure the debugger pauses execution for debugging, only when the program itself first executes (and not in the DOS prompt)? I have tried inserting an INT3 opcode into the ASM itself, and made that the first instruction in my program, because it's industry standard to break at INT3. But it didn't break. Can you recommend another technique to accomplish this? INT3 (0xCC) should work fine. When starting up the debugger (grdb invaders.com), it should automatically be at the start of your program anyways. So if you're running 'g' (for "go"), it will continue beyond that until the next INT3 (if any) is found. Of course, .COM starts at the beginning of the file itself, but .EXE has a header and will usually start later (32 bytes?). So .COM is easier, but most debuggers can handle .EXE fine also. Heck, DOS usually comes with DEBUG itself, so did even 32-bit Vista. (But the MS-DOS one is limited to 8086 only, so try the one from FreeDOS, or any others. I see you're using Insight, I've tried it but am not very familiar with it.) |
|||
02 Oct 2018, 07:11 |
|
Ben321 02 Oct 2018, 07:27
rugxulo wrote:
I no longer am using VirtualBox + MSDos6.22 + Insight. I've switched to using Bochs debugger version + MSDos6.22 as my testing platform. Bochs debugger version is its own emulator with builtin debugger. The simulated computer monitor (what DOS and any programs show up on) is one window, and the debugger is a separate window. It works much better (even showing 32bit registers, for when you are running in real mode but using opcodes that write 32bits to the registers, which are opcodes with a prefix). However it still has the problem of not stopping when it encounters an INT3 (so placing INT3 at the start of the program does not make sure it pauses execution at the start of the program). I've found a work around for this though. Make sure the first opcode in your program is "jmp start" (assuming your program starts with the label called start" which makes the program lock up at its first opcode. This gives you time to hit Ctrl+C to pause execution in the debugger. It is a 2 byte opcode (including the operand), so to skip it and continue with the program, just use the debugger itself to set the execution pointer 2 bytes ahead, and then step through the program one opcode at a time with F11. If you plan to release the program for others to use though, after debugging it make sure to remove the "jmp start" line at the beginning of the program, or whoever runs it will simply lock up their computer. |
|||
02 Oct 2018, 07:27 |
|
rugxulo 02 Oct 2018, 07:35
Ben321 wrote:
Actually, MS worked on many OSes, including Xenix and OS/2. In fact, MS' main work on OS/2 (before being fired, 1990??) was on 1.x series (up through 1.3), which was the 16-bit / 286 version. OS/2 2.x (32-bit) came later (IBM only, 1992??) and used LX format (but still using lots of 16-bit stuff internally). So technically NE was used (incompatibly) in both Win16 and OS/2 16-bit. I think Windows will get confused if you try running an OS/2 binary. They dropped OS/2 (1.x??) textmode app support after Win2k. And DOS can use various formats, but normally all you have is .COM (flat binary) and MZ .EXE. Although the rare, European-only multitasking MS-DOS 4.x used NE format (but that was more or less a predecessor to OS/2, which itself was originally/erroneously called "DOS 5".) I know I'm forgetting some things, and I'm far from a historian or expert, but it gets complicated fast. (DJGPP uses non-PE "COFF" while OpenWatcom uses LE. And there were other tools who supported PE/COFF or ELF in DOS, too. Oh, and several a.out variants.) BTW, isn't Win64 using what is called "PE+"? So it's not vanilla PE (although similar). I don't think you can link together 32-bit and 64-bit code (normally). Ben321 wrote:
NASM doesn't compile, it assembles, and it doesn't directly output any .EXE anyways (at least not without macros, but that's a very incomplete kludge). You need a linker to create an .EXE. Win16 (and OS/2) support is very rare these days and was never that widely supported in recent times. Even Win9x has been unsupported by MS since 2006, and XP has been dead since 2014. While there are many major DOS vendors (FreeDOS, DR-DOS, ROM-DOS, PTS-DOS), there were almost none that supported Win16 (maybe WINE and/or ReactOS halfway count, and OS/2 obviously). But even DOS is extremely overlooked, so most of that is legacy (and lots of even that is lost or bitrotted). Though there was i8086-msdos target support officially added to FPC in 3.0.0 (2015) with ppcross8086.exe, which does (in trunk??) have very experimental Win16 support. Ben321 wrote:
NE is segmented, pmode, and thus more complicated than even MZ .EXE (which isn't necessarily ultra simple). Varying headers, optional sections, overlays, resources, etc. I don't know jack, but I know it's very complicated! Very little people care about 286-only code. Even IA-32 is deprecated by many people. Heck, with AVX-512, it feels like even SSE (2, 3, 4) is deprecated! MS has very little interest in legacy these days. And Win64 doesn't like 16-bit apps at all, so you can't run any DOS (not even DJGPP!) or Win16 or OS/2 stuff. Even the BIOS (and CSM) won't exist on newer machines starting in 2020. EDIT: OpenWatcom has good OS/2 support, so it probably supports NE. (Check out Arca Noae, if morbidly curious.) Also, Japheth's HX has some partial 16-bit (286) DPMI and NE loader support (and partial OS/2 API emulation albeit not nearly as good as Win32). If you wanted to investigate, those are probably the places to look. Well, I couldn't find Wotsit.org NE text, but I did find winresdump and NE Format (nice description). |
|||
02 Oct 2018, 07:35 |
|
rugxulo 02 Oct 2018, 08:08
Ben321 wrote:
Please use RUFUS to create a bootable USB jump drive that has (minimal) DOS on it. (You don't even need any extra files although you can use FreeDOS' .iso if desired, I think. But I haven't tried again lately.) Then you won't have to worry about buggy emulators. (Although I still think you're doing it wrong, but I can't be sure. You don't need to put INT3 as first instruction, the debugger already starts at the first instruction.) That assumes you have a BIOS machine (but later than P4, which normally didn't boot from USB natively). Actually, you could use PLoP Boot Manager (floppy? CD?) to boot on such an old machine (like my old P4), but it would be considered read-only. |
|||
02 Oct 2018, 08:08 |
|
rugxulo 02 Oct 2018, 08:12
Ben321 wrote:
You could probably call the BIOS by "xor ah,ah" and "int 16h" instead. ("Wait for Keypress and Read Character". See HelpPC or RBIL for more info.) |
|||
02 Oct 2018, 08:12 |
|
DimonSoft 02 Oct 2018, 08:14
Ben321 wrote: I no longer am using VirtualBox + MSDos6.22 + Insight. I've switched to using Bochs debugger version + MSDos6.22 as my testing platform. Pretty strange choice of a debugger for MS-DOS programs. And the questions following that choice show that. AFAIR, Bochs has special behaviour of breakpoint for xchg bx, bx. May be wrong though. What are you really debugging: MS-DOS programs or your own OS? Bochs seems to be more suitable for the second case than the first one. |
|||
02 Oct 2018, 08:14 |
|
alexfru 02 Oct 2018, 08:27
Ben321 wrote: Just curious. Is it also possible to output NZ (16bit Windows EXE such as programs for Windows 3.1), using FASM? Should be. I mainly use NASM and I have a small NE program written for NASM. |
|||
02 Oct 2018, 08:27 |
|
Ben321 02 Oct 2018, 20:12
DimonSoft wrote:
I'm trying to write a program that runs in 32bit protected mode. This mode has a major advantage, over 16bit real mode. It uses 32bit instructions with the same opcode that would be 16bit instructions in real mode. This means no need for an opcode prefix when using 32bit instructions. This makes each instruction take 1 byte less, and this saves both space (fewer bytes) and time during execution (executing a program with shorter instructions takes less time, simply because the CPU has fewer bits to process). My plan is to create a very simple 32bit protected mode program (not an OS), that runs directly from DOS, and thus does not need to run in a 32bit OS. It will switch itself into 32bit protected mode as the first thing it does when executing, and switch itself back to 16bit real mode as the last thing it does just before exiting to DOS. As you can see, because of these real/protected mode switches, it will need a debugger than can handle real/protected mode switches. So far, the ONLY DOS debugger I've found that can do that is the that comes with the Bochs emulator. The program is to have only the 3 required 32bit segments (code segment, data segment, stack segment). This way I can keep the GDT (global descriptor table) very simple. Even so, the switching to/from 32bit mode is itself a MAJOR UNDERTAKING (requiring MANY hours of debugging just to test the GDT itself, and other code related to the switching to/from 32bit mode) |
|||
02 Oct 2018, 20:12 |
|
DimonSoft 02 Oct 2018, 23:12
Ben321 wrote: I'm trying to write a program that runs in 32bit protected mode. This mode has a major advantage, over 16bit real mode. It uses 32bit instructions with the same opcode that would be 16bit instructions in real mode. This means no need for an opcode prefix when using 32bit instructions. This makes each instruction take 1 byte less, and this saves both space (fewer bytes) and time during execution (executing a program with shorter instructions takes less time, simply because the CPU has fewer bits to process). I guess everyone here is well aware of what 32-bit protected mode is. If you are worried with code size, the choice of mov/mov sequence instead of push/pop for moving immediate into a segment register might not be a good idea, IIRC. Also, wait for an obligatory post from revolution about the dangers of talking about performance without measuring actual times. Ben321 wrote: My plan is to create a very simple 32bit protected mode program (not an OS), that runs directly from DOS, and thus does not need to run in a 32bit OS. It will switch itself into 32bit protected mode as the first thing it does when executing, and switch itself back to 16bit real mode as the last thing it does just before exiting to DOS. As you can see, because of these real/protected mode switches, it will need a debugger than can handle real/protected mode switches. So far, the ONLY DOS debugger I've found that can do that is the that comes with the Bochs emulator. Then, as other forum members have already suggested, using an existing DOS extender might be a good idea. Staying in protected mode for the whole program lifetime might not be a good idea if your program requires anything except memory reads and writes, because MS-DOS functions are unaware of 32-bit protected mode, as well as most BIOS functions. Which, in turn, makes it quite a strange thing to do, especially in 2018. What are you really trying to do? The only valid purpose I can see is if you have to run this code on some very limited hardware (like something embedded based on x86???) and can’t use an OS which already uses PM but provides an even richer set of APIs. And even then writing your own custom OS for the specific task seems to be a better idea. |
|||
02 Oct 2018, 23:12 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.