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 .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 */
|
||||
|
||||
begtext:
|
||||
mov eax, 0x4c00
|
||||
int 0x21
|
||||
|
||||
! Make sure we are running under MS-DOS 2 or above.
|
||||
!
|
||||
! While at it, also remember the actual DOS version, so that we know
|
||||
|
|
|
@ -6,6 +6,32 @@ ackfile {
|
|||
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 {
|
||||
name = "libs",
|
||||
arch = "i386",
|
||||
|
@ -19,6 +45,7 @@ installable {
|
|||
"+libs",
|
||||
"./include+pkg",
|
||||
["$(PLATIND)/msdos386/boot.o"] = "+boot",
|
||||
["$(PLATIND)/msdos386/stub.exe"] = "+stub_exe",
|
||||
["$(PLATIND)/msdos386/libsys.a"] = "./libsys+lib",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,6 @@ name cv
|
|||
from .out
|
||||
to .exe
|
||||
program {EM}/bin/aslod
|
||||
args < >
|
||||
args -p {PLATFORMDIR}/stub.exe < >
|
||||
outfile msdos386.exe
|
||||
end
|
||||
|
|
|
@ -162,7 +162,7 @@ exe_start:
|
|||
mov bx, (fh)
|
||||
mov ax, 0x4200
|
||||
xor cx, cx ! high offset
|
||||
xor dx, dx ! low offset
|
||||
mov dx, text_top ! low offset
|
||||
int 0x21 ! lseek
|
||||
|
||||
o32 xor edi, edi ! destination 32-bit register
|
||||
|
@ -194,7 +194,7 @@ exe_start:
|
|||
o32 mov eax, (pmemhandle)
|
||||
o32 movzx ebx, (rseg)
|
||||
push es
|
||||
push text_top
|
||||
push 0
|
||||
retf
|
||||
|
||||
bad_dpmi:
|
||||
|
@ -225,12 +225,6 @@ exit_with_error:
|
|||
mov ax, 0x4cff
|
||||
int 0x21 ! terminate with error code al
|
||||
|
||||
pmode:
|
||||
.use32
|
||||
mov ax, 0x4c00
|
||||
int 0x21
|
||||
.use16
|
||||
|
||||
! Simulate DOS interrupt.
|
||||
int21:
|
||||
mov (dpmi_eax), ax
|
||||
|
@ -266,6 +260,7 @@ no_file_msg:
|
|||
.asciz "Couldn't open .exe"
|
||||
no_dpmi_msg:
|
||||
.asciz "No DPMI host installed"
|
||||
.align 2
|
||||
text_top:
|
||||
|
||||
exe_text_pages = [text_top - exe_header + 511] / 512
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
aslod \- ACK simple loader
|
||||
.SH SYNOPSIS
|
||||
.B aslod
|
||||
[\-h] [\-v] inputfile outputfile
|
||||
[\-h] [\-v] [\-p prefixfile] inputfile outputfile
|
||||
.SH DESCRIPTION
|
||||
.I aslod
|
||||
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
|
||||
that the first byte of TEXT is at offset 0 in the file
|
||||
(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"
|
||||
ack.out(5)
|
||||
|
|
|
@ -37,6 +37,7 @@ struct outsect outsect[S_MAX];
|
|||
char* stringarea;
|
||||
|
||||
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] */
|
||||
|
||||
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 */
|
||||
#define Xchar(ch) ((ch) & 0377)
|
||||
|
@ -204,6 +218,12 @@ int main(int argc, char* argv[])
|
|||
verbose = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
argv++;
|
||||
argc--;
|
||||
prefixfile = argv[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
syntaxerror:
|
||||
fatal("syntax error --- try -h for help");
|
||||
|
@ -288,6 +308,8 @@ int main(int argc, char* argv[])
|
|||
|
||||
/* And go! */
|
||||
|
||||
if (prefixfile)
|
||||
emitprefixfile();
|
||||
emits(&outsect[TEXT], &outsect[ROM]);
|
||||
emits(&outsect[ROM], &outsect[DATA]);
|
||||
emits(&outsect[DATA], NULL);
|
||||
|
|
Loading…
Reference in a new issue