Annotation of os2sdk/demos/apps/life/life2.asm, revision 1.1

1.1     ! root        1: ;***   life2.asm - assembler routines for life.c
        !             2: ;*
        !             3: ;*     Contains:       _draw_grid - draws 79x45 grid on screen
        !             4: ;*                     _dostep    - advances the internal and screen grids
        !             5: ;*                                      one generation
        !             6: ;*                     scrfill    - private screen routine for _dostep
        !             7: ;*                     scrremove  - private screen routine for _dostep
        !             8: ;*
        !             9: 
        !            10: 
        !            11: ;***   segment definitions for the link with C
        !            12: ;
        !            13: _TEXT  SEGMENT  BYTE PUBLIC 'CODE'
        !            14: _TEXT  ENDS
        !            15: _DATA  SEGMENT  WORD PUBLIC 'DATA'
        !            16: _DATA  ENDS
        !            17: CONST  SEGMENT  WORD PUBLIC 'CONST'
        !            18: CONST  ENDS
        !            19: _BSS   SEGMENT  WORD PUBLIC 'BSS'
        !            20: _BSS   ENDS
        !            21: DGROUP GROUP   CONST, _BSS, _DATA
        !            22:        ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
        !            23: 
        !            24: ;***   the public routines
        !            25: ;
        !            26:        PUBLIC  _draw_grid, _dostep
        !            27: 
        !            28: 
        !            29: ;***   Global variables from LIFE.C
        !            30: ;
        !            31:        EXTRN   _ScrSeg:WORD
        !            32:        EXTRN   _ScrCol:WORD
        !            33:        EXTRN   _ScrRow:WORD
        !            34: 
        !            35: ;***   OS/2 functions
        !            36: ;
        !            37:        EXTRN   VIOSCRUNLOCK:FAR
        !            38:        EXTRN   VIOSCRLOCK:FAR
        !            39: 
        !            40: 
        !            41: _TEXT     SEGMENT
        !            42: ;***   _draw_grid - clears screen and draws 79x45 grid
        !            43: ;*
        !            44: ;*     Entry:  ds:_ScrSeg - screen buffer segment, from life.c
        !            45: ;*
        !            46: ;*     Exit:   None
        !            47: ;*
        !            48: _draw_grid     PROC NEAR
        !            49:        push    bp                      ; startup
        !            50:        mov     bp,sp
        !            51:        sub     sp,2                    ; one word variable for VIOSCRLOCK
        !            52:        push    di                      ; save register used by C compiler
        !            53: 
        !            54: ;      get screen access
        !            55:        mov     ax,1
        !            56:        push    ax                      ; wait until screen available
        !            57:        lea     ax,byte ptr [bp-2]
        !            58:        push    ss
        !            59:        push    ax                      ; far address of return code
        !            60:        sub     ax,ax
        !            61:        push    ax                      ; reserved word
        !            62:        call    VIOSCRLOCK              ; call DOS for access
        !            63: 
        !            64: ;      get parameter and set up
        !            65:        mov     es,ds:_ScrSeg           ; (es) = screen buffer segment
        !            66:        xor     di,di                   ; (di) = offset in screen (start at 0)
        !            67: 
        !            68: ;      loop to draw 45 rows of the tops and middles of grid squares
        !            69:        mov     dx,45                   ; (dx) = rows of grid squares, counter
        !            70: dg1:   mov     ax,5555h                ; (ax) = alternating bit pattern
        !            71:        mov     cx,39                   ; (cx) = number of full words on a line
        !            72:        rep     stosw                   ; fill line with 5555h
        !            73:        mov     es:[di],al              ; finish off last odd byte
        !            74:        inc     di                      ; (di) = start of next row
        !            75:        inc     di
        !            76:        mov     ax,08080h               ; (ax) = left bit on
        !            77:        mov     cx,40                   ; (cx) = number of words on a line
        !            78:        rep     stosw                   ; fill next line with f0f0h
        !            79:        dec     dx                      ; at screen bottom?
        !            80:        jnz     dg1                     ; if no, loop
        !            81: 
        !            82: ;      draw the last line
        !            83:        mov     ax,5555h                ; (ax) = alternating bits
        !            84:        mov     cx,39                   ; (cx) = full words on last line
        !            85:        rep     stosw                   ; do fill
        !            86:        mov     es:[di],al              ; finish off line with odd byte
        !            87: 
        !            88: ;      clear bottom on screen on even bit plane
        !            89:        inc     di                      ; (di) = start of last few lines
        !            90:        sub     ax,ax                   ; (ax) = blank
        !            91:        mov     cx,400                  ; (cx) = words left at bottom
        !            92:        rep     stosw
        !            93: 
        !            94: ;      draw the grid lines on the odd bit plane
        !            95:        mov     di,2000h                ; (di) = top of odd bit plane
        !            96:        mov     ax,08080h               ; (ax) = left bit on
        !            97:        mov     cx,40*2*45              ; (cx) = words to fill
        !            98:        rep     stosw                   ; fill remainder with f0f0h
        !            99: 
        !           100: ;      clear bottom on screen on odd bit plane
        !           101:        sub     ax,ax                   ; (ax) = blank
        !           102:        mov     cx,400                  ; (cx) = words left at bottom
        !           103:        rep     stosw
        !           104: 
        !           105: ;      return the screen
        !           106:        sub     ax,ax
        !           107:        push    ax                      ; reserved word
        !           108:        call    VIOSCRUNLOCK            ; call DOS to return screen
        !           109: 
        !           110: ;      return
        !           111:        pop     di
        !           112:        mov     sp,bp
        !           113:        pop     bp
        !           114:        ret
        !           115: _draw_grid     ENDP
        !           116: 
        !           117: 
        !           118: ;***   _dostep - advances InGrid one generation.
        !           119: ;*
        !           120: ;*     Entry:  char far *INGRID - InGrid, main internal bit map of cells
        !           121: ;*             char far *INGRID2 - InGrid2, working area of same size
        !           122: ;*             unsigned INROW - InRow, bits per row of above to areas
        !           123: ;*             unsigned INCOL - InCol, rows of above to areas
        !           124: ;*             ds:_ScrSeg       - from life.c
        !           125: ;*             ds:_ScrRow       - from life.c
        !           126: ;*             ds:_ScrCol       - from life.c
        !           127: ;*
        !           128: ;*     Exit:   InGrid is updated on generation in accordance with
        !           129: ;*             the rules of life.
        !           130: ;*             Returns in AX the return code from its VIOSCRLOCK call
        !           131: ;*
        !           132: INGRID EQU [bp+4]
        !           133: INGRID2 EQU [bp+8]
        !           134: INROW EQU [bp+12]
        !           135: INCOL EQU [bp+14]
        !           136: 
        !           137: _dostep PROC   NEAR
        !           138:        push    bp
        !           139:        mov     bp,sp
        !           140:        sub     sp,2                    ; make room for local var
        !           141:        push    di
        !           142:        push    si
        !           143:        push    es
        !           144:        push    ds
        !           145: 
        !           146:        ; try to lock screen and put return code in [BP-2]
        !           147:        xor     ax,ax
        !           148:        push    ax                      ; don't wait until screen available
        !           149:        lea     ax,byte ptr [bp-2]
        !           150:        push    ss
        !           151:        push    ax                      ; far address of return code
        !           152:        sub     ax,ax
        !           153:        push    ax                      ; reserved word
        !           154:        call    VIOSCRLOCK              ; call DOS for access
        !           155: 
        !           156:        ; get pointers to the two internal grids
        !           157:        les     di,INGRID2               ; (es:di) = @InGrid2
        !           158:        lds     si,INGRID               ; (ds:si) = @InGrid
        !           159: 
        !           160:        ; copy InGrid into InGrid2
        !           161:        mov     ax,INCOL              ; (ax) = cells per row
        !           162:        mul     word ptr INROW        ; (ax) = total cells
        !           163:        mov     cl,4
        !           164:        shr     ax,cl                   ; (ax) = cell/16 = total words
        !           165:        mov     cx,ax                   ; (cx) = total words
        !           166:        rep     movsw                   ; move InGrid into InGrid2
        !           167: 
        !           168: 
        !           169:        ; main step loop
        !           170:        ;   I use a rather odd algorithm.  "neighbors" is defined
        !           171:        ;   here as all cells in a 3x3 grid summed.  If neighbors < 3, the
        !           172:        ;   the cell in the center is turned off.  If neighbors = 3, the cell
        !           173:        ;   is turned on.  If neighbors = 4, the cell is left in its current
        !           174:        ;   state.  If neighbors > 4, the cell is turned off.
        !           175:        push    ds
        !           176:        pop     es                      ; (es) = InGrid's segment
        !           177:        lds     bx,INGRID2               ; (ds) = InGrid2's segment
        !           178:                                        ; (bx) = pointer to offset in both
        !           179:        mov     di,INROW              ; (di) = row count
        !           180:        mov     si,INCOL              ; (si) = column count
        !           181:        shr     si,1
        !           182:        shr     si,1
        !           183:        shr     si,1                    ; (si) = bytes per row in grids
        !           184: 
        !           185:        ; loop within the grid through all its rows
        !           186:        ;    here we come when at the start of a row
        !           187: ds1:   mov     cx,INCOL              ; (cx) = column count
        !           188:        mov     al,80h                  ; (al) = bit mask for current bit
        !           189:        xor     dx,dx                   ; (dh) = #of neighbors 1 col back
        !           190:                                        ; (dl) = #of neighbors at cur col
        !           191: 
        !           192:        ; get number of neighbors on current row
        !           193: ds2:   xor     ah,ah                   ; (ah) = count of neighbors on cur row
        !           194:        test    ds:[bx],al              ; is current bit on?
        !           195:        jz      ds3                     ; if not go on
        !           196:        inc     ah                      ; if yes, inc neighbor count
        !           197: ds3:   cmp     bx,si                   ; are we on top row
        !           198:        jb      ds4                     ; if yes, don't check above top
        !           199:        push    bx                      ; save bx
        !           200:        sub     bx,si                   ; backup bx to previous row
        !           201:        test    ds:[bx],al              ; is up a row bit on?
        !           202:        pop     bx                      ; restore bx
        !           203:        jz      ds4                     ; if not go on
        !           204:        inc     ah                      ; if yes, inc neighbor count
        !           205: ds4:   cmp     di,1                    ; are we on last row?
        !           206:        jz      ds5                     ; if yes, don't read off edge
        !           207:        test    ds:[bx+si],al           ; is bit down a row on?
        !           208:        jz      ds5                     ; if not, go on to final neighbor addin
        !           209:        inc     ah                      ; if yes, inc neighbor count
        !           210: 
        !           211:        ; add up the total number of neighbors and decide what to do
        !           212: ds5:   cmp     cx,INCOL                ; are we at far left?
        !           213:        jz      ds12                    ; if yes, don't affect bits off edge
        !           214:        add     dh,dl                   ; (dh) = previous two rows of neighbors
        !           215:        add     dh,ah                   ; (dh) = total neighbor count
        !           216:        cmp     dh,3
        !           217:        jb      ds6                     ; if neighbors <3, turn off the cell
        !           218:        je      ds9                     ; if neighbors = 3, turn on the cell
        !           219:        cmp     dh,4                    ;
        !           220:        je      ds12                    ; if neighbors = 4, do nothing
        !           221: 
        !           222:        ; turn off the center bit
        !           223: ds6:   rol     al,1                    ; backup to center bit
        !           224:        jnc     ds7                     ; if no overflow, go on
        !           225:        dec     bx                      ; else, backup to last byte
        !           226: ds7:   test    es:[bx],al              ; is it already off
        !           227:        jz      ds8                     ; if yes, don't do it again
        !           228:        not     al                      ; turn on all bits but one to blank
        !           229:        and     es:[bx],al              ; force off bit in InGrid
        !           230:        not     al                      ; restore al
        !           231: 
        !           232:        pop     ds                      ; (ds) =  C's data ptr
        !           233:        call    scrremove               ; turn off on screen
        !           234:        push    ds                      ; resave C's data ptr
        !           235:        mov     ds,[bp+8+2]             ; (ds) = seg of InGrid2
        !           236: 
        !           237: ds8:   ror     al,1                    ; put back al to foreward bit
        !           238:        jnc     ds12                    ; if no overflow, go to next bit
        !           239:        inc     bx                      ; if overflow, restore bx
        !           240:        jmp     ds12                    ; go on to next bitl
        !           241: 
        !           242:        ; turn on the center bit
        !           243: ds9:   rol     al,1                    ; backup to center bit
        !           244:        jnc     ds10                    ; if no overflow, go on
        !           245:        dec     bx                      ; else, backup to last byte
        !           246: ds10:  test    es:[bx],al              ; is it already on?
        !           247:        jnz     ds11                    ; if yes, don't do it again
        !           248:        or      es:[bx],al              ; force on bit in InGrid
        !           249:        pop     ds                      ; (ds) =  C's data ptr
        !           250:        call    scrfill                 ; turn on on screen
        !           251:        push    ds                      ; resave C's data ptr
        !           252:        mov     ds,[bp+8+2]             ; (ds) = seg of InGrid2
        !           253: ds11:  ror     al,1                    ; put back al to foreward bit
        !           254:        jnc     ds12                    ; if no overflow, go to next bit
        !           255:        inc     bx                      ; if overflow, restore bx
        !           256: 
        !           257:        ; advance to the next bit
        !           258: ds12:  ror     al,1                    ; (al) mask advances to next bit
        !           259:        mov     dh,dl                   ; move done neighbor count
        !           260:        mov     dl,ah                   ; move the new neighbor row into bl
        !           261:        jnc     ds13                    ; if still in same byte, jmp
        !           262:        inc     bx                      ; if at byte end, advance to next byte
        !           263: ds13:  loop    ds2                     ; loop through rest of bits on line
        !           264: 
        !           265: 
        !           266:        ; at the end of the row
        !           267:        dec     di                      ; decrement row count
        !           268:        jz      dsx                     ; if at end of grid, goto exit routine
        !           269:        jmp     ds1                     ; if not at bottom, go to next row
        !           270: 
        !           271:        ; at the end of the grid
        !           272:        ; return the screen
        !           273: dsx:   cmp     byte ptr [bp-2],0       ; is the screen locked?
        !           274:        jnz     dsx1                    ; if not, don't unlock
        !           275: 
        !           276:        sub     ax,ax
        !           277:        push    ax                      ; reserved word
        !           278:        call    VIOSCRUNLOCK            ; call DOS to return screen
        !           279: 
        !           280: dsx1:  xor     ah,ah
        !           281:        mov     al,[bp-2]               ; return code from SCRLOCK
        !           282: 
        !           283:        pop     ds
        !           284:        pop     es
        !           285:        pop     si
        !           286:        pop     di
        !           287:        mov     sp,bp
        !           288:        pop     bp
        !           289:        ret
        !           290: _dostep ENDP
        !           291: 
        !           292: 
        !           293: ;***   scrfill - fills in a cell on the screen in 79x45 grid
        !           294: ;*
        !           295: ;*     Entry:  (di) = row number counted from bottom up (InRow-di=row to fill)
        !           296: ;*             (cx) = col number from right-1 (InCol-1-cx = col to fill)
        !           297: ;*             (ds) = data segment of life.c
        !           298: ;*
        !           299: ;*     Exit:   None, saves all registers
        !           300: ;*
        !           301: scrfill proc   near
        !           302:        cmp     [bp-2],byte ptr 0       ; is the screen available?
        !           303:        jnz     sfxx                    ; if not, exit
        !           304: 
        !           305:        push    es
        !           306:        push    ax
        !           307:        push    bx
        !           308:        push    dx
        !           309: 
        !           310:        ; get screen pointer
        !           311:        mov     es,ds:_ScrSeg           ; (es) = screen buf segment
        !           312:        mov     ax,INROW
        !           313:        sub     ax,di                   ; (ax) = row
        !           314:        cmp     ax,ds:_ScrRow           ; is it on the screen?
        !           315:        jae     sfx                     ; if off, exit
        !           316:        mul     WORD PTR INCOL          ;        * InCol
        !           317:        shl     ax,1                    ;        * 2
        !           318:        mov     dx,INCOL
        !           319:        sub     dx,cx
        !           320:        dec     dx                      ;               (dx) = col to fill
        !           321:        cmp     dx,ds:_ScrCol           ; is it on the screen?
        !           322:        jae     sfx                     ; if off, exit
        !           323:        add     ax,dx                   ;        + col = scrn offset of cell
        !           324: 
        !           325:        ; fill in screen cell
        !           326:        mov     bx,ax                   ; (es:bx) = far ptr to screen cell
        !           327:        mov     BYTE PTR es:[bx+2000h],7fh      ; first line of cell
        !           328:        mov     BYTE PTR es:[bx+80],7fh         ; second
        !           329:        mov     BYTE PTR es:[bx+2000h+80],7fh   ; third line of cell
        !           330: 
        !           331: sfx:   pop     dx
        !           332:        pop     bx
        !           333:        pop     ax
        !           334:        pop     es
        !           335: sfxx:  ret
        !           336: scrfill endp
        !           337: 
        !           338: 
        !           339: ;***   scrremove - removes a cell on the screen in 79x45 grid
        !           340: ;*
        !           341: ;*     Entry:  (di) = row number counted from bottom up (InRow-di=row to fill)
        !           342: ;*             (cx) = col number from right-1 (InCol-1-cx = col to fill)
        !           343: ;*             (ds) = data segment of life.c
        !           344: ;*
        !           345: ;*     Exit:   None, saves all registers
        !           346: ;*
        !           347: scrremove proc  near
        !           348:        cmp     [bp-2],byte ptr 0       ; is the screen available?
        !           349:        jnz     srxx                    ; if not, exit
        !           350: 
        !           351:        push    es
        !           352:        push    ax
        !           353:        push    bx
        !           354:        push    dx
        !           355: 
        !           356:        ; get screen pointer
        !           357:        mov     es,ds:_ScrSeg           ; (es) = screen buf segment
        !           358:        mov     ax,INROW
        !           359:        sub     ax,di                   ; (ax) = row
        !           360:        cmp     ax,ds:_ScrRow           ; is it on the screen?
        !           361:        jae     srx                     ; if off, exit
        !           362:        mul     WORD PTR INCOL          ;        * InCol
        !           363:        shl     ax,1                    ;        * 2
        !           364:        mov     dx,INCOL
        !           365:        sub     dx,cx
        !           366:        dec     dx                      ;               (dx) = col
        !           367:        cmp     dx,ds:_ScrCol           ; is it on the screen?
        !           368:        jae     srx                     ; if off, exit
        !           369:        add     ax,dx                   ;        + col = scrn offset of cell
        !           370: 
        !           371:        ; remove screen cell
        !           372:        mov     bx,ax                   ; (es:bx) = far ptr to screen cell
        !           373:        mov     BYTE PTR es:[bx+2000h],80h      ; first line of cell
        !           374:        mov     BYTE PTR es:[bx+80],80h         ; second
        !           375:        mov     BYTE PTR es:[bx+2000h+80],80h   ; third line of cell
        !           376: 
        !           377: srx:   pop     dx
        !           378:        pop     bx
        !           379:        pop     ax
        !           380:        pop     es
        !           381: srxx:  ret
        !           382: scrremove endp
        !           383: 
        !           384: _TEXT  ENDS
        !           385: END

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.