summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-04-30 21:02:01 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-04-30 21:02:01 +0000
commit788e6c10e175ab4b3e67feefbffe570619ae2330 (patch)
treefdbac44f81f28b729e74ce8a8379b5211f2d6f95
parent4cf1748e6829f80be251b8d7d274738009f934cf (diff)
downloadnasm-788e6c10e175ab4b3e67feefbffe570619ae2330.tar.gz
nasm-788e6c10e175ab4b3e67feefbffe570619ae2330.tar.bz2
nasm-788e6c10e175ab4b3e67feefbffe570619ae2330.zip
NASM 0.98.12
-rw-r--r--assemble.c13
-rw-r--r--insns.dat140
-rw-r--r--macros.c16
-rw-r--r--macros.pl2
-rw-r--r--misc/exasm.zipbin491 -> 6058 bytes
-rw-r--r--nasm.c27
-rw-r--r--nasm.h2
-rw-r--r--parser.c2
-rw-r--r--preproc.c3
-rw-r--r--rdoff/Makefile.in170
-rw-r--r--rdoff/ldrdf.c1378
-rw-r--r--test/bintest.asm90
12 files changed, 1586 insertions, 257 deletions
diff --git a/assemble.c b/assemble.c
index 39ffd46..f93457d 100644
--- a/assemble.c
+++ b/assemble.c
@@ -59,7 +59,8 @@
* as a literal byte in order to aid the disassembler.
* \340 - reserve <operand 0> bytes of uninitialised storage.
* Operand 0 had better be a segmentless constant.
- * \370,\371,\372 - match only if operand 0, 1, 2 meets byte jump criteria.
+ * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
+ * 370 is used for Jcc, 371 is used for JMP.
* \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
* used for conditional jump over longer jump
*/
@@ -151,9 +152,11 @@ static int jmp_match (long segment, long offset, int bits,
unsigned char c = code[0];
- if (c != 0370) return 0;
- if (ins->oprs[0].opflags & OPFLAG_FORWARD) return (!pass0); /* match a forward reference */
-
+ if (c != 0370 && c != 0371) return 0;
+ if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
+ if (optimizing<0 && c==0370) return 1;
+ else return (pass0==0); /* match a forward reference */
+ }
isize = calcsize (segment, offset, bits, ins, code);
if (ins->oprs[0].segment != segment) return 0;
isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
@@ -546,7 +549,7 @@ static int is_sbyte (insn *ins, int op, int size)
int ret;
ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
- (optimizing || !(ins->oprs[op].type & (BITS16|BITS32))) &&
+ (optimizing>0 || !(ins->oprs[op].type & (BITS16|BITS32))) &&
ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
v = ins->oprs[op].offset;
diff --git a/insns.dat b/insns.dat
index c34fa0e..d626fcd 100644
--- a/insns.dat
+++ b/insns.dat
@@ -37,15 +37,15 @@ ADC rm16,imm8 \320\300\1\x83\202\15 8086
ADC rm32,imm8 \321\300\1\x83\202\15 386
ADC reg_al,imm \1\x14\21 8086,SM
ADC reg_ax,imm \320\1\x15\31 8086,SM
-ADC reg_eax,sbyte \321\1\x83\202\15 386,SM,ND
-ADC reg_eax,sbig \321\1\x15\41 386,SM,ND
+ADC reg_eax,sbyte \321\1\x83\202\15 386,SM,ND
+ADC reg_eax,sbig \321\1\x15\41 386,SM,ND
ADC reg_eax,imm32 \321\1\x15\41 386
ADC rm8,imm \300\1\x80\202\21 8086,SM
-ADC rm16,imm \320\300\134\1\x81\202\131 8086,SM
-ADC rm32,imm \321\300\144\1\x81\202\141 386,SM
+ADC rm16,imm \320\300\134\1\x81\202\131 8086,SM
+ADC rm32,imm \321\300\144\1\x81\202\141 386,SM
ADC mem,imm8 \300\1\x80\202\21 8086,SM
-ADC mem,imm16 \320\300\134\1\x81\202\131 8086,SM
-ADC mem,imm32 \321\300\144\1\x81\202\141 386,SM
+ADC mem,imm16 \320\300\134\1\x81\202\131 8086,SM
+ADC mem,imm32 \321\300\144\1\x81\202\141 386,SM
ADD mem,reg8 \300\17\101 8086,SM
ADD reg8,reg8 \300\17\101 8086
ADD mem,reg16 \320\300\1\x01\101 8086,SM
@@ -62,15 +62,15 @@ ADD rm16,imm8 \320\300\1\x83\200\15 8086
ADD rm32,imm8 \321\300\1\x83\200\15 386
ADD reg_al,imm \1\x04\21 8086,SM
ADD reg_ax,imm \320\1\x05\31 8086,SM
-ADD reg_eax,sbyte \321\1\x83\200\15 386,SM,ND
-ADD reg_eax,sbig \321\1\x05\41 386,SM,ND
+ADD reg_eax,sbyte \321\1\x83\200\15 386,SM,ND
+ADD reg_eax,sbig \321\1\x05\41 386,SM,ND
ADD reg_eax,imm32 \321\1\x05\41 386
ADD rm8,imm \300\1\x80\200\21 8086,SM
-ADD rm16,imm \320\300\134\1\x81\200\131 8086,SM
-ADD rm32,imm \321\300\144\1\x81\200\141 386,SM
+ADD rm16,imm \320\300\134\1\x81\200\131 8086,SM
+ADD rm32,imm \321\300\144\1\x81\200\141 386,SM
ADD mem,imm8 \300\1\x80\200\21 8086,SM
-ADD mem,imm16 \320\300\134\1\x81\200\131 8086,SM
-ADD mem,imm32 \321\300\144\1\x81\200\141 386,SM
+ADD mem,imm16 \320\300\134\1\x81\200\131 8086,SM
+ADD mem,imm32 \321\300\144\1\x81\200\141 386,SM
AND mem,reg8 \300\1\x20\101 8086,SM
AND reg8,reg8 \300\1\x20\101 8086
AND mem,reg16 \320\300\1\x21\101 8086,SM
@@ -87,15 +87,15 @@ AND rm16,imm8 \320\300\1\x83\204\15 8086
AND rm32,imm8 \321\300\1\x83\204\15 386
AND reg_al,imm \1\x24\21 8086,SM
AND reg_ax,imm \320\1\x25\31 8086,SM
-AND reg_eax,sbyte \321\1\x83\204\15 386,SM,ND
-AND reg_eax,sbig \321\1\x25\41 386,SM,ND
+AND reg_eax,sbyte \321\1\x83\204\15 386,SM,ND
+AND reg_eax,sbig \321\1\x25\41 386,SM,ND
AND reg_eax,imm32 \321\1\x25\41 386
AND rm8,imm \300\1\x80\204\21 8086,SM
-AND rm16,imm \320\300\134\1\x81\204\131 8086,SM
-AND rm32,imm \321\300\144\1\x81\204\141 386,SM
+AND rm16,imm \320\300\134\1\x81\204\131 8086,SM
+AND rm32,imm \321\300\144\1\x81\204\141 386,SM
AND mem,imm8 \300\1\x80\204\21 8086,SM
-AND mem,imm16 \320\300\134\1\x81\204\131 8086,SM
-AND mem,imm32 \321\300\144\1\x81\204\141 386,SM
+AND mem,imm16 \320\300\134\1\x81\204\131 8086,SM
+AND mem,imm32 \321\300\144\1\x81\204\141 386,SM
ARPL mem,reg16 \300\1\x63\101 286,PROT,SM
ARPL reg16,reg16 \300\1\x63\101 286,PROT
BOUND reg16,mem \320\301\1\x62\110 186
@@ -181,15 +181,15 @@ CMP rm16,imm8 \320\300\1\x83\207\15 8086
CMP rm32,imm8 \321\300\1\x83\207\15 386
CMP reg_al,imm \1\x3C\21 8086,SM
CMP reg_ax,imm \320\1\x3D\31 8086,SM
-CMP reg_eax,sbyte \321\1\x83\207\15 386,SM,ND
-CMP reg_eax,sbig \321\1\x3D\41 386,SM,ND
+CMP reg_eax,sbyte \321\1\x83\207\15 386,SM,ND
+CMP reg_eax,sbig \321\1\x3D\41 386,SM,ND
CMP reg_eax,imm32 \321\1\x3D\41 386
CMP rm8,imm \300\1\x80\207\21 8086,SM
-CMP rm16,imm \320\300\134\1\x81\207\131 8086,SM
-CMP rm32,imm \321\300\144\1\x81\207\141 386,SM
+CMP rm16,imm \320\300\134\1\x81\207\131 8086,SM
+CMP rm32,imm \321\300\144\1\x81\207\141 386,SM
CMP mem,imm8 \300\1\x80\207\21 8086,SM
-CMP mem,imm16 \320\300\134\1\x81\207\131 8086,SM
-CMP mem,imm32 \321\300\144\1\x81\207\141 386,SM
+CMP mem,imm16 \320\300\134\1\x81\207\131 8086,SM
+CMP mem,imm32 \321\300\144\1\x81\207\141 386,SM
CMPSB void \332\1\xA6 8086
CMPSD void \332\321\1\xA7 386
CMPSW void \332\320\1\xA7 8086
@@ -427,29 +427,29 @@ IMUL reg16,reg16 \320\2\x0F\xAF\110 386
IMUL reg32,mem \321\301\2\x0F\xAF\110 386,SM
IMUL reg32,reg32 \321\2\x0F\xAF\110 386
IMUL reg16,mem,imm8 \320\301\1\x6B\110\16 186,SM
-IMUL reg16,mem,sbyte \320\301\1\x6B\110\16 186,SM,ND
-IMUL reg16,mem,imm16 \320\301\1\x69\110\32 186,SM
-IMUL reg16,mem,imm \320\301\135\1\x69\110\132 186,SM,ND
+IMUL reg16,mem,sbyte \320\301\1\x6B\110\16 186,SM,ND
+IMUL reg16,mem,imm16 \320\301\1\x69\110\32 186,SM
+IMUL reg16,mem,imm \320\301\135\1\x69\110\132 186,SM,ND
IMUL reg16,reg16,imm8 \320\1\x6B\110\16 186
-IMUL reg16,reg16,sbyte \320\1\x6B\110\16 186,SM,ND
-IMUL reg16,reg16,imm16 \320\1\x69\110\32 186
-IMUL reg16,reg16,imm \320\135\1\x69\110\132 186,SM,ND
+IMUL reg16,reg16,sbyte \320\1\x6B\110\16 186,SM,ND
+IMUL reg16,reg16,imm16 \320\1\x69\110\32 186
+IMUL reg16,reg16,imm \320\135\1\x69\110\132 186,SM,ND
IMUL reg32,mem,imm8 \321\301\1\x6B\110\16 386,SM
-IMUL reg32,mem,sbyte \321\301\1\x6B\110\16 386,SM,ND
-IMUL reg32,mem,imm32 \321\301\1\x69\110\42 386,SM
-IMUL reg32,mem,imm \321\301\145\1\x69\110\142 386,SM,ND
+IMUL reg32,mem,sbyte \321\301\1\x6B\110\16 386,SM,ND
+IMUL reg32,mem,imm32 \321\301\1\x69\110\42 386,SM
+IMUL reg32,mem,imm \321\301\145\1\x69\110\142 386,SM,ND
IMUL reg32,reg32,imm8 \321\1\x6B\110\16 386
-IMUL reg32,reg32,sbyte \321\1\x6B\110\16 386,SM,ND
-IMUL reg32,reg32,imm32 \321\1\x69\110\42 386
-IMUL reg32,reg32,imm \321\145\1\x69\110\142 386,SM,ND
+IMUL reg32,reg32,sbyte \321\1\x6B\110\16 386,SM,ND
+IMUL reg32,reg32,imm32 \321\1\x69\110\42 386
+IMUL reg32,reg32,imm \321\145\1\x69\110\142 386,SM,ND
IMUL reg16,imm8 \320\1\x6B\100\15 186
-IMUL reg16,sbyte \320\1\x6B\100\15 186,SM,ND
-IMUL reg16,imm16 \320\1\x69\100\31 186
-IMUL reg16,imm \320\134\1\x69\100\131 186,SM,ND
+IMUL reg16,sbyte \320\1\x6B\100\15 186,SM,ND
+IMUL reg16,imm16 \320\1\x69\100\31 186
+IMUL reg16,imm \320\134\1\x69\100\131 186,SM,ND
IMUL reg32,imm8 \321\1\x6B\100\15 386
-IMUL reg32,sbyte \321\1\x6B\100\15 386,SM,ND
-IMUL reg32,imm32 \321\1\x69\100\41 386
-IMUL reg32,imm \321\144\1\x69\100\141 386,SM,ND
+IMUL reg32,sbyte \321\1\x6B\100\15 386,SM,ND
+IMUL reg32,imm32 \321\1\x69\100\41 386
+IMUL reg32,imm \321\144\1\x69\100\141 386,SM,ND
IN reg_al,imm \1\xE4\25 8086,SB
IN reg_ax,imm \320\1\xE5\25 8086,SB
IN reg_eax,imm \321\1\xE5\25 386,SB
@@ -479,7 +479,7 @@ IRETW void \320\1\xCF 8086
JCXZ imm \310\1\xE3\50 8086
JECXZ imm \311\1\xE3\50 386
JMP imm|short \1\xEB\50 8086
-JMP imm \370\1\xEB\50 8086,ND
+JMP imm \371\1\xEB\50 8086,ND
JMP imm \322\1\xE9\64 8086
JMP imm|near \322\1\xE9\64 8086,ND
JMP imm|far \322\1\xEA\34\37 8086,ND
@@ -558,9 +558,9 @@ LSS reg32,mem \321\301\2\x0F\xB2\110 386
LTR mem \300\1\x0F\17\203 286,PROT,PRIV
LTR mem16 \300\1\x0F\17\203 286,PROT,PRIV
LTR reg16 \300\1\x0F\17\203 286,PROT,PRIV
-MOV mem,reg_cs \300\1\x8C\201 8086,SM
-MOV mem,reg_dess \300\1\x8C\101 8086,SM
-MOV mem,reg_fsgs \300\1\x8C\101 386,SM
+MOV mem,reg_cs \300\1\x8C\201 8086,SM
+MOV mem,reg_dess \300\1\x8C\101 8086,SM
+MOV mem,reg_fsgs \300\1\x8C\101 386,SM
MOV reg16,reg_cs \320\300\1\x8C\201 8086
MOV reg16,reg_dess \320\300\1\x8C\101 8086
MOV reg16,reg_fsgs \320\300\1\x8C\101 386
@@ -653,15 +653,15 @@ OR rm16,imm8 \320\300\1\x83\201\15 8086
OR rm32,imm8 \321\300\1\x83\201\15 386
OR reg_al,imm \1\x0C\21 8086,SM
OR reg_ax,imm \320\1\x0D\31 8086,SM
-OR reg_eax,sbyte \321\1\x83\201\15 386,SM,ND
-OR reg_eax,sbig \321\1\x0D\41 386,SM,ND
+OR reg_eax,sbyte \321\1\x83\201\15 386,SM,ND
+OR reg_eax,sbig \321\1\x0D\41 386,SM,ND
OR reg_eax,imm32 \321\1\x0D\41 386
OR rm8,imm \300\1\x80\201\21 8086,SM
-OR rm16,imm \320\300\134\1\x81\201\131 8086,SM
-OR rm32,imm \321\300\144\1\x81\201\141 386,SM
+OR rm16,imm \320\300\134\1\x81\201\131 8086,SM
+OR rm32,imm \321\300\144\1\x81\201\141 386,SM
OR mem,imm8 \300\1\x80\201\21 8086,SM
-OR mem,imm16 \320\300\134\1\x81\201\131 8086,SM
-OR mem,imm32 \321\300\144\1\x81\201\141 386,SM
+OR mem,imm16 \320\300\134\1\x81\201\131 8086,SM
+OR mem,imm32 \321\300\144\1\x81\201\141 386,SM
OUT imm,reg_al \1\xE6\24 8086,SB
OUT imm,reg_ax \320\1\xE7\24 8086,SB
OUT imm,reg_eax \321\1\xE7\24 386,SB
@@ -946,15 +946,15 @@ SBB rm16,imm8 \320\300\1\x83\203\15 8086
SBB rm32,imm8 \321\300\1\x83\203\15 8086
SBB reg_al,imm \1\x1C\21 8086,SM
SBB reg_ax,imm \320\1\x1D\31 8086,SM
-SBB reg_eax,sbyte \321\1\x83\203\15 386,SM,ND
-SBB reg_eax,sbig \321\1\x1D\41 386,SM,ND
+SBB reg_eax,sbyte \321\1\x83\203\15 386,SM,ND
+SBB reg_eax,sbig \321\1\x1D\41 386,SM,ND
SBB reg_eax,imm32 \321\1\x1D\41 386
SBB rm8,imm \300\1\x80\203\21 8086,SM
-SBB rm16,imm \320\300\134\1\x81\203\131 8086,SM
-SBB rm32,imm \321\300\144\1\x81\203\141 386,SM
+SBB rm16,imm \320\300\134\1\x81\203\131 8086,SM
+SBB rm32,imm \321\300\144\1\x81\203\141 386,SM
SBB mem,imm8 \300\1\x80\203\21 8086,SM
-SBB mem,imm16 \320\300\134\1\x81\203\131 8086,SM
-SBB mem,imm32 \321\300\144\1\x81\203\141 386,SM
+SBB mem,imm16 \320\300\134\1\x81\203\131 8086,SM
+SBB mem,imm32 \321\300\144\1\x81\203\141 386,SM
SCASB void \332\1\xAE 8086
SCASD void \332\321\1\xAF 386
SCASW void \332\320\1\xAF 8086
@@ -1029,15 +1029,15 @@ SUB rm16,imm8 \320\300\1\x83\205\15 8086
SUB rm32,imm8 \321\300\1\x83\205\15 386
SUB reg_al,imm \1\x2C\21 8086,SM
SUB reg_ax,imm \320\1\x2D\31 8086,SM
-SUB reg_eax,sbyte \321\1\x83\205\15 386,SM,ND
-SUB reg_eax,sbig \321\1\x2D\41 386,SM,ND
+SUB reg_eax,sbyte \321\1\x83\205\15 386,SM,ND
+SUB reg_eax,sbig \321\1\x2D\41 386,SM,ND
SUB reg_eax,imm32 \321\1\x2D\41 386
SUB rm8,imm \300\1\x80\205\21 8086,SM
-SUB rm16,imm \320\300\134\1\x81\205\131 8086,SM
-SUB rm32,imm \321\300\144\1\x81\205\141 386,SM
+SUB rm16,imm \320\300\134\1\x81\205\131 8086,SM
+SUB rm32,imm \321\300\144\1\x81\205\141 386,SM
SUB mem,imm8 \300\1\x80\205\21 8086,SM
-SUB mem,imm16 \320\300\134\1\x81\205\131 8086,SM
-SUB mem,imm32 \321\300\144\1\x81\205\141 386,SM
+SUB mem,imm16 \320\300\134\1\x81\205\131 8086,SM
+SUB mem,imm32 \321\300\144\1\x81\205\141 386,SM
SVDC mem80,reg_sreg \300\2\x0F\x78\101 486,CYRIX,SMM
SVLDT mem80 \300\2\x0F\x7A\200 486,CYRIX,SMM
SVTS mem80 \300\2\x0F\x7C\200 486,CYRIX,SMM
@@ -1132,15 +1132,15 @@ XOR rm16,imm8 \320\300\1\x83\206\15 8086
XOR rm32,imm8 \321\300\1\x83\206\15 386
XOR reg_al,imm \1\x34\21 8086,SM
XOR reg_ax,imm \320\1\x35\31 8086,SM
-XOR reg_eax,sbyte \321\1\x83\206\15 386,SM,ND
-XOR reg_eax,sbig \321\1\x35\41 386,SM,ND
+XOR reg_eax,sbyte \321\1\x83\206\15 386,SM,ND
+XOR reg_eax,sbig \321\1\x35\41 386,SM,ND
XOR reg_eax,imm32 \321\1\x35\41 386
XOR rm8,imm \300\1\x80\206\21 8086,SM
-XOR rm16,imm \320\300\134\1\x81\206\131 8086,SM
-XOR rm32,imm \321\300\144\1\x81\206\141 386,SM
+XOR rm16,imm \320\300\134\1\x81\206\131 8086,SM
+XOR rm32,imm \321\300\144\1\x81\206\141 386,SM
XOR mem,imm8 \300\1\x80\206\21 8086,SM
-XOR mem,imm16 \320\300\134\1\x81\206\131 8086,SM
-XOR mem,imm32 \321\300\144\1\x81\206\141 386,SM
+XOR mem,imm16 \320\300\134\1\x81\206\131 8086,SM
+XOR mem,imm32 \321\300\144\1\x81\206\141 386,SM
CMOVcc reg16,mem \320\301\1\x0F\330\x40\110 P6,SM
CMOVcc reg16,reg16 \320\301\1\x0F\330\x40\110 P6
CMOVcc reg32,mem \321\301\1\x0F\330\x40\110 P6,SM
diff --git a/macros.c b/macros.c
index 38a7e0f..ed70a75 100644
--- a/macros.c
+++ b/macros.c
@@ -1,12 +1,6 @@
/* This file auto-generated from standard.mac by macros.pl - don't edit it */
static char *stdmac[] = {
- "%idefine IDEAL",
- "%idefine JUMPS",
- "%idefine P386",
- "%idefine P486",
- "%idefine P586",
- "%idefine END",
"%define __NASM_MAJOR__ 0",
"%define __NASM_MINOR__ 98",
"%define __FILE__",
@@ -63,12 +57,6 @@ static char *stdmac[] = {
"%imacro bits 1+.nolist",
"[bits %1]",
"%endmacro",
- "%imacro use16 0.nolist",
- "[bits 16]",
- "%endmacro",
- "%imacro use32 0.nolist",
- "[bits 32]",
- "%endmacro",
"%imacro global 1-*.nolist",
"%rep %0",
"[global %1]",
@@ -81,9 +69,5 @@ static char *stdmac[] = {
"%rotate 1",
"%endrep",
"%endmacro",
- "%imacro cpu 1+.nolist",
- "[cpu %1]",
- "%endmacro",
NULL
};
-#define TASM_MACRO_COUNT 6
diff --git a/macros.pl b/macros.pl
index ecf0595..1de90e7 100644
--- a/macros.pl
+++ b/macros.pl
@@ -7,7 +7,7 @@
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
-# use strict; # if your PERL's got it
+# use strict;
my $fname;
my $line = 0;
diff --git a/misc/exasm.zip b/misc/exasm.zip
index e813018..b4e9e58 100644
--- a/misc/exasm.zip
+++ b/misc/exasm.zip
Binary files differ
diff --git a/nasm.c b/nasm.c
index c3575cd..20485d8 100644
--- a/nasm.c
+++ b/nasm.c
@@ -51,7 +51,7 @@ static struct ofmt *ofmt = NULL;
static FILE *error_file; /* Where to write error messages */
static FILE *ofile = NULL;
-int optimizing = 0; /* number of optimization passes to take */
+int optimizing = -1; /* number of optimization passes to take */
static int sb, cmd_sb = 16; /* by default */
static unsigned long cmd_cpu = IF_PLEVEL; /* highest level by default */
static unsigned long cpu = IF_PLEVEL; /* passed to insn_size & assemble.c */
@@ -386,11 +386,14 @@ static int process_arg (char *p, char *q)
else
ofmt->current_dfmt = ofmt->debug_formats[0];
} else if (p[1]=='O') { /* Optimization level */
+ int opt;
if (!isdigit(*param)) report_error(ERR_FATAL,
"command line optimization level must be 0..3 or <nn>");
- optimizing = atoi(param);
- if (optimizing <= 0) optimizing = 0;
- else if (optimizing <= 3) optimizing *= 5; /* 5 passes for each level */
+ opt = atoi(param);
+ if (opt<=0) optimizing = -1; /* 0.98 behaviour */
+ else if (opt==1) optimizing = 0; /* Two passes, 0.98.09 behavior */
+ else if (opt<=3) optimizing = opt*5; /* Multiple passes */
+ else optimizing = opt; /* Multiple passes */
} else if (p[1]=='P' || p[1]=='p') { /* pre-include */
pp_pre_include (param);
} else if (p[1]=='D' || p[1]=='d') { /* pre-define */
@@ -754,8 +757,8 @@ static void assemble_file (char *fname)
report_error(ERR_FATAL, "command line: "
"32-bit segment size requires a higher cpu");
- pass_max = optimizing + 2; /* passes 1, optimizing, then 2 */
- pass0 = !optimizing; /* start at 1 if not optimizing */
+ pass_max = (optimizing>0 ? optimizing : 0) + 2; /* passes 1, optimizing, then 2 */
+ pass0 = !(optimizing>0); /* start at 1 if not optimizing */
for (pass = 1; pass <= pass_max && pass0 <= 2; pass++) {
int pass1, pass2;
ldfunc def_label;
@@ -1027,11 +1030,11 @@ static void assemble_file (char *fname)
report_error, evaluate,
def_label);
- if (!optimizing && pass == 2) {
+ if (!(optimizing>0) && pass == 2) {
if (forwref != NULL && globallineno == forwref->lineno) {
output_ins.forw_ref = TRUE;
do {
- output_ins.oprs[forwref->operand].opflags|= OPFLAG_FORWARD;
+ output_ins.oprs[forwref->operand].opflags |= OPFLAG_FORWARD;
forwref = saa_rstruct (forwrefs);
} while (forwref != NULL && forwref->lineno == globallineno);
} else
@@ -1039,7 +1042,7 @@ static void assemble_file (char *fname)
}
- if (!optimizing && output_ins.forw_ref)
+ if (!(optimizing>0) && output_ins.forw_ref)
{
if (pass == 1) {
for(i = 0; i < output_ins.operands; i++)
@@ -1251,13 +1254,13 @@ static void assemble_file (char *fname)
if (pass>1 && !global_offset_changed) {
pass0++;
if (pass0==2) pass = pass_max - 1;
- } else if (!optimizing) pass0++;
+ } else if (!(optimizing>0)) pass0++;
} /* for (pass=1; pass<=2; pass++) */
nasmlist.cleanup();
#if 1
- if (optimizing && using_debug_info) /* -On and -g switches */
+ if (optimizing>0 && using_debug_info) /* -On and -g switches */
fprintf(error_file,
"info:: assembly required 1+%d+1 passes\n", pass_cnt-2);
#endif
@@ -1511,6 +1514,8 @@ static unsigned long get_cpu (char *value)
!nasm_stricmp(value, "p2") ) return IF_P6;
if (!nasm_stricmp(value, "p3") ||
!nasm_stricmp(value, "katmai") ) return IF_KATMAI;
+ if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
+ !nasm_stricmp(value, "willamette") ) return IF_WILLAMETTE;
report_error (pass0<2 ? ERR_NONFATAL : ERR_FATAL, "unknown 'cpu' type");
diff --git a/nasm.h b/nasm.h
index 55d8a8f..c463879 100644
--- a/nasm.h
+++ b/nasm.h
@@ -13,7 +13,7 @@
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 98
-#define NASM_VER "0.98.11"
+#define NASM_VER "0.98.12"
#ifndef NULL
#define NULL 0
diff --git a/parser.c b/parser.c
index d802f05..c3c00fc 100644
--- a/parser.c
+++ b/parser.c
@@ -686,7 +686,7 @@ insn *parse_line (int pass, char *buffer, insn *result,
if (is_simple(value)) {
if (reloc_value(value)==1)
result->oprs[operand].type |= UNITY;
- if (optimizing) {
+ if (optimizing>0) {
if (reloc_value(value) >= -128 &&
reloc_value(value) <= 127)
result->oprs[operand].type |= SBYTE;
diff --git a/preproc.c b/preproc.c
index 488517b..a62fe85 100644
--- a/preproc.c
+++ b/preproc.c
@@ -917,7 +917,8 @@ delete_Token(Token * t)
{
Token *next = t->next;
nasm_free(t->text);
- t->next = freeTokens ? freeTokens->next : NULL;
+/* t->next = freeTokens ? freeTokens->next : NULL; */
+ t->next = freeTokens;
freeTokens = t;
return next;
}
diff --git a/rdoff/Makefile.in b/rdoff/Makefile.in
index 38620d7..5ea14a0 100644
--- a/rdoff/Makefile.in
+++ b/rdoff/Makefile.in
@@ -1,86 +1,84 @@
-***************
-*** 1,4 ****
-- # $Id$
- #
- # Auto-configuring Makefile for RDOFF object file utils; part of the
- # Netwide Assembler
---- 1,4 ----
-+ # $Id$
- #
- # Auto-configuring Makefile for RDOFF object file utils; part of the
- # Netwide Assembler
-***************
-*** 31,37 ****
- .c.o:
- $(CC) -c $(CFLAGS) $<
-
-- all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
- rdfdump: rdfdump.o
- $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
---- 31,37 ----
- .c.o:
- $(CC) -c $(CFLAGS) $<
-
-+ all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
-
- rdfdump: rdfdump.o
- $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
-***************
-*** 45,51 ****
- $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
- rdf2com:
- rm -f rdf2com && $(LN_S) rdf2bin rdf2com
-
- rdf2bin.o: rdf2bin.c
- rdfdump.o: rdfdump.c
- rdoff.o: rdoff.c rdoff.h
---- 45,54 ----
- $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
- rdf2com:
- rm -f rdf2com && $(LN_S) rdf2bin rdf2com
-+ rdf2ihx: rdf2ihx.o $(RDXLIBS) nasmlib.o
-+ $(CC) $(LDFLAGS) -o rdf2ihx rdf2ihx.o $(RDXLIBS) nasmlib.o
-
-+ rdf2ihx.o: rdf2ihx.c
- rdf2bin.o: rdf2bin.c
- rdfdump.o: rdfdump.c
- rdoff.o: rdoff.c rdoff.h
-***************
-*** 62,78 ****
- $(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
-
- clean:
-- rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-
- spotless: clean
- rm -f Makefile
-
- distclean: spotless
-
-- install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
- $(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
- $(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
- $(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
- $(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
- $(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
- cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
---- 65,82 ----
- $(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
-
- clean:
-+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
-
- spotless: clean
- rm -f Makefile
-
- distclean: spotless
-
-+ install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
- $(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
- $(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
- $(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
- $(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
- $(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
-+ $(INSTALL_PROGRAM) rdf2ihx $(INSTALLROOT)$(bindir)/rdf2ihx
- cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
+# $Id$
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the licence given in the file "Licence"
+# distributed in the NASM archive.
+
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+
+CC = @CC@
+CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I$(top_srcdir)
+LDFLAGS = @LDFLAGS@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+LN_S = @LN_S@
+
+LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
+RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) $<
+
+all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
+
+rdfdump: rdfdump.o
+ $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
+ldrdf: ldrdf.o $(LDRDFLIBS)
+ $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS)
+rdx: rdx.o $(RDXLIBS)
+ $(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS)
+rdflib: rdflib.o
+ $(CC) $(LDFLAGS) -o rdflib rdflib.o
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
+rdf2com:
+ rm -f rdf2com && $(LN_S) rdf2bin rdf2com
+rdf2ihx: rdf2ihx.o $(RDXLIBS) nasmlib.o
+ $(CC) $(LDFLAGS) -o rdf2ihx rdf2ihx.o $(RDXLIBS) nasmlib.o
+
+rdf2ihx.o: rdf2ihx.c
+rdf2bin.o: rdf2bin.c
+rdfdump.o: rdfdump.c
+rdoff.o: rdoff.c rdoff.h
+ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
+symtab.o: symtab.c symtab.h
+collectn.o: collectn.c collectn.h
+rdx.o: rdx.c rdoff.h rdfload.h symtab.h
+rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.o: rdlib.c rdlib.h
+rdflib.o: rdflib.c
+segtab.o: segtab.c
+
+nasmlib.o: $(top_srcdir)/nasmlib.c
+## $(CC) -c $(CFLAGS) $(top_srcdir)/nasmlib.c
+ cd $(top_srcdir);make nasmlib.o
+ cp $(top_srcdir)/nasmlib.o $(srcdir)
+
+clean:
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
+
+spotless: clean
+ rm -f Makefile
+
+distclean: spotless
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com rdf2ihx
+ $(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
+ $(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
+ $(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
+ $(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
+ $(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
+ $(INSTALL_PROGRAM) rdf2ihx $(INSTALLROOT)$(bindir)/rdf2ihx
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c
index d9aac2f..3d9d749 100644
--- a/rdoff/ldrdf.c
+++ b/rdoff/ldrdf.c
@@ -1,31 +1,1347 @@
-***************
-*** 29,42 ****
- #include <stdlib.h>
- #include <string.h>
-
- #include "rdoff.h"
- #include "symtab.h"
- #include "collectn.h"
- #include "rdlib.h"
- #include "segtab.h"
-- #include "multboot.h"
-
-- #define LDRDF_VERSION "1.01 alpha 2"
-
- #define RDF_MAXSEGS 64
- /* #define STINGY_MEMORY */
---- 29,42 ----
- #include <stdlib.h>
- #include <string.h>
-
-+ #include "multboot.h"
- #include "rdoff.h"
- #include "symtab.h"
- #include "collectn.h"
- #include "rdlib.h"
- #include "segtab.h"
-
-+ #define LDRDF_VERSION "1.02"
-
- #define RDF_MAXSEGS 64
- /* #define STINGY_MEMORY */
+/* ldrdf.c RDOFF Object File linker/loader main program
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/*
+ * TODO: actually get this new version working!
+ * - finish off write_output() - appears to be done
+ * - implement library searching - appears to be done
+ * - maybe we only want to do one pass, for performance reasons?
+ * this makes things a little harder, but unix 'ld' copes...
+ * - implement command line options - appears to be done
+ * - improve symbol table implementation - done, thanks to Graeme Defty
+ * - keep a cache of symbol names in each library module so
+ * we don't have to constantly recheck the file
+ * - general performance improvements
+ *
+ * BUGS & LIMITATIONS: this program doesn't support multiple code, data
+ * or bss segments, therefore for 16 bit programs whose code, data or BSS
+ * segment exceeds 64K in size, it will not work. This program probably
+ * wont work if compiled by a 16 bit compiler. Try DJGPP if you're running
+ * under DOS. '#define STINGY_MEMORY' may help a little.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "multboot.h"
+#include "rdoff.h"
+#include "symtab.h"
+#include "collectn.h"
+#include "rdlib.h"
+#include "segtab.h"
+
+#define LDRDF_VERSION "1.02"
+
+#define RDF_MAXSEGS 64
+/* #define STINGY_MEMORY */
+
+/* =======================================================================
+ * Types & macros that are private to this program
+ */
+
+struct segment_infonode {
+ int dest_seg; /* output segment to be placed into, -1 to
+ skip linking this segment */
+ long reloc; /* segment's relocation factor */
+};
+
+
+struct modulenode {
+ rdffile f; /* the RDOFF file structure */
+ struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
+ with each segment? */
+ void * header;
+ char * name;
+ struct modulenode * next;
+ long bss_reloc;
+};
+
+#include "ldsegs.h"
+
+#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
+#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
+
+/* ==========================================================================
+ * Function prototypes of private utility functions
+ */
+
+void processmodule(const char * filename, struct modulenode * mod);
+int allocnewseg(int16 type,int16 reserved);
+int findsegment(int16 type,int16 reserved);
+void symtab_add(const char * symbol, int segment, long offset);
+int symtab_get(const char * symbol, int * segment, long * offset);
+
+/* =========================================================================
+ * Global data structures.
+ */
+
+/* a linked list of modules that will be included in the output */
+struct modulenode * modules = NULL;
+struct modulenode * lastmodule = NULL;
+
+/* a linked list of libraries to be searched for unresolved imported symbols */
+struct librarynode * libraries = NULL;
+struct librarynode * lastlib = NULL;
+
+/* the symbol table */
+void * symtab = NULL;
+
+/* objects search path */
+char * objpath = NULL;
+
+/* libraries search path */
+char * libpath = NULL;
+
+/* error file */
+static FILE * error_file;
+
+#ifdef _MULTBOOT_H
+
+/* loading address for multiboot header */
+unsigned MBHloadAddr;
+
+/*
+ * Tiny code that moves RDF loader to its working memory region:
+ * mov esi,SOURCE_ADDR ; BE xx xx xx xx
+ * mov edi,DEST_ADDR ; BF xx xx xx xx
+ * mov esp,edi ; 89 FC
+ * push edi ; 57
+ * mov ecx,RDFLDR_LENGTH/4 ; B9 xx xx xx xx
+ * cld ; FC
+ * rep movsd ; F3 A5
+ * ret ; C3
+ */
+
+#define RDFLDR_LENGTH 4096 /* Loader will be moved to unused */
+#define RDFLDR_DESTLOC 0xBF000 /* video page */
+
+unsigned char RDFloaderMover[]={
+ 0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0,
+ 0x89, 0xFC, 0x57,
+ 0xB9, 0, 4, 0, 0,
+ 0xFC, 0xF3, 0xA5, 0xC3
+};
+
+#endif
+
+/* the header of the output file, built up stage by stage */
+rdf_headerbuf * newheader = NULL;
+
+/* The current state of segment allocation, including information about
+ * which output segment numbers have been allocated, and their types and
+ * amount of data which has already been allocated inside them.
+ */
+struct SegmentHeaderRec outputseg[RDF_MAXSEGS];
+int nsegs = 0;
+long bss_length;
+
+/* global options which affect how the program behaves */
+struct ldrdfoptions {
+ int verbose;
+ int align;
+ int warnUnresolved;
+ int errorUnresolved;
+ int strip;
+ int respfile;
+ int stderr_redir;
+ int objpath;
+ int libpath;
+ int addMBheader;
+} options;
+
+int errorcount = 0; /* determines main program exit status */
+
+/* =========================================================================
+ * Utility functions
+ */
+
+
+/*
+ * initsegments()
+ *
+ * sets up segments 0, 1, and 2, the initial code data and bss segments
+ */
+
+void initsegments()
+{
+ nsegs = 3;
+ outputseg[0].type = 1;
+ outputseg[0].number = 0;
+ outputseg[0].reserved = 0;
+ outputseg[0].length = 0;
+ outputseg[1].type = 2;
+ outputseg[1].number = 1;
+ outputseg[1].reserved = 0;
+ outputseg[1].length = 0;
+ outputseg[2].type = 0xFFFF; /* reserved segment type */
+ outputseg[2].number = 2;
+ outputseg[2].reserved = 0;
+ outputseg[2].length = 0;
+ bss_length = 0;
+}
+
+/*
+ * loadmodule
+ *
+ * Determine the characteristics of a module, and decide what to do with
+ * each segment it contains (including determining destination segments and
+ * relocation factors for segments that are kept).
+ */
+
+void loadmodule(const char * filename)
+{
+ if (options.verbose)
+ printf("loading `%s'\n", filename);
+
+ /* allocate a new module entry on the end of the modules list */
+ if (!modules)
+ {
+ modules = malloc (sizeof(*modules));
+ lastmodule = modules;
+ }
+ else
+ {
+ lastmodule->next = malloc (sizeof(*modules));
+ lastmodule = lastmodule->next;
+ }
+
+ if ( ! lastmodule)
+ {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ /* open the file using 'rdfopen', which returns nonzero on error */
+
+ if (rdfopen(&lastmodule->f, filename) != 0)
+ {
+ rdfperror("ldrdf", filename);
+ exit(1);
+ }
+
+ /*
+ * store information about the module, and determine what segments
+ * it contains, and what we should do with them (determine relocation
+ * factor if we decide to keep them)
+ */
+
+ lastmodule->header = NULL;
+ lastmodule->name = strdup(filename);
+ lastmodule->next = NULL;
+
+ processmodule(filename, lastmodule);
+}
+
+/*
+ * processmodule()
+ *
+ * step through each segment, determine what exactly we're doing with
+ * it, and if we intend to keep it, determine (a) which segment to
+ * put it in and (b) whereabouts in that segment it will end up.
+ * (b) is fairly easy, cos we're now keeping track of how big each segment
+ * in our output file is...
+ */
+
+void processmodule(const char * filename, struct modulenode * mod)
+{
+ struct segconfig sconf;
+ int seg, outseg;
+ void * header;
+ rdfheaderrec * hr;
+ long bssamount = 0;
+
+ for (seg = 0; seg < mod->f.nsegs; seg++)
+ {
+ /*
+ * get the segment configuration for this type from the segment
+ * table. getsegconfig() is a macro, defined in ldsegs.h.
+ */
+ getsegconfig(sconf, mod->f.seg[seg].type);
+
+ if (options.verbose > 1) {
+ printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number,
+ mod->f.seg[seg].type, sconf.typedesc);
+ }
+ /*
+ * sconf->dowhat tells us what to do with a segment of this type.
+ */
+ switch (sconf.dowhat) {
+ case SEG_IGNORE:
+ /*
+ * Set destination segment to -1, to indicate that this segment
+ * should be ignored for the purpose of output, ie it is left
+ * out of the linked executable.
+ */
+ mod->seginfo[seg].dest_seg = -1;
+ if (options.verbose > 1) printf("IGNORED\n");
+ break;
+
+ case SEG_NEWSEG:
+ /*
+ * The configuration tells us to create a new segment for
+ * each occurrence of this segment type.
+ */
+ outseg = allocnewseg(sconf.mergetype,
+ mod->f.seg[seg].reserved);
+ mod->seginfo[seg].dest_seg = outseg;
+ mod->seginfo[seg].reloc = 0;
+ outputseg[outseg].length = mod->f.seg[seg].length;
+ if (options.verbose > 1)
+ printf ("=> %04x:%08lx (+%04lx)\n", outseg,
+ mod->seginfo[seg].reloc,
+ mod->f.seg[seg].length);
+ break;
+
+ case SEG_MERGE:
+ /*
+ * The configuration tells us to merge the segment with
+ * a previously existing segment of type 'sconf.mergetype',
+ * if one exists. Otherwise a new segment is created.
+ * This is handled transparently by 'findsegment()'.
+ */
+ outseg = findsegment(sconf.mergetype,
+ mod->f.seg[seg].reserved);
+ mod->seginfo[seg].dest_seg = outseg;
+
+ /*
+ * We need to add alignment to these segments.
+ */
+ if (outputseg[outseg].length % options.align != 0)
+ outputseg[outseg].length +=
+ options.align - (outputseg[outseg].length % options.align);
+
+ mod->seginfo[seg].reloc = outputseg[outseg].length;
+ outputseg[outseg].length += mod->f.seg[seg].length;
+
+ if (options.verbose > 1)
+ printf ("=> %04x:%08lx (+%04lx)\n", outseg,
+ mod->seginfo[seg].reloc,
+ mod->f.seg[seg].length);
+ }
+
+ }
+
+ /*
+ * extract symbols from the header, and dump them into the
+ * symbol table
+ */
+ header = malloc(mod->f.header_len);
+ if (!header) {
+ fprintf(stderr, "ldrdf: not enough memory\n");
+ exit(1);
+ }
+ if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
+ rdfperror("ldrdf", filename);
+ exit(1);
+ }
+
+ while ((hr = rdfgetheaderrec (&mod->f)))
+ {
+ switch(hr->type) {
+ case 2: /* imported symbol - define with seg = -1 */
+ case 7:
+ symtab_add(hr->i.label, -1, 0);
+ break;
+
+ case 3: /* exported symbol */
+ {
+ int destseg;
+ long destreloc;
+
+ if (hr->e.segment == 2)
+ {
+ destreloc = bss_length;
+ if (destreloc % options.align != 0)
+ destreloc += options.align - (destreloc % options.align);
+ destseg = 2;
+ }
+ else
+ {
+ if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
+ continue;
+ destreloc = mod->seginfo[(int)hr->e.segment].reloc;
+ }
+ symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
+ break;
+ }
+
+ case 5: /* BSS reservation */
+ /*
+ * first, amalgamate all BSS reservations in this module
+ * into one, because we allow this in the output format.
+ */
+ bssamount += hr->b.amount;
+ break;
+ }
+ }
+
+ if (bssamount != 0)
+ {
+ /*
+ * handle the BSS segment - first pad the existing bss length
+ * to the correct alignment, then store the length in bss_reloc
+ * for this module. Then add this module's BSS length onto
+ * bss_length.
+ */
+ if (bss_length % options.align != 0)
+ bss_length += options.align - (bss_length % options.align);
+
+ mod->bss_reloc = bss_length;
+ if (options.verbose > 1) {
+ printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n",
+ filename, bss_length, bssamount);
+ }
+ bss_length += bssamount;
+ }
+
+#ifdef STINGY_MEMORY
+ /*
+ * we free the header buffer here, to save memory later.
+ * this isn't efficient, but probably halves the memory usage
+ * of this program...
+ */
+ mod->f.header_loc = NULL;
+ free(header);
+
+#endif
+
+}
+
+
+/*
+ * Look in list for module by its name.
+ */
+int lookformodule(const char *name)
+ {
+ struct modulenode *curr=modules;
+
+ while(curr) {
+ if (!strcmp(name,curr->name)) return 1;
+ curr = curr->next;
+ }
+ return 0;
+ }
+
+
+/*
+ * allocnewseg()
+ * findsegment()
+ *
+ * These functions manipulate the array of output segments, and are used
+ * by processmodule(). allocnewseg() allocates a segment in the array,
+ * initialising it to be empty. findsegment() first scans the array for
+ * a segment of the type requested, and if one isn't found allocates a
+ * new one.
+ */
+int allocnewseg(int16 type,int16 reserved)
+{
+ outputseg[nsegs].type = type;
+ outputseg[nsegs].number = nsegs;
+ outputseg[nsegs].reserved = reserved;
+ outputseg[nsegs].length = 0;
+ outputseg[nsegs].offset = 0;
+ outputseg[nsegs].data = NULL;
+
+ return nsegs++;
+}
+
+int findsegment(int16 type,int16 reserved)
+{
+ int i;
+
+ for (i = 0; i < nsegs; i++)
+ if (outputseg[i].type == type) return i;
+
+ return allocnewseg(type,reserved);
+}
+
+/*
+ * symtab_add()
+ *
+ * inserts a symbol into the global symbol table, which associates symbol
+ * names either with addresses, or a marker that the symbol hasn't been
+ * resolved yet, or possibly that the symbol has been defined as
+ * contained in a dynamic [load time/run time] linked library.
+ *
+ * segment = -1 => not yet defined
+ * segment = -2 => defined as dll symbol
+ *
+ * If the symbol is already defined, and the new segment >= 0, then
+ * if the original segment was < 0 the symbol is redefined, otherwise
+ * a duplicate symbol warning is issued. If new segment == -1, this
+ * routine won't change a previously existing symbol. It will change
+ * to segment = -2 only if the segment was previously < 0.
+ */
+
+void symtab_add(const char * symbol, int segment, long offset)
+{
+ symtabEnt * ste;
+
+ ste = symtabFind(symtab, symbol);
+ if (ste)
+ {
+ if (ste->segment >= 0) {
+ /*
+ * symbol previously defined
+ */
+ if (segment < 0) return;
+ fprintf (error_file, "warning: `%s' redefined\n", symbol);
+ return;
+ }
+
+ /*
+ * somebody wanted the symbol, and put an undefined symbol
+ * marker into the table
+ */
+ if (segment == -1) return;
+ /*
+ * we have more information now - update the symbol's entry
+ */
+ ste->segment = segment;
+ ste->offset = offset;
+ ste->flags = 0;
+ return;
+ }
+ /*
+ * this is the first declaration of this symbol
+ */
+ ste = malloc(sizeof(symtabEnt));
+ if (!ste) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ ste->name = strdup(symbol);
+ ste->segment = segment;
+ ste->offset = offset;
+ ste->flags = 0;
+ symtabInsert(symtab, ste);
+}
+
+/*
+ * symtab_get()
+ *
+ * Retrieves the values associated with a symbol. Undefined symbols
+ * are assumed to have -1:0 associated. Returns 1 if the symbol was
+ * successfully located.
+ */
+
+int symtab_get(const char * symbol, int * segment, long * offset)
+{
+ symtabEnt * ste = symtabFind(symtab, symbol);
+ if (!ste) {
+ *segment = -1;
+ *offset = 0;
+ return 0;
+ }
+ else
+ {
+ *segment = ste->segment;
+ *offset = ste->offset;
+ return 1;
+ }
+}
+
+/*
+ * add_library()
+ *
+ * checks that a library can be opened and is in the correct format,
+ * then adds it to the linked list of libraries.
+ */
+
+void add_library(const char * name)
+{
+ if (rdl_verify(name)) {
+ rdl_perror("ldrdf", name);
+ errorcount++;
+ return;
+ }
+ if (! libraries)
+ {
+ lastlib = libraries = malloc(sizeof(*libraries));
+ if (! libraries) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ }
+ else
+ {
+ lastlib->next = malloc(sizeof(*libraries));
+ if (!lastlib->next) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ lastlib = lastlib->next;
+ }
+ lastlib->next = NULL;
+ if (rdl_open(lastlib, name)) {
+ rdl_perror("ldrdf", name);
+ errorcount++;
+ return;
+ }
+}
+
+/*
+ * search_libraries()
+ *
+ * scans through the list of libraries, attempting to match symbols
+ * defined in library modules against symbols that are referenced but
+ * not defined (segment = -1 in the symbol table)
+ *
+ * returns 1 if any extra library modules are included, indicating that
+ * another pass through the library list should be made (possibly).
+ */
+
+int search_libraries()
+{
+ struct librarynode * cur;
+ rdffile f;
+ int i;
+ void * header;
+ int segment;
+ long offset;
+ int doneanything = 0, pass = 1, keepfile;
+ rdfheaderrec * hr;
+
+ cur = libraries;
+
+ while (cur)
+ {
+ if (options.verbose > 2)
+ printf("scanning library `%s', pass %d...\n", cur->name, pass);
+
+ for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
+ {
+ if (pass == 2 && lookformodule(f.name)) continue;
+
+ if (options.verbose > 3)
+ printf(" looking in module `%s'\n", f.name);
+
+ header = malloc(f.header_len);
+ if (!header) {
+ fprintf(stderr, "ldrdf: not enough memory\n");
+ exit(1);
+ }
+ if (rdfloadseg(&f, RDOFF_HEADER, header)) {
+ rdfperror("ldrdf", f.name);
+ errorcount++;
+ return 0;
+ }
+
+ keepfile = 0;
+
+ while ((hr = rdfgetheaderrec (&f)))
+ {
+ /* we're only interested in exports, so skip others: */
+ if (hr->type != 3) continue;
+
+ /*
+ * Find the symbol in the symbol table. If the symbol isn't
+ * defined, we aren't interested, so go on to the next.
+ * If it is defined as anything but -1, we're also not
+ * interested. But if it is defined as -1, insert this
+ * module into the list of modules to use, and go
+ * immediately on to the next module...
+ */
+ if (! symtab_get(hr->e.label, &segment, &offset)
+ || segment != -1)
+ {
+ continue;
+ }
+
+ doneanything = 1;
+ keepfile = 1;
+
+ /*
+ * as there are undefined symbols, we can assume that
+ * there are modules on the module list by the time
+ * we get here.
+ */
+ lastmodule->next = malloc(sizeof(*lastmodule->next));
+ if (!lastmodule->next) {
+ fprintf(stderr, "ldrdf: not enough memory\n");
+ exit(1);
+ }
+ lastmodule = lastmodule->next;
+ memcpy(&lastmodule->f, &f, sizeof(f));
+ lastmodule->name = strdup(f.name);
+ lastmodule->next = NULL;
+ processmodule(f.name, lastmodule);
+ break;
+ }
+ if (!keepfile)
+ {
+ free(f.name);
+ f.name = NULL;
+ f.fp = NULL;
+ }
+ }
+ if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
+ rdl_perror("ldrdf", cur->name);
+
+ cur = cur->next;
+ if (cur == NULL && pass == 1) {
+ cur = libraries;
+ pass++;
+ }
+ }
+
+ return doneanything;
+}
+
+/*
+ * write_output()
+ *
+ * this takes the linked list of modules, and walks through it, merging
+ * all the modules into a single output module, and then writes this to a
+ * file.
+ */
+void write_output(const char * filename)
+{
+ FILE * f;
+ rdf_headerbuf * rdfheader;
+ struct modulenode * cur;
+ int i, availableseg, seg, localseg, isrelative;
+ void * header;
+ rdfheaderrec * hr, newrec;
+ symtabEnt * se;
+ segtab segs;
+ long offset;
+ byte * data;
+
+ if ((f = fopen(filename, "wb"))==NULL) {
+ fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
+ exit(1);
+ }
+ if ((rdfheader=rdfnewheader())==NULL) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ /*
+ * Add multiboot header if appropriate option is specified.
+ * Multiboot record *MUST* be the first record in output file.
+ */
+ if (options.addMBheader) {
+ if (options.verbose)
+ puts("\nadding multiboot header record");
+
+ hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec));
+ hr->mbh.type = 9;
+ hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE;
+
+ hr->mbh.mb.Magic = MB_MAGIC;
+ hr->mbh.mb.Flags = MB_FL_KLUDGE;
+ hr->mbh.mb.Checksum = ~(MB_MAGIC+MB_FL_KLUDGE-1);
+ hr->mbh.mb.HeaderAddr = MBHloadAddr+16;
+ hr->mbh.mb.LoadAddr = MBHloadAddr;
+ hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader);
+
+ memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE);
+
+ rdfaddheader(rdfheader,hr);
+ free(hr);
+ }
+
+ if (options.verbose)
+ printf ("\nbuilding output module (%d segments)\n", nsegs);
+
+ /*
+ * Allocate the memory for the segments. We may be better off
+ * building the output module one segment at a time when running
+ * under 16 bit DOS, but that would be a slower way of doing this.
+ * And you could always use DJGPP...
+ */
+ for (i = 0; i < nsegs; i++)
+ {
+ outputseg[i].data=NULL;
+ if(!outputseg[i].length) continue;
+ outputseg[i].data = malloc(outputseg[i].length);
+ if (!outputseg[i].data) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ }
+
+ /*
+ * initialise availableseg, used to allocate segment numbers for
+ * imported and exported labels...
+ */
+ availableseg = nsegs;
+
+ /*
+ * Step through the modules, performing required actions on each one
+ */
+ for (cur = modules; cur; cur=cur->next)
+ {
+ /*
+ * Read the actual segment contents into the correct places in
+ * the newly allocated segments
+ */
+
+ for (i = 0; i < cur->f.nsegs; i++)
+ {
+ int dest = cur->seginfo[i].dest_seg;
+
+ if (dest == -1) continue;
+ if (rdfloadseg(&cur->f, i,
+ outputseg[dest].data + cur->seginfo[i].reloc))
+ {
+ rdfperror("ldrdf", cur->name);
+ exit(1);
+ }
+ }
+
+ /*
+ * Perform fixups, and add new header records where required
+ */
+
+ header = malloc(cur->f.header_len);
+ if (!header) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (cur->f.header_loc)
+ rdfheaderrewind(&cur->f);
+ else
+ if (rdfloadseg(&cur->f, RDOFF_HEADER, header))
+ {
+ rdfperror("ldrdf", cur->name);
+ exit(1);
+ }
+
+ /*
+ * we need to create a local segment number -> location
+ * table for the segments in this module.
+ */
+ init_seglocations(&segs);
+ for (i = 0; i < cur->f.nsegs; i++)
+ {
+ add_seglocation(&segs, cur->f.seg[i].number,
+ cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);
+ }
+ /*
+ * and the BSS segment (doh!)
+ */
+ add_seglocation (&segs, 2, 2, cur->bss_reloc);
+
+ while ((hr = rdfgetheaderrec(&cur->f)))
+ {
+ switch(hr->type) {
+ case 1: /* relocation record - need to do a fixup */
+ /*
+ * First correct the offset stored in the segment from
+ * the start of the segment (which may well have changed).
+ *
+ * To do this we add to the number stored the relocation
+ * factor associated with the segment that contains the
+ * target segment.
+ *
+ * The relocation could be a relative relocation, in which
+ * case we have to first subtract the amount we've relocated
+ * the containing segment by.
+ */
+
+ if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
+ {
+ fprintf(stderr, "%s: reloc to undefined segment %04x\n",
+ cur->name, (int) hr->r.refseg);
+ errorcount++;
+ break;
+ }
+
+ isrelative = (hr->r.segment & 64) == 64;
+ hr->r.segment &= 63;
+
+ if (hr->r.segment == 2 ||
+ (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)
+ {
+ fprintf(stderr, "%s: reloc from %s segment (%d)\n",
+ cur->name,
+ hr->r.segment == 2 ? "BSS" : "unknown",
+ hr->r.segment);
+ errorcount++;
+ break;
+ }
+
+ if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4)
+ {
+ fprintf(stderr, "%s: nonstandard length reloc "
+ "(%d bytes)\n", cur->name, hr->r.length);
+ errorcount++;
+ break;
+ }
+
+ /*
+ * okay, now the relocation is in the segment pointed to by
+ * cur->seginfo[localseg], and we know everything else is
+ * okay to go ahead and do the relocation
+ */
+ data = outputseg[cur->seginfo[localseg].dest_seg].data;
+ data += cur->seginfo[localseg].reloc + hr->r.offset;
+
+ /*
+ * data now points to the reference that needs
+ * relocation. Calculate the relocation factor.
+ * Factor is:
+ * offset of referred object in segment [in offset]
+ * (- relocation of localseg, if ref is relative)
+ * For simplicity, the result is stored in 'offset'.
+ * Then add 'offset' onto the value at data.
+ */
+
+ if (isrelative) offset -= cur->seginfo[localseg].reloc;
+ switch (hr->r.length)
+ {
+ case 1:
+ offset += *data;
+ if (offset < -127 || offset > 128)
+ fprintf(error_file, "warning: relocation out of range "
+ "at %s(%02x:%08lx)\n", cur->name,
+ (int)hr->r.segment, hr->r.offset);
+ *data = (char) offset;
+ break;
+ case 2:
+ offset += * (short *)data;
+ if (offset < -32767 || offset > 32768)
+ fprintf(error_file, "warning: relocation out of range "
+ "at %s(%02x:%08lx)\n", cur->name,
+ (int)hr->r.segment, hr->r.offset);
+ * (short *)data = (short) offset;
+ break;
+ case 4:
+ * (long *)data += offset;
+ /* we can't easily detect overflow on this one */
+ break;
+ }
+
+ /*
+ * If the relocation was relative between two symbols in
+ * the same segment, then we're done.
+ *
+ * Otherwise, we need to output a new relocation record
+ * with the references updated segment and offset...
+ */
+ if (! isrelative
+ || cur->seginfo[localseg].dest_seg != seg)
+ {
+ hr->r.segment = cur->seginfo[localseg].dest_seg;
+ hr->r.offset += cur->seginfo[localseg].reloc;
+ hr->r.refseg = seg;
+ rdfaddheader(rdfheader, hr);
+ }
+ break;
+
+ case 2: /* import symbol */
+ case 7:
+ /*
+ * scan the global symbol table for the symbol
+ * and associate its location with the segment number
+ * for this module
+ */
+ se = symtabFind(symtab, hr->i.label);
+ if (!se || se->segment == -1) {
+ if (options.warnUnresolved) {
+ fprintf(error_file, "warning: unresolved reference to `%s'"
+ " in module `%s'\n", hr->i.label, cur->name);
+ if (options.errorUnresolved==1) errorcount++;
+ }
+ /*
+ * we need to allocate a segment number for this
+ * symbol, and store it in the symbol table for
+ * future reference
+ */
+ if (!se) {
+ se=malloc(sizeof(*se));
+ if (!se) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ se->name = strdup(hr->i.label);
+ se->flags = 0;
+ se->segment = availableseg++;
+ se->offset = 0;
+ symtabInsert(symtab, se);
+ }
+ else {
+ se->segment = availableseg++;
+ se->offset = 0;
+ }
+ /*
+ * output a header record that imports it to the
+ * recently allocated segment number...
+ */
+ newrec = *hr;
+ newrec.i.segment = se->segment;
+ rdfaddheader(rdfheader, &newrec);
+ }
+
+ add_seglocation(&segs, hr->i.segment, se->segment, se->offset);
+
+ break;
+
+ case 3: /* export symbol */
+ /*
+ * need to insert an export for this symbol into the new
+ * header, unless we're stripping symbols [unless this
+ * symbol is in an explicit keep list]. *** FIXME ***
+ */
+ if (options.strip)
+ break;
+
+ if (hr->e.segment == 2) {
+ seg = 2;
+ offset = cur->bss_reloc;
+ }
+ else {
+ localseg = rdffindsegment(&cur->f, hr->e.segment);
+ if (localseg == -1) {
+ fprintf(stderr, "%s: exported symbol `%s' from "
+ "unrecognised segment\n", cur->name,
+ hr->e.label);
+ errorcount++;
+ break;
+ }
+ offset = cur->seginfo[localseg].reloc;
+ seg = cur->seginfo[localseg].dest_seg;
+ }
+
+ hr->e.segment = seg;
+ hr->e.offset += offset;
+ rdfaddheader(rdfheader, hr);
+ break;
+
+ case 8: /* module name */
+ /*
+ * insert module name record if export symbols
+ * are not stripped.
+ */
+ if (options.strip) break;
+
+ rdfaddheader(rdfheader, hr);
+ break;
+
+ case 6: /* segment fixup */
+ /*
+ * modify the segment numbers if necessary, and
+ * pass straight through to the output module header
+ *
+ * *** FIXME ***
+ */
+ if (hr->r.segment == 2) {
+ fprintf(stderr, "%s: segment fixup in BSS section\n",
+ cur->name);
+ errorcount++;
+ break;
+ }
+ localseg = rdffindsegment(&cur->f, hr->r.segment);
+ if (localseg == -1) {
+ fprintf(stderr, "%s: segment fixup in unrecognised"
+ " segment (%d)\n", cur->name, hr->r.segment);
+ errorcount++;
+ break;
+ }
+ hr->r.segment = cur->seginfo[localseg].dest_seg;
+ hr->r.offset += cur->seginfo[localseg].reloc;
+
+ if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
+ {
+ fprintf(stderr, "%s: segment fixup to undefined "
+ "segment %04x\n", cur->name, (int)hr->r.refseg);
+ errorcount++;
+ break;
+ }
+ hr->r.refseg = seg;
+ rdfaddheader(rdfheader, hr);
+ break;
+ }
+ }
+
+ free(header);
+ done_seglocations(&segs);
+
+ }
+
+ /*
+ * combined BSS reservation for the entire results
+ */
+ newrec.type = 5;
+ newrec.b.reclen = 4;
+ newrec.b.amount = bss_length;
+ rdfaddheader(rdfheader, &newrec);
+
+ /*
+ * Write the header
+ */
+ for (i = 0; i < nsegs; i++)
+ {
+ if (i == 2) continue;
+ rdfaddsegment (rdfheader, outputseg[i].length);
+ }
+
+ if (options.addMBheader) {
+ struct MultiBootHdrRec *mbhrec = (struct MultiBootHdrRec *)(rdfheader->buf->buffer);
+ unsigned l = membuflength(rdfheader->buf) + 14 +
+ 10*rdfheader->nsegments + rdfheader->seglength;
+ unsigned *ldraddr = (unsigned *)(mbhrec->mover+1);
+
+ mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH;
+ mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr;
+ *ldraddr = MBHloadAddr+l+10;
+ }
+
+ rdfwriteheader(f, rdfheader);
+ rdfdoneheader(rdfheader);
+ /*
+ * Step through the segments, one at a time, writing out into
+ * the output file
+ */
+
+ for (i = 0; i < nsegs; i++)
+ {
+ int16 s;
+ long l;
+
+ if (i == 2) continue;
+
+ s = translateshort(outputseg[i].type);
+ fwrite(&s, 2, 1, f);
+ s = translateshort(outputseg[i].number);
+ fwrite(&s, 2, 1, f);
+ s = translateshort(outputseg[i].reserved);
+ fwrite(&s, 2, 1, f);
+ l = translatelong(outputseg[i].length);
+ fwrite(&l, 4, 1, f);
+
+ fwrite(outputseg[i].data, outputseg[i].length, 1, f);
+ }
+
+ fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
+}
+
+/* =========================================================================
+ * Main program
+ */
+
+void usage()
+{
+ printf("usage:\n");
+ printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
+ printf(" ldrdf -r\n");
+ printf("options:\n");
+ printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
+ printf(" -a nn sets segment alignment value (default 16)\n");
+ printf(" -s strips exported symbols\n");
+ printf(" -x warn about unresolved symbols\n");
+ printf(" -o name write output in file 'name'\n");
+ printf(" -j path specify objects search path\n");
+ printf(" -L path specify libraries search path\n");
+ printf(" -mbh [address] add multiboot header to output file. Default\n");
+ printf(" loading address is 0x110000\n");
+ exit(0);
+}
+
+int main(int argc, char ** argv)
+{
+ char * outname = "aout.rdf";
+ int moduleloaded = 0;
+ char *respstrings[128] = {0, };
+
+ options.verbose = 0;
+ options.align = 16;
+ options.warnUnresolved = 0;
+ options.strip = 0;
+
+ error_file = stderr;
+
+ argc --, argv ++;
+ if (argc == 0) usage();
+ while (argc && **argv == '-' && argv[0][1] != 'l')
+ {
+ switch(argv[0][1]) {
+ case 'r':
+ printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
+ printf( _RDOFF_H "\n");
+ exit(0);
+ case 'v':
+ if (argv[0][2] == '=') {
+ options.verbose = argv[0][3] - '0';
+ if (options.verbose < 0 || options.verbose > 9) {
+ fprintf(stderr, "ldrdf: verbosity level must be a number"
+ " between 0 and 9\n");
+ exit(1);
+ }
+ }
+ else
+ options.verbose++;
+ break;
+ case 'a':
+ options.align = atoi(argv[1]);
+ if (options.align <= 0) {
+ fprintf(stderr,
+ "ldrdf: -a expects a positive number argument\n");
+ exit(1);
+ }
+ argv++, argc--;
+ break;
+ case 's':
+ options.strip = 1;
+ break;
+ case 'x':
+ options.warnUnresolved = 1;
+ if (argv[0][2]=='e')
+ options.errorUnresolved = 1;
+ break;
+ case 'o':
+ outname = argv[1];
+ argv++, argc--;
+ break;
+ case 'j':
+ if (!objpath)
+ {
+ options.objpath = 1;
+ objpath = argv[1];
+ argv++, argc--;
+ break;
+ }
+ else
+ {
+ fprintf(stderr,"ldrdf: more than one objects search path specified\n");
+ exit(1);
+ }
+ case 'L':
+ if (!libpath)
+ {
+ options.libpath = 1;
+ libpath = argv[1];
+ argv++, argc--;
+ break;
+ }
+ else
+ {
+ fprintf(stderr,"ldrdf: more than one libraries search path specified\n");
+ exit(1);
+ }
+ case '@': {
+ int i=0;
+ char buf[256];
+ FILE *f;
+
+ options.respfile = 1;
+ if (argv[1] != NULL) f = fopen(argv[1],"r");
+ else
+ {
+ fprintf(stderr,"ldrdf: no response file name specified\n");
+ exit(1);
+ }
+
+ if (f == NULL)
+ {
+ fprintf(stderr,"ldrdf: unable to open response file\n");
+ exit(1);
+ }
+ argc-=2;
+ while(fgets(buf,sizeof(buf)-1,f)!=NULL)
+ {
+ char *p;
+ if (buf[0]=='\n') continue;
+ if ((p = strchr(buf,'\n')) != 0)
+ *p=0;
+ if (i >= 128)
+ {
+ fprintf(stderr,"ldrdf: too many input files\n");
+ exit(1);
+ }
+ *(respstrings+i) = newstr(buf);
+ argc++, i++;
+ }
+ goto done;
+ }
+ case '2':
+ options.stderr_redir = 1;
+ error_file = stdout;
+ break;
+ case 'm':
+ if (argv[0][2] == 'b' && argv[0][3] == 'h') {
+ if (argv[1][0] != '-') {
+ MBHloadAddr = atoi(argv[1]);
+ } else {
+ MBHloadAddr = MB_DEFAULTLOADADDR;
+ }
+ options.addMBheader = 1;
+ break;
+ }
+ default:
+ usage();
+ }
+ argv++, argc--;
+ }
+done:
+ if (options.verbose > 4) {
+ printf("ldrdf invoked with options:\n");
+ printf(" section alignment: %d bytes\n", options.align);
+ printf(" output name: `%s'\n", outname);
+ if (options.strip)
+ printf(" strip symbols\n");
+ if (options.warnUnresolved)
+ printf(" warn about unresolved symbols\n");
+ if (options.errorUnresolved)
+ printf(" error if unresolved symbols\n");
+ if (options.objpath)
+ printf(" objects search path: %s\n",objpath);
+ if (options.libpath)
+ printf(" libraries search path: %s\n",libpath);
+ if (options.addMBheader)
+ printf(" loading address for multiboot header: 0x%X\n",MBHloadAddr);
+ printf("\n");
+ }
+
+ symtab = symtabNew();
+ initsegments();
+
+ if (!symtab) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (*respstrings) argv = respstrings;
+ while (argc)
+ {
+ if (!strncmp(*argv, "-l", 2)) /* library */
+ {
+ if(libpath) add_library(newstrcat(libpath,*argv + 2));
+ else add_library(*argv + 2);
+ }
+ else {
+ if(objpath) loadmodule(newstrcat(objpath,*argv));
+ else loadmodule(*argv);
+ moduleloaded = 1;
+ }
+ argv++, argc--;
+ }
+
+ if (! moduleloaded) {
+ printf("ldrdf: nothing to do. ldrdf -h for usage\n");
+ return 0;
+ }
+
+
+ search_libraries();
+
+ if (options.verbose > 2)
+ {
+ printf ("symbol table:\n");
+ symtabDump(symtab, stdout);
+ }
+
+ write_output(outname);
+
+ if (errorcount > 0) exit(1);
+ return 0;
+}
diff --git a/test/bintest.asm b/test/bintest.asm
index 96a1dce..94d2bf7 100644
--- a/test/bintest.asm
+++ b/test/bintest.asm
@@ -1,34 +1,56 @@
-***************
-*** 26,32 ****
-
- jmp start ; [6]
-
-- end mov ax,0x4c00 ; [1]
- int 0x21
-
- start mov byte [bss_sym],',' ; [1] [8]
---- 26,32 ----
-
- jmp start ; [6]
-
-+ endX mov ax,0x4c00 ; [1]
- int 0x21
-
- start mov byte [bss_sym],',' ; [1] [8]
-***************
-*** 49,55 ****
- datasym db 'hello world', 13, 10, '$' ; [2]
- bssptr dw bss_sym ; [2] [11]
- dataptr dw datasym+5 ; [2] [10]
-- textptr dw end ; [2] [9]
-
- SECTION .bss
-
---- 49,55 ----
- datasym db 'hello world', 13, 10, '$' ; [2]
- bssptr dw bss_sym ; [2] [11]
- dataptr dw datasym+5 ; [2] [10]
-+ textptr dw endX ; [2] [9]
-
- SECTION .bss
-
+; test source file for assembling to binary files
+; build with:
+; nasm -f bin -o bintest.com bintest.asm
+
+; When run (as a DOS .COM file), this program should print
+; hello, world
+; on two successive lines, then exit cleanly.
+
+; This file should test the following:
+; [1] Define a text-section symbol
+; [2] Define a data-section symbol
+; [3] Define a BSS-section symbol
+; [4] Define a NASM local label
+; [5] Reference a NASM local label
+; [6] Reference a text-section symbol in the text section
+; [7] Reference a data-section symbol in the text section
+; [8] Reference a BSS-section symbol in the text section
+; [9] Reference a text-section symbol in the data section
+; [10] Reference a data-section symbol in the data section
+; [11] Reference a BSS-section symbol in the data section
+
+ BITS 16
+ ORG 0x100
+
+ SECTION .text
+
+ jmp start ; [6]
+
+endX mov ax,0x4c00 ; [1]
+ int 0x21
+
+start mov byte [bss_sym],',' ; [1] [8]
+ mov bx,[bssptr] ; [7]
+ mov al,[bx]
+ mov bx,[dataptr] ; [7]
+ mov [bx],al
+ mov cx,2
+.loop mov dx,datasym ; [1] [4] [7]
+ mov ah,9
+ push cx
+ int 0x21
+ pop cx
+ loop .loop ; [5] [6]
+ mov bx,[textptr] ; [7]
+ jmp bx
+
+ SECTION .data
+
+datasym db 'hello world', 13, 10, '$' ; [2]
+bssptr dw bss_sym ; [2] [11]
+dataptr dw datasym+5 ; [2] [10]
+textptr dw endX ; [2] [9]
+
+ SECTION .bss
+
+bss_sym resb 1 ; [3]