📄 entry.asm
字号:
;; File:; entry.asm; Description:; System call entry code;; Copyright (c) 1998; Pasquale J. Villani; All Rights Reserved;; This file is part of DOS-C.;; DOS-C is free software; you can redistribute it and/or; modify it under the terms of the GNU General Public License; as published by the Free Software Foundation; either version; 2, or (at your option) any later version.;; DOS-C is distributed in the hope that it will be useful, but; WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See; the GNU General Public License for more details.;; You should have received a copy of the GNU General Public; License along with DOS-C; see the file COPYING. If not,; write to the Free Software Foundation, 675 Mass Ave,; Cambridge, MA 02139, USA.;; $Id: entry.asm,v 1.28 2004/09/12 04:46:27 perditionc Exp $; %include "segs.inc" %include "stacks.inc"segment HMA_TEXT extern _int21_syscall extern _int21_service extern _int2526_handler extern _error_tos:wrt DGROUP extern _char_api_tos:wrt DGROUP extern _disk_api_tos:wrt DGROUP extern _user_r:wrt DGROUP extern _ErrorMode:wrt DGROUP extern _InDOS:wrt DGROUP extern _cu_psp:wrt DGROUP extern _MachineId:wrt DGROUP extern critical_sp:wrt DGROUP extern int21regs_seg:wrt DGROUP extern int21regs_off:wrt DGROUP extern _Int21AX:wrt DGROUP extern _DGROUP_ global reloc_call_cpm_entry global reloc_call_int20_handler global reloc_call_int21_handler global reloc_call_low_int25_handler global reloc_call_low_int26_handler global reloc_call_int27_handler;; MS-DOS CP/M style entry point;; VOID FAR; cpm_entry(iregs UserRegs);; This one is a strange one. The call is to psp:0005h but it returns to the; function after the call. What we do is convert it to a normal call and; fudge the stack to look like an int 21h call.;reloc_call_cpm_entry: ; Stack is: ; return offset ; psp seg ; 000ah ; push bp ; trash old return address mov bp,sp xchg bp,[2+bp] pop bp pushf ; start setting up int 21h stack ; ; now stack is ; return offset ; psp seg ; flags ; push bp mov bp,sp ; set up reference frame ; ; reference frame stack is ; return offset bp + 6 ; psp seg bp + 4 ; flags bp + 2 ; bp <--- bp ; push ax mov ax,[2+bp] ; get the flags xchg ax,[6+bp] ; swap with return address mov [2+bp],ax pop ax ; restore working registers pop bp ; ; Done. Stack is ; flags ; psp seg (alias .COM cs) ; return offset ; cmp cl,024h jbe cpm_error mov ah,cl ; get the call # from cl to ah jmp reloc_call_int21_handler ; do the system callcpm_error: mov al,0 iret;; interrupt zero divide handler:; print a message 'Interrupt divide by zero'; Terminate the current process;; VOID INRPT far; int20_handler(iregs UserRegs);print_hex: mov cl, 12hex_loop: mov ax, dx shr ax, cl and al, 0fh cmp al, 10 sbb al, 69h das mov bx, 0070h mov ah, 0eh int 10h sub cl, 4 jae hex_loop retdivide_by_zero_message db 0dh,0ah,'Interrupt divide by zero, stack:',0dh,0ah,0 global reloc_call_int0_handlerreloc_call_int0_handler: mov si,divide_by_zero_messagezero_message_loop: mov al, [cs:si] test al,al je zero_done inc si mov bx, 0070h mov ah, 0eh int 10h jmp short zero_message_loop zero_done: mov bp, sp xor si, si ; print 13 words of stack for debugging LUDIV etc.stack_loop: mov dx, [bp+si] call print_hex mov al, ' ' int 10h inc si inc si cmp si, 13*2 jb stack_loop mov al, 0dh int 10h mov al, 0ah int 10h mov ax,04c7fh ; terminate with errorlevel 127 int 21h stithats_it: hlt jmp short thats_it ; it might be command.com that nukesinvalid_opcode_message db 0dh,0ah,'Invalid Opcode at ',0 global reloc_call_int6_handlerreloc_call_int6_handler: mov si,invalid_opcode_message jmp short zero_message_loop ;; Terminate the current process;; VOID INRPT far; int20_handler(iregs UserRegs);reloc_call_int20_handler: mov ah,0 ; terminate through int 21h;; MS-DOS system call entry point;; VOID INRPT far; int21_handler(iregs UserRegs);reloc_call_int21_handler: ; ; Create the stack frame for C call. This is done to ; preserve machine state and provide a C structure for ; access to registers. ; ; Since this is an interrupt routine, CS, IP and flags were ; pushed onto the stack by the processor, completing the ; stack frame. ; ; NB: stack frame is MS-DOS dependent and not compatible ; with compiler interrupt stack frames. ; sti PUSH$ALL mov bp,sp Protect386Registers ; ; Create kernel reference frame. ; ; NB: At this point, SS != DS and won't be set that way ; until later when which stack to run on is determined. ;int21_reentry: mov dx,[cs:_DGROUP_] mov ds,dx cmp ah,25h je int21_user cmp ah,33h je int21_user cmp ah,35h je int21_user cmp ah,50h je int21_user cmp ah,51h je int21_user cmp ah,62h jne int21_1int21_user: call dos_crit_sect push ss push bp call _int21_syscall pop cx pop cx jmp short int21_ret;; normal entry, use one of our 4 stacks; ; DX=DGROUP; CX=STACK; SI=userSS; BX=userSPint21_1: mov si,ss ; save user stack, to be retored later ; ; Now DS is set, let's save our stack for rentry (???TE) ; ; I don't know who needs that, but ... (TE) ; mov word [_user_r+2],ss mov word [_user_r],bp ; store and init ; ; Decide which stack to run on. ; ; Unlike previous versions of DOS-C, we need to do this here ; to guarantee the user stack for critical error handling. ; We need to do the int 24h from this stack location. ; ; There are actually four stacks to run on. The first is the ; user stack which is determined by system call number in ; AH. The next is the error stack determined by _ErrorMode. ; Then there's the character stack also determined by system ; call number. Finally, all others run on the disk stack. ; They are evaluated in that order. cmp byte [_ErrorMode],0 je int21_2int21_onerrorstack: mov cx,_error_tos cli mov ss,dx mov sp,cx sti push si ; user SS:SP push bp call _int21_service jmp short int21_exit_nodec int21_2: inc byte [_InDOS] mov cx,_char_api_tos or ah,ah jz int21_3 cmp ah,0ch jbe int21_normalentryint21_3: call dos_crit_sect mov cx,_disk_api_tos
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -