Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the board
Thread view  Mix view  Order
ecm

Homepage E-mail

Düsseldorf, Germany,
06.09.2020, 23:04
 

Building NASM 2.09 for 8086 (Announce)

In reply to Rugxulo's question in March:

> (NASM
> version 2.09 available)
> >
> > I today got it to compile for an 8086 DOS target after stripping
> > the supported instruction set down to 686 - both executables
> > (NASM and NDISASM) appear to work, but NASM.EXE is a 460 KiB file
> > which means that it barely runs at all and usually crashes if I try
> > to assemble anything at all (at least I hope the crash is only due
> > to running out of memory). NDISASM.EXE works fine though, and is
> > just about 110 KiB.
> >
> > So NASM still can be compiled for 8086 systems. If I have time for that,
> > I might look into stripping it down better to get the executable's size
> > down. Maybe write some code to let it use disk or XMS swapping? Hmm.
>
> ecm, do you remember, ten years ago (2010), saying you reduced NASM
> 2.09 down to get it to build for 16-bit DOS?

I found the source tree / binaries that I'd modified in 2010 August to make it compile with OpenWatcom for an 8086 target. A simple test (in current dosemu2) causes a crash, but I assume the binary worked at some point or on some machine. Running out of memory is the most likely error.

I didn't get around to examining all the changes yet, but you can diff the files present in the original NASM source distribution to the files in my development copy.

The mak.bat file shows that I manually called wcl (the OpenWatcom compiler driver) with the -nd option for several files, each specifying a different name. According to the manual that means:

> nd=<name> set name of the "data" segment

I also modified the instruction set tables to drop many if not all post-686 instructions. I don't know which file I edited to recreate the tables or how I did these edits, though.

---
l

Rugxulo

Homepage

Usono,
13.09.2020, 01:15

@ ecm

Building NASM 2.09 for 8086

Thanks for uploading this. Sorry for delay in responding, but I wanted something practical and informative to share first (ideally a working binary, which I've achieved, at least partially, but I haven't barely tested it at all).

> I found the source tree / binaries that I'd modified in 2010 August to make
> it compile with OpenWatcom for an 8086 target. A simple test (in current
> dosemu2) causes a crash, but I assume the binary worked at some point or on
> some machine. Running out of memory is the most likely error.

Your NASM.EXE doesn't work at all for me. It does print the version number ("-v") but even assembling a simple "hello world" fails. Part of the problem is also that default stack for 16-bit is only 2 kb (use "-k16384" or whatever; WDUMP is your friend). The biggest waste (of space and? memory) is output formats. You don't need them all. Just use "-DOF_ONLY -DOF_BIN -DOF_OBJ" for a minimal DOS build. That gives me a 300 kb NASM.EXE, much smaller than yours (460 kb?).

NASM 0.98.39 (2005) was SSE3 only (no x64, that came in 2007) and the last to have pre-built 16-bit binaries for DOS. It was also the last to care about C89, so newer versions heavily demanded C99. In fact, I'm surprised OpenWatcom ever worked because they have very incomplete C99 support. (IIRC, NASM more or less dropped OW support because of bugs ["switch(uint64_t)" ??] and lack of interest. Though one guy, "Joe Forster", was hacking NASM to add features in his own private fork in 2017, built using OpenWatcom/Win32, but he only sent me an unfinished/incomplete version.) I did submit a VERY trivial patch to NASM, years ago, to get 2.09.10 to build in plain DOS (8.3) with OpenWatcom for 32-bit DOS, which seemed to work fine. Long cmdlines was the biggest problem (put an asterisk "*wcl", and it will workaround that for its own tools). Also, Wmake has "rm" built in, so no "del" needed. You also don't need tabs at all, and it can ".AUTODEPEND", which gives cleaner makefiles, too. (I already built "full" 0.98.39 with OpenWatcom for 16-bit DOS using "large" model and a simplified makefile.)

So, as you've noticed, there are spots in the code that clearly don't care about 16-bit (e.g. bigger shifts). Not to mention many more instructions (AVX, ugh). Even disregarding all of that, it may not be feasible to have a truly reliable build. It would need more vetting and testing, of course.

N.B. "-Ox" is default now in this one. So manually specify "-O0" for previous behavior. Also, if you don't need the preprocessor, it may be faster and waste less RAM to use "-a". Also, -DLOGALLOC [malloc.log] shows what looks like incredibly tiny allocations, which probably wastes/fragments due to paragraph granularity, right? Ugh. Not sure if most naive mallocs hide/fix that behind the scenes. Caveat emptor.

I don't know if anyone is truly interested in this specific version or any 2.x versions, honestly. I don't demand anyone waste their time to fix or test it, but here's a quick effort from me anyways. This is atop the "original NASM [2.09] source distribution" that you also uploaded, borrowing slightly from your modified version. (I would probably prefer targeting stable 2.09.10 instead.)

"cd nasm209 && patch -p1 -i nasm209.dif"

(If lack of tabs confuses Patch, try "-l" to ignore whitespace.)


