The Art of
ASSEMBLY LANGUAGE PROGRAMMING

Chapter Nineteen (Part 10)

Table of Content

Chapter Nineteen (Part 12)

CHAPTER NINETEEN:
PROCESSES COROUTINES AND CONCURRENCY (Part 11)
19.4.4 - A Sample Program with Threads

19.4.4 A Sample Program with Threads

The following program provides a simple demonstration of the Standard Library processes package. This short program creates two threads - the main program and a timer process. On each timer tick the background (timer) process kicks in and increments a memory variable. It then yields the CPU back to the main program. On the next timer tick control returns to the background process and this cycle repeats. The main program reads a string from the user while the background process is counting off timer ticks. When the user finishes the line by pressing the enter key the main program kills the background process and then prints the amount of time necessary to enter the line of text.

Of course this isn't the most efficient way to time how long it takes someone to enter a line of text but it does provide an example of the multitasking features of the Standard Library. This short program segment demonstrates all the process routines except die. Note that it also demonstrates the fact that you must supply int 23h and int 24h handlers when using the process package.

; Simple program to demonstrate the use of multitasking.


.xlist
include         stdlib.a
includelib      stdlib.lib
.list


dseg            segment para public 'data'

ChildPID        word    0
BackGndCnt      word    0

; PCB for our background process:

BkgndPCB        pcb     {0
offset EndStk2
seg EndStk2}

; Data buffer to hold an input string.

InputLine       byte    128 dup (0)

dseg            ends

cseg            segment para public 'code'
assume  cs:cseg
ds:dseg

; A replacement critical error handler.  This routine calls prcsquit
; if the user decides to abort the program.


CritErrMsg      byte    cr
lf
byte    "DOS Critical Error!"
cr
lf
byte    "A)bort
R)etry
I)gnore
F)ail? $"

MyInt24         proc    far
push    dx
push    ds
push    ax

push    cs
pop     ds
Int24Lp:        lea     dx
CritErrMsg
mov     ah
9                   ;DOS print string call.
int     21h

mov     ah
1                   ;DOS read character call.
int     21h
and     al
5Fh                 ;Convert l.c. -> u.c.

cmp     al
'I'                 ;Ignore?
jne     NotIgnore
pop     ax
mov     al
0
jmp     Quit24

NotIgnore:      cmp     al
'r'                 ;Retry?
jne     NotRetry
pop     ax
mov     al
1
jmp     Quit24

NotRetry:       cmp     al
'A'                 ;Abort?
jne     NotAbort
prcsquit                        ;If quitting
fix INT 8.
pop     ax
mov     al
2
jmp     Quit24

NotAbort:       cmp     al
'F'
jne     BadChar
pop     ax
mov     al
3
Quit24:         pop     ds
pop     dx
iret

BadChar:        mov     ah
2
mov     dl
7                   ;Bell character
jmp     Int24Lp
MyInt24         endp



; We will simply disable INT 23h (the break exception).

MyInt23         proc    far
iret
MyInt23         endp



; Okay
this is a pretty weak background process
but it does demonstrate
; how to use the Standard Library calls.

BackGround      proc
sti
mov     ax
dseg
mov     ds
ax
inc     BackGndCnt              ;Bump call Counter by one.
yield                           ;Give CPU back to foregnd.
jmp     BackGround
BackGround      endp


Main            proc
mov     ax
dseg
mov     ds
ax
mov     es
ax
meminit


; Initialize the INT 23h and INT 24h exception handler vectors.

mov     ax
0
mov     es
ax
mov     word ptr es:[24h*4]
offset MyInt24
mov     es:[24h*4 + 2]
cs
mov     word ptr es:[23h*4]
offset MyInt23
mov     es:[23h*4 + 2]
cs

prcsinit                ;Start multitasking system.

lesi    BkgndPCB        ;Fire up a new process
fork
test    ax
ax          ;Parent's return?
je      ParentPrcs
jmp     BackGround      ;Go do backgroun stuff.

ParentPrcs:     mov     ChildPID
bx    ;Save child process ID.

print
byte    "I am timing you while you enter a string. So type"
byte    cr
lf
byte    "quickly: "
0

lesi    InputLine
gets

mov     ax
ChildPID    ;Stop the child from running.
kill

printf
byte    "While entering '%s' you took %d clock ticks"
byte    cr
lf
0
dword   InputLine
BackGndCnt

prcsquit

Quit:           ExitPgm                 ;DOS macro to quit program.
Main            endp

cseg            ends

sseg            segment para stack 'stack'

; Here is the stack for the background process we start

stk2            byte    256 dup (?)
EndStk2         word    ?

;Here's the stack for the main program/foreground process.

stk             byte    1024 dup (?)
sseg            ends

zzzzzzseg       segment para public 'zzzzzz'
LastBytes       db      16 dup (?)
zzzzzzseg       ends
end     Main

Chapter Nineteen (Part 10)

Table of Content

Chapter Nineteen (Part 12)

Chapter Nineteen: Processes Coroutines and Concurrency (Part 11)
29 SEP 1996