home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
CEXPRESS.ZIP
/
TURBOBUG.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-09-16
|
23KB
|
441 lines
cseg segment
org 100h
assume cs:cseg, ds:cseg
buffer equ 0B000h ;address of video buffer (presently monochrome)
int_num equ 80h ;1st INT of consecutive series of five
begin: jmp set_up
tag1 db 'S T A',26,'C K '
tag2 db ' VAR',26
bottom db ' AX BX CX DX SI DI BP SP DS ES '
msg db 'TURBOBUG loaded',0AH,0DH,'$'
;---NOTE: no provision for retrace synchronization -- causes a blizzard on CGA
;---ROUTINE THAT DRAWS THE STACK BEGINS HERE:
stack: sti ;enable interrupts
pushf ;save flags
push ds ;save all changed registers
push es ;
push di ;
push si ;
push ax ;
push bx ;
push cx ;
push dx ;
push cs ;to get at variables (above) place
pop ds ; code segment value in DS
mov ax,buffer ;point ES to video buffer
mov es,ax ;
cld ;set direction flag
;---DRAW "STACK" LABEL ON TOP LEFT OF SCREEN:
mov ah,112 ;use reverse image
lea si,tag1 ;point to the data string
mov cx,5 ;extends over five rows
mov di,0 ;ES:DI points to top left of screen
L1: lodsb ;get a character
stosw ;write it, with attribute
lodsb ;get next character
stosw ;write it to the right of the former
add di,156 ;point to next row
loop L1 ;repeat
;---WRITE OUT THE STACK CONTENTS AND HEX EQUIVALENTS:
mov cx,78 ;78 columns available
mov di,324 ;point to 3rd col from left on 3rd row
push bp ;will use BP as stack pointer
mov bp,0FFFFH ;point to top of stack
L2: mov ah,112 ;drawn in reverse image
mov al,[bp] ;get a byte from the stack
dec bp ;point to byte below for next time
stosw ;write the byte in reverse image
sub ah,ah ;byte in AL, clear AH
shl ax,1 ;move top half of byte into AH
shl ax,1 ;
shl ax,1 ;
shl ax,1 ;
shr al,1 ;move bottom half back to bottom of AL
shr al,1 ;
shr al,1 ;
shr al,1 ;
cmp al,9 ;low nibble first: is it a numeral?
jb L3 ;if so, jump ahead
add al,55 ;else is A - F, add 55 to get ASCII code
jmp short L4 ;go write it
L3: add al,48 ;add 48 to get ASCII code for numeral
L4: mov es:[di+318],al ;write it
cmp ah,9 ;high nibble next: is it a numeral?
jb L5 ;repeat same process as above
add ah,55 ;
jmp short L6 ;
L5: add ah,48 ;
L6: mov es:[di+158],ah ;
loop L2 ;
pop bp ;restore BP
;---PLOT BP POSITION:
mov ax,bp ;BP value to AX
neg ax ;NEG gives distance from top of stack
mov bh,0 ;BH=0 flags that no scale drawn to right of BP
mov dl,100 ;divide distance by 100
div dl ;
cmp al,0 ;less than 100?
ja L8 ;if not, no BP label is written
cmp ah,78 ;less than or equal to 78? (available space)
ja L8 ;if not, no label
je L7 ;BP on last col, don't set flag for right scale
mov bh,1 ;no jump, flag that chars later drawn to right
;---WRITE "BP" IF BP IS ON THE SCALE:
L7: push ax ;save distance to BP
shl ah,1 ;double it to calculate video buffer position
inc ah ;plus two more, since offsets are from BP=0
inc ah ;
mov al,ah ;transfer value to AL
sub ah,ah ;extend through AX
mov di,ax ;add value to buffer pointer
mov ah,112 ;use reverse image
mov al,'B' ;prepare to write the 'B'
stosw ;write it
add di,158 ;shift to character cell below
mov al,'P' ;prepare to write the 'P'
stosw ;write it
pop ax ;restore distance to BP
;---CALCULATE AND WRITE SCALE FROM LEFT UP TO BP:
sub cx,cx ;clear cx for counter
mov cl,ah ;distance to BP
dec cl ;minus 1 = number of chars to write
mov ax,cx ;copy in AX
push ax ;use later to calc chars to right
jmp short L9 ;go make the division
;---CASE WHERE BP IS OFF THE SCALE:
L8: mov bh,0 ;flag that no chars to right
mov cx,78 ;BP off scale, write 78 chars
mov al,ah ;move to AL the distance to BP
dec al ;minus 1 to adjust for offset from 0
sub ah,ah ;extend through AX
push ax ;pseudo-PUSH, since other cases use it
;---WRITE SCALE TO LEFT OF BP:
L9: mov di,164 ;pointer to first char
mov dl,10 ;will divide by 10 for top line of scale
div dl ;now ten's place in AL, one's place in AH
add ah,48 ;add 48 to get the ASCII char equivalent
inc ah ;INC to compensate for first DEC below
add al,48 ;add 48 to get ASCII char equivalent
L10: dec ah ;in loop, decrement 1's place digit
cmp ah,'0' ;gotten to 0?
ja L12 ;if not, no 10's place printed, jump ahead
jb L11 ;if below '0', reset to '9'
mov es:[di-160],al ;1's place is '0', so print 10's place char
dec al ;decrement tens counter
cmp al,'0' ;below '0'yet?
jae L12 ;if not, jump ahead
mov al,'9' ;else, reset to '9'
jmp short L12 ;jump ahead
L11: mov ah,'9' ;this line used when 1's place is reset
L12: mov es:[di],ah ;print 1's place digit
inc di ;point 2 bytes ahead in the video buffer
inc di ;
loop L10 ;go do next char(s) of the scale
;---DRAW SCALE TO RIGHT OF BP (IF REQUIRED):
pop ax ;number chars to left
cmp bh,0 ;test flag whether any chars
je L16 ;if not, jump ahead and quit
mov cx,77 ;max number of chars to draw (78 - 1 for bp)
sub cx,ax ;subtract number chars drawn on left
add ax,5 ;adjust for extra chars on left
shl ax,1 ;double the number for video buffer position
mov di,156 ;start of line position in buffer
add di,ax ;add the offset
mov al,'1' ;start counting from 1
mov ah,al ;ten's place also starts from 1
L13: mov es:[di],al ;loop: write a 1's place character
inc di ;point to next buffer position
inc di ;
cmp al,'0' ;test whether 1's place has gotten to 0
jne L14 ;if not, jump ahead
mov es:[di-162],ah ;if so, write a ten's place character
inc ah ;inc ten's place counter
L14: inc al ;inc one's place counter
cmp al,':' ;test if one's place has surpassed '9'
jb L15 ;if not, jump ahead
mov al,'0' ;else, reset one's place counter to '0'
L15: loop L13 ;go write next character(s)
L16: pop dx ;done!
pop cx ;
pop bx ;
pop ax ;
pop si ;
pop di ;
pop es ;
pop ds ;
popf ;restore flags
iret ;return from the DISPLAY STACK interrupt
;-------------------------Display Memory Variable---------------------------
;---ON ENTRY, bx HOLDS OFFSET FROM bp OF VAR ADDRESS ON STACK
;---THE CALLING CODE MUST SAVE PRIOR CONTENTS OF bx IF THEY ARE REQUIRED
var: sti ;enable hardware interrupts
pushf ;save flags
push ds ;save all changed registers
push es ;
push ax ;
push cx ;
push di ;
push si ;
cld ;set direction flag
;---WRITE THE 'VAR' LABEL:
push cs ;set DS to CS value...
pop ds ;...in order to access TAG2
mov ax,buffer ;point ES to monochrome buffer
mov es,ax ;
mov di,800 ;point to 6th row of screen
lea si,tag2 ;DS:SI points to 'VAR' string
mov cx,6 ;these are six characters
mov ah,112 ;write them in reverse image
B1: lodsb ;get a character
stosw ;write it
loop B1 ;go do next
;---NOW WRITE OUT THE MEMORY CONTENTS:
mov cx,74 ;number of cols available on the line
add bx,bp ;add BP value to the offset from BP
mov ax,ss:[bx+2] ;get segment address of var
mov ds,ax ;place in DS
mov si,ss:[bx] ;place offset of var in SI
mov ah,15 ;write in intensified attribute
B2: lodsb ;get a char
stosw ;write it, setting the new attribute
loop B2 ;go do next char
pop si ;done! restore changed registers
pop di ;
pop cx ;
pop ax ;
pop es ;
pop ds ;
popf ;restore flags
iret ;return from the DISPLAY VARIABLE interrupt
;-------------------------Register Display Routine--------------------------
;---THIS PROCEDURE WRITES OUT AX CONTENTS AS CHARS AND IN HEX:
hexwrite proc near
push bx ;save changed registers
push ds ;
push ax ;point DS to BIOS data area
mov ax,40h ;
mov ds,ax ;
pop ax ;
mov bh,4 ;test if ctrl key down
test ds:[17h],bh ;
mov bx,ax ;copy input reg in case jump taken
jnz C2 ;go make hex write if ctrl down
cmp ah,es:[di-156] ;test if high char is same as before
jne C2 ;if not, go write hex equivalent
cmp ah,32 ;is it a space char?
jne C1 ;if not, will definitely not write in hex, jump
cmp es:[di-160],ah ;if spc, chk line above. Will be 32 if first
je C2 ; call on cleared screen, else FF from scroll
C1: add di,4 ;not writing in hex, set buffer pointer ahead
jmp short C7 ;jump ahead
;---WRITE THE HIGH BYTE IN HEX:
C2: shr ax,1 ;shift AH halfway down into AL
shr ax,1 ;
shr ax,1 ;
shr ax,1 ;
shr al,1 ;shift AL nibble rest of the way down
shr al,1 ;
shr al,1 ;
shr al,1 ;now high nibble in AH, low nibble in AL
cmp ah,9 ;is high nibble a numeral?
ja C3 ;if not, jump ahead
add ah,48 ;add 48 to make ASCII char
jmp short C4 ;jump ahead
C3: add ah,55 ;A - F, so add 55 to make ASCII char
C4: cmp al,9 ;repeat process for low nibble
ja C5 ; (not looped here and elsewhere
add al,48 ; for the sake of speed)
jmp short C6 ;
C5: add al,55 ;
C6: mov es:[di],ah ;write the high nibble
inc di ;move video buffer pointer to next col
inc di ;
stosb ;write the low nibble
inc di ;move pointer to next col
;---WRITE THE HIGH AND LOW CHARS IN REVERSE IMAGE:
C7: mov ah,112 ;code for reverse image
mov al,bh ;get copy of high char
stosw ;write it
mov al,bl ;get copy of low char
stosw ;write it
;---WRITE THE LOW BYTE IN HEX:
mov bh,4 ;100B tests ctrl key
test ds:[17h],bh ;chk BIOS variable whether ctrl key is down
mov ah,bl ;copy of low byte to AH now, before jump taken
jnz C9 ;if ctrl down, write the char in hex
cmp ah,es:[di-162] ;test is char is the same as prior one
jne C9 ;if not, write it in hex
cmp ah,32 ;spc char is special case, since clears screen
jne C8 ;if not spc, don't write hex equivalent
cmp es:[di-160],ah ;if a spc, chk if it is one from CLRSCR
je C9 ;if so, write out the hex code
C8: add di,8 ;don't write hex, adjust buffer pointer
jmp short C14 ;finished, go quit routine
C9: shr ax,1 ;write out the two hex digits as above
shr ax,1 ;
shr ax,1 ;
shr ax,1 ;
shr al,1 ;
shr al,1 ;
shr al,1 ;
shr al,1 ;
cmp ah,9 ;
ja C10 ;
add ah,48 ;
jmp short C11 ;
C10: add ah,55 ;
C11: cmp al,9 ;
ja C12 ;
add al,48 ;
jmp short C13 ;
C12: add al,55 ;
C13: mov es:[di],ah ;
inc di ;
inc di ;
stosb ;
add di,5 ;forward buffer pointer to next register pos
C14: pop ds ;restore changed registers
pop bx ;
ret ;quit
hexwrite endp
;---THE REGISTER DISPLAY PROCEDURE STARTS HERE:
regs: sti ;enable hardware interrupts
pushf ;save flags
cld ;set direction flag
push ax ;these three re-restored at end
push di ; since used in writing their own contents
push es ;
push es ;temporarily save ES and AX
push ax ; while checking Alt key
mov ax,40h ;point ES to BIOS data area
mov es,ax ;
mov ah,8 ;see if Alt key is down
test es:[17h],ah ;
pop ax ;restore ES and AX
pop es ;
jz D1 ;go ahead if Alt key not down
jmp D5 ;else, quit the routine
D1: push es ;push altered registers onto stack
push ds ; in the left-right order in which they
push di ; are displayed
push si ;
push cx ;
push bx ;
push ax ;
mov ax,buffer ;now point ES to the video buffer
mov es,ax ;
push cs ;set DS to CS to get at bottom-of-screen labels
pop ds ;
;---WRITE LABELS ON BOTTOM OF SCREEN:
mov di,3842 ;ES:DI points to buffer position
lea si,bottom ;DS:SI points to data string
mov cx,10 ;there are 10 labels
mov ah,112 ;will draw in reverse image
D2: lodsb ;get a byte
stosw ;write it with attribute
lodsb ;etc...
stosw ;
lodsb ;
stosw ;
lodsb ;
stosw ;
lodsb ;
stosw ;
lodsb ;
stosw ;
add di,4 ;forward pointer to next label
loop D2 ;go write next label
;---SCROLL THE 8TH - 24TH ROWS UPWARDS 1 LINE:
push es ;set DS to video buffer address
pop ds ;
mov di,960 ;di points to start of 7th row
mov si,1120 ;si points to start of 8th row
mov cx,1360 ;number of chars+attribute to transfer
rep movsw ;make the transfer
;---CLEAR 24TH ROW:
mov cx,80 ;chars to clear
mov ax,07FFH ;use FF as the 'space' char, 7 as the attribute
mov di,3680 ;DI points to start of the line
rep stosw ;clear it
;---DISPLAY THE REGISTERS:
mov di,3682 ;point DI to position of first register
pop ax ;momentarily restore AX contents
call hexwrite ;write AX
pop bx ;restore BX contents
mov ax,bx ;move copy to AX
call hexwrite ;write BX
pop cx ;restore CX contents
mov ax,cx ;move copy to AX
call hexwrite ;write CX
mov ax,dx ;DX unchanged, copy to AX
call hexwrite ;write DX
pop si ;restore SI contents
mov ax,si ;move copy to AX
call hexwrite ;write SI
pop ax ;DI in use, pop contents straight into AX
call hexwrite ;write DI
mov ax,bp ;BP unchanged, copy to AX
call hexwrite ;write BP
mov ax,sp ;SP unchanged
call hexwrite ;write SP
pop ds ;restore DS
mov ax,ds ;move copy to AX
call hexwrite ;write DS
pop ax ;ES in use, pop contents straight into AX
call hexwrite ;write ES
;---CHECK SHIFT KEYS:
mov ax,40h ;point ES back to BIOS data area
mov es,ax ;
D3: mov ah,8 ;1000B tests Alt key
test es:[17h],ah ;is Alt down?
jnz D5 ;if so, quit the routine
mov ax,0102h ;1B in AH, 10B in AL
test es:[17h],ah ;test right shift
jnz D5 ;no delay if right shift down
test es:[17h],al ;test left shift
jz D3 ;keep looping until shift or Alt key down
mov al,es:[6Ch] ;left shift down, read BIOS time-of-day
add al,4 ;wait 4/18ths sec (may change this value)
D4: cmp es:[6Ch],al ;read new time-of-day -- ready?
jne D4 ;keep looping until ready
D5: pop es ;done! restore registers used
pop di ; to display the register values
pop ax ;
popf ;
iret ;quit
;---------------------DRAW STACK PLUS REGISTERS---------------------------
all: int int_num ;call stack routine
int int_num+2 ;call register routine
iret ;done
;--------------------------SETUP CODE-------------------------------------
finish equ $ ;mark end of code for int 27h below
set_up: mov dx,offset stack ;point DX to start of STACK DISPLAY code
mov al,int_num ;assign it to the base vector
mov ah,25h ;DOS function to set interrupt vector
int 21h ;set the vector
mov dx,offset var ;point DX to start of DISPLAY VAR code
mov al,int_num+1 ;assign it to the base vector + 1
int 21h ;set the vector
mov dx,offset regs ;point DX to start of REGISTER DISPLAY code
mov al,int_num+2 ;assign it to the base vector + 2
int 21h ;set the vector
mov dx,offset all ;point DX to start of STACK PLUS REGS code
mov al,int_num+3 ;assign it to the base vector + 3
int 21h ;set the vector
mov ah,9 ;DOS function to write string
lea dx,msg ;DS:DX pts to load message
int 21h ;write the message
lea dx,finish ;point DX to end of all resident code
int 27h ;exit, leaving all resident except setup code
cseg ends
end begin