We can now load and run 32-bit protected-mode executables. We have not,
however, set up the data segment.
This commit is contained in:
parent
b48b5b13ce
commit
d464606dd6
|
@ -11,144 +11,12 @@
|
||||||
.sect .bss
|
.sect .bss
|
||||||
|
|
||||||
.sect .text
|
.sect .text
|
||||||
.use16
|
|
||||||
exe_header:
|
|
||||||
.data2 0x5a4d ! magic number
|
|
||||||
.data2 0 ! number of bytes in last loadable page
|
|
||||||
.data2 exe_text_paras ! size of .exe, in pages
|
|
||||||
.data2 0 ! number of relocation entries
|
|
||||||
.data2 0 ! start of loadable area, in 16-byte paragraphs
|
|
||||||
.data2 exe_ram_paras ! required RAM size, in 16-byte paragraphs
|
|
||||||
.data2 0 ! maximum RAM siz, in 16-byte paragraphse
|
|
||||||
.data2 0 ! initial SS, relative to program
|
|
||||||
.data2 exe_stack ! initial SP
|
|
||||||
.data2 0 ! checksum (ignored)
|
|
||||||
.data2 exe_start ! initial IP
|
|
||||||
.data2 0 ! initial CS, relative to program
|
|
||||||
.data2 0 ! offset of relocation table
|
|
||||||
.data2 0 ! overlay number
|
|
||||||
|
|
||||||
dpmi_edi = 0x00
|
|
||||||
dpmi_esi = 0x04
|
|
||||||
dpmi_ebp = 0x08
|
|
||||||
dpmi_ebx = 0x10
|
|
||||||
dpmi_edx = 0x14
|
|
||||||
dpmi_ecx = 0x18
|
|
||||||
dpmi_eax = 0x1c
|
|
||||||
dpmi_flags = 0x20
|
|
||||||
dpmi_es = 0x22
|
|
||||||
dpmi_ds = 0x24
|
|
||||||
dpmi_fs = 0x26
|
|
||||||
dpmi_gs = 0x28
|
|
||||||
dpmi_ip = 0x2a
|
|
||||||
dpmi_cs = 0x2c
|
|
||||||
dpmi_sp = 0x2e
|
|
||||||
dpmi_ss = 0x30
|
|
||||||
|
|
||||||
dpmi_rs = 0x32 ! WORD: real segment
|
|
||||||
dpmi_psp = 0x34 ! WORD: PSP segment
|
|
||||||
dpmi_switch = 0x38 ! DWORD: far pointer of pmode switch routine
|
|
||||||
|
|
||||||
.seek 0x3c
|
|
||||||
exe_start:
|
|
||||||
! On entry, DS=ES=PSP. Make DS=CS, so we're running in tiny mode.
|
|
||||||
|
|
||||||
push cs
|
|
||||||
pop ds
|
|
||||||
mov (dpmi_rs), ds
|
|
||||||
mov (dpmi_psp), es
|
|
||||||
|
|
||||||
! Initialise DPMI.
|
|
||||||
|
|
||||||
mov ax, 0x1687
|
|
||||||
int 0x2f
|
|
||||||
or ax, ax
|
|
||||||
jnz no_dpmi
|
|
||||||
mov (dpmi_switch+0), di ! write back PMODE switch routine
|
|
||||||
mov (dpmi_switch+2), es
|
|
||||||
or si, si ! do we need a DPMI private area?
|
|
||||||
jz 1f
|
|
||||||
|
|
||||||
mov bx, si
|
|
||||||
movb ah, 0x48
|
|
||||||
int 0x21 ! allocate memory from DOS
|
|
||||||
mov es, ax ! data area segment -> es
|
|
||||||
1:
|
|
||||||
! Switch to protected mode.
|
|
||||||
|
|
||||||
mov ax, 1 ! 32-bit app
|
|
||||||
callf (dpmi_switch)
|
|
||||||
jnc pmode ! Success!
|
|
||||||
|
|
||||||
! Could not switch to protected mode.
|
|
||||||
|
|
||||||
mov dx, no_pmode_msg
|
|
||||||
jmp exit_with_error
|
|
||||||
|
|
||||||
no_dpmi:
|
|
||||||
mov dx, no_dpmi_msg
|
|
||||||
! fall through
|
|
||||||
|
|
||||||
! Displays the message in dx and exits.
|
|
||||||
exit_with_error:
|
|
||||||
movb ah, 9
|
|
||||||
int 0x21 ! print $-terminated string
|
|
||||||
mov ax, 0x4cff
|
|
||||||
int 0x21 ! terminate with error code al
|
|
||||||
|
|
||||||
pmode:
|
|
||||||
! We're now in protected mode! Switch our code segment to 32-bit mode.
|
|
||||||
|
|
||||||
mov cx, cs
|
|
||||||
lar cx, cx
|
|
||||||
movb cl, ch
|
|
||||||
movb ch, 0xc0
|
|
||||||
mov bx, cs
|
|
||||||
mov ax, 0x0009
|
|
||||||
int 0x31 ! Make selector 32 bit
|
|
||||||
|
|
||||||
.use32
|
|
||||||
o16 mov (dpmi_edx), go_msg
|
|
||||||
o16 mov ax, (dpmi_rs)
|
|
||||||
o16 mov (dpmi_ds), ax
|
|
||||||
movb (dpmi_eax+1), 9
|
|
||||||
call int21
|
|
||||||
o16 mov ax, 0x4c00
|
|
||||||
int 0x21
|
|
||||||
|
|
||||||
! Simulate DOS interrupt bx.
|
|
||||||
int21:
|
|
||||||
o16 mov bx, 0x21
|
|
||||||
callint:
|
|
||||||
o16 xor ax, ax
|
|
||||||
o16 mov (dpmi_ss), ax ! zero stack: DPMI host allocates one.
|
|
||||||
o16 mov (dpmi_sp), ax
|
|
||||||
push ds
|
|
||||||
pop es
|
|
||||||
mov di, ax
|
|
||||||
o16 mov ax, 0x300
|
|
||||||
int 0x31 ! simulate DOS interrupt
|
|
||||||
push cs
|
|
||||||
pop ds
|
|
||||||
ret
|
|
||||||
|
|
||||||
go_msg:
|
|
||||||
.ascii "Go!$"
|
|
||||||
no_pmode_msg:
|
|
||||||
.ascii "Couldn't switch to protected mode$"
|
|
||||||
no_dpmi_msg:
|
|
||||||
.ascii "No DPMI$"
|
|
||||||
|
|
||||||
exe_top:
|
|
||||||
|
|
||||||
exe_stack = exe_top + 512
|
|
||||||
exe_text_paras = [exe_top - exe_header + 511] / 512
|
|
||||||
exe_ram_paras = [exe_stack - exe_top + 15] / 16
|
|
||||||
|
|
||||||
|
|
||||||
#define STACK_BUFFER 128 /* number of bytes to leave for stack */
|
#define STACK_BUFFER 128 /* number of bytes to leave for stack */
|
||||||
|
|
||||||
begtext:
|
begtext:
|
||||||
|
mov eax, 0x4c00
|
||||||
|
int 0x21
|
||||||
|
|
||||||
! Make sure we are running under MS-DOS 2 or above.
|
! Make sure we are running under MS-DOS 2 or above.
|
||||||
!
|
!
|
||||||
! While at it, also remember the actual DOS version, so that we know
|
! While at it, also remember the actual DOS version, so that we know
|
||||||
|
|
|
@ -6,6 +6,32 @@ ackfile {
|
||||||
vars = { plat = "msdos386" }
|
vars = { plat = "msdos386" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ackfile {
|
||||||
|
name = "stub",
|
||||||
|
srcs = { "./stub.s" },
|
||||||
|
vars = { plat = "msdos386" }
|
||||||
|
}
|
||||||
|
|
||||||
|
normalrule {
|
||||||
|
name = "stub_aout",
|
||||||
|
ins = {
|
||||||
|
"util/led+led",
|
||||||
|
"+stub"
|
||||||
|
},
|
||||||
|
outleaves = { "stub.aout" },
|
||||||
|
commands = { "%{ins[1]} %{ins[2]} -o %{outs[1]}" }
|
||||||
|
}
|
||||||
|
|
||||||
|
normalrule {
|
||||||
|
name = "stub_exe",
|
||||||
|
ins = {
|
||||||
|
"util/amisc+aslod",
|
||||||
|
"+stub_aout"
|
||||||
|
},
|
||||||
|
outleaves = { "stub.exe" },
|
||||||
|
commands = { "%{ins[1]} %{ins[2]} %{outs[1]}" }
|
||||||
|
}
|
||||||
|
|
||||||
build_plat_libs {
|
build_plat_libs {
|
||||||
name = "libs",
|
name = "libs",
|
||||||
arch = "i386",
|
arch = "i386",
|
||||||
|
@ -19,6 +45,7 @@ installable {
|
||||||
"+libs",
|
"+libs",
|
||||||
"./include+pkg",
|
"./include+pkg",
|
||||||
["$(PLATIND)/msdos386/boot.o"] = "+boot",
|
["$(PLATIND)/msdos386/boot.o"] = "+boot",
|
||||||
|
["$(PLATIND)/msdos386/stub.exe"] = "+stub_exe",
|
||||||
["$(PLATIND)/msdos386/libsys.a"] = "./libsys+lib",
|
["$(PLATIND)/msdos386/libsys.a"] = "./libsys+lib",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,6 @@ name cv
|
||||||
from .out
|
from .out
|
||||||
to .exe
|
to .exe
|
||||||
program {EM}/bin/aslod
|
program {EM}/bin/aslod
|
||||||
args < >
|
args -p {PLATFORMDIR}/stub.exe < >
|
||||||
outfile msdos386.exe
|
outfile msdos386.exe
|
||||||
end
|
end
|
||||||
|
|
|
@ -162,7 +162,7 @@ exe_start:
|
||||||
mov bx, (fh)
|
mov bx, (fh)
|
||||||
mov ax, 0x4200
|
mov ax, 0x4200
|
||||||
xor cx, cx ! high offset
|
xor cx, cx ! high offset
|
||||||
xor dx, dx ! low offset
|
mov dx, text_top ! low offset
|
||||||
int 0x21 ! lseek
|
int 0x21 ! lseek
|
||||||
|
|
||||||
o32 xor edi, edi ! destination 32-bit register
|
o32 xor edi, edi ! destination 32-bit register
|
||||||
|
@ -194,7 +194,7 @@ exe_start:
|
||||||
o32 mov eax, (pmemhandle)
|
o32 mov eax, (pmemhandle)
|
||||||
o32 movzx ebx, (rseg)
|
o32 movzx ebx, (rseg)
|
||||||
push es
|
push es
|
||||||
push text_top
|
push 0
|
||||||
retf
|
retf
|
||||||
|
|
||||||
bad_dpmi:
|
bad_dpmi:
|
||||||
|
@ -225,12 +225,6 @@ exit_with_error:
|
||||||
mov ax, 0x4cff
|
mov ax, 0x4cff
|
||||||
int 0x21 ! terminate with error code al
|
int 0x21 ! terminate with error code al
|
||||||
|
|
||||||
pmode:
|
|
||||||
.use32
|
|
||||||
mov ax, 0x4c00
|
|
||||||
int 0x21
|
|
||||||
.use16
|
|
||||||
|
|
||||||
! Simulate DOS interrupt.
|
! Simulate DOS interrupt.
|
||||||
int21:
|
int21:
|
||||||
mov (dpmi_eax), ax
|
mov (dpmi_eax), ax
|
||||||
|
@ -266,6 +260,7 @@ no_file_msg:
|
||||||
.asciz "Couldn't open .exe"
|
.asciz "Couldn't open .exe"
|
||||||
no_dpmi_msg:
|
no_dpmi_msg:
|
||||||
.asciz "No DPMI host installed"
|
.asciz "No DPMI host installed"
|
||||||
|
.align 2
|
||||||
text_top:
|
text_top:
|
||||||
|
|
||||||
exe_text_pages = [text_top - exe_header + 511] / 512
|
exe_text_pages = [text_top - exe_header + 511] / 512
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
aslod \- ACK simple loader
|
aslod \- ACK simple loader
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B aslod
|
.B aslod
|
||||||
[\-h] [\-v] inputfile outputfile
|
[\-h] [\-v] [\-p prefixfile] inputfile outputfile
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.I aslod
|
.I aslod
|
||||||
converts an absolute ack.out file into a simple binary memory dump.
|
converts an absolute ack.out file into a simple binary memory dump.
|
||||||
|
@ -16,5 +16,8 @@ The file must have all references resolved and be linked to a
|
||||||
fixed address. aslod will dump the segments, in order, such
|
fixed address. aslod will dump the segments, in order, such
|
||||||
that the first byte of TEXT is at offset 0 in the file
|
that the first byte of TEXT is at offset 0 in the file
|
||||||
(regardless of where it is in memory).
|
(regardless of where it is in memory).
|
||||||
|
.PP
|
||||||
|
If a prefix file is specified, this is prepended to the output before writing.
|
||||||
|
No changes to the output itself are made.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
ack.out(5)
|
ack.out(5)
|
||||||
|
|
|
@ -37,6 +37,7 @@ struct outsect outsect[S_MAX];
|
||||||
char* stringarea;
|
char* stringarea;
|
||||||
|
|
||||||
char* outputfile = NULL; /* Name of output file, or NULL */
|
char* outputfile = NULL; /* Name of output file, or NULL */
|
||||||
|
char* prefixfile = NULL; /* Name of prefix file, or NULL */
|
||||||
char* program; /* Name of current program: argv[0] */
|
char* program; /* Name of current program: argv[0] */
|
||||||
|
|
||||||
FILE* input; /* Input stream */
|
FILE* input; /* Input stream */
|
||||||
|
@ -136,6 +137,19 @@ void emits(struct outsect* section, struct outsect* nextsect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emitprefixfile(void)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen(prefixfile, "rb");
|
||||||
|
|
||||||
|
while (!feof(fp))
|
||||||
|
{
|
||||||
|
char buffer[BUFSIZ];
|
||||||
|
size_t blocksize = fread(buffer, 1, BUFSIZ, fp);
|
||||||
|
writef(buffer, 1, blocksize);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Macros from modules/src/object/obj.h */
|
/* Macros from modules/src/object/obj.h */
|
||||||
#define Xchar(ch) ((ch) & 0377)
|
#define Xchar(ch) ((ch) & 0377)
|
||||||
|
@ -204,6 +218,12 @@ int main(int argc, char* argv[])
|
||||||
verbose = true;
|
verbose = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
prefixfile = argv[1];
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
syntaxerror:
|
syntaxerror:
|
||||||
fatal("syntax error --- try -h for help");
|
fatal("syntax error --- try -h for help");
|
||||||
|
@ -288,6 +308,8 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
/* And go! */
|
/* And go! */
|
||||||
|
|
||||||
|
if (prefixfile)
|
||||||
|
emitprefixfile();
|
||||||
emits(&outsect[TEXT], &outsect[ROM]);
|
emits(&outsect[TEXT], &outsect[ROM]);
|
||||||
emits(&outsect[ROM], &outsect[DATA]);
|
emits(&outsect[ROM], &outsect[DATA]);
|
||||||
emits(&outsect[DATA], NULL);
|
emits(&outsect[DATA], NULL);
|
||||||
|
|
Loading…
Reference in a new issue