10 ms·
What's the difference between the com and exe extensions? (2008)
- TazeTSchnitzel 9y agoAh, so DOS did this too! I was aware that Windows NT similarly has a few “.COM” command-line utilities that are actually Portable Executables (the successor to the successor to the MZ format), for compatibility's sake.
- dfox 9y agoI find it actually somewhat hard to believe that DOS ever cared about the extension of filename passed to EXEC because the same syscall is also used (with AL != 0) for overlays and can also be used as generic MZ loader, in both these cases such files typically did not have EXE extension. In DOS 5.0+ (at least, never tried it on earlier) and probably every version of Windows DOS's EXEC and Windows' CreateProcess()/LoadLibrary() does not care about the filename and just uses loader implementation appropriate for whatever was detected from the header. ShellExecute() (and it's DOS "equivalent" EXEC(%COMSPEC%, "/C foo")) does care about the extension. In DOS there is hardcoded list of extensions that are executable (BAT, COM, EXE, in this order, with BAT being handled by the command.com itself. There is no way to directly execute image with different extension from the command line), while in Windows what happens depends on contents of HKCR. One notable feature of how this is handled by DOS is that when you have both foo.exe and foo.com then foo.com takes precedence (IIRC this has something to do with the fact that traditional Windows entrypoint was called WIN.COM although it always was MZ binary).
- int_19h 9y agoIf I remember correctly, the order was COM, EXE, BAT. On NT platforms today, this is actually user-configurable via the PATHEXT environment variable - and that definitely has them in that order. I wonder why that was the case. I remember reading some explanation about how it was about backwards compatibility, but that doesn't make much sense, since the first release of DOS 1.0 already had all three. Strictly speaking, COM as a format predates DOS (it's originally from CP/M), while EXE and BAT are more recent additions, COM files compiled for CP/M cannot run on DOS for other reasons, so there's still no compat issue there.
- TazeTSchnitzel 9y agoHaving an order of precedence provides predictable behaviour and, perhaps more importantly, is simpler to implement than forcing disambiguation. But probably it's just that they added the checks in that order and put no further thought into it.
- johnchristopher 9y agoAh! I used to wonder about that when I was a kid playing with DOS. I had the vague notion that com programs were 'dumber' than exe or less complex and were often part of the operating system. And if a 'big' application was a com then it means there were a bunch of additional com or exe files in the directory.
- deleted 9y ago[deleted]
- Waterluvian 9y agoSo why not do something like make a shim COMMAND.COM that handles compatibility and calls the new COMMAND.EXE? From my novice view, it seems like it would be generally simpler to reason about.
- imron 9y agoBecause then you also need a shim format.com and a shim this.com and that.com and so on. Much easier just to make the loader check the header.
- Waterluvian 9y agoAhh yes. I misunderstood. The loader was modified, not COMMAND.COM, etc.
- dfox 9y agoEfficiency. On the platforms DOS was meant for the hundred or so bytes of memory wasted by creating another process (PSP + few bytes for the actual code) was significant so the simple approach of writing trivial .COM that does EXEC(COMMAND.EXE), EXIT is wasteful. DOS does not have exact equivalent of unix-style exec() so replacing the process in memory would involve either adding that to DOS or implementing it in the .COM stub, both approaches have the slight problem that there is no way to guarantee that the block of free memory that was selected by DOS for the .COM stub (and thus starts with the PSP of our process and its starting paragraph is our PID) is large enough so the EXE would fit there. Also such .COM stub will have to be stored on the disk as separate file which on FAT16 would probably waste most of the used cluster given the expectation that it would be few bytes long stub.
- rocky1138 9y agoI was thinking a symlink would be even easier.
- ygra 9y agoNTFS gained symlink support in 2007. FAT never had it. If presented with this problem, I'd say changing the executable loader is a better solution to the problem than adding symlink support to the file system.
- mojuba 9y agoIf I remember correctly, not just the files themselves but the entire memory available to COM programs at run time was limited to 64k. It's funny how engineers think those times are long gone whereas the demand for very compact systems with low energy footprint is still there. So mastering programming within kilobytes is still a thing, don't disregard it!
- pizza234 9y agoTo be more specific, COM files were loaded into a single segment (64k) - this is where the limitation comes from. At the time of DOS, memory access was unrestricted, so, in a basic form, one had direct access to the entire base memory (640k). DOS viruses for example frequently resided just below the top of it, and/or manipulated the interrupt descriptor table (located instead at the very beginning).
- userbinator 9y agoCOM files can access all addressable memory in the system: https://news.ycombinator.com/item?id=14427269 https://news.ycombinator.com/item?id=14427269 Remember that they run in an environment with no memory protection.
- dfox 9y agoCOM files were not limited to only 64k of accessible memory, but the difference was that upon loading COM file got one full preallocated 64kB segment that got used for all of data, code and stack, while MZ format files specified in their header how many paragraphs (segment register increments, ie. 16 byte blocks) they need for code and how many additional uninitialized paragraphs should follow that (minimum and maximum required). In both cases programs were free to allocate additional memory from DOS, but by default EXE files were loaded in such way that this wasn't necessary and automatically got the largest continuous block of free memory allocated to them (in fact they got the highest addressed block of free memory, but in any sane state of DOS it was also the largest).
- nils-m-holm 9y ago> upon loading COM file got one full preallocated 64kB segment IIRC, COM files got all available memory up to the 640K boundary and if you wanted to load additional programs, you had to shrink the preallocated region first.
- unethical_ban 9y ago>So when did the program loader change to ignore the extension entirely and just use the presence or absence of an MZ header to determine what type of program it is? Compatibility, of course. Either "Compatibility" is a time, or they should have asked "why".
- xg15 9y agoNice info. My suspicion is this also explains why many corrupted EXE files cause the cryptic error "program is too large to fit in memory" error if you try to execute them: The corruption mangles the header, removing the "MZ" magic number -> Windows thinks the file is a COM executable and attempts to load it into memory, COM style -> the file is not actually COM though and thus is far too large to fit into the memory available to the loader -> that error appears.
- hypervis0r 9y agoYou might want to read this: https://blogs.msdn.microsoft.com/oldnewthing/20060130-00/?p=32483 https://blogs.msdn.microsoft.com/oldnewthing/20060130-00/?p=...
- codeflo 9y agoBack when I was a kid, in the days before Google, you tried to figure out how things worked just by poking around your computer. For example, I noticed that professional programs were always .com/.exe files, but I only knew how to edit simple batch scripts. So of course, the "logical" thing to try was to write a .bat and save it with a different extension and see what happened. .exe files created this way wouldn't launch, but a .com created this way would instantly reboot the computer. Even more weirdly, this only worked for the specific command that happened to enter in my first attempt -- it might have been something like "cd games". If I changed anything at all, it no longer worked. Only years later I realized that the characters I typed were directly executed as machine code, and that I must have stumbled upon a set of instructions that caused a CPU exception! For several years, this weird file was the only way I knew to programmatically reboot a computer, so I renamed it "reset.com" and kept it around. I think it stopped working only in the Windows XP era when DOS programs were finally sandboxed to some extent.
- UnoriginalGuy 9y agoI'd imagine that wouldn't have worked on NT or 2000 either. You just likely jumped from the 9x series of OSs to XP which was the first one to offer "good" memory protection. Full explanation for how you could do this here[0]. It really was the wild west back when 9x was popular. I'm genuinely surprised they ran as well as they did. NT was a vast improvement. [0] https://en.wikipedia.org/wiki/Windows_9x#Kernel https://en.wikipedia.org/wiki/Windows_9x#Kernel
- dfox 9y agoWhile NT was vast improvement, the 3.1/9x was pretty significant feat of engineering and in comparison NT is "just another OS". In my opinion the lacking memory protection was not about the architecture itself but about the fact that it was meant to be single-user and thus there were no permissions. IIRC from Win32 code you had to jump though some hoops to be able to access whatever memory/hardware you wanted (ie. you could not overwrite random non-owned memory by mistake), the fact that you could do almost whatever you wanted in vm86 code was essentially an feature and that Win16 code could access any other Win16 process data was weird design decision that is also shared by all NT versions up to 2000 (where it is configurable).
- return0 9y agoBut wait what does "MZ" stand for ?
- hannob 9y agoThe initials of the formats designer: https://en.wikipedia.org/wiki/Mark_Zbikowski https://en.wikipedia.org/wiki/Mark_Zbikowski
- chime 9y agoThat's one way to immortalize yourself. Wonder if 'MZ' is the most common electronic initials in the world. Can't think of any other initials or acronym repeated more frequently than # of Windows Systems x # of Exe files per system.
- deleted 9y ago[deleted]
- oneplane 9y agoToo bad that things back then done for 'compatibility' meant that things now suck because breaking changes back then weren't done. This is probably why UTC time on Windows is still broken.
- jwilk 9y agohttps://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html https://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html
- mungoid 9y agoHuh.. This was one question i have always wondered but never thought to look up even after 15 years of coding..
- minikites 9y agoMore details on what comes after MZ: https://blogs.msdn.microsoft.com/oldnewthing/20060130-00/?p=32483 https://blogs.msdn.microsoft.com/oldnewthing/20060130-00/?p=...
- ajdlinux 9y agoIIRC, when the DOS/Windows shell needs to resolve "program" to either "program.com" or "program.exe", the .com file takes precedence - ISTR this being abused by malware once upon a time.
- colejohnson66 9y agoI'm guessing it's because `example.com` comes before `example.exe` when you sort alphabetically? So when it goes looking for `example`, it gets the list of files and takes the first matching one it sees.
- vram22 9y agoOr maybe because .COM format was invented before .EXE format (since .COM is simpler)? Just guessing.
- colejohnson66 9y agoMaybe someone could disassemble DOS to find out why? Sounds like a project for me this weekend
- lucb1e 9y agoIirc, MS-DOS is open source and in some museum now.
- maxlybbert 9y agoDOS 1.1 is available online from the Computer History Museum ( http://www.computerhistory.org/press/ms-source-code.html http://www.computerhistory.org/press/ms-source-code.html ). But I think that may be too early to be useful.
- int_19h 9y agoThey also offer DOS 2.0. But DOS had EXE, COM and BAT files since version 1.0.
- berlincount 9y agoMy favorite .COM-file still: X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* (yes, you can just copy-paste it into a .COM-file and it will execute and just show a text - unless you've got a correctly working virus scanner) This is a Virus Scanner test signature (https://en.wikipedia.org/wiki/EICAR_test_file https://en.wikipedia.org/wiki/EICAR_test_file), so the fact alone that you can read this comment might be meaningful ;)
- tomcam 9y agoFor years I made a living off a batch file and compiler named Combat, then Son of a Batch, and finally Builder.
- bitwize 9y agoCOM is a binary image that just gets copied into memory. Because it is a holdover from CP/M it can only occupy one 64k segment for code, data -- everything. EXE files have a header which tells the loader whether and how they use different segments in memory. They can have much larger memory footprints than COM programs.
- molticrystal 9y agoI miss being able to make small programs in debug on a Dos prompt and just dumping the machine code to a com file. It was a great way to test out and learn assembly language, and you didn't need a compiler or any other programs to make something that executed other than what was built in and a nice printed list of interrupts. Some simple things I remember playing with in middle school, might work in a dosbox emulator window?: pc speaker: out 61,1 change video mode: mov ax,0x13 int 0x10 Then there were cool msdos debug scripts, where you had text listings of assembly with debug commands that when piped into debug it wrote out a com file: https://www.google.com/search?q=dos+debug+script&ie=utf-8&oe=utf-8 https://www.google.com/search?q=dos+debug+script&ie=utf-8&oe... Some could low level format hard drives, and there were lots of other fun utilities and amusements, much more so than batch files. I'd say the modern analogue is python scripts.
- int_19h 9y agoIf you're feeling nostalgic about the DOS era and the associated hackery, give PCem a try: https://pcem-emulator.co.uk/ https://pcem-emulator.co.uk/ It's an x86 emulator that works on hardware level (so from BIOS on, you're running real code that was running on those DOS machines), and with a focus on emulating the hardware from that era specifically, ranging from the earliest 8086 machines and MDA adapters, and up to 3dfx Voodoo era. Obviously this is mostly useful for gaming, but if you wanted to hack around with TASM or Borland Pascal just like in good old times, it's also great.
- webtechgal 9y agoAnd this one is a live/online emulator: http://www.pcjs.org/ http://www.pcjs.org/
- grkvlt 9y agoYeah, I remember getting a huge Microsoft reference book as a birthday present that listed all the BIOS, DOS and VGA system calls and their INT numbers and arguments. I then used it and DEBUG to write a tiny 'paint' program in ~80 bytes that did the following: 1. entered VGA mode 2. enabled the mouse cursor 3. checked the mouse status 4. turned on the pixel at the mouse location if the button was down 5. goto 3
- pjc50 9y agoNote that lots of other extensions can be interpreted as executable: https://superuser.com/questions/228680/on-windows-what-filename-extensions-denote-an-executable/228693 https://superuser.com/questions/228680/on-windows-what-filen... (and you can also run code out of DLL and CPL files)
- gerard 9y ago> The format of a COM file is... um, none. There is no format. This makes any small file a valid COM file as far as Windows is concerned. NTVDM doesn't care, it will happily execute your holiday snaps if given the chance. It's not difficult to craft a valid GIF, PNG, etc that does something useful when executed from byte 0. Such an image will pass most mime-sniffing protections. For example, given such an image and a "foo.png.exe" Content-Disposition header, Internet Explorer used to skip all security warnings. Combined with "Hide extensions for known file types" it would ask you where you'd like to save "foo.png", preserving the executable extension behind your back. Upon double-click the loader notices the MZ signature is missing, fires up NTVDM, and starts executing the image from byte 0. If running under NTVDM is too restrictive, it can always break out with BOP instructions. The lack of structure also makes COM files a simple vector for exploiting hash collisions. Any two prefix blocks with matching hash that can survive execution can be used to create two variants of an program with matching hashes. Bit differences in the two blocks can be used as switches to control program behaviour.
- justin66 9y agoMy first experience with truly low-level programming was when I was a teenager. I saw a list of PC interrupts in BYTE magazine and was interested in the one that brought you to the ROM-based BASIC (18h), something I'd never seen. I stuck it into a text editor, saved it as a .com file, and boom! Something that took you to BASIC, which turned out not to be very useful compared to the Apple II (and its DOS) that I was used to at school, but still.
- graycat 9y agoGood stuff. Good to know. Thanks, I needed that. Always wondered. Good explanation, 20 years late for me to read this, but better late than never. Yes, it sounds like a COM file, with no relocation dictionary, etc., would have to be loaded at the same virtual memory address. IIRC one of the OP comments mentioned this. Uh, more of the same, piled higher and deeper? Okay, for my startup I decided to use the .NET Framework 4 with Visual Basic .NET and the usual acronyms SQL (structured query language) Server, ADO.NET (active data objects for using SQL Server), ASP.NET (active server pages for writing Web pages), IIS (Internet information server, which actually makes the TCP/IP calls for moving the data on the Internet and runs my VB.NET program that writes the Web pages), etc. Okay. But eventually it dawned on me that there is a lot of code running on my Windows machine that very likely is not from Visual Basic and .NET; I'm concluding that there is an older, say, Windows 95, 98, NT development environment based on C++ and a lot of library calls, a message queue for inputs, some entry variables and call backs to them, and quite a lot of functionality not also in .NET. E.g., when my HP laser printer quit and I got a Brother laser printer, my old HP/GL (Hewlett Packard graphics language, a cute, simple thing for printing and drawing on pages) program to print files didn't work -- the Brother printer didn't do with HP/GL just what my HP printer did. So, via .NET I wrote a replacement for such simple printing. Well, for writing the characters to the page, object, image, whatever it was (I don't recall the details just now), all I could see to use was some GDI+ (graphical data interface or some such?) calls, but those seem not to be the usual way old Windows programs write to paper, graphics files, or the screen and instead there's something else, maybe back before .NET, and I don't know what that older stuff was. E.g., the GDI or whatever it is didn't let me actually calculate accurately how many pixels horizontally a string of printable characters would occupy when printed and, thus, all my careful arithmetic about alignment became just crude approximations -- no doubt Firefox, Chrome, Windows Image and FAX Viewer, etc. all use something better, more accurate. So, what am I missing? Am I supposed to get out some 20 year old books by Petzold or some such, get a Windows Software Development Kit or some such, review C and C++, get lots of include files organized, etc., start with some sample code that illustrates all the Windows standard things of a standard Windows app or some such? Okay, but it appears that .NET does not yet replace all that old stuff? I mean, is it possible to write a full function Windows app with just .NET, VB.NET/C#? Q 1. What really is that old stuff? Where is it? Are there good tutorials? E.g., if we are to explain COM files, then let's also point to explanations of some of the other old stuff also still important? Q 2. Is the functionality of that old stuff, for user level programs, maybe not for device drivers, by now all available via .NET but I've just not found it all yet? If so, where is it in .NET, say, for graphics and printing the .NET presentation thingy or whatever? The code for my startup looks fine, all seems to work, does all I intended, but still I wonder about that old stuff. E.g., eventually I noticed that my favorite editor KEdit, apparently like any well behaved old standard Windows program, will let me print a file. And the printing works great! I get a standard Windows popup window that lets me select font, font size, bold or italic, etc., and it works fine with the Brother printer. KEdit knows some things about writing to a printer I didn't see in .NET. So, with just .NET, I'm missing a lot of Windows functionality?
- NewSystems 9y agoThe days of .COM/.EXE got me started in programming. I thought, gee, I have some game ideas. So I looked into BASIC, seemed great, but the distributed files required a certain flavor of BASIC. After looking into C for developing standalone binaries, I switched to C. Programming something like DOOM required 'vertical strips' calculated across the screen and other graphics gems, so I learned about graphics gems and programming. C++ and TurboPascal and then Delphi and VB6 were released. Seemed like a never ending journey! Today we have CocosX for cross-platform sprites so games can be quickly deployed on multiple platforms, plus Unity and Unreal engines for 3D development. It's much better today, but I wonder what it's like to not have the kind of background of learning that I did.
- dwarman 9y agoCorrect me if I'm wrong, but I seem to be the only person here to have weathered the entire evolution from 8008 on, for a living not as a hobby (though is both for me). I am possibly approaching Senior Curmidgeon status, but I mean well. Even the early chips definitely required RTFM and some serious visualization chops, there are millions of bad and very bad things in a random poke, those two help you probe their borders instead of blue screening your brain. I see examples of ignoring both boasted about here. It's not lame to study before committing, and the needed info has never been secret. Please forgive me this, if you feel targeted. I am 70 years old, and am still doing this shit, on modern multicore 64 bit architectures, and would not be here without doing what I say. RTFM, run code in your head, when you got both start runnin the real thing. Short term nor for the impatient, but long term? I wrote in ASM up to i286, and always had the specifications handly. Never poke around randomly executing nonsense code. Too easy to trash your HD, if you had one. Or find the real "Halt and Catch Fire". Messy. The books were easily avaiable, back to way before even the 4004, no excuse for not using them to run your probes in the virtual model of the chip implanted in your head from reading that book. The first experiments should then be in areas of confidence with valid data and no addressing violations. Steps, not f*it leaping off a cliff into clouds. 8080 was the last small space part, with only a total addressable 64K. I consider it the root of all evil, as it were, because it set the parameters for 64K limited program. All else flows from there because of the decision to maintain backward binary compatibility. So it was wrapped in redirectors and segment registers in an expanded 1M space, without any security or permissions management. Which would cost peanuts, a flag and some specific address decoder disables. Simple days. I often took advantage of COM runtimes in those days. Often, and actually most usefully, without a DOS or RTOS between me and the metal. It was trivial to write a serial interface COM loader, and drop my FORTH into it for itelligent debugging. Or anything else, investigative or command. The freedom started to go away with extra wrappers in 80286, which among other things intoduce "Real" and "Protected" execution modes, plus some extended native addressing modes. Starting to grow up, can still run 8008 COM code, but in that mode it sees only COM compatible register set, and has no access to the execution mode flag. Much "safer", sorta. Except still gets the 32 bit 808x indirect instruction address modes, if invoked in Real Mode. Heard about "non-modal design"? 68000 got much closer. Every additional wrapper introduces large arrays of data re-routing and management logic. Needs a restart in design and philosopy. dropping COM support hardware and only allowing virtual machines to play is today's answer, getting closer, and much safer. And as core counts go up, have only latest clean architectures run on most cores, no wrappers, and a dedicated legacy core. Or chip. with FPGGA run time loadable architecture for that, agan no wrappers. But it may alreadt be too late. Too much investment that may get broken in amusing ways. After the i286, the i386 on on to the present have foccussed more on speed and size of, and access to, Protected mode, runtimes, sharing memory, and verious support tricks. All carefully avoiding disturbing the ability to run by now ancient OS utities, buried deep in the underground of the OS. till WinNT, Win32, and the Pentium etc IIRC. Though I swear I still see several in the procces list on W7.