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