DATA SEGMENT PUBLIC 'DATA'
;
DATA ENDS
DGROUP GROUP DATA
CODE SEGMENT 'CODE'
ASSUME CS:CODE,DS:DGROUP,SS:DGROUP
;
PUBLIC TRACE
PUBLIC SSORT
PUBLIC RANDU
PUBLIC DELETE
PUBLIC RENAME
PUBLIC CPUON
;
trace proc far
push ds
mov ax,cs ;set DS /
mov ds,ax ;to local /
mov si,offset tr_msg1 ;point to message area
mov cl,4 ;bit counter for right-justify
mov dx,cs ;This segment
call bin2asc ;make ascii and copy
inc si ;skip ':'
mov dx,offset trace ;This offset
call bin2asc ;make ascii and copy
mov dx,offset tr_msg ;point to message
mov ah,09 ;select DOS function
int 21h ;call DOS
pop ds
ret ;end procedure
trace endp
;
tr_msg: db 13,10,'Assembler address:',13,10
tr_msg1: db 0,0,0,0,':',0,0,0,0,13,10,'$'
;
bin2asc proc near
mov al,dh ;get high byte
shr al,cl ;get high nibble
call mkasc ;make ascii
mov ds:[si],al ;put in message area
inc si ;point to next
mov al,dh ;get high byte
and al,0fh ;get low nibble
call mkasc ;make ascii
mov ds:[si],al ;put in message area
inc si ;point to next
mov al,dl ;get low byte
shr al,cl ;get high nibble
call mkasc ;make ascii
mov ds:[si],al ;put in message area
inc si ;point to next
mov al,dl ;get low byte
and al,0fh ;get low nibble
call mkasc ;make ascii
mov ds:[si],al ;put in message area
inc si ;point to next
ret ;end procedure
bin2asc endp
;
mkasc proc near
cmp al,10 ;see if less than 10
jnc ma1 ;jump if letter
add al,30h ;make a number
jmp ma2 ;jump to end
ma1: add al,55 ;make a letter
ma2: ret ;end process
mkasc endp
;
;
; THIS PROGRAM GENERATES UNIFORM RANDOM DEVIATES VIA
; AN 8086 PROCESSOR. ONE INPUT VARIABLE IS ASSUMED:
; THE SEED FOR THE GENERATOR
;
; ------
; | seed | +08
; | (ret) | +04
; | ds | +02
; | bp | +00
; ------
;
FF: db 0
Rl: dw 0
Rh: dw 0
;
ID1: db 32 dup('1') ;RANDU
randu proc far
push ds ;save segment pointer
push bp ;save base pointer
mov ax,cs ;change /
mov ds,ax ;data segment /
mov bp,sp ;point to stack
;
; If it is the first time:
; a) Make sure X0 is odd.
; b) Copy the initial Seed to the unformatted variable.
; c) Make the flag (i) equal to 1.
;
pas1: mov al,byte ptr FF ;get flag
or al,al ;see if first time over
jnz pas2 ;jump if not first time
inc al ;increment ax
mov byte ptr FF,al ;and put in memory
les bx,dword ptr[bp+8] ;Seed's initial address in es[bx]
mov ax,es:[bx] ;lsw seed
or ax,1 ;make odd seed
mov dx,es:[bx+2] ;msw seed
mov word ptr Rl,ax ;copy initial Seed value
mov word ptr Rh,dx ;to unformatted variable
;
; Make Xn+1=65539Xn
;
pas2: mov ax,word ptr Rl ;get
mov dx,word ptr Rh ;Unformatted variable
add ax,ax ; *2
adc dx,dx ;
add ax,word ptr Rl ; *3
adc dx,word ptr Rh ;
add dx,word ptr Rl ; *65539
mov word ptr Rl,ax ;replace value
mov word ptr Rh,dx ;of unformatted variable
;
; Subtract 0.5 and multiply by 2
;
mov cl,127 ;initialize xs127 counter
exp1: add ax,ax ;1st part of
adc dx,dx ;32 bit shift
dec cl ;decrement xs127 counter
jnc exp1 ;loop while not overflow
mov al,ah ;copy higher
mov ah,dl ;18 bits of
mov dl,dh ;dx&ax down
mov dh,cl ;set exponent
shr dx,1 ;normalize for sign
rcr ax,1 ;through dx & ax
les bx,dword ptr[bp+8] ;Seed's address in es[bx]
mov es:[bx],ax ;copy value of
mov es:[bx+2],dx ;Seed
pop bp ;restore bp
pop ds ;restore DS
ret 04h ;return & pop 4 bytes
randu endp
;
; RecSort(First, Size, Bit)
;
; PtrUp=First-1
; PtrDn=First+Size
; do while true
; do while true
; PtrUp=PtrUp+1
; if (PtrUp.eq.PtrDn) go to end_sweep
; if (Array(PtrUp).[Bit].eq.1) go to found_1
; enddo
;found_1 do while true
; PtrDn=PtrDn-1
; if (PtrDn.eq.PtrUp) go to end_sweep
; if (Array(PtrDn).[Bit].eq.0) go to found_0
; enddo
;found_0 swap=Array(PtrDn)
; Array(PtrDn)=Array(PtrUp)
; Array(PtrUp)=swap
; enddo
;end_sweep Nzeros=PtrUp-First
; Nones=Size-Nzeros
; if (Bit.eq.0) return
; if (Nzeros.gt.1) call RecSort(First,Nzeros,Bit-1)
; if (Nones.gt.1) call RecSort(First+Nzeros,Nones,Bit-1)
; return
; end
;
STACK_SEG DW 0
STACK_OFF DW 0
jSIZE DW 0
ARRAY_SEG DW 0
ARRAY_OFF DW 0
IARRAY_SEG DW 0
IARRAY_OFF DW 0
MAXI DW 0
;
; ------
; |Maximize| +24
; |Nelemnts| +20
; |ValueArr| +16
; |NdxArray| +12
; | (RET) | +08
; | SI | +06
; | DI | +04
; | BP | +02
; | DS | +00
; ------
;
ID2: db 32 dup('2') ;SSORT
SSORT PROC FAR
PUSH SI ;SAVE /
PUSH DI ;SPECIAL /
PUSH BP ;REG'S: /
PUSH DS ;SI, DI, BP, DS
MOV AX,CS ;**************
MOV DS,AX ;*** NEW DS ***
;**************
MOV STACK_SEG,SS ; STORE /
MOV STACK_OFF,SP ; SS:SP /
MOV BP,SP ;POINT TO STACK
LES BX,DWORD PTR [BP+24] ;MAXIMIZE FLAG
MOV AX,ES:[BX] ;GET VALUE
MOV MAXI,AX ;STORE IN MEMORY
LES BX,DWORD PTR [BP+20] ;SIZE OF ARRAY
MOV AX,ES:[BX] ;GET SIZE OF ARRAY
CMP AX,2 ;SORT IS NEEDED ?
JC L00 ;END IF NOT
CMP AX,16379 ;EXCEEDS LARGEST ?
JC L01 ;NO: JUMP
MOV DX,OFFSET MSG_ERR ;APUNTA AL MENSAJE
MOV AH,09H ;FUNCIàN DE DESPLIEGUE
INT 21H ;LLAMA A DOS
STC ;CF = 1
JMP L05
L00: JMP L04 ;FINAL DESTINATION JUMP
L01: MOV jSIZE,AX ;AND STORE IN SIZE
LES BX,DWORD PTR [BP+16] ;ADDRESS OF ARRAY
CALL AbsEsBx ;GET THE ABSOLUTE ADDRESS
MOV SI,OFFSET ARRAY_SEG ;POINT TO VARIABLE
MOV [SI],ES ;SEGMENT /
MOV [SI+2],BX ;AND OFFSET /
LES BX,DWORD PTR [BP+12] ;ADDRESS OF ARRAY INDEX
CALL AbsEsBx ;GET THE ABSOLUTE ADDRESS
MOV SI,OFFSET IARRAY_SEG ;POINT TO VARIABLE
MOV [SI],ES ;SEGMENT /
MOV [SI+2],BX ;AND OFFSET /
MOV AX,CS ;**************
MOV SS,AX ;*** NEW SS ***
;**************
MOV SP,OFFSET TOS ;AND NEW TOP OF STACK
;
; INITIALIZE IARRAY
; (ASSUME 2 BYTES/INDEX)
;
MOV ES,IARRAY_SEG ;GET SEGMENT OF INDEX ARRAY
MOV BX,IARRAY_OFF ;AND ITS OFFSET
MOV CX,jSIZE ;GET SIZE OF ARRAY
MOV AX,1 ;INITIAL VALUE
L02: MOV ES:[BX],AX ;STORE VALUE IN MEMORY
INC BX ;POINT TO NEXT
INC BX ;MEMORY LOCATION
INC AX ;INCREMENT COUNTER
LOOP L02 ;LOOP SIZE TIMES
CALL CHNG_SGN ;CHANGE SIGNS OF ALL ELEMENTS
L03: MOV AX,0 ;INITIAL OFFSET = 0
PUSH AX ;1ST PARAMETER IS BIT OFFSET
MOV AX,jSIZE ;INITIAL SIZE OF ARRAY
PUSH AX ;2ND PARAMETER IS SIZE OF BLOCK
MOV AX,MAXBIT*256 ;DH=MAXBIT & DL=0
PUSH AX ;3RD PARAMETER IS BIT TO TEST
CALL BINSORT ;CALL RECURSIVE SORT
CALL INVRT_NEGS ;SWAP ELEMENTS WITH POSITIVE SIGN
CALL CHNG_SGN ;CHANGE SIGNS OF ALL ELEMENTS
MOV AX,MAXI ;GET VALUE OF ASCEND/DESCEND
OR AX,AX ;SET FLAGS
JZ L04 ;JUMP IF NO NEED TO SWAP
CALL SWAP_ALL ;SWAP DATA
L04: CLC ;ALL IS OK
L05: MOV SS,STACK_SEG ;GET COMPILER'S STACK SEGMENT
MOV SP,STACK_OFF ;RESTORE SS:SP
POP DS ;RESTORE DS
POP BP ;RESTORE BP
POP DI ;RESTORE DI
POP SI ;RESTORE SI
JNC L06 ;CONTINUE IF OK
MOV AX,4C00H ;TERMINATE PROGRAM
INT 21H ;VIA DOS
L06: RET 10H ;RETURN & POP 16 BYTES
SSORT ENDP
;
MSG_ERR: DB 13,10,' Exceeded maximum array size (16380)'
DB 13,10,' *** End of Program ***',13,10,'$'
;
SWAP_ALL PROC NEAR
MOV AX,jSIZE ;GET SIZE OF ARRAY
CMP AX,2 ;SEE IF ONLY ONE WORD
JC SA2 ;JUMP IF ONE OR NO WORDS
MOV ES,ARRAY_SEG ;ES=ARRAY SEGMENT
MOV BX,ARRAY_OFF ;BX=ARRAY OFFSET
MOV SI,0 ;POINT TO FIRST WORD WITH SI
MOV DI,AX ;POINT TO LAST WORD /
DEC DI ;WITH DI /
SHR AX,1 ;DIVIDE COUNTER BY 2
MOV CX,AX ;MOVE COUNTER TO CX
SA1: PUSH CX ;STORE COUNTER IN STACK
CALL SWAP_INFO ;SWAP THE TWO EXTREME WORDS
INC SI ;INCREMENT UPWARD POINTER
DEC DI ;DECREMENT DOWNWARD POINTER
POP CX ;GET COUNTER FROM STACK
LOOP SA1 ;LOOP
SA2: RET ;END PROCEDURE
SWAP_ALL ENDP
;
; CHANGE SIGN
;
CHNG_SGN PROC NEAR
MOV CX,jSIZE ;GET SIZE OF ARRAY
MOV AL,80H ;SET MSB BIT FOR XOR
MOV DX,N_BYTES ;GET BYTES IN WORD
MOV BX,ARRAY_OFF ;BX=ARRAY OFFSET
ADD BX,N_BYTES-1 ;POINT TO MSB BYTE IN WORD
MOV ES,ARRAY_SEG ;ES=ARRAY SEGMENT
CS1: XOR ES:[BX],AL ;CHANGE MSB OF WORD
ADD BX,DX ;POINT TO MSB OF NEXT WORD
LOOP CS1 ;LOOP SIZE TIMES
RET ;END OF PROCEDURE
CHNG_SGN ENDP
;
INVRT_NEGS PROC NEAR
MOV CX,jSIZE ;GET SIZE OF ARRAY
MOV ES,ARRAY_SEG ;ES=ARRAY SEGMENT
MOV BX,ARRAY_OFF ;BX=ARRAY OFFSET
ADD BX,N_BYTES-1 ;POINT TO MSB BYTE OF WORD
MOV AX,0 ;INITIALIZE COUNTER
MOV SI,N_BYTES ;SI=SIZE OF WORD
IN0: MOV DL,ES:[BX] ;GET MSB BYTE OF WORD
SHL DL,1 ;MOVE MSB BIT TO CARRY
JC IN1 ;JUMP IF WE REACH FIRST POSITIVE WORD
INC AX ;INCREMENT COUNTER
ADD BX,SI ;POINT TO MSB OF NEXT WORD
LOOP IN0 ;LOOP
IN1: CMP AX,2 ;SEE IF ONLY ONE WORD
JC IN3 ;JUMP IF ONE OR NO NEGS
MOV SI,0 ;POINT TO FIRST WORD WITH SI
MOV DI,AX ;POINT TO LAST WORD /
DEC DI ;WITH DI /
SHR AX,1 ;DIVIDE COUNTER BY 2
MOV CX,AX ;MOVE COUNTER TO CX
IN2: PUSH CX ;STORE COUNTER IN STACK
CALL SWAP_INFO ;SWAP THE TWO EXTREME WORDS
INC SI ;INCREMENT UPWARD POINTER
DEC DI ;DECREMENT DOWNWARD POINTER
POP CX ;GET COUNTER FROM STACK
LOOP IN2 ;LOOP
IN3: RET ;END PROCEDURE
INVRT_NEGS ENDP
;
AbsEsBx PROC NEAR
push ax
push cx
push dx
MOV AX,ES ;STORE 'ES' IN/
MOV DX,0 ;DX & AX /
MOV CX,4 ;PREPARE SHIFT
L1: SHL AX,1 ;SHIFT INTO /
RCL DX,1 ;DX&AX /
LOOP L1 ; /
ADD AX,BX ;GET ABSOLUTE ADDRESS /
ADC DX,0 ; /
MOV BX,AX ;COPY LSB
AND BX,000FH ;RETAIN LOWEST NIBBLE
MOV CX,4 ;PREPARE SHIFT
L2: SHR DX,1 ;RIGHT SHIFT /
RCR AX,1 ;INTO AX /
LOOP L2 ; /
MOV ES,AX
pop dx
pop cx
pop ax
RET
AbsEsBx ENDP
;
MAXBIT EQU 31 ;MAXIMUM BIT IN WORD
LOG_NBYTES EQU 2 ;LOG2 OF BYTES IN WORD
N_BYTES EQU 4 ;BYTES IN WORD
;
IBIT DW 0 ;STORE FOR BIT IN THIS PASS OF SORT
ISIZE DW 0 ;STORE FOR SIZE IN THIS PASS OF SORT
IFIRST DW 0 ;STORE FOR FIRST ELEMENT IN THIS PASS
;
BINSORT PROC NEAR
POP BP ;RETURN ADDRESS
POP DX ;GET IBIT
MOV IBIT,DX ;AND STORE
POP DI ;GET ISIZE
MOV ISIZE,DI ;AND STORE
POP SI ;GET OFFSET
MOV IFIRST,SI ;AND STORE
PUSH BP ;RESTORE RETURN ADDRESS
;DH = IBIT & DL = 0
MOV CL,3 ;PREPARE SHIFT
SHR DX,CL ;DH = BYTE OFFSET
ROL DL,CL ;DL = BIT SHIFT /
INC DL ; COUNT /
MOV ES,ARRAY_SEG ;POINT TO ARRAY /
MOV BX,ARRAY_OFF ;WITH ES:[BX] /
MOV AH,0 ; /
MOV AL,DH ;AX=BYTE /
ADD BX,AX ;POINT TO BYTE TO TEST
PUSH BX ;(SP) = ARRAY_OFF.[BYTE]
ADD DI,SI ;PtrDn
DEC SI ;PtrUp
L10: INC SI ;PtrUp = * +1
CMP SI,DI ;PtrUp = PtrDn ?
JZ L50 ;JUMP IF POINTERS MEET
MOV CL,LOG_NBYTES ;LOAD TIMES TO SHIFT/ROTATE
MOV AX,SI ;AX=PtrUp
SHL AX,CL ;SHIFT LEFT LOG_NBYTES
POP BX ;GET ARRAY_OFF.[BYTE]
PUSH BX ;PUT IN STACK
ADD BX,AX ;ARRAY(PtrUp).[BYTE]
MOV AL,ES:[BX] ;GET BYTE IN WORD
MOV CL,DL ;# OF BITS TO SHIFT
SHR AL,CL ;GET BIT TO CARRY
JC L20 ;JUMP IF WORD TESTED IS POSITIVE
JMP L10 ;OR TRY NEXT WORD
L20: DEC DI ;PtrDn = * -1
CMP SI,DI ;PtrUp = PtrDn ?
JZ L50 ;JUMP IF POINTERS MEET
MOV CL,LOG_NBYTES ;GET LOG_NBYTES AGAIN
MOV AX,DI ;GET PtrUp
SHL AX,CL ;MULTIPLY BY 2^LOG_NBYTES
POP BX ;GET FIRST.[BYTE] FROM STACK
PUSH BX ;PUT IN STACK AGAIN
ADD BX,AX ;ARRAY(PtrDn).[BYTE]
MOV AL,ES:[BX] ;GET BYTE FROM ARRAY
MOV CL,DL ;TEST THE /
SHR AL,CL ;DESIRED BIT /
JNC L40 ;JUMP IF WORD TESTED IS NEGATIVE
JMP L20 ;OR TRY NEXT WORD
L40: CALL SWAP_INFO ;SWAP NEGATIVE AND POSITIVE WORDS
JMP L10 ;TRY TO FIND A NEW +/- COUPLE
L50: POP BX ;RESTORE STACK
MOV BX,IBIT ;GET THE NUMBER OF BIT BEING TESTED
CMP BX,0 ;LAST (LSB) BIT ?
JNZ L60 ;IF NOT LAST, CONTINUE
RET ;RETURN IF LAST BIT
L60: MOV CX,SI ;CX=PtrUp
SUB CX,IFIRST ;NZEROS=PtrUp-FIRST
PUSH CX ;STORE NZEROS FOR NEXT CALL
MOV AX,ISIZE ;GET SIZE
SUB AX,CX ;NONES=SIZE-NZEROS
PUSH AX ;STORE NONES FOR NEXT CALL
MOV AX,IFIRST ;GET FIRST
PUSH AX ;STORE FIRST FOR NEXT CALL
DEC BH ;NEW IBIT IS IBIT-1
PUSH BX ;STORE IBIT-1 FOR NEXT CALL
CMP CX,2 ;SEE IF NZEROS IS 0 OR 1
JC L70 ;NO CALL IF LESS THAN 2 ELEMENTS
;
PUSH AX ;IFIRST
PUSH CX ;NZEROS
PUSH BX ;IBIT-1
CALL BINSORT ;NEXT LEVEL OF RECURSION
L70: POP CX ;IBIT-1
POP AX ;IFIRST
POP DX ;NONES
POP BX ;NZEROS
;
CMP DX,2 ;SEE IF NONES IS 0 OR 1
JC L80 ;NO CALL IF LESS THAN 2 ELEMENTS
ADD AX,BX ;IFIRST+NZEROS
PUSH AX ;PASS NEW IFIRST AS PARAMETER
PUSH DX ;NONES
PUSH CX ;IBIT-1
CALL BINSORT ;NEXT LEVEL OF RECURSION
L80: RET ;END THIS LEVEL OF RECURSION
BINSORT ENDP
;
PARAMS: DB 7 DUP(0) ;STORE FOR PARAMETERS (7 BYTES)
;
PAR_SEG EQU 0 ;BYTES 0&1 ARE SEGMENT
PAR_OFF EQU 2 ;BYTES 2&3 ARE OFFSET
NBYTES EQU 4 ;BYTES 4&5 IS NUMBER OF BYTES
LOG2NBYTES EQU 6 ;THE LOG IS BYTE 6
;
SWAP_INFO PROC NEAR
;
; ON INPUT:
;
; SI = # OF ELEMENT OF 1ST WORD TO BE SWAPPED
; DI = # OF ELEMENT OF 2ND WORD TO BE SWAPPED
;
MOV BP,OFFSET PARAMS ;POINT TO PARAMS WITH BP
;
; SWAP WORDS FROM DATA ARRAY
;
MOV AX,ARRAY_SEG ;GET ARRAY SEGMENT
MOV [BP+PAR_SEG],AX ;SET PARAMETER
MOV AX,ARRAY_OFF ;GET ARRAY OFFSET
MOV [BP+PAR_OFF],AX ;SET PARAMETER
MOV AX,N_BYTES ;GET NUMBER OF BYTES IN WORD
MOV [BP+NBYTES],AX ;SET PARAMETER
MOV AL,LOG_NBYTES ;GET LOG OF # OF BYTES
MOV [BP+LOG2NBYTES],AL ;SET PARAMETER
CALL SWAP_ARRAY ;CALL SWAPING ROUTINE
;
; SWAP WORDS FROM INDEX ARRAY
;
MOV AX,IARRAY_SEG ;GET INDEX ARRAY SEGMENT
MOV [BP+PAR_SEG],AX ;SET PARAMETER
MOV AX,IARRAY_OFF ;GET INDEX ARRAY OFFSET
MOV [BP+PAR_OFF],AX ;SET PARAMETER
MOV AX,2 ;GET BYTES IN INTEGER WORD
MOV [BP+NBYTES],AX ;SET PARAMETER
MOV AL,1 ;GET LOG OF "2"
MOV [BP+LOG2NBYTES],AL ;SET PARAMETER