Skip to content

Commit 57f199e

Browse files
committed
add divzfix command
It is trying to fix divizion by zero by doing fnclex before calling the realmode handler. This prevents potential IGNNE stuck-ups, and also makes some handlers to cleanly exit w/o terminating the program. See dosemu2/dosemu2#2724
1 parent 5a55706 commit 57f199e

File tree

6 files changed

+97
-2
lines changed

6 files changed

+97
-2
lines changed

32/makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ LINK_OPT =
1515
SRCS = $(SRCDIR)/command.c $(SRCDIR)/cmdbuf.c $(SRCDIR)/ms.c \
1616
$(SRCDIR)/env.c $(SRCDIR)/psp.c $(SRCDIR)/umb.c $(SRCDIR)/ae0x.c \
1717
$(SRCDIR)/compl.c $(SRCDIR)/clip.c memmem.c fmemcpy.c findclos.c
18-
ASSRCS = $(SRCDIR)/asm.S $(SRCDIR)/int23.S $(SRCDIR)/int0.S $(SRCDIR)/mouse.S
18+
ASSRCS = $(SRCDIR)/asm.S $(SRCDIR)/int23.S $(SRCDIR)/int0.S $(SRCDIR)/int75.S \
19+
$(SRCDIR)/mouse.S
1920
OBJS = $(notdir $(SRCS:.c=.o)) $(notdir $(ASSRCS:.S=.o))
2021
CMD = comcom32.exe
2122
REVISIONID := $(shell git describe --dirty=+)

src/asm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
int ASMCFUNC do_int23(void);
1414
void ASMCFUNC do_int0(void);
15+
int ASMCFUNC do_int75(void);
1516
void ASMCFUNC do_mouse(void);
1617

1718
#else

src/command.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ static int mouseopt_enabled;
142142

143143
static __dpmi_raddr int0_vec;
144144
static int int0_wa;
145+
static __dpmi_paddr int75_vec;
146+
static int int75_wa;
145147

146148
/*
147149
* Command parser defines/variables
@@ -243,6 +245,7 @@ static void perform_popd(const char *arg);
243245
static void perform_prompt(const char *arg);
244246
static void perform_pushd(const char *arg);
245247
static void perform_r200fix(const char *arg);
248+
static void perform_divzfix(const char *arg);
246249
static void perform_rd(const char *arg);
247250
static void perform_rename(const char *arg);
248251
static void perform_shift(const char *arg);
@@ -303,6 +306,7 @@ struct built_in_cmd cmd_table[] =
303306
{"prompt", perform_prompt, "", "customize prompt string"},
304307
{"pushd", perform_pushd, "", "push cwd to stack and cd"},
305308
{"r200fix", perform_r200fix, "", "runtime error 200 fix"},
309+
{"divzfix", perform_divzfix, "", "division by zero fix"},
306310
{"rd", perform_rd, "", "remove directory"},
307311
{"rmdir", perform_rd, "", "remove directory"},
308312
{"rename", perform_rename, "", "rename with wildcards"},
@@ -3065,6 +3069,15 @@ static int is_HMA_enabled(void)
30653069
return !!(r.h.dh & 0x10);
30663070
}
30673071

3072+
static void activate_int75_handling(void)
3073+
{
3074+
__dpmi_paddr pa;
3075+
3076+
pa.selector = _my_cs();
3077+
pa.offset32 = (uintptr_t)my_int75_handler;
3078+
__dpmi_set_protected_mode_interrupt_vector(0x75, &pa);
3079+
}
3080+
30683081
static void perform_external_cmd(int call, int lh, char *ext_cmd)
30693082
{
30703083
finddata_t ff;
@@ -3231,6 +3244,7 @@ static void perform_external_cmd(int call, int lh, char *ext_cmd)
32313244
#ifdef __DJGPP__
32323245
__djgpp_exception_toggle();
32333246
#endif
3247+
activate_int75_handling();
32343248
set_env_seg();
32353249
/* prepend command tail with space */
32363250
alen = strlen(cmd_args);
@@ -3709,6 +3723,21 @@ static void perform_r200fix(const char *arg)
37093723
int0_wa = 0;
37103724
}
37113725

