diff options
author | ripsaw8080 <ripsaw8080@users.sourceforge.net> | 2022-07-14 21:37:10 +0300 |
---|---|---|
committer | ripsaw8080 <ripsaw8080@users.sourceforge.net> | 2022-07-14 21:37:10 +0300 |
commit | 6314c03bcba892994746bdcf83cc25928d229330 (patch) | |
tree | 1c5507ac5801fb1f8f104cec6caa72ffb3f8b3fd | |
parent | 20345b5f1ed8a93369d1485ebc2432e6dcd8ebde (diff) |
Push registers for most DOS function calls; prevents a bug in UNLZEXE from causing a crash, and maybe helps other buggy programs and unusual cases. Use real addressing to support stack pointer wraparound.svn/trunk
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@4481
-rw-r--r-- | src/cpu/callback.cpp | 16 | ||||
-rw-r--r-- | src/dos/dos.cpp | 12 | ||||
-rw-r--r-- | src/dos/dos_execute.cpp | 55 | ||||
-rw-r--r-- | src/dos/dos_mscdex.cpp | 5 |
4 files changed, 38 insertions, 50 deletions
diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index 07917d306..9c233faff 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -86,8 +86,8 @@ static Bitu stop_handler(void) { void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) { reg_sp-=4; - mem_writew(SegPhys(ss)+reg_sp,RealOff(CALLBACK_RealPointer(call_stop))); - mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop))); + real_writew(SegValue(ss),reg_sp+0,RealOff(CALLBACK_RealPointer(call_stop))); + real_writew(SegValue(ss),reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop))); Bit32u oldeip=reg_eip; Bit16u oldcs=SegValue(cs); reg_eip=off; @@ -108,24 +108,24 @@ void CALLBACK_RunRealInt(Bit8u intnum) { } void CALLBACK_SZF(bool val) { - Bit16u tempf = mem_readw(SegPhys(ss)+reg_sp+4); + Bit16u tempf = real_readw(SegValue(ss),reg_sp+4); if (val) tempf |= FLAG_ZF; else tempf &= ~FLAG_ZF; - mem_writew(SegPhys(ss)+reg_sp+4,tempf); + real_writew(SegValue(ss),reg_sp+4,tempf); } void CALLBACK_SCF(bool val) { - Bit16u tempf = mem_readw(SegPhys(ss)+reg_sp+4); + Bit16u tempf = real_readw(SegValue(ss),reg_sp+4); if (val) tempf |= FLAG_CF; else tempf &= ~FLAG_CF; - mem_writew(SegPhys(ss)+reg_sp+4,tempf); + real_writew(SegValue(ss),reg_sp+4,tempf); } void CALLBACK_SIF(bool val) { - Bit16u tempf = mem_readw(SegPhys(ss)+reg_sp+4); + Bit16u tempf = real_readw(SegValue(ss),reg_sp+4); if (val) tempf |= FLAG_IF; else tempf &= ~FLAG_IF; - mem_writew(SegPhys(ss)+reg_sp+4,tempf); + real_writew(SegValue(ss),reg_sp+4,tempf); } void CALLBACK_SetDescription(Bitu nr, const char* descr) { diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 7db8a1cc2..442ba62db 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -121,6 +121,16 @@ static Bitu DOS_21Handler(void) { if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) { DOS_PSP psp(dos.psp()); psp.SetStack(RealMake(SegValue(ss),reg_sp-18)); + /* Save registers */ + real_writew(SegValue(ss),reg_sp-18,reg_ax); + real_writew(SegValue(ss),reg_sp-16,reg_bx); + real_writew(SegValue(ss),reg_sp-14,reg_cx); + real_writew(SegValue(ss),reg_sp-12,reg_dx); + real_writew(SegValue(ss),reg_sp-10,reg_si); + real_writew(SegValue(ss),reg_sp- 8,reg_di); + real_writew(SegValue(ss),reg_sp- 6,reg_bp); + real_writew(SegValue(ss),reg_sp- 4,SegValue(ds)); + real_writew(SegValue(ss),reg_sp- 2,SegValue(es)); } char name1[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; @@ -130,7 +140,7 @@ static Bitu DOS_21Handler(void) { switch (reg_ah) { case 0x00: /* Terminate Program */ - DOS_Terminate(mem_readw(SegPhys(ss)+reg_sp+2),false,0); + DOS_Terminate(real_readw(SegValue(ss),reg_sp+2),false,0); break; case 0x01: /* Read character from STDIN, with echo */ { diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index f218494bc..9cac7540e 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -61,33 +61,6 @@ struct EXE_Header { #define OVERLAY 3 - -static void SaveRegisters(void) { - reg_sp-=18; - mem_writew(SegPhys(ss)+reg_sp+ 0,reg_ax); - mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx); - mem_writew(SegPhys(ss)+reg_sp+ 4,reg_dx); - mem_writew(SegPhys(ss)+reg_sp+ 6,reg_bx); - mem_writew(SegPhys(ss)+reg_sp+ 8,reg_si); - mem_writew(SegPhys(ss)+reg_sp+10,reg_di); - mem_writew(SegPhys(ss)+reg_sp+12,reg_bp); - mem_writew(SegPhys(ss)+reg_sp+14,SegValue(ds)); - mem_writew(SegPhys(ss)+reg_sp+16,SegValue(es)); -} - -static void RestoreRegisters(void) { - reg_ax=mem_readw(SegPhys(ss)+reg_sp+ 0); - reg_cx=mem_readw(SegPhys(ss)+reg_sp+ 2); - reg_dx=mem_readw(SegPhys(ss)+reg_sp+ 4); - reg_bx=mem_readw(SegPhys(ss)+reg_sp+ 6); - reg_si=mem_readw(SegPhys(ss)+reg_sp+ 8); - reg_di=mem_readw(SegPhys(ss)+reg_sp+10); - reg_bp=mem_readw(SegPhys(ss)+reg_sp+12); - SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14)); - SegSet16(es,mem_readw(SegPhys(ss)+reg_sp+16)); - reg_sp+=18; -} - extern void GFX_SetTitle(Bit32s cycles,int frameskip,bool paused); void DOS_UpdatePSPName(void) { DOS_MCB mcb(dos.psp()-1); @@ -124,14 +97,23 @@ void DOS_Terminate(Bit16u pspseg,bool tsr,Bit8u exitcode) { /* Restore the SS:SP to the previous one */ SegSet16(ss,RealSeg(parentpsp.GetStack())); reg_sp = RealOff(parentpsp.GetStack()); - /* Restore the old CS:IP from int 22h */ - RestoreRegisters(); + /* Restore registers */ + reg_ax = real_readw(SegValue(ss),reg_sp+ 0); + reg_bx = real_readw(SegValue(ss),reg_sp+ 2); + reg_cx = real_readw(SegValue(ss),reg_sp+ 4); + reg_dx = real_readw(SegValue(ss),reg_sp+ 6); + reg_si = real_readw(SegValue(ss),reg_sp+ 8); + reg_di = real_readw(SegValue(ss),reg_sp+10); + reg_bp = real_readw(SegValue(ss),reg_sp+12); + SegSet16(ds,real_readw(SegValue(ss),reg_sp+14)); + SegSet16(es,real_readw(SegValue(ss),reg_sp+16)); + reg_sp+=18; /* Set the CS:IP stored in int 0x22 back on the stack */ - mem_writew(SegPhys(ss)+reg_sp+0,RealOff(old22)); - mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(old22)); + real_writew(SegValue(ss),reg_sp+0,RealOff(old22)); + real_writew(SegValue(ss),reg_sp+2,RealSeg(old22)); /* set IOPL=3 (Strike Commander), nested task set, interrupts enabled, test flags cleared */ - mem_writew(SegPhys(ss)+reg_sp+4,0x7202); + real_writew(SegValue(ss),reg_sp+4,0x7202); // Free memory owned by process if (!tsr) DOS_FreeProcessMemory(pspseg); DOS_UpdatePSPName(); @@ -224,11 +206,8 @@ bool DOS_ChildPSP(Bit16u segment, Bit16u size) { psp.SetFCB1(RealMake(parent_psp_seg,0x5c)); psp.SetFCB2(RealMake(parent_psp_seg,0x6c)); psp.SetEnvironment(psp_parent.GetEnvironment()); + psp.SetStack(psp_parent.GetStack()); psp.SetSize(size); - // push registers in case child PSP is terminated - SaveRegisters(); - psp.SetStack(RealMakeSeg(ss,reg_sp)); - reg_sp+=18; return true; } @@ -434,8 +413,8 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { if ((flags==LOAD) || (flags==LOADNGO)) { /* Get Caller's program CS:IP of the stack and set termination address to that */ - RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp))); - SaveRegisters(); + RealSetVec(0x22,RealMake(real_readw(SegValue(ss),reg_sp+2),real_readw(SegValue(ss),reg_sp))); + reg_sp-=18; DOS_PSP callpsp(dos.psp()); /* Save the SS:SP on the PSP of calling program */ callpsp.SetStack(RealMakeSeg(ss,reg_sp)); diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 13a9f49bc..14bd9216b 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -1125,10 +1125,9 @@ static bool MSCDEX_Handler(void) { if(reg_ah == 0x11) { if(reg_al == 0x00) { if (mscdex->rootDriverHeaderSeg==0) return false; - PhysPt check = PhysMake(SegValue(ss),reg_sp); - if(mem_readw(check+6) == 0xDADA) { + if(real_readw(SegValue(ss),reg_sp+6) == 0xDADA) { //MSCDEX sets word on stack to ADAD if it DADA on entry. - mem_writew(check+6,0xADAD); + real_writew(SegValue(ss),reg_sp+6,0xADAD); } reg_al = 0xff; return true; |