diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 21:02:01 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 21:02:01 +0000 |
commit | 788e6c10e175ab4b3e67feefbffe570619ae2330 (patch) | |
tree | fdbac44f81f28b729e74ce8a8379b5211f2d6f95 | |
parent | 4cf1748e6829f80be251b8d7d274738009f934cf (diff) | |
download | nasm-788e6c10e175ab4b3e67feefbffe570619ae2330.tar.gz nasm-788e6c10e175ab4b3e67feefbffe570619ae2330.tar.bz2 nasm-788e6c10e175ab4b3e67feefbffe570619ae2330.zip |
NASM 0.98.12
-rw-r--r-- | assemble.c | 13 | ||||
-rw-r--r-- | insns.dat | 140 | ||||
-rw-r--r-- | macros.c | 16 | ||||
-rw-r--r-- | macros.pl | 2 | ||||
-rw-r--r-- | misc/exasm.zip | bin | 491 -> 6058 bytes | |||
-rw-r--r-- | nasm.c | 27 | ||||
-rw-r--r-- | nasm.h | 2 | ||||
-rw-r--r-- | parser.c | 2 | ||||
-rw-r--r-- | preproc.c | 3 | ||||
-rw-r--r-- | rdoff/Makefile.in | 170 | ||||
-rw-r--r-- | rdoff/ldrdf.c | 1378 | ||||
-rw-r--r-- | test/bintest.asm | 90 |
12 files changed, 1586 insertions, 257 deletions
@@ -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; @@ -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 @@ -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 @@ -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 Binary files differindex e813018..b4e9e58 100644 --- a/misc/exasm.zip +++ b/misc/exasm.zip @@ -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"); @@ -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 @@ -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; @@ -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] |