You need to look into OS concepts and preferably build your own OS - this will help answer your questions
Basically, an OS supports the programs which run under it. A program is not allowed to access the machine directly, instead it will access the OS which may or may not access the underlying hardware as required. There are numerous reasons for this including support for portability, security and abstraction. For instance, if a program wants to write a file it will ask the OS to open the file, will tell the OS what it wants in the file and then will ask the OS the close the file. The programmer need not worry about the underlying issues such as the disk format, where to locate the file, how to deal with fragmentation, making sure they link it in the catalogue and synchronising the disks, as the OS will sort all this out for them. This can be seen quite easily in language such as C - the functions in the standard header files (such as stdio.h) have direct support in the OS (actually it is a little more complex than this, but no need to worry about that for now.)
Now, in order to support all this, the OS will provide a number of services in an API which can be called from applications. Now, OSes are designed in different ways, so the APIs differ greatly between operating systems. At that level it is why you can not (easily) write a portable program between 2 distinct OSes running on the same architecture. When you write code in languages like Java, the byte code will run on different RTEs (one for Windows, one for Linux, one for MacOS etc) and this is how they support portability. On a related note, even code compiled for one flavour of Linux is not nescesarilly compatable with another flavour - which is why often Linux programs come as the code which you need to compile yourself (and have the correct supporting headers/libraries.)
There are a few reasons why DOS support is poor in Windows - DOS is 16 bit, whereas Windows is 32 (or 64), DOS is designed to run predominantly in real mode whereas Windows is in Protected/Virtual mode. Also simply Windows has dropped the legacy support from the OS, which is quite right to be honest - you should not limit your modern features and bloat the OS just to allow for (very) backwards compatability. Unlike days of old, DOS now runs under "emulation" in Windows, but for reasons mentioned above this is certainly not perfect and applications often try to run in ways which Windows now disallows. The likes of DosBox overcome this problem and I definately recommend their use if you need that sort of thing.
There is no need what so ever to have a GUI. Certainly many servers (including mine) do not have GUIs and even if they did would not be of much use as all the required programs are text based (and very rightly so.) Flavours of Unix (including Linux and Solaris) can run very happily without a GUI. However, if you wish to use graphical programs (which have windows and the mouse) such as Office then you will need a GUI to run them... without a GUI you are limited to text based interface.
Making an OS run on anything certainly is very difficult - as the designer/programmer you are forced to make a number of assumptions, using techniques such as HAL does help, but bear in mind the excellent portability of Linux is thanks to the huge level of expertese in the community and the thousands and thousands of man hours devoted to it. When you get into supporting none native programs (i.e. programs written for other OSes and other architectures) then you need to run them under emulation.... there is some level of support for this in existing OSes but there is certainly a huge performance hit in doing so.
So - making an OS that can run anything on anything... atainable but only with a huge level of experience, expertese and time to spare...