home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj8908.zip / THOMAS.LST < prev   
File List  |  1989-07-06  |  33KB  |  847 lines

  1. SMALLTALK + C: THE POWER OF TWO
  2. by Dave Thomas and Randolph Best
  3.  
  4. [LISTING ONE]
  5.  
  6. Object subclass: #Dos
  7.   instanceVariableNames: 
  8.     'registers temp1 temp2 '
  9.   classVariableNames: ''
  10.   poolDictionaries: '' !
  11.  
  12. !Dos methods !
  13.  
  14. doDCSPrimitive: opcode
  15.      "PRIVATE - Call the DCS Primitives using an interrupt"
  16.      <primitive: 96>
  17. getEnvironmentValue: anEnvironmentString
  18.      "Private- This is a method for getting the
  19.      value of an environment variable(string). Answers
  20.      the value if anEnvironmentString is valid or nil
  21.      if not found.
  22.      Here the instance variables are
  23.      used as follows:
  24.         temp1 = the name of the environment variable wanted
  25.         temp2 = the value of the environment, if the
  26.                       environment variable exists.      "
  27.     temp1 := anEnvironmentString asAsciiZ.
  28.     temp2 := String new: 128.
  29.     (self doDcsPrimitive: -11)
  30.         ifTrue:[ ^temp2 trimBlanks ]
  31.         ifFalse:[ ^''].!
  32.  
  33. [LISTIN╟ TWO]
  34.  
  35. ;*****************************************************************************
  36. ;ACCESS.USR - PRIMITIVE ENTRY MACRO - SMALLTALK/V
  37. ;Copyright (C) 1986 - Digitalk, Inc. - Reprinted by Permission
  38. ;*****************************************************************************
  39. ; It is essential that this macro appear at the beginning of
  40. ; the primitive in that it saves certain registers.  Some of
  41. ; the registers may or may not have to be restored depending on
  42. ; whether or not the primitive is successful, and some
  43. ; must be restored before exiting the primitive.
  44.  
  45. enterPrimitive     MACRO
  46.  
  47. ; At the end of this macro the stack will appear as below:
  48. ;  SP--> BP--> - saved BP - must be restored on exit
  49. ;          +2  - saved BX - must be restored in case of failure
  50. ;          +4  - saved DI - must be restored in case of failure
  51. ;          +6  - saved SI - must be restored on exit
  52. ;          +8  - saved DS - must be restored on exit
  53. ;          +10 - IP
  54. ;          +12 - CS
  55. ;          +14 - FLAGS
  56. ; if there are any argument passed to the primitive they are found here
  57. ;          +16 - last argument to primitive
  58. ;          +18 - second last argument to primitive
  59. ;              - etc...
  60. ; high address -
  61. ; Note: some of the following macros use BP assuming the value has not
  62. ;       changed from what this macro sets it to.  If you use BP be sure
  63. ;       to restore it before using the macros that make use of BP.
  64.  
  65.                    PUSH   DS                     ;set up stack as shown above
  66.                    PUSH   SI
  67.                    PUSH   DI
  68.                    PUSH   BX
  69.                    PUSH   BP
  70.                    MOV    BP,SP                  ;set BP to Top of Stack
  71.                    ENDM
  72.  
  73. ; This macro must be used when the primitive must be exited and the
  74. ; primitive was SUCCESSFUL.  The resulting pointer or small integer 
  75. ; must be in BX before invoking this macro.  The macro will:
  76. ;   - mark the object (pointer) in BX so that the garbage collector 
  77. ;     will not collect it as garbage  
  78. ;   - certain registers are restored
  79. ;   - the return address and flags are popped into temporary registers
  80. ╗   ¡ thσ argument≤ arσ flusheΣ anΣ replaceΣ witΦ thσ resul⌠ iε BX
  81. ;   - the return address and flags are put back on the stack
  82. ;   - AX is set to zero (AH=0 indicates that the primitive was successful)
  83. ;   - and the IRET instruction is executed
  84.  
  85. exitWithSuccess    MACRO  numOfArgs
  86.  
  87. ; On entry BX must contains the result to be pushed 
  88. ; on the stack.è
  89.                    markPtr BX,ES                 ;mark result object in BX
  90.                    POP    BP                     ;restore BP
  91.                    ADD    SP,4
  92.                    POP    SI                     ;restore DS:SI pair
  93.                    POP    DS
  94.                    POP    CX                     ;pop the offset,segment and
  95.                    POP    DX                     ;flags into temp registers
  96.                    POP    AX
  97. IF numOfArgs       
  98.                    ADD    SP,numOfArgs * 2 + 2   ;flush all args of primitive
  99. ENDIF
  100.                    PUSH   BX                     ;push result on stack
  101.                    PUSH   AX                     ;push flags, segment and
  102.                    PUSH   DX                     ;offset back onto stack
  103.                    PUSH   CX
  104.                    XOR    AX,AX                  ;AH to 0 (prim was successful)
  105.                    IRET                          ;interrupt return
  106.                    ENDM
  107.  
  108. ; This macro must be used when the primitive must be exited and the
  109. ; primitive FAILED.  The macro will:
  110. ;   - restore all saved registers
  111. ;   - set AH to 1 indicating failure condition and AL to the number 
  112. ;     of arguments passed to the primitive
  113. ;   - and the IRET instruction is executed
  114.  
  115. exitWithFailure    MACRO  numOfArgs
  116.  
  117.                    POP    BP                     ;restore all saved registers
  118.                    POP    BX
  119.                    POP    DI
  120.                    POP    SI
  121.                    POP    DS
  122.                    MOV    AX,256 + numOfArgs     ;AH to 1 (prim failed)
  123.                    IRET                          ;interrupt return
  124.                    ENDM
  125.  
  126. ; This macro will return the address of the object with object pointer
  127. ; in objectReg.  The address will be returned in the register pair
  128. ; segmentReg:offsetReg.  segmentReg must be a segment register.
  129.  
  130. getObjectAddress   MACRO  objectReg,offsetReg,segmentReg
  131.  
  132. ; All the arguments must be different registers.
  133. ; BP must not have changed from the value it was 
  134. ; set to in the enterPrimitive macro.
  135.  
  136.                    MOV    segmentReg,[BP+12]
  137.                    ROR    objectReg,1
  138.                    MOV    offsetReg,segmentReg:[objectReg]
  139.                    ROL    objectReg,1
  140.                    MOV    segmentReg,SS:[objectReg]
  141.                    AND    offsetReg,MASK offsetMask
  142.                    ENDMè
  143. ; This macro will mark the object whose object pointer is in objectReg
  144. ; so the garbage collector will not collect as garbage.  It is to be used
  145. ; whenever an object pointer is stored.  If the object in objectReg is 
  146. ; a small integer, no marking occurs.
  147.  
  148. markPtr            MACRO  objectReg,segmentReg
  149.                    LOCAL  done
  150.  
  151. ; BP must not have changed from the value it was 
  152. ; set to in the enterPrimitive macro.
  153.  
  154.                    ROR    objectReg,1
  155.                    JNC    done
  156.                    MOV    segmentReg,[BP+12]
  157.                    OR     BYTE PTR segmentReg:[objectReg],MASK grayMask
  158. done:              ROL    objectReg,1
  159.  
  160.                    ENDM
  161.  
  162. ; This macro will get the class (pointer) of the object whose pointer
  163. ; is in objectReg.  If the object in objectReg is a small integer then
  164. ; the class pointer is set to ClassSmallInt.
  165.  
  166. getClass           MACRO  objectReg,classReg,segmentReg
  167.                    LOCAL  done
  168. ;all the arguments must be different registers
  169.  
  170.                    MOV    classReg,ClassSmallInt
  171.                    TEST   objectReg,1
  172.                    JZ     done
  173.                    MOV    classReg,SS
  174.                    SHR    classReg,1
  175.                    MOV    segmentReg,classReg
  176.                    MOV    classReg,segmentReg:[objectReg]
  177. done:
  178.                    ENDM
  179.  
  180. ; This macro will set the zero condition flag as to whether the object size
  181. ; is an even or odd number of bytes.  This test should be performed on
  182. ; byte-addressable objects.  A zero condition means that the object is an
  183. ; even number of bytes (actual size = object header - 2).  A non-zero 
  184. ; condition means that the object is an odd number of bytes 
  185. ; (actual size = object header - 3).
  186.  
  187. isSizeEven         MACRO  objectReg,workReg,segmentReg
  188.  
  189. ; BP must not have changed from the value it was
  190. ; set to in the enterPrimitive macro.
  191.  
  192.                    MOV    workReg,objectReg
  193.                    ROR    objectReg,1
  194.                    MOV    segmentReg,[BP+12]
  195.                    TEST   BYTE PTR segmentReg:[objectReg],MASK oddMask
  196.                    MOV    objectReg,workRegè                   ENDM
  197.  
  198. ;*****************************************************************************
  199. ; PRIMITIVE ENTRY POINT SAMPLE CODE FRAGMENTS
  200. ;*****************************************************************************
  201.  
  202.                 DW      getCountryEnt
  203.                 DW      getEnvironEnt
  204.         DW    exeApplicEnt
  205.                 DW      exeProgramEnt                
  206.         DW    setNoXlatEnt
  207.         DW    setXlatEnt
  208.         DW    atEndEnt
  209.                 DW      bufFlushEnt
  210.         DW    bufWriteEnt
  211.         DW    bufReadEnt
  212.         DW    initOutputEnt
  213.         DW    initInputEnt
  214. jumpTable    DW    interruptEnt
  215.         DW    inWordEnt
  216.         DW    inByteEnt
  217.         DW    outWordEnt
  218.         DW    outByteEnt
  219.         DW    peekEnt
  220.         DW    pokeEnt
  221.         DW    blockMoveEnt   
  222.  
  223.                 *
  224.                 *
  225.                 *
  226.  
  227. dcsPrims        proc    far
  228.  
  229. ; This is code that will be executed everytime this primitive
  230. ; is invoked from "Smalltalk/V"
  231.  
  232.         enterPrimitive                  ;enter primitive macro 
  233.  
  234.         mov     bx,[bp+16]              ;get function code from first instance
  235.         test    bl,1                    ; variable of receiving object.  if it
  236.         jnz     failure                 ; isn't a number then something's very
  237.                                         ; rotten in the state of Denmark.
  238.  
  239.         cmp     bx,16                   ;the function code is already shifted
  240.         jge     failure                 ; left by one (courtesy of smalltalk's
  241.         cmp     bx,-26                  ; way of identifying integers), so do
  242.         jle     failure                 ; some range checks and abort if the
  243.                                         ; value is out of bounds.
  244.  
  245.         jmp     cs:[bx+jumpTable]       ;otherwise, jump to the code associated
  246.                                         ; with this function number.
  247.          *
  248.          *
  249.          *
  250. è        mov     cs:stackOfs,sp          ;save the current Smalltalk stack, and
  251.         mov     cs:stackSeg,ss          ; replace it with a local stack in low
  252.         mov     ax,cs                   ; (protected memory).
  253.     cli
  254.     mov    ss,ax
  255.     lea    sp,cs:_stack
  256.     sti
  257.  
  258.         mov     ah,2fh                  ;save the DOS DTA pointer, just in case
  259.         int     21h                     ; it gets clobbered by the application.
  260.     mov    cs:dtaOfs,bx
  261.     mov    cs:dtaSeg,es
  262.     
  263.         call    exec                    ;load and execute the program
  264.         mov     bx,truePtr              ; the errorlevel
  265.         jnc     exec01                  ; code is returned in "retCode". If the
  266.         mov     bx,falsePtr             ; carry was set, then an error occurred
  267. exec01: mov     retVal,bx               ; and we answer "false", otherwise we
  268.                                         ; answer "true".
  269.         mov     ah,1ah                  ;restore the DOS DTA pointer.
  270.     lds    dx,cs:dtaPtr
  271.     int    21h
  272.     
  273.         cli                             ;and, restore the Smalltalk stack with
  274.         mov     ss,cs:stackseg          ; the saved pointer.
  275.     mov    sp,cs:stackofs
  276.     sti
  277.  
  278.         mov     ax,retCode              ;convert the errorlevel to a Smalltalk
  279.         shl     ax,1                    ; integer format, and return it in the
  280.         les     bx,receiverPtr          ; fifth instance variable of receiver
  281.         mov     es:[bx+12],ax           ; object.
  282.  
  283.         mov     bx,retVal               ;the Smalltalk convention is to put the
  284.         jmp     success1                ; answer for this obj in bx, and call
  285.                                         ; the "leavePrimitive" macro.  a jump
  286.                                         ; to success will do this quite nicely
  287.                                         ; thank yew!
  288.  
  289. [LISTIN╟ THREE]
  290.  
  291. ;queue an interpreter interrupt (in protected mode)
  292. ;  AL=interrupt number to queue
  293. interruptVM MACRO 
  294.             CALL DWORD PTR SS:[queueVMinterrupt] 
  295.             ENDM
  296. ;queue an interpreter interrupt (in real mode)
  297. ISVinterruptVM MACRO 
  298.             MOV ES,CS:[realParmSeg]  
  299.             CALL DWORD PTR ES:[ISVqueueVMinterrupt]
  300.             ENDM     
  301. The code to call the socket primitive in Smalltalk is:
  302. socketPrimitiveOpcode: opcode withArguments: argumentArray
  303.     "PRIVATE: Call the socket primitive."
  304.     <primitive: socketPrimitive>
  305.     ^self error: 'Network Primitive failed - is sockprim.bin loaded?'
  306.  
  307.  
  308. [LISTIN╟ FOUR]
  309.  
  310. ;*****************************************************************************
  311. ;* FIXDPTRS.USR 
  312. ;*****************************************************************************
  313.  
  314. ;fixed segments     
  315.  
  316. plusSmallSeg            = 6         ;segment of small positive integers 
  317. nilSegment              = 106H      ;segment of nil object
  318. minusSmallSeg           = 116H      ;segment of small negative integers
  319. booleanSeg              = 10EH      ;segment for true and false
  320. characterSeg            = 11EH      ;segment for all character objects
  321. fixedPtrSeg             = 126H      ;segment for all fixed ptr objects 
  322.  
  323. ;fixed offsets      
  324.  
  325. nilOffset               = 106H      ;offset of nil object
  326. trueOffset              = 0fff3H    ;offset of true object
  327. falseOffset             = 0fff1H    ;offset of false object  
  328. firstCharOffset         = 2         ;offset of ascii char 0
  329.  
  330. ;all of the following objects are in the segment fixedPtrSeg
  331. ;what is given below are their offsets 
  332.                                     ;array of classes in system
  333. classArrayOffset    equ nilOffset+size objectHeader  
  334. Smalltalk           equ classArrayOffset + size assoc
  335. ErrorCode           equ Smalltalk + size assoc  
  336.  
  337. ;*****************************************************************************
  338. ; OBJECTS.USR 
  339. ;*****************************************************************************
  340.                    
  341. ;Object header structure
  342.  
  343. objectHeader STRUC
  344. ClassPtrHash    DW ?        ;see below for values for fixed classesèObjectPtrHash   DW ?        ;usually contains object hash
  345. GCreserved      DW ?
  346. NumberFixed     DW ?        ;number of named instance variables
  347. ObjectSize      DB 3 DUP(?) ;stored as low,middle,high order
  348.                             ;  size is stored as # of instance variables
  349. ObjectFlags     DB ?        ;defined below
  350. objectHeader    ENDS
  351.  
  352. ;object flags (contained in objectFlag byte of objectHeader)
  353. PointerBit      EQU 10H     ;Object contains pointers
  354. IndexedBit      EQU 8       ;Object has indexed instance variables
  355. ;other bits in byte are reserved
  356.  
  357. ;Array Object
  358. arrayObj STRUC
  359.             DB size objectHeader DUP (?)
  360. arrayObj    ENDS
  361.  
  362. ;Character Object
  363. charObj STRUC           
  364.             DB size objectHeader DUP (?)
  365. asciiValue  DD ?            ;ascii value
  366. charObj     ENDS
  367. ;Note that this is 16 bytes in size
  368.  
  369. ; Association Object
  370. assoc STRUC
  371.             DB size objectHeader DUP (?)
  372. assocKey    DD  ?
  373. assocValue  DD  ?
  374. assoc       ENDS
  375.  
  376. ; Point object
  377. pointObj STRUC
  378.             DB size objectHeader DUP (?)
  379. pointX      DD  ?
  380. pointY      DD  ?
  381. pointObj    ENDS
  382.  
  383. ; Hash values for classes 
  384. SmallIntegerHash equ    0
  385. emptySlotHash   equ     SmallIntegerHash + 8
  386. StringHash      equ     emptySlotHash + 8
  387. MessageHash     equ     StringHash + 8
  388. SymbolClassHash equ     MessageHash + 8
  389. LargePosIntHash equ     SymbolClassHash + 8
  390. HomeContextHash equ     LargePosIntHash + 8
  391. LargeNegIntHash equ     HomeContextHash + 8
  392. ContextHash     equ     LargeNegIntHash + 8
  393. PointHash       equ     ContextHash + 8
  394. ArrayHash       equ     PointHash + 8
  395. LinkHash        equ     ArrayHash + 8
  396.       
  397. ; This is a useful struc for accessing arguments in primitives
  398. ; For example, to load the receiver into DS:SIè;           LDS SI,[BP+receiverPtr]
  399.  
  400. ;stack after enterPrimitive macro
  401. primitiveFrame STRUC
  402. savedBP         DW  ?
  403. returnAddr      DD  ?
  404. receiverPtr     DD  ?
  405. arg1Ptr         DD  ?
  406. arg2Ptr         DD  ?
  407. arg3Ptr         DD  ?
  408. primitiveFrame  ENDS  
  409.  
  410. ;This struc defines the beginning of a user primitive load module
  411. primLoadModule STRUC
  412. installEntry        DW ?       ; 0 entry point for installation routine
  413. reserved1           DW 0       ; 2
  414.                     DW 0       ; 4
  415. realCodeSeg         DW ?       ; 6 after loading, will contain real mode addr
  416. primTableOffset     DW ?       ; 8 offset of table of primitive subroutines
  417. realParmSeg         DW ?       ; A after loading, will contain real mode addr 
  418.                                ;   of virtual machine communication area.
  419. reserved2           DW 0       ; C  
  420.                     DW 0       ; E                          
  421. primLoadModule ENDS
  422.  
  423. ;*****************************************************************************
  424. ;* ACCESS.USR -PRIMITIVE ENTRY MACRO - SMALLTALK/V286
  425. ;* Copyright (C) 1988 - Digitalk, Inc. - Reprinted by Permission
  426. ;*****************************************************************************
  427.  
  428. ; It is essential that this macro appear at the beginning of
  429. ; the primitive in that it saves certain registers.  Some of
  430. ; the registers may or may not have to be restored depending on
  431. ; whether or not the primitive is successful, and some
  432. ; must be restored before exiting the primitive.
  433.  
  434. enterPrimitive MACRO
  435.  
  436. ; At the end of this macro the stack will appear as below:
  437. ;
  438. ;  SP--> BP-->  - saved BP 
  439. ;           +2  - return addr (offset)
  440. ;           +4  - return addr (segment)
  441. ; If there are any argument passed to the primitive they are found here.   
  442. ; All arguments and the receiver are passed as 32 bit pointers
  443. ;           +6  - receiver of primitive  (offset)
  444. ;           +8  - receiver of primitive  (segment)
  445. ;           +10 - first argument to primitive  (offset)   
  446. ;           +12 - first argument to primitive  (segment)
  447. ;               -           :
  448. ; high address  -           :
  449. ;
  450. ; Note: some of the following macros use BP assuming the value has not
  451. ;       changed from what this macro sets it to.  If you use BP be sure
  452. ;       to restore it before using the macros that make use of BP.è                  
  453.             PUSH    BP              ;save old BP                            
  454.             MOV     BP,SP           ;set BP to Top of Stack
  455.             ENDM
  456.  
  457. ; This macro must be used when the primitive must be exited and the
  458. ; primitive was SUCCESSFUL.  The resulting pointer or small integer
  459. ; must be in DX,AX (DX=segment, AX=offset) before invoking this macro. 
  460.  
  461. exitWithSuccess MACRO 
  462.  
  463. ; On entry DX,AX must contains the result to be pushed
  464. ; on the stack.
  465.             MOV     SP,BP                                                    
  466.             POP     BP              ;restore BP   
  467.             RETF                    ;far return
  468.             ENDM
  469.  
  470. ; This macro must be used when the primitive must be exited and the
  471. ; primitive FAILED. 
  472.  
  473. exitWithFailure MACRO  
  474.                    
  475.             XOR     AX,AX           ;AX=DX=0, for failure return
  476.             XOR     DX,DX              
  477.             MOV     SP,BP
  478.             POP     BP              ;restore BP
  479.             RETF                    ;far return
  480.             ENDM  
  481.                           
  482. ;Object testing macros 
  483. ;
  484. ;in the following testing macros,
  485. ;the result is returned in the zero flag as follows:  z=no,  nz=yes
  486.  
  487. ;Object has pointers?? jz=no, jnz=yes
  488. isPointerObject MACRO objSeg,objOff
  489.             TEST objSeg:[objOff+objectFlags],PointerBit
  490.             ENDM
  491.                      
  492. ;Object is indexable?? jz=no, jnz=yes
  493. isIndexedObject MACRO objSeg,objOff
  494.             TEST objSeg:[objOff+objectFlags],IndexedBit
  495.             ENDM
  496.  
  497. ;Object is contained in single segment?? jz=no, jnz=yes                    
  498. isSmallObject MACRO objSeg,objOff
  499.             OR  objOff,objOff
  500.             ENDM
  501.  
  502. ;**** size extraction macros **** 
  503.  
  504. ;Object size is expressable in elements or bytes.
  505. ;   elements is the number of smalltalk objects it contains
  506. ;   bytes is the number of bytes it occupies (including header)è;       note that objects always occupy an even number of bytes
  507. ;For example:
  508. ;   #( 1 2 3 ) is an array with three element≤ and it occupies 24 bytes
  509. ;   'hello'    is a string with 5 element≤ and it occupies 18 bytes 
  510.  
  511. ;extract the size in elements                        
  512. getElementSize MACRO objSeg,objOff,resultLowWord,resultHighByte
  513.             MOV resultHighByte,byte ptr objSeg:[objOff+objectSize+2]
  514.             MOV resultLowWord,word ptr objSeg:[objOff+objectSize]
  515.             ENDM           
  516.  
  517. ;compute the size in bytes
  518. getBigByteSize MACRO objSeg,objOff,resultLowWord,resultHighByte
  519.             LOCAL addHeader
  520.             getElementSize objSeg,objOff,resultLowWord,resultHighByte
  521.             isPointerObject objSeg,objOff
  522.             JZ  addHeader
  523.             ADD resultLowWord,resultLowWord
  524.             ADC resultHighByte,resultHighByte
  525.             ADD resultLowWord,resultLowWord
  526.             ADC resultHighByte,resultHighByte
  527. addHeader:  ADD resultLowWord,size objectHeader+1
  528.             ADC resultHighByte,0
  529.             AND resultLowWord,0FFFEH
  530.             ENDM  
  531.  
  532. ;user calls to interpreter routines 
  533.  
  534. ;routine vector offsets
  535. ISVqueueVMinterrupt equ 0FFF0H - 4
  536. queueVMInterrupt    equ ISVqueueVMinterrupt-4
  537. oldToNewStore       equ queueVMinterrupt-4      ;used in oldToNewUpdate macro
  538.  
  539. ;queue an interpreter interrupt (in protected mode)
  540. ;  AL=interrupt number to queue
  541. interruptVM MACRO 
  542.             CALL DWORD PTR SS:[queueVMinterrupt] 
  543.             ENDM
  544.  
  545. ;queue an interpreter interrupt (in real mode)
  546. ISVinterruptVM MACRO 
  547.             MOV ES,CS:[realParmSeg]  
  548.             CALL DWORD PTR ES:[ISVqueueVMinterrupt]
  549.             ENDM     
  550.              
  551. ;miscellaneous but usefull macros    
  552.  
  553. ;is object a small positive integer --  je=yes, jne=no
  554. ;(only segment needs to be tested) 
  555. isSmallPosInt MACRO segmentExpression
  556.         CMP segmentExpression,plusSmallSeg
  557.         ENDM
  558.               
  559. ;is object a small negative integer --  je=yes, jne=no
  560. ;(only segment needs to be tested)èisSmallNegInt MACRO segmentExpression
  561.         CMP segmentExpression,minusSmallSeg
  562.         ENDM   
  563.  
  564. ;is object a character --   je=yes, jne=no
  565. ;(only segment needs to be tested)
  566. isCharacter MACRO segmentExpression
  567.         CMP segmentExpression,characterSeg
  568.         ENDM   
  569.  
  570. ;is object static, i.e. constant, no stores allowed -- ja=no, jbe=yes
  571. ;(only segment needs to be tested)
  572. isStaticObject MACRO segmentExpression
  573.         CMP segmentExpression,characterSeg  
  574.         ENDM
  575.        
  576. ;****** This macro must be called after EVERY pointer store *******
  577. ;****** Failure to do so will invalidate the garbage collector ****
  578. ;****** leading to catastrophic and unpredicable results **********
  579.  
  580. ;This macro detects old space to new space pointer stores, 
  581. ;and updates the GC data base accordingly.  
  582. ;
  583. ;macro arguments are as follows:
  584. ;   segReg    = seg reg of object stored into
  585. ;   offReg    = offset reg of object stored into  
  586. ;   valueSeg  = segment of pointer that was stored  
  587. ;   workReg   = a work register 
  588. ;
  589. ;example of use:  store ptr BX:AX into object ES:DI at slot 'contents'
  590. ;           MOV word ptr es:[di+contents],AX    ;store offset
  591. ;           MOV word ptr es:[di+contents+2],BX  ;store segment
  592. ;           OldToNewUpdate es,di,bx,ax                
  593. OldToNewUpdate macro segReg,offReg,valueSeg,workReg
  594.             LOCAL done  
  595.             MOV workReg,segReg
  596.             CMP workReg,92EH
  597.             JAE done   
  598.             CMP valueSeg,92EH
  599.             JB  done     
  600.             PUSH segReg
  601.             PUSH offReg 
  602.             CALL DWORD PTR SS:[oldToNewStore] 
  603.             POP offReg
  604.             POP segReg  
  605. done:
  606.             ENDM  
  607.                                      
  608. ;****************************************************************************
  609. ; SOCKPRIM.ASM
  610. ;               The V286 Socket Primitives V2.0
  611. ;               In this implementation, recv() and accept() only operate in
  612. ;               a nonblocking fashion, returning errno EWOULDBLOCK if the
  613. ;               operation can not be completed immediately.  All other calls
  614. ;               block until completion or error.è;               Opcode 0 is implemented in this version as Socket closeAll.
  615. ;               Opcode 18 is implemented in this version as Socket version.
  616. ;               An additional non-standard errno EDRIVER (254) is returned if
  617. ;               installation fails or the installed driver behaves strangely.
  618. ;****************************************************************************
  619. ;
  620. TITLE Socket Primitives
  621. .286P
  622.             INCLUDE fixdptrs.usr 
  623.             INCLUDE objects.usr
  624.             INCLUDE access.usr
  625.  
  626.             INCLUDE sockprim.inc
  627.  
  628. code        SEGMENT PUBLIC 'CODE'
  629.             ASSUME CS:code,DS:nothing,ES:nothing  
  630.  
  631. PGROUP  GROUP   CODE
  632.  
  633. ;****************************************************************************
  634. ;               Smalltalk/V286 Reserved Area
  635. ;****************************************************************************
  636. ;
  637.             ORG 0
  638.             DW OFFSET install   ;installation routine entry point 
  639.  
  640.             DW 0                                ;reserved for future use
  641.             DW 0  
  642.  
  643.                         DW 0                    ;real mode segment of this code
  644.  
  645.             DW OFFSET primTable ;addr of table of primitives and entry points
  646.             DW 0                   ;real mode segment address of protected mode
  647.                                    ;parameter area
  648.  
  649.             DW 0                   ;cell used for real mode calls to VM
  650.             DW 0          
  651.  
  652. ;****************************************************************************
  653. ;               Local Data
  654. ;****************************************************************************
  655. ;
  656. initialized_flag        DW      0
  657. Socket_PB                       DB      32 DUP (0)
  658. Name_Buffer                     DB      MAX_NAME_SIZE DUP (0)
  659. Data_Buffer                     DB      MAX_BUFFER_SIZE DUP (0)
  660.  
  661. ;****************************************************************************
  662. ;               The socketPrimitive operation dispatcher
  663. ;****************************************************************************
  664. ;
  665. socketPrimitive    PROC   FAR                              
  666. ;
  667. ;   Dispatch the socket primitive specified by opcode.
  668. ;       PARAM(1) is the opcode
  669. ;       PARAM(2) is the argumentArrayè;
  670.             enterPrimitive
  671.             isSmallPosInt <WORD PTR [BP+arg1ptr+2]> ;opcode SmallInteger?
  672.             JE              ok_opcode
  673.             FAIL                                      ;FAIL if not
  674. ok_opcode:
  675.             MOV             AX,initialized_flag       ;perform initialization 
  676.             OR              AX,AX
  677.             JNE             initialized
  678.             PUSH    BP
  679.             CALL    socket_install
  680.             POP             BP
  681.             CMP             AX,0
  682.             JE              initialized
  683.             SUCCEED_ERROR
  684. initialized:
  685.              MOV             AX,     WORD PTR [BP+arg1ptr]   ;opcode
  686. ;
  687. ;       check opcode bounds
  688. ;
  689.                 CMP             AX,0
  690.                 JL              exit_FAIL
  691.                 CMP             AX,MAX_OPCODE
  692.                 JG              exit_FAIL
  693.                 SHL             AX,1
  694.                 MOV             SI,AX
  695. ;
  696. ;       dispatch operation
  697. ;
  698.                 MOV             AX,WORD PTR DS:[Socket_Primitives+SI]
  699.                 JMP             AX
  700.                 SUCCEED_POSITIVE_INTEGER
  701.  
  702. exit_FAIL:
  703.                 FAIL
  704.  
  705. socketPrimitive ENDP    
  706.  
  707. ;****************************************************************************
  708. ;       The socket event handler - called by resident driver in real mode
  709. ;****************************************************************************
  710. ;
  711. socket_event_handler    PROC    FAR
  712.                 MOV             AX,Network_VMInterrupt
  713.                 ISVinterruptVM
  714.                 RET
  715. socket_event_handler    ENDP
  716.  
  717. ;****************************************************************************
  718. ;               General purpose success exit
  719. ;               AX = integer value to be returned (positive or negative)
  720. ;****************************************************************************
  721. ;
  722. ;SUCCEED_INTEGER        PROC    NEAR
  723. ;               CMP             AX,0è;               JL              SUCCEED_NEGATIVE
  724. ;               SUCCEED_POSITIVE_INTEGER
  725. ;SUCCEED_NEGATIVE:
  726. ;               SUCCEED_NEGATIVE_INTEGER
  727. ;SUCCEED_INTEGER        ENDP
  728.  
  729. ;****************************************************************************
  730. ;               Install Socket Event Handler - called automatically by dispatch
  731. ;****************************************************************************
  732. ;
  733. socket_install  PROC    NEAR
  734.                 MOV             AX,1
  735.                 MOV             SI,OFFSET initialized_flag
  736.                 MOV             DS:[SI],AX
  737. ;
  738.                 SET_PB_FOR      OPCODE_register_event_handler
  739.                 MOV             WORD PTR DS:PB_Event_Handler[BX],OFFSET socket_event_handler
  740.                 MOV             AX,DS:[realCodeSeg]
  741.                 MOV             WORD PTR DS:PB_Event_Handler+2[BX],AX
  742. ;
  743.                 MOV             BYTE PTR DS:PB_errno[BX],EDRIVER
  744.                 MOV             WORD PTR DS:PB_Return_Code[BX],-1
  745. ;
  746.                 CALL_NETWORK
  747.                 RET
  748. socket_install  ENDP
  749.  
  750. ;****************************************************************************
  751. ;               The socket operations
  752. ;****************************************************************************
  753.  
  754. op_unimplemented        PROC    NEAR
  755.                 MOV             AX,EINVAL
  756.                 SET_errno
  757.                 SUCCEED_ERROR
  758. op_unimplemented        ENDP
  759.  
  760. op_closeAll                     PROC    NEAR
  761.                 SET_PB_FOR      OPCODE_socket_close_all
  762. ;
  763.                 CALL_NETWORK
  764.                 SUCCEED_INTEGER
  765. op_closeAll                     ENDP
  766.  
  767. ;****************************************************************************
  768. ;               deinstall() - perform required cleanup before Smalltalk/V exit
  769. ;****************************************************************************
  770. ;
  771. op_deinstall    PROC    NEAR
  772.                 MOV             AX,0
  773.                 MOV             SI,OFFSET initialized_flag
  774.                 MOV             DS:[SI],AX
  775. ;
  776.                 SET_PB_FOR      OPCODE_register_event_handler
  777.                 MOV             WORD PTR DS:PB_Event_Handler[BX],0è                MOV             WORD PTR DS:PB_Event_Handler+2[BX],0
  778. ;
  779.                 CALL_NETWORK
  780.                 SUCCEED_INTEGER
  781. op_deinstall    ENDP
  782.  
  783. ;****************************************************************************
  784. ;               socket()
  785. ;               ARG 1   Address_Format
  786. ;               ARG 2   Type
  787. ;               ARG 3   Protocol
  788. ;****************************************************************************
  789. ;
  790. op_socket                       PROC    NEAR
  791.                 SET_PB_FOR      OPCODE_socket
  792. ;
  793.                 GET_POSITIVE_INTEGER_ARG        1
  794.                 MOV             DS:PB_Address_Format[BX],AX
  795. ;
  796.                 GET_POSITIVE_INTEGER_ARG        2
  797.                 MOV             DS:PB_Type[BX],AX
  798. ;
  799.                 GET_POSITIVE_INTEGER_ARG        3
  800.                 MOV             DS:PB_Protocol[BX],AX
  801. ;
  802.                 CALL_NETWORK            ;sets errno, result in AX
  803.                 SUCCEED_INTEGER
  804. op_socket                       ENDP
  805.  
  806.                  * 
  807.                  *
  808.                  *
  809.  
  810. ;=================================================================
  811. ; doEthernetInt
  812. ;    This procedure executes in REAL MODE. The parameter block has
  813. ;    been filled. setup es:bx to point to the parameter block and
  814. ;    call the ethernet driver.
  815.  
  816. doEthernetInt   PROC    FAR
  817.         PUSH    AX                              ; Save registers
  818.         PUSH    BX                              ;
  819.         PUSH    ES                              ;
  820.         MOV             AX,CS                   ;  
  821.         MOV             ES,AX                   ; es points to this segment
  822.         MOV             BX, OFFSET Socket_PB    ; bx contains offset to pblock
  823.         INT             Resident_Driver_Interrupt       ; call driver
  824.         POP             ES                              ; restore registers
  825.         POP             BX                              ;
  826.         POP             AX                              ;
  827.         RET
  828. doEthernetInt   ENDP
  829.  
  830. ;table of primitive names and entry points
  831. primTable:è            DB  'socketPrimitive'          ;Smalltalk name of primitive
  832.             DB 0
  833.             DW offset socketPrimitive      ;offset of entry point 
  834. ;
  835. ;     more entries can go here     
  836.  
  837.             DW 0                           ;end of table   
  838.  
  839. ;installation routine, called at the time the module is loaded
  840. install     PROC FAR
  841.             ret                            ;we have nothing to do, so return
  842. install     endp  
  843.    
  844. code        ENDS
  845.             END  
  846.         
  847.