|
|
@@ -57,11 +57,11 @@ TIMEOUT = 15
|
|
|
# so these are written out here and checked against each other; if the
|
|
|
# assembly's layout changes, the mismatch shows up as a loud failure rather
|
|
|
# than as a program loaded somewhere harmless.
|
|
|
-LOAD_SEG = 0x0000 # the .COM's load segment
|
|
|
+LOAD_SEG = 0x1000 # the .COM's load segment
|
|
|
LOAD_OFF = 0x0100 # ...and offset; DOS puts a .COM at CS:0100
|
|
|
FLAT_LOAD = LOAD_SEG * 16 + LOAD_OFF
|
|
|
-INLEN_OFF = 0x7000 # word: how many input bytes follow
|
|
|
-INBUF_OFF = 0x7004 # the input bytes
|
|
|
+INLEN_OFF = 0x9000 # word: how many input bytes follow
|
|
|
+INBUF_OFF = 0x9004 # the input bytes
|
|
|
INBUF_MAX = 0x00FC # 7100h - 7004h
|
|
|
SECTORS = 72 # what bootcom.s reads off the disk
|
|
|
FLOPPY_SECTORS = 2880 # 1.44M, 18 sectors per track
|
|
|
@@ -72,12 +72,14 @@ COM_MAX = INLEN_OFF - LOAD_OFF # the image must end before the input
|
|
|
# boot sector reads whatever the BIOS left there. This is a check on the two
|
|
|
# constant blocks agreeing, and it is the reason they are both written down.
|
|
|
READ_END = FLAT_LOAD + SECTORS * 512
|
|
|
-if INBUF_OFF + INBUF_MAX > READ_END:
|
|
|
+INLEN_FLAT = LOAD_SEG * 16 + INLEN_OFF
|
|
|
+INBUF_FLAT = LOAD_SEG * 16 + INBUF_OFF
|
|
|
+if INBUF_FLAT + INBUF_MAX > READ_END:
|
|
|
sys.exit("run_com_exec.py: the input descriptor at %04X..%04X runs past the "
|
|
|
"%d sectors bootcom.s reads (which end at %04X)"
|
|
|
% (INBUF_OFF, INBUF_OFF + INBUF_MAX, SECTORS, READ_END))
|
|
|
# ...and past the end of any .COM, or it would land inside the program.
|
|
|
-if FLAT_LOAD + COM_MAX > INBUF_OFF:
|
|
|
+if FLAT_LOAD + COM_MAX > INLEN_FLAT:
|
|
|
sys.exit("run_com_exec.py: COM_MAX ends at %04X, past the input "
|
|
|
"descriptor at %04X"
|
|
|
% (FLAT_LOAD + COM_MAX, INBUF_OFF))
|
|
|
@@ -88,13 +90,21 @@ if FLAT_LOAD + COM_MAX > INBUF_OFF:
|
|
|
EXIT_BASE = 1
|
|
|
|
|
|
|
|
|
-def build_boot_sector():
|
|
|
+def build_boot_sector(load_seg=None, inlen=None, copy_bytes=None, scratch=None):
|
|
|
"""Assemble tests/exec/bootcom.s and return its 512 bytes."""
|
|
|
with tempfile.TemporaryDirectory() as td:
|
|
|
obj, raw = os.path.join(td, "b.o"), os.path.join(td, "b.bin")
|
|
|
- r = subprocess.run(["as", "--32", "-o", obj,
|
|
|
- os.path.join(HERE, "exec", "bootcom.s")],
|
|
|
- capture_output=True)
|
|
|
+ cmd = ["as", "--32"]
|
|
|
+ if load_seg is not None:
|
|
|
+ cmd += ["--defsym", "LOAD_SEG=%d" % load_seg]
|
|
|
+ if inlen is not None:
|
|
|
+ cmd += ["--defsym", "INLEN=%d" % inlen]
|
|
|
+ if copy_bytes is not None:
|
|
|
+ cmd += ["--defsym", "COPY_BYTES=%d" % copy_bytes]
|
|
|
+ if scratch is not None:
|
|
|
+ cmd += ["--defsym", "SCRATCH_SEG=%d" % scratch]
|
|
|
+ cmd += ["-o", obj, os.path.join(HERE, "exec", "bootcom.s")]
|
|
|
+ r = subprocess.run(cmd, capture_output=True)
|
|
|
if r.returncode != 0:
|
|
|
sys.exit("as failed:\n" + r.stderr.decode(errors="replace"))
|
|
|
r = subprocess.run(["objcopy", "-O", "binary", obj, raw],
|
|
|
@@ -129,11 +139,12 @@ def to_file(mem_off):
|
|
|
return mem_off - LOAD_OFF + 512
|
|
|
|
|
|
|
|
|
-def build_floppy(boot, com, stdin=b""):
|
|
|
+def build_floppy(boot, com, stdin=b"", load_seg=LOAD_SEG, inlen_off=INLEN_OFF, inbuf_off=INBUF_OFF):
|
|
|
"""Assemble the 1.44M image: boot sector, then the .COM, then the input."""
|
|
|
- if len(com) > COM_MAX:
|
|
|
+ com_max = inlen_off - LOAD_OFF
|
|
|
+ if len(com) > com_max:
|
|
|
sys.exit("the .COM is %d bytes and the boot sector reads only %d"
|
|
|
- % (len(com), COM_MAX))
|
|
|
+ % (len(com), com_max))
|
|
|
if len(stdin) > INBUF_MAX:
|
|
|
sys.exit("%d bytes of input, at most %d fit" % (len(stdin), INBUF_MAX))
|
|
|
img = bytearray(FLOPPY_BYTES)
|
|
|
@@ -141,7 +152,7 @@ def build_floppy(boot, com, stdin=b""):
|
|
|
# The .COM goes at disk sector 2, which is where bootcom.s reads from.
|
|
|
# to_file(LOAD_OFF) == 512, so this agrees with the mapping above.
|
|
|
img[512:512 + len(com)] = com
|
|
|
- inlen_f, inbuf_f = to_file(INLEN_OFF), to_file(INBUF_OFF)
|
|
|
+ inlen_f, inbuf_f = to_file(inlen_off), to_file(inbuf_off)
|
|
|
img[inlen_f:inlen_f + 2] = len(stdin).to_bytes(2, "little")
|
|
|
img[inbuf_f:inbuf_f + len(stdin)] = stdin
|
|
|
return bytes(img)
|