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