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

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

unix.superglobalmegacorp.com

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