3726+
static void perform_divzfix(const char *arg)
3727+
{
3728+
if (!*arg)
3729+
{
3730+
cprintf("divzfix: command name missing\r\n");
3731+
reset_batfile_call_stack();
3732+
return;
3733+
}
3734+
shift_cmdline();
3735+
3736+
int75_wa = 1;
3737+
perform_external_cmd(false, false, cmd);
3738+
int75_wa = 0;
3739+
}
3740+
37123741
static void perform_rd(const char *arg)
37133742
{
37143743
while (*cmd_switch) // skip switches
@@ -4705,6 +4734,20 @@ void do_int0(void)
47054734
__dpmi_set_real_mode_interrupt_vector(0, &int0_vec);
47064735
}
47074736

4737+
static void setup_int75_handling(void)
4738+
{
4739+
__djgpp_exception_toggle();
4740+
__dpmi_get_protected_mode_interrupt_vector(0x75, &int75_vec);
4741+
__djgpp_exception_toggle();
4742+
_prev75_eip = int75_vec.offset32;
4743+
_prev75_cs = int75_vec.selector;
4744+
}
4745+
4746+
int do_int75(void)
4747+
{
4748+
return int75_wa;
4749+
}
4750+
47084751
int main(int argc, const char *argv[], const char *envp[])
47094752
{
47104753
int a;
@@ -4729,6 +4772,7 @@ int main(int argc, const char *argv[], const char *envp[])
47294772
_osmajor = 7; // fake _osmajor to enable extended functionality
47304773
setup_break_handling();
47314774
setup_int0_handling();
4775+
setup_int75_handling();
47324776

47334777
// unbuffer stdin and stdout
47344778
setbuf(stdin, NULL);

src/glob_asm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
__ASM(unsigned short, _ds) SEMIC
22
__ASM_FUNC(my_int23_handler) SEMIC
33
__ASM_FUNC(my_int0_handler) SEMIC
4+
__ASM_FUNC(my_int75_handler) SEMIC
45
__ASM_FUNC(my_mouse_handler) SEMIC
56
__ASM(unsigned int, _prev0_eip) SEMIC
67
__ASM(unsigned short, _prev0_cs) SEMIC
8+
__ASM(unsigned int, _prev75_eip) SEMIC
9+
__ASM(unsigned short, _prev75_cs) SEMIC

src/int75.S

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* comcom64 - 64bit command.com
3+
* Copyright (C) 2023-2024 @stsp
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#include "asm.h"
20+
.include "asm.inc"
21+
22+
.bss
23+
.balign 2
24+
__prev75:
25+
.global __prev75_eip
26+
__prev75_eip: .long 0
27+
.global __prev75_cs
28+
__prev75_cs: .word 0
29+
30+
.text
31+
.global _my_int75_handler
32+
_my_int75_handler:
33+
pusha
34+
handler_prolog SIGSTK_LEN
35+
call _do_int75
36+
restore_stack
37+
testl %eax, %eax
38+
jz 0f
39+
fnclex
40+
0:
41+
popa
42+
ljmpl *__prev75
43+
44+
#ifdef __ELF__
45+
.section .note.GNU-stack,"",%progbits
46+
#endif

src/makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ HEADERS = $(addprefix $(srcdir)/,ae0x.h cmdbuf.h compl.h psp.h command.h env.h m
2222
PDHDR = $(srcdir)/asm.h
2323
GLOB_ASM = $(srcdir)/glob_asm.h
2424
OBJECTS = $(SOURCES:.c=.o)
25-
AS_SOURCES = int23.S int0.S asm.S ms.S
25+
AS_SOURCES = int23.S int0.S int75.S asm.S ms.S
2626
AS_OBJECTS = $(AS_SOURCES:.S=.o)
2727
CMD = $(if $(LINK),comcom64.exe,)
2828
DBG = $(if $(LINK),$(CMD).dbg,)

0 commit comments

Comments
 (0)