diff -warNdU0 old/ilog2.c new/ilog2.c
--- old/ilog2.c 2010-08-25 02:04:04 -0500
+++ new/ilog2.c 2010-08-26 18:53:58 -0500
@@ -49 +49 @@
-    int n;
+    long n;
@@ -61 +61 @@
-    int n;
+    long n;
@@ -84 +84 @@
-    int p = 0;
+    long p = 0;
@@ -123 +123 @@
-    int p = 0;
+    long long p = 0;
diff -warNdU0 old/mkfiles/openwcom.mak new/mkfiles/openwcom.mak
--- old/mkfiles/openwcom.mak    2010-08-25 02:04:14 -0500
+++ new/mkfiles/openwcom.mak    2020-09-12 15:10:18 -0500
@@ -10 +10 @@
-VPATH          = .\output
+VPATH          = .\output;.\lib
@@ -16 +16 @@
-CC             = wcl386
+CC             = *wcl
@@ -18 +18 @@
-CFLAGS         = -6 -ox -wx -ze -fpi $(DEBUG)
+CFLAGS         = -ml -os -w0 -q -ze -zt32 -zp1 -j -s -fpi -k16384 $(DEBUG)
@@ -20 +20,2 @@
-INTERNAL_CFLAGS = -I$(srcdir) -I. -DHAVE_SNPRINTF -DHAVE_VSNPRINTF
+INTERNAL_CFLAGS = -I$(srcdir) -I. -DHAVE_SNPRINTF -DHAVE_VSNPRINTF &
+                  -DOF_ONLY -DOF_BIN -DOF_OBJ #-DLOGALLOC
@@ -74 +75 @@
-       $(MAKE) /f $(__MAKEFILES__) all TARGET_FLAGS="-bt=DOS -l=DOS4G"
+       $(MAKE) /f $(__MAKEFILES__) all TARGET_FLAGS="-bcl=DOS"
diff -warNdU0 old/raa.h new/raa.h
--- old/raa.h   2010-08-25 02:04:04 -0500
+++ new/raa.h   2010-08-26 18:13:40 -0500
@@ -45 +45 @@
-#define RAA_BLKSHIFT   15      /* 2**this many longs allocated at once */
+#define RAA_BLKSHIFT   12      /* 2**this many longs allocated at once */
@@ -47 +47 @@
-#define RAA_LAYERSHIFT 15      /* 2**this many _pointers_ allocated */
+#define RAA_LAYERSHIFT 12      /* 2**this many _pointers_ allocated */
diff -warNdU0 old/saa.c new/saa.c
--- old/saa.c   2010-08-25 02:04:04 -0500
+++ new/saa.c   2020-09-12 15:05:40 -0500
@@ -39 +39 @@
-#define SAA_BLKSHIFT   16
+#define SAA_BLKSHIFT   12  /* incorrect?? but "out of memory" otherwise! */


> I also modified the instruction set tables to drop many if not all post-686
> instructions. I don't know which file I edited to recreate the tables or
> how I did these edits, though.

I can't (easily) seem to reproduce INSNS8.DAT because, for whatever reason (mislabeling? error?), you only halfway included CYRIX and 3DNOW instructions. Otherwise, it's close enough to identical and doesn't seem to hurt. If it matters, that should be looked at more closely.

"insnspl.bat"


@echo off
REM vanilla NASM 2.09-20100825 sources (2010) from ecm (BTTR)
if not exist %0 %0.bat

::#--- INSNS.AWK begins ---
:: NF == 4 {
::   if (($1 !~ /HINT_NOP|LZCNT/) &&
::     ($4 !~ /X64|X86_64,AMD|VMX|NEHALEM|SSSE3|SSE4[12A]/) &&
::       ($4 !~ /KATMAI|WILLAMETTE|PRESCOTT|IA64/))
::         print >"insns.new"
:: }
::#--- INSNS.AWK ends ---

if "%AWK%"=="" set AWK=awk
::for %%a in (insns.dat insns.pl) do if not exist %%a goto end
if exist insns.new del insns.new >NUL
set B1=[b]egins ---
set E1=[e]nds ---$
%AWK% "/\.AWK %B1%/,/ %E1%/{sub(\"^:: *\",\"\");print}" %0|%AWK% -f - insns.dat
for %%z in (B1 E1) do set %%z=
if not exist insns.new goto end
ren insns.dat *.da~
ren insns.new *.dat
REM using DJGPP Perl 5.8.8 (2007)
wmake -h -f mkfiles\openwcom.mak perlreq
:end
if "%AWK%"=="awk" set AWK=


So yeah, INSNS.DAT may be mislabeled in some spots. And clearly they increased the requirements on Perl for some other files. Ideally, rebuilding this won't need Perl at all (as my other efforts didn't), for simplicity, and also won't need lugging around fully (large) modified files (INSNSA.C or whatever). I would probably (again) use Sed or maybe Awk.

So what's the motivation for having such a "newer" release? Should we focus on the latest of this major version instead (2.09.10)? Or even newer (2.10? 2.15?)? Faster, less bugs, more powerful preprocessor, looser license, newer cpu instructions, etc.? Well, it's not crucial, and none of us truly "need" or want it that badly, do we? Still, it's cool to have "something"!

I still haven't emailed the TinyAsm guy. His is extremely small (30 kb!) but simplistic (8086 only, bin output only, no preprocessor, NASM syntax). He was focusing more on DeSmet C build tools (8086 bootstrapping?) rather than others, though. I don't blame him, especially for licensing reasons, but Turbo C++ 1.01 freeware is still pretty good. For cross-building, IA-16 ELF is also somewhat good (for Tiny and Small models only). Maybe he could help us.

Back to the board
Thread view  Mix view  Order
22049 Postings in 2034 Threads, 396 registered users, 269 users online (0 registered, 269 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum