Statistics

Members: 1927
News: 293
Web Links: 1
Visitors: 3962016

Who's Online

We have 1 guest online
Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home arrow Conference Proceedings arrow Assembly arrow Chaos Animation
Chaos Animation
User Rating: / 1
PoorBest 
Written by Laura Fairhead   


To assemble this program you are going to require most of the library routines I have so far presented here. You can consider this an example in just how easy it is to write software in assembler if you continue to build and refine a library system. The program probably took me about half an hour of work and most of that was making myself satisfied with the niceness of the code:-

;issue #5
INCLUDE NUCONV.ASM

;issue #6
INCLUDE SCANU.ASM

;issue #7
;scalst list scanner
INCLUDE SCAWS.ASM

;random number generator
INCLUDE RAND.ASM

;ASM building blocks
INCLUDE PSTR.ASM
INCLUDE PSTRCR.ASM
INCLUDE PSTRCX.ASM
INCLUDE OUTCR.ASM
INCLUDE STRLEN.ASM
INCLUDE PUTCH.ASM

Overview


This is a simple but endearing graphical animation minature that is based on the iterative function:-

x' = x*x + y + a

y' = b - x

Where a,b are constants, x,y are old coordinates and x',y' are the new ones. All values are taken to be in [0,1). That is the operations are all performed modulo 1.

If you haven't covered this in mathematics yet it is quite simple, your function mod1 would be:-

mod1(x) = x - int(x)

This can all be done nicely within the bounds of 32-bit values, simply view the binary point as being just before the MSbit.

We only really have 4 values to keep since x',y' are the next x,y.

kaa     EQU kaera+1
kab     EQU kaa+4
kax     EQU kab+4
kay     EQU kax+4

The EQU's at the program end are defining offsets for uninitialised data that lies in the primary code segment. Here we have kaa<->a, kab<->b, kax<->x, kay<->y

;EAX=x

MOV EAX,DWORD PTR DS:[kax]
;EBX=b

MOV EBX,DWORD PTR DS:[kab]
;EBX=b-x =y'

SUB EBX,EAX
;ECX=y' for later use

MOV ECX,EBX
;EBX=y, y'->y (didn't I say XCHG is useful!)

XCHG EBX,DWORD PTR DS:[kay]
;EBX=y+a

ADD EBX,DWORD PTR DS:[kaa]
;EDX:EAX=xx
;high dword is the first 32 b.p's....

MUL EAX
;EBX=x
x+y+a =x' (how much of the pattern is due to loss of accuracy here?)

ADD EBX,EDX
;x<-x'

MOV DWORD PTR DS:[kax],EBX

Reasonably efficient, and we come out with the x,y coordinate pair also in EBX,ECX.

To jazz things up a little, instead of the basic idea:-

        (i)   set some random x,y,a,b
(ii)  do our function on the x,y,a,b
(iii) plot point on the screen representing x,y
(iv)  go back to (ii)

We implement a "trail". This is basically where we keep a store of the last so many points drawn (remember that classic WORM game??). Then one end is added to and the other is deleted from. Points are all plotted with XOR, especially since doing a second XOR will erase a plotted point (so there is no erase routine).

Furthermore for every point, 4-reflections of the point are plotted to the screen. This gives you symmetry for free.

The plot routine


I'm going to first explain the plot routine before going into the main code body. I had some fun writing it, but it also illustrates some important points.

We are using mode 011h. This is 640x480x2, ( 0280hx01E0h )

With mode 011h you have of course only the one plane. You've got bytes from +00h to +04Fh on each row representing 8-bit pixel groups.

So given an x coordinate you need to take the 2 parts:-

        offset =x SHR 3
bit    =x AND 3

The y coordinate is just the one part, the offset:-

offset =y *050h (row=050h bytes)

Now of course it is plain to see that the offset is simply the result of multiplication by 5 and then shift left 4. (unless you work always in decimal, ala 050h=5*010h)

Oh, I LOVE the x86:-

LEA SI,[EDX*4+EDX]

This puts DX*5 straight into SI. Thats about 5 operations all in one go:)

So then SI is shifted 4 left and the resultant offset y*050h is the y component of the offset on screen of the pixel we want to plot.

The routine keeps the x/y components apart because we want to plot (x,y) (-x,y) (-x,-y) (x,-y). And as soon as they are put together for one they need to be disassembled/reconstructed for the next.

The x component, which is always in BX, is obviously created with a shift right 3, however we first have to rescue the least significant 3 bits. They give the bit in the byte.

        MOV CL,BL
MOV AX,0180h
ROR AL,CL;ROL AH,CL

Here I am getting AL with the bit set that corresponds to the the pixel on screen. AH is being set up the opposite way around. Think of the screen as four quadrants:-

                    |
x+     |    x-
y+  |
|
-----------+-------------
|
|
y-  |
|
|

If our point starts in the x+y+ quadrant, we have the values to draw that:-

( SHR BX,3 )

XOR [SI+BX],AL

Now to reflect the point x-wise, so it goes to x-y+, you only need to get the x offset = 04Fh-x. Well x86 lets you do powerful things, we don't need to mess; just negate BX to get the -x and add the 04Fh in as a displacement. Of course the bit offset gets negated as well, which is exactly why we have the two opposite masks in AL/AH:-

NEG BX;XOR [SI+BX+04Fh],AH

Next y is reflected, so we go to -x-y. This is the same thing again, only the y coordinate will only affect the offset:-

NEG SI;XOR [SI+BX+04Fh+01DFh*050h],AH

And finally to +x-y:

NEG BX;XOR [SI+BX+01DFh*050h],AL

Notes


During the program run you can press any key to set different values for the chaos function. Press ESC to abort. On abortion a message will give you 2 hex d-words, these are the random number seed that generated the last pattern you were watching. To see it again simply record the values and invoke the program with the values on the command line:-

(ESC abort)

random seed=01234567 FEDCBA98 (program output)

KAOS 01234567 FEDCBA98 (invoke program with seed as parameter)

(chaos pattern displayed is the same as the one broken out of)

The code is left undelayed and as such it may run too fast on a fast machine. The optimum speed is for it to be only slighty over-fast. If you want to achieve this you should add some sort of delay loop in. Alternatively just get out your old 386 and give it some work to do.

Code is, as usual, is MASM format. Assemble to a COM file.

========START OF CODE======================================================

OPTION SCOPED
OPTION SEGMENT:USE16
.486

stksiz EQU 0400h ;stack size

kadatx EQU 0C00h ;#points length of trail

cseg SEGMENT BYTE

ASSUME NOTHING
ORG 0100h

kode PROC NEAR

;initialise, allocate memory and stack

        CLD
MOV AH,04Ah
MOV BX,OFFSET endof+0Fh
SHR BX,4
INT 021h
JC errmem
MOV SP,OFFSET stk+stksiz

;zero-terminate command line to facilitate ;parsing

        MOV SI,080h
LODSB
CBW
XCHG BX,AX
MOV [BX+SI],BH

;any parameters given?

        CALL NEAR PTR scaws
CMP AL,0
JZ SHORT ko0

;yes, so read 2 dwords as random seed

        MOV DI,OFFSET rndn
MOV AL,010h
CALL NEAR PTR scanur
CALL NEAR PTR scanu
JNA erripa
STOSD
CALL NEAR PTR scaws
CALL NEAR PTR scanu
JNA erripa
STOSD
JMP SHORT ko1

;no, so set random seed from system time ko0: CALL NEAR PTR rndseed
ko1:

lop2

;set mode 011h, fade grey background

        MOV AX,011h
INT 010h
MOV EAX,040404h
MOV BL,0
CALL NEAR PTR spal

;save random seed so that kaos params can be restored ;by user

        MOV SI,OFFSET rndn
MOV DI,OFFSET seed
MOVSD;MOVSD

;set random params for function

        MOV DI,OFFSET kaa
MOV CX,4
lop1:
CALL NEAR PTR rndgen32
STOSD
LOOP lop1

;initialise for plot trail
; [kaera]=0 on the first pass of the store ; [kaera]=-1 thereafter
; [kaoff]=offset of store pointer

        MOV BYTE PTR DS:[kaera],0
MOV WORD PTR DS:[kaoff],OFFSET kadat
lop0

;iterate x,y
; x'=x*x+y+a
; y'=b-x

        MOV EAX,DWORD PTR DS:[kax]
MOV EBX,DWORD PTR DS:[kab]
SUB EBX,EAX
MOV ECX,EBX
XCHG EBX,DWORD PTR DS:[kay]
ADD EBX,DWORD PTR DS:[kaa]
MUL EAX
ADD EBX,EDX
MOV DWORD PTR DS:[kax],EBX

;x,y scale to screen bounds
; gets the x,y [0,1) values into screen coordinate pair (BX,DX)

        SHR EBX,12
LEA EBX,[EBX*4+EBX]
SHR EBX,13
MOV EDX,ECX
SHR ECX,4
SUB EDX,ECX
SHR EDX,23

;do point
; [kaera] is -1 on and after the store had become full for the first

;          time
MOV DI,WORD PTR DS:[kaoff]
TEST BYTE PTR DS:[kaera],-1
JZ SHORT ko3
;unplot trail end point
PUSH BX
PUSH DX
MOV BX,[DI]
MOV DX,[DI+2]
CALL NEAR PTR plo4
POP DX
POP BX

;current position is saved in store
ko3: MOV AX,BX

        STOSW
MOV AX,DX
STOSW
;store ptr incremented wrapping at the end
CMP DI,OFFSET kadat+kadatx*4
JNZ SHORT ko4
MOV DI,OFFSET kadat
OR BYTE PTR DS:[kaera],-1

ko4: MOV WORD PTR DS:[kaoff],DI

