How to make for, say, /bin/echo:
cpp writestr.s writestr-cpp.s cpp echo.s echo-cpp.s as -o writestr.o writestr-cpp.s as -o echo.o echo-cpp.s ld -e echo -o -static -o echo echo.o writestr.oPlease note:
There is a makefile here using the same general idea, although it actually does things a little differently. The Makefile creates files called FILE.exe as a standalone version of FILE.s, and also creates a wrapper called driver.exe with all of the individual program code linked. driver.exe then expects to be called via a soft-link FILE --> driver.exe, much like sendmail or BusyBox.
If you take the next step of using strip over the resulting binaries, they are quite small (I believe that all of the standalone versions are 1k or less in size; using the driver.exe approach, these all link together in a stripped binary at 2472 bytes currently.)
These programs aren't particularly clean or elegant; echo for instance calls write(2) many times when it would probably be more reasonable to call write(2) once. Block comparisons and moves are done in a less efficient manner than the x86_64 supports.
It's interesting to do an strace of one of these binaries and a standard library; there are no dependencies on other programs at all, and while the programs, as noted previously, are not elegant, they do tend to do whatever they need to and not much else.
For the programs that use writestr.s to call write(2), the code in writestr.s should loop through on any incomplete write(2), but is not vetted yet. (This is also true of dmesg.s.)
For 386/x86-64 specific information, you can look at this section:
Red Hat Enterprise Linux 3: Using as, the Gnu Assembler: Chapter 21. 80386 Dependent Features
For an overall view of using GAS: