📄 barrier.asm
字号:
; BARRIER.ASM
;
; This sample program demonstrates how to use the Standard Library's
; semaphore objects to synchronize several processes at a barrier.
; This program is similar to the MULTIDOS.ASM program insofar as the
; background processes all print a set of strings. However, rather than
; using an inelegant delay loop to synchronize the foreground and background
; processes, this code uses barrier synchronization to achieve this.
.xlist
include stdlib.a
includelib stdlib.lib
.list
dseg segment para public 'data'
BarrierSemaph semaphore {0} ;Must init SemaCnt to zero.
DOSsmaph semaphore {}
; Macros to wait and release the DOS semaphore:
DOSWait macro
push es
push di
lesi DOSsmaph
WaitSemaph
pop di
pop es
endm
DOSRls macro
push es
push di
lesi DOSsmaph
RlsSemaph
pop di
pop es
endm
; Macro to synchronize on a barrier:
Barrier macro Wait4Cnt
local AllHere, AllDone
cmp es:[di].semaphore.SemaCnt, -(Wait4Cnt-1)
jle AllHere
WaitSemaph
cmp es:[di].semaphore.SemaCnt, 0
jge AllDone
AllHere: RlsSemaph
AllDone:
endm
; PCBs for our background processes:
BkgndPCB2 pcb {0,offset EndStk2, seg EndStk2}
BkgndPCB3 pcb {0,offset EndStk3, seg EndStk3}
; Data the foreground and background processes print:
StrPtrs1 dword str1_a, str1_b, str1_c, str1_d, str1_e, str1_f
dword str1_g, str1_h, str1_i, str1_j, str1_k, str1_l
dword 0
str1_a byte "Foreground: string 'a'",cr,lf,0
str1_b byte "Foreground: string 'b'",cr,lf,0
str1_c byte "Foreground: string 'c'",cr,lf,0
str1_d byte "Foreground: string 'd'",cr,lf,0
str1_e byte "Foreground: string 'e'",cr,lf,0
str1_f byte "Foreground: string 'f'",cr,lf,0
str1_g byte "Foreground: string 'g'",cr,lf,0
str1_h byte "Foreground: string 'h'",cr,lf,0
str1_i byte "Foreground: string 'i'",cr,lf,0
str1_j byte "Foreground: string 'j'",cr,lf,0
str1_k byte "Foreground: string 'k'",cr,lf,0
str1_l byte "Foreground: string 'l'",cr,lf,0
StrPtrs2 dword str2_a, str2_b, str2_c, str2_d, str2_e, str2_f
dword str2_g, str2_h, str2_i
dword 0
str2_a byte "Background 1: string 'a'",cr,lf,0
str2_b byte "Background 1: string 'b'",cr,lf,0
str2_c byte "Background 1: string 'c'",cr,lf,0
str2_d byte "Background 1: string 'd'",cr,lf,0
str2_e byte "Background 1: string 'e'",cr,lf,0
str2_f byte "Background 1: string 'f'",cr,lf,0
str2_g byte "Background 1: string 'g'",cr,lf,0
str2_h byte "Background 1: string 'h'",cr,lf,0
str2_i byte "Background 1: string 'i'",cr,lf,0
StrPtrs3 dword str3_a, str3_b, str3_c, str3_d, str3_e, str3_f
dword str3_g, str3_h, str3_i
dword 0
str3_a byte "Background 2: string 'j'",cr,lf,0
str3_b byte "Background 2: string 'k'",cr,lf,0
str3_c byte "Background 2: string 'l'",cr,lf,0
str3_d byte "Background 2: string 'm'",cr,lf,0
str3_e byte "Background 2: string 'n'",cr,lf,0
str3_f byte "Background 2: string 'o'",cr,lf,0
str3_g byte "Background 2: string 'p'",cr,lf,0
str3_h byte "Background 2: string 'q'",cr,lf,0
str3_i byte "Background 2: string 'r'",cr,lf,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
; This background processes call DOS to print several strings to the
; screen. In the meantime, the foreground process is also printing
; strings to the screen. To prevent reentry, or at least a jumble of
; characters on the screen, this code uses semaphores to protect the
; DOS calls. Therefore, each process will print one complete line
; then release the semaphore. If the other process is waiting it will
; print its line.
BackGround1 proc
mov ax, dseg
mov ds, ax
; Wait for everyone else to get ready:
lesi BarrierSemaph
barrier 3
; Okay, start printing the strings:
lea bx, StrPtrs2 ;Array of str ptrs.
PrintLoop: cmp word ptr [bx+2], 0 ;At end of pointers?
je BkGndDone
les di, [bx] ;Get string to print.
DOSWait
puts ;Calls DOS to print string.
DOSRls
add bx, 4 ;Point at next str ptr.
jmp PrintLoop
BkGndDone: die
BackGround1 endp
BackGround2 proc
mov ax, dseg
mov ds, ax
lesi BarrierSemaph
barrier 3
lea bx, StrPtrs3 ;Array of str ptrs.
PrintLoop: cmp word ptr [bx+2], 0 ;At end of pointers?
je BkGndDone
les di, [bx] ;Get string to print.
DOSWait
puts ;Calls DOS to print string.
DOSRls
add bx, 4 ;Point at next str ptr.
jmp PrintLoop
BkGndDone: die
BackGround2 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.
; Start the first background process:
lesi BkgndPCB2 ;Fire up a new process
fork
test ax, ax ;Parent's return?
je StartBG2
jmp BackGround1 ;Go do backgroun stuff.
; Start the second background process:
StartBG2: lesi BkgndPCB3 ;Fire up a new process
fork
test ax, ax ;Parent's return?
je ParentPrcs
jmp BackGround2 ;Go do backgroun stuff.
; The parent process will print a bunch of strings at the same time
; the background process is doing this. We'll use the DOS semaphore
; to protect the call to DOS that PUTS makes.
ParentPrcs: lesi BarrierSemaph
barrier 3
lea bx, StrPtrs1 ;Array of str ptrs.
PrintLoop: cmp word ptr [bx+2], 0 ;At end of pointers?
je ForeGndDone
les di, [bx] ;Get string to print.
DOSWait
puts ;Calls DOS to print string.
DOSRls
add bx, 4 ;Point at next str ptr.
jmp PrintLoop
ForeGndDone: prcsquit
Quit: ExitPgm ;DOS macro to quit program.
Main endp
cseg ends
sseg segment para stack 'stack'
; Here are the stacks for the background processes we start
stk2 byte 1024 dup (?)
EndStk2 word ?
stk3 byte 1024 dup (?)
EndStk3 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -