pagesize 86 include mintdefs.a86 HT equ 9 LF equ 10 CR equ 13 data dseg word public ;*************************************************************************** ; ;Introduction: ; ; The MINT data structures are laid out in memory as given below. ;First are the variables, followed by the neutral string. Next is the ;block of free memory. Last is the active string followed by forms. ; ; variables, neutral string ... free memory ... neutral string, forms ; ;The neutral string: ; ; The neutral string consists of a list of arguments. Each argument ;begins with header which might be laid out as so in Pascal: ; arg_header = record ; marker : (active_marker, neutral_marker, comma_marker); ; previous : ^arg_header; ; end; ; ;The pointer, previous, points to the previous arg_header. The last one in the ;list has a nil pointer. This will always be the #(ps) which is the outermost ;function to be executed. ; ;The neutral string during function execution: ; ; Since we are interested in counting arguments from left to right, ;not right to left, we need to reverse the pointers so that they point ;from the first argument, to the second argument, to the third argument, ;etc. At this point, [fbgn] points to the first argument (the name of the ;funciton), and [fend] points past the last argument. To make argument ;fetching more efficient, the last argument is followed by a null argument ;which points to itself. This causes missing arguments to be fetched as ;nulls, in according to the definition of the language. ; Functions which return a value will build that value at either ;[fbgn]-1 or [fend]-2, depending on whether or not they need to refer to ;arguments supplied to the function. In general, single argument functions ;will use [fbgn]-1, and multiple argument functions will use [fend]-2. ; ;Neutral function results will eventually be moved to [fbgn]-1. ; ;The active string: ; ; The active string consists of a string of ASCII characters which ;have not yet been scanned. Typically, only ASCII characters appear here, ;although any eight bit value may occur. ; ;The active string during function execution: ; ; [actptr] points to the end of the active string. Active function ;results are built as described above and then moved to the left of [actptr]. ;Actptr is then adjusted to point to the result just moved in. Primitives ;check for memory overflow by comparing [fend] to [actptr]. If they come ;closer than some magic constant, then the 'No Memory' error is given ;and the idling string is reloaded. ; ; ;The forms: ; ; Forms are laid out as a linear list of forms. [formb] points to the ;beginning, and [forme] points to the end. The most recently defined forms are ;placed at the beginning of the list. The forms consists of three elements: a ;header, the name, and the data. The header contains the link to the next ;form, the length of the name, the length of the data, and the form pointer ;(which is always <= the length of the data). The form structure is defined in ;the file 'mintdefs.asm'. ; When a form is to be looked up in form storage, the form is first ;hashed. Then the form is looked up in the list of hash links. A linear search ;is performed for all the forms that hash to that value. ; ; ; ;************************************************************************** public trace public next_ids extrn standard_ids: byte public formb, forme, fbgn, fend, actptr extrn lomem: byte trace db 0 ;trace is initially off. next_ids dw standard_ids formb rw 1 forme rw 1 fbgn rw 1 fend rw 1 actptr rw 1 fcn_save rb 1 prev_fcn rw 1 ;some constant definitions ;the _mark constants mark where a particular type of string occurs in ; the linked list. comma_marker equ 0 ;comma_marker must not have function_marker_mask set! active_marker equ 1 ;active_marker must have function_marker_mask set! neutral_marker equ 3 ;neutral_marker must have function_marker_mask set! function_marker_mask equ 1 nomem_prompt db 'No memory!',0 fatal_prompt db 'No disk in drive or door open!',0 protected_prompt db 'Disk is write protected!',0 extrn stackp: byte ;data ends code cseg byte public ;this data are constant scan_xlat_table db (offset scan_copy)-(offset scan_loop) ;00 db (offset scan_copy)-(offset scan_loop) ;01 db (offset scan_copy)-(offset scan_loop) ;02 db (offset scan_copy)-(offset scan_loop) ;03 db (offset scan_copy)-(offset scan_loop) ;04 db (offset scan_copy)-(offset scan_loop) ;05 db (offset scan_copy)-(offset scan_loop) ;06 db (offset scan_copy)-(offset scan_loop) ;07 db (offset scan_copy)-(offset scan_loop) ;08 db (offset scan_ignore)-(offset scan_loop) ;09 db (offset scan_ignore)-(offset scan_loop) ;0A db (offset scan_copy)-(offset scan_loop) ;0B db (offset scan_copy)-(offset scan_loop) ;0C db (offset scan_ignore)-(offset scan_loop) ;0D db (offset scan_copy)-(offset scan_loop) ;0E db (offset scan_copy)-(offset scan_loop) ;0F db (offset scan_copy)-(offset scan_loop) ;10 db (offset scan_copy)-(offset scan_loop) ;11 db (offset scan_copy)-(offset scan_loop) ;12 db (offset scan_copy)-(offset scan_loop) ;13 db (offset scan_copy)-(offset scan_loop) ;14 db (offset scan_copy)-(offset scan_loop) ;15 db (offset scan_copy)-(offset scan_loop) ;16 db (offset scan_copy)-(offset scan_loop) ;17 db (offset scan_copy)-(offset scan_loop) ;18 db (offset scan_copy)-(offset scan_loop) ;19 db (offset scan_copy)-(offset scan_loop) ;1A db (offset scan_copy)-(offset scan_loop) ;1B db (offset scan_copy)-(offset scan_loop) ;1C db (offset scan_copy)-(offset scan_loop) ;1D db (offset scan_copy)-(offset scan_loop) ;1E db (offset scan_copy)-(offset scan_loop) ;1F db (offset scan_copy)-(offset scan_loop) ;20 db (offset scan_copy)-(offset scan_loop) ;21 db (offset scan_copy)-(offset scan_loop) ;22 db (offset scan_sharp)-(offset scan_loop) ;23 '#' db (offset scan_copy)-(offset scan_loop) ;24 db (offset scan_copy)-(offset scan_loop) ;25 db (offset scan_copy)-(offset scan_loop) ;26 db (offset scan_copy)-(offset scan_loop) ;27 db (offset scan_lpar)-(offset scan_loop) ;28 '(' db (offset scan_rpar)-(offset scan_loop) ;29 ')' db (offset scan_copy)-(offset scan_loop) ;2A db (offset scan_copy)-(offset scan_loop) ;2B db (offset scan_comma)-(offset scan_loop) ;2C ',' db (offset scan_copy)-(offset scan_loop) ;2D db (offset scan_copy)-(offset scan_loop) ;2E db (offset scan_copy)-(offset scan_loop) ;2F db (offset scan_copy)-(offset scan_loop) ;30 db (offset scan_copy)-(offset scan_loop) ;31 db (offset scan_copy)-(offset scan_loop) ;32 db (offset scan_copy)-(offset scan_loop) ;33 db (offset scan_copy)-(offset scan_loop) ;34 db (offset scan_copy)-(offset scan_loop) ;35 db (offset scan_copy)-(offset scan_loop) ;36 db (offset scan_copy)-(offset scan_loop) ;37 db (offset scan_copy)-(offset scan_loop) ;38 db (offset scan_copy)-(offset scan_loop) ;39 db (offset scan_copy)-(offset scan_loop) ;3A db (offset scan_copy)-(offset scan_loop) ;3B db (offset scan_copy)-(offset scan_loop) ;3C db (offset scan_copy)-(offset scan_loop) ;3D db (offset scan_copy)-(offset scan_loop) ;3E db (offset scan_copy)-(offset scan_loop) ;3F db (offset scan_copy)-(offset scan_loop) ;40 db (offset scan_copy)-(offset scan_loop) ;41 db (offset scan_copy)-(offset scan_loop) ;42 db (offset scan_copy)-(offset scan_loop) ;43 db (offset scan_copy)-(offset scan_loop) ;44 db (offset scan_copy)-(offset scan_loop) ;45 db (offset scan_copy)-(offset scan_loop) ;46 db (offset scan_copy)-(offset scan_loop) ;47 db (offset scan_copy)-(offset scan_loop) ;48 db (offset scan_copy)-(offset scan_loop) ;49 db (offset scan_copy)-(offset scan_loop) ;4A db (offset scan_copy)-(offset scan_loop) ;4B db (offset scan_copy)-(offset scan_loop) ;4C db (offset scan_copy)-(offset scan_loop) ;4D db (offset scan_copy)-(offset scan_loop) ;4E db (offset scan_copy)-(offset scan_loop) ;4F db (offset scan_copy)-(offset scan_loop) ;50 db (offset scan_copy)-(offset scan_loop) ;51 db (offset scan_copy)-(offset scan_loop) ;52 db (offset scan_copy)-(offset scan_loop) ;53 db (offset scan_copy)-(offset scan_loop) ;54 db (offset scan_copy)-(offset scan_loop) ;55 db (offset scan_copy)-(offset scan_loop) ;56 db (offset scan_copy)-(offset scan_loop) ;57 db (offset scan_copy)-(offset scan_loop) ;58 db (offset scan_copy)-(offset scan_loop) ;59 db (offset scan_copy)-(offset scan_loop) ;5A db (offset scan_copy)-(offset scan_loop) ;5B db (offset scan_copy)-(offset scan_loop) ;5C db (offset scan_copy)-(offset scan_loop) ;5D db (offset scan_copy)-(offset scan_loop) ;5E db (offset scan_copy)-(offset scan_loop) ;5F db (offset scan_copy)-(offset scan_loop) ;60 db (offset scan_copy)-(offset scan_loop) ;61 db (offset scan_copy)-(offset scan_loop) ;62 db (offset scan_copy)-(offset scan_loop) ;63 db (offset scan_copy)-(offset scan_loop) ;64 db (offset scan_copy)-(offset scan_loop) ;65 db (offset scan_copy)-(offset scan_loop) ;66 db (offset scan_copy)-(offset scan_loop) ;67 db (offset scan_copy)-(offset scan_loop) ;68 db (offset scan_copy)-(offset scan_loop) ;69 db (offset scan_copy)-(offset scan_loop) ;6A db (offset scan_copy)-(offset scan_loop) ;6B db (offset scan_copy)-(offset scan_loop) ;6C db (offset scan_copy)-(offset scan_loop) ;6D db (offset scan_copy)-(offset scan_loop) ;6E db (offset scan_copy)-(offset scan_loop) ;6F db (offset scan_copy)-(offset scan_loop) ;70 db (offset scan_copy)-(offset scan_loop) ;71 db (offset scan_copy)-(offset scan_loop) ;72 db (offset scan_copy)-(offset scan_loop) ;73 db (offset scan_copy)-(offset scan_loop) ;74 db (offset scan_copy)-(offset scan_loop) ;75 db (offset scan_copy)-(offset scan_loop) ;76 db (offset scan_copy)-(offset scan_loop) ;77 db (offset scan_copy)-(offset scan_loop) ;78 db (offset scan_copy)-(offset scan_loop) ;79 db (offset scan_copy)-(offset scan_loop) ;7A db (offset scan_copy)-(offset scan_loop) ;7B db (offset scan_copy)-(offset scan_loop) ;7C db (offset scan_copy)-(offset scan_loop) ;7D db (offset scan_copy)-(offset scan_loop) ;7E db (offset scan_copy)-(offset scan_loop) ;7F db (offset scan_copy)-(offset scan_loop) ;80 db (offset scan_copy)-(offset scan_loop) ;81 db (offset scan_copy)-(offset scan_loop) ;82 db (offset scan_copy)-(offset scan_loop) ;83 db (offset scan_copy)-(offset scan_loop) ;84 db (offset scan_copy)-(offset scan_loop) ;85 db (offset scan_copy)-(offset scan_loop) ;86 db (offset scan_copy)-(offset scan_loop) ;87 db (offset scan_copy)-(offset scan_loop) ;88 db (offset scan_copy)-(offset scan_loop) ;89 db (offset scan_copy)-(offset scan_loop) ;8A db (offset scan_copy)-(offset scan_loop) ;8B db (offset scan_copy)-(offset scan_loop) ;8C db (offset scan_copy)-(offset scan_loop) ;8D db (offset scan_copy)-(offset scan_loop) ;8E db (offset scan_copy)-(offset scan_loop) ;8F db (offset scan_copy)-(offset scan_loop) ;90 db (offset scan_copy)-(offset scan_loop) ;91 db (offset scan_copy)-(offset scan_loop) ;92 db (offset scan_copy)-(offset scan_loop) ;93 db (offset scan_copy)-(offset scan_loop) ;94 db (offset scan_copy)-(offset scan_loop) ;95 db (offset scan_copy)-(offset scan_loop) ;96 db (offset scan_copy)-(offset scan_loop) ;97 db (offset scan_copy)-(offset scan_loop) ;98 db (offset scan_copy)-(offset scan_loop) ;99 db (offset scan_copy)-(offset scan_loop) ;9A db (offset scan_copy)-(offset scan_loop) ;9B db (offset scan_copy)-(offset scan_loop) ;9C db (offset scan_copy)-(offset scan_loop) ;9D db (offset scan_copy)-(offset scan_loop) ;9E db (offset scan_copy)-(offset scan_loop) ;9F db (offset scan_copy)-(offset scan_loop) ;A0 db (offset scan_copy)-(offset scan_loop) ;A1 db (offset scan_copy)-(offset scan_loop) ;A2 db (offset scan_copy)-(offset scan_loop) ;A3 db (offset scan_copy)-(offset scan_loop) ;A4 db (offset scan_copy)-(offset scan_loop) ;A5 db (offset scan_copy)-(offset scan_loop) ;A6 db (offset scan_copy)-(offset scan_loop) ;A7 db (offset scan_copy)-(offset scan_loop) ;A8 db (offset scan_copy)-(offset scan_loop) ;A9 db (offset scan_copy)-(offset scan_loop) ;AA db (offset scan_copy)-(offset scan_loop) ;AB db (offset scan_copy)-(offset scan_loop) ;AC db (offset scan_copy)-(offset scan_loop) ;AD db (offset scan_copy)-(offset scan_loop) ;AE db (offset scan_copy)-(offset scan_loop) ;AF db (offset scan_copy)-(offset scan_loop) ;B0 db (offset scan_copy)-(offset scan_loop) ;B1 db (offset scan_copy)-(offset scan_loop) ;B2 db (offset scan_copy)-(offset scan_loop) ;B3 db (offset scan_copy)-(offset scan_loop) ;B4 db (offset scan_copy)-(offset scan_loop) ;B5 db (offset scan_copy)-(offset scan_loop) ;B6 db (offset scan_copy)-(offset scan_loop) ;B7 db (offset scan_copy)-(offset scan_loop) ;B8 db (offset scan_copy)-(offset scan_loop) ;B9 db (offset scan_copy)-(offset scan_loop) ;BA db (offset scan_copy)-(offset scan_loop) ;BB db (offset scan_copy)-(offset scan_loop) ;BC db (offset scan_copy)-(offset scan_loop) ;BD db (offset scan_copy)-(offset scan_loop) ;BE db (offset scan_copy)-(offset scan_loop) ;BF db (offset scan_copy)-(offset scan_loop) ;C0 db (offset scan_copy)-(offset scan_loop) ;C1 db (offset scan_copy)-(offset scan_loop) ;C2 db (offset scan_copy)-(offset scan_loop) ;C3 db (offset scan_copy)-(offset scan_loop) ;C4 db (offset scan_copy)-(offset scan_loop) ;C5 db (offset scan_copy)-(offset scan_loop) ;C6 db (offset scan_copy)-(offset scan_loop) ;C7 db (offset scan_copy)-(offset scan_loop) ;C8 db (offset scan_copy)-(offset scan_loop) ;C9 db (offset scan_copy)-(offset scan_loop) ;CA db (offset scan_copy)-(offset scan_loop) ;CB db (offset scan_copy)-(offset scan_loop) ;CC db (offset scan_copy)-(offset scan_loop) ;CD db (offset scan_copy)-(offset scan_loop) ;CE db (offset scan_copy)-(offset scan_loop) ;CF db (offset scan_copy)-(offset scan_loop) ;D0 db (offset scan_copy)-(offset scan_loop) ;D1 db (offset scan_copy)-(offset scan_loop) ;D2 db (offset scan_copy)-(offset scan_loop) ;D3 db (offset scan_copy)-(offset scan_loop) ;D4 db (offset scan_copy)-(offset scan_loop) ;D5 db (offset scan_copy)-(offset scan_loop) ;D6 db (offset scan_copy)-(offset scan_loop) ;D7 db (offset scan_copy)-(offset scan_loop) ;D8 db (offset scan_copy)-(offset scan_loop) ;D9 db (offset scan_copy)-(offset scan_loop) ;DA db (offset scan_copy)-(offset scan_loop) ;DB db (offset scan_copy)-(offset scan_loop) ;DC db (offset scan_copy)-(offset scan_loop) ;DD db (offset scan_copy)-(offset scan_loop) ;DE db (offset scan_copy)-(offset scan_loop) ;DF db (offset scan_copy)-(offset scan_loop) ;E0 db (offset scan_copy)-(offset scan_loop) ;E1 db (offset scan_copy)-(offset scan_loop) ;E2 db (offset scan_copy)-(offset scan_loop) ;E3 db (offset scan_copy)-(offset scan_loop) ;E4 db (offset scan_copy)-(offset scan_loop) ;E5 db (offset scan_copy)-(offset scan_loop) ;E6 db (offset scan_copy)-(offset scan_loop) ;E7 db (offset scan_copy)-(offset scan_loop) ;E8 db (offset scan_copy)-(offset scan_loop) ;E9 db (offset scan_copy)-(offset scan_loop) ;EA db (offset scan_copy)-(offset scan_loop) ;EB db (offset scan_copy)-(offset scan_loop) ;EC db (offset scan_copy)-(offset scan_loop) ;ED db (offset scan_copy)-(offset scan_loop) ;EE db (offset scan_copy)-(offset scan_loop) ;EF db (offset scan_copy)-(offset scan_loop) ;F0 db (offset scan_copy)-(offset scan_loop) ;F1 db (offset scan_copy)-(offset scan_loop) ;F2 db (offset scan_copy)-(offset scan_loop) ;F3 db (offset scan_copy)-(offset scan_loop) ;F4 db (offset scan_copy)-(offset scan_loop) ;F5 db (offset scan_copy)-(offset scan_loop) ;F6 db (offset scan_copy)-(offset scan_loop) ;F7 db (offset scan_copy)-(offset scan_loop) ;F8 db (offset scan_copy)-(offset scan_loop) ;F9 db (offset scan_copy)-(offset scan_loop) ;FA db (offset scan_copy)-(offset scan_loop) ;FB db (offset scan_copy)-(offset scan_loop) ;FC db (offset scan_copy)-(offset scan_loop) ;FD db (offset scan_copy)-(offset scan_loop) ;FE db (offset scan_copy)-(offset scan_loop) ;FF extrn function_name_table: word extrn function_name_length: word extrn function_address: word ;code ends ;code cseg byte public ;*** assume cs:code, ds:data, es:data public abort_fatal abort_fatal: add sp,22 ;magic number from Z-DOS II, page I.3 pop es ;restore our es and ds. push es pop ds mov sp,offset stackp sti ;enable interrupts again. mov si,offset protected_prompt cmp di,0 ;write protect? je nomem_1 mov si,offset fatal_prompt jmps nomem_1 public nomem nomem: mov sp,offset stackp mov si,offset nomem_prompt nomem_1: lodsb or al,al je nomem_2 mov dl,al ; mov ah,2 ; int 21h mov cl,2 ! int 0E0h ;<<<-- CCPM jmps nomem_1 nomem_2: jmp init_ids extrn init_ids: near public init_ids_continue init_ids_continue: mov di,next_ids ;get the desired idling string. mov si,di ;save a copy mov next_ids,offset standard_ids ;reset to ids. mov al,0 mov cx,-1 repne scasb ;find the terminating null. not cx mov di,formb sub di,cx push di rep movsb pop si ;pushed as di mov di,offset lomem mov dx,0 cld mov bp,formb mov bx,offset scan_xlat_table ;->translate table jmps scan_loop init_ids_jump_2: jmp init_ids ;**************************************************************************** ; The following is the MINT scan loop. This loop must be as fast as ;possible because it takes the most time to execute. As a consequence, the ;code is quite unstructured. However, the code follows the algorithm given in ;the MINT language definition document. ; During scan, si -> (points to) the active string, di -> the ;neutral string, dx -> previous argument, and bp -> end of active string. ; As we scan a character, we must branch to certain routines on certain ;characters. To make best use of the 8086 instruction set, we have set up a ;translate table. Therefore, the translate table, scan_xlat_table, contains an ;offset from the beginning of the scan loop. ; ; When the scan loop has finally found a function to be executed, ;a jump is performed to that primitive (unknown primitives cause jump to dflt). ;When the primitive is finished, it jumps (with the exception of hl) to one of ;the 'return_???' functions. Each of the return_??? routines puts the returned ;value in the proper place in the proper string (active or neutral), and jumps ;back to scan. ; The scan loop is repeatedly executed until there are no more functions ;to be executed, or the available memory has been exhausted. ;***************************************************************************** scan_copy: ;come here to copy a char from active to neutral dec si movsb scan_ignore: ;come here to throw a char away from active. scan_loop: cmp si,bp ;if we scan off the right end, init_ids je init_ids_jump_2 lodsb xlat scan_xlat_table ;al was char, is now offset cbw ;ax is now offset. add ax,offset scan_loop jmp ax scan_comma: mov al,comma_marker scan_mark: stosb ;store marker mov ax,dx ;get previous pointer mov dx,di ;save current (will soon be previous) stosw jmps scan_loop scan_sharp: cmp word ptr [si],'(#' ;'##(' ? je scan_two_sharps ;yes. cmp byte ptr [si],'(' ;'#(' ? jne scan_copy ;no. inc si mov al,active_marker jmps scan_mark scan_two_sharps: add si,2 mov al,neutral_marker jmps scan_mark scan_lpar: mov cx,1 call scan_lpar_sub jmps scan_loop ;scan until we find a matching rpar. public scan_lpar_sub ;public so that we can profile it. scan_lpar_sub: scan_lpar_1: cmp si,bp je init_ids_jump_2 lodsb ;can't use movsb, because it doesn't load al stosb cmp al,'(' je scan_lpar_2 cmp al,')' jne scan_lpar_1 loop scan_lpar_1 dec di ;remove final rpar ret scan_lpar_2: inc cx jmps scan_lpar_1 init_ids_jump_1: jmp init_ids scan_rpar: ;si -> neutral string ;di -> active string ;dx -> previous argument or function pointer. call scan_rpar_sub call function_address-2[di] mov bp,formb mov bx,offset scan_xlat_table ;->translate table jmps scan_loop public scan_rpar_sub scan_rpar_sub: ;store last argument mark mov al,comma_marker stosb mov ax,di ;make final arg -> itself stosw ;*************************************************************************** ; We have a problem here. Currently, the pointers point backwards ;to the previous function/arg. We want this function's pointers to point ;forwards, so we can start at the active/neutral marker and count arguments ;forwards. ; ;  is a pointer, • is what is points to. ; ; ; aSS,ONE,TWO, ; • ‚• ‚• ‚• ; ‚ ‚‚ ‚‚ ‚‚ ; ›š›š‚ ›š ; dx ;********************************************************************** mov fend,di sub di,2 ;make di ->final pointer mov actptr,si scan_rpar_1: or dx,dx ;if end of list, we must be running off jz init_ids_jump_1 ; the left end (too many rpars) mov bx,dx ;get previous pointer. mov dx,[bx] ;get the current pointer [previous pointer]. mov [bx],di ;store the next pointer. mov di,bx ;save current pointer. ; bx, di -> current arg/fcn ; dx -> previous (to the left) arg/fcn test byte ptr 0ffffh[bx],function_marker_mask jz scan_rpar_1 mov al,-1[bx] mov fcn_save,al ;remember the type of function. mov prev_fcn,dx mov fbgn,bx call check_breakchar call trace_invoke ;destroys al ;remember that fbgn is really one more than the space taken by the function. mov ax,[bx] ;get pointer to first arg. sub ax,bx ;compute length of name cmp ax,2 + mark_overhead ;two character function name? jne default_to_cl ;no - must be default. mov ax,2[bx] ;get function name. mov di,offset function_name_table mov cx,function_name_length push es ! push cs ! pop es ;the table is in the code segment repne scasw ! pop es jne default_to_cl ;if not found, default sub di,offset function_name_table ret default_to_cl: mov di,0 ret ;return data routines here public return_null return_null: mov cx,0 call trace_result ;destroys al return_nothing: mov si,actptr mov di,fbgn dec di mov dx,prev_fcn ret public return_string return_string: ;al=string number to return, bx=>list of strings. add al,al mov ah,0 add bx,ax mov si,[bx] mov cx,2[bx] sub cx,si jmps return_sicx public return_tos return_tos: ;tos -> string, di -> byte after end of string pop si mov cx,di sub cx,si jmps return_sicx public return_arg_active return_arg_active: mov fcn_save,active_marker ;fall through to return_arg public return_arg return_arg: ;enter with cx = number of arg to return. call getarg ;fall through to return_sicx public return_sicx return_sicx: ;si -> string, cx = count. cmp fcn_save,active_marker ;active or neutral jne return_neutral ; jmps return_active ;fall through! public return_active return_active: ;we need to move [si] count cx ; to [actptr-cx] through [actptr-1] reverse ;Then we return si = [actptr-cx], di=fbgn-1 call trace_result ;destroys al jcxz return_nothing ;quick check for 0 chars. mov di,actptr dec di add si,cx ;point si to end of string + 1. dec si ;remember, it's postdecrement. std ;reverse move rep movsb cld ;everybody assumes it's cleared. inc di ;make di -> last byte moved. mov si,di ;si -> what we just moved. mov di,fbgn ;remove previous function. dec di mov dx,prev_fcn ret public return_neutral return_neutral: ;we need to move [si] count cx ; to [fbgn-1] through [fbgn-1] - (cx - 1) ;Then we return si=actptr, di=[fbgn-1] - cx call trace_result ;destroys al jcxz return_nothing ;quick check for 0 chars. mov di,fbgn dec di cmp di,si ;is it there already? je return_neutral_1 ;yes, save some time. rep movsb ;put it there. return_neutral_1: ;tricky time! If we performed the movsb, cx is zero, so we're doing ;nothing. If we took the jump to return_neutral_1, cx is the proper ;count, so di will point to the right place. add di,cx mov si,actptr mov dx,prev_fcn ret extrn trace_result: near extrn trace_invoke: near ;utility subroutines extrn check_breakchar: near public getarg1, getarg getarg1: mov cx,1 ;fall through to getarg getarg: ;enter with cx = number of argument to get. ;exit with si -> argument, cx=length of argument. ;************************************************************************* ; ;The pointer after the last supplied argument points to itself, which allows ;us to loop at getarg_loop until we think that we have found the argument. Of ;course, if that argument has not been supplied, all that we've done is to chase ;the last pointer a few times. As an aside, had you ever noticed that when the ;amount of comments exceeds the amount of code, the code is likely to be ;confusing? Well, this code is probably confusing. ; ;************************************************************************* mov si,fbgn jcxz getarg_2 ;skip loop if count is zero. getarg_loop: mov si,[si] ;get our argument loop getarg_loop getarg_2: mov cx,[si] ;get cx=next argument sub cx,si ;get cx=length of our argument jcxz getarg_1 ;in case we ran into fend, it doesn't matter what si -> to. sub cx,mark_overhead add si,mark_overhead-1 ;make si-> text of argument. getarg_1: ret ;code ends end