;current position is plotted

CALL NEAR PTR plo4

;user
; ESC aborts, any key sets a new function going

        MOV AH,0Bh
INT 021h
CMP AL,0
JZ lop0
MOV AH,7
INT 021h
CMP AL,01Bh
JNZ lop2

;display random seed value and terminate

        MOV SI,OFFSET t0
CALL NEAR PTR pstr
MOV EAX,02083010h
CALL NEAR PTR nuconvs
MOV SI,OFFSET seed

;those instructions at the program start are never going to be ;executed again so use them as a temp workspace instead of kadat ;which could possibly be dangerous if somebody EQU's kadatx to ;some low value

        MOV DI,0100h
PUSH DI
LODSD
CALL NEAR PTR nuconv
MOV AL,020h
STOSB
LODSD
CALL NEAR PTR nuconv
MOV AL,0
STOSB
POP SI
CALL NEAR PTR pstrcr

;screen mode is not put back to 02h you may wish to add ;a MOV AX,2;INT 010h here however I left it out because I ;see way too much of that mode

;program termination
terminat0:

MOV AL,0

terminat

MOV AH,04Ch INT 021h

;error aborts
erripa:

        MOV SI,OFFSET terripa
MOV AL,2
JMP SHORT err
errmem:
MOV SI,OFFSET terrmem
MOV AL,1
err:
PUSH SI
MOV SI,OFFSET terr
CALL NEAR PTR pstr
POP SI
CALL NEAR PTR pstrcr
JMP terminat

terr: DB "ERROR: ",0
terrmem:

DB "memory allocation failure",0 terripa:

DB "invalid parameter format",0

;program text (in it's entirely)
t0: DB "random seed=",0

kode ENDP

;plo4- 4-way plot routine for mode 011h ;

;         plots 4 reflections of a single point on the mode 011h
;         screen these are (x,y) (-x,y) (-x,-y) (x,-y)
;
;         plots using XOR

;
;entry: BX,DX=x,y coordinates
;
;exit: SI,CL,AX,BX destroyed

plo4 PROC NEAR

PUSH DS

;screen segment 0A000h
; for further comment please refer above

        PUSH 0A000h
POP DS
LEA SI,[EDX4+EDX]
SHL SI,4
MOV CL,BL
MOV AX,0180h
ROR AL,CL
ROL AH,CL
SHR BX,3
XOR [SI+BX],AL
NEG BX
XOR [SI+BX+04Fh],AH
NEG SI
XOR [SI+BX+04Fh+01DFh050h],AH
NEG BX
XOR [SI+BX+01DFh*050h],AL
POP DS
RET

plo4 ENDP

;if you don't like my fade grey background you can delete this and ;the line that invokes it. However this is also the next library ;routine, so do cut/paste it into a file it will be used in future ;articles.

;spal- set VGA DAC register via hardware ;entry: EAX=XXGGBBRR (hex of course)
;

;           RR=red component
;           BB=blue component
;           GG=green component
;
;       don't forget that these values are <=03Fh
;
;       BL=DAC register to set

;
;
;exit: (all registers are preserved)

spal PROC NEAR

;the code here is straightforward so I shall add no comment apart ;from a small moan:( I have used direct hardware access instead ;of the BIOS calls to affect the palette since square one, I'm ;not unreasonable in my desire to program the hard-metal of the machine, ;however the quality of the BIOS graphics routines is absolutely ;despicable. If you've ever tried using them you will know what I'm ;talking about.
;

        PUSH EAX
PUSH DX
MOV DX,03C8h
CLI
XCHG BX,AX
OUT DX,AL
INC DX
XCHG BX,AX
OUT DX,AL
SHR EAX,8
OUT DX,AL
SHR EAX,8
OUT DX,AL
STI
POP DX
POP EAX
RET

spal ENDP

;library routines

        INCLUDE RAND.ASM
INCLUDE SCAWS.ASM
INCLUDE SCANU.ASM
INCLUDE NUCONV.ASM
INCLUDE PSTR.ASM
INCLUDE PSTRCR.ASM
INCLUDE PSTRCX.ASM
INCLUDE OUTCR.ASM
INCLUDE STRLEN.ASM
INCLUDE PUTCH.ASM

;data

kaoff   EQU $                   ;(w)  offset of trail store pointer (absolute)
kaera   EQU kaoff+2             ;(b)  flag indicating 1st trail pass
kaa     EQU kaera+1             ;(dw) a
kab     EQU kaa+4               ;(dw) b   kaos function parameters
kax     EQU kab+4               ;(dw) x
kay     EQU kax+4               ;(dw) y
kadat   EQU kay+4               ;()  store space for trail data
seed    EQU kadat+kadatx4      ;(qw) copy of initial random number seed
stk     EQU seed+8              ;(*)  stack space
endof   EQU stk+stksiz          ;[endofprogram]

cseg ENDS

END FAR PTR kode

========END OF CODE========================================================