?? pascal.asm
字號:
; A win32asm graphics app, which generates an image of Pascal's Triangle by a method best
; know as The Chaos Game.
; I fully indorse any plagiarism of this code.
; E骾n O'Callaghan, eoinoc@iol.ie
.586
.MODEL FLAT,STDCALL
OPTION SCOPED
OPTION CASEMAP:NONE
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
WM_CASE MACRO reg,msgs ; The Svins MACRO for Window Message processing
irp msg,<msgs>
cmp reg,WM_&msg
je j&msg
endm
endm
.data
ClassName db "Win32",0
AppName db "Order in Chaos",0
.DATA?
wc WNDCLASSEX {?}
msg MSG {?}
rect RECT {?}
gWnd dd ? ; Global variable with window handle
gIst dd ? ; Global variable holds Instance
bDc dd ? ; Back Buffer DC
pBb dd ? ; Pointer to Back Buffer Bitmap Bits
hBm dd ? ; Back Buffer Bitmap Handle
TriPoint POINT {?, ?}, {?, ?}, {?, ?} ; Will hold 3 corners of triangle
.CODE
ALIGN 4
WinProc Proc uses ebx edi esi hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL ps:PAINTSTRUCT
mov eax,uMsg
WM_CASE eax,<PAINT,SIZE,DESTROY> ; MACRO will process these three messages
invoke DefWindowProc,hWnd,uMsg,wParam,lParam; Otherwise message is passed to default proc
ret
jSIZE:
invoke GetClientRect,hWnd,addr rect ; Store Window dimensions in rect struct
call InitDoubleBuffer ; Initalsie Back Buffer
call RenderFractal ; Render Fractal
xor eax,eax
ret
jPAINT:
invoke BeginPaint,hWnd,addr ps
invoke BitBlt,ps.hdc,0,0,rect.right,rect.bottom,\ ; Blt Backbuffer to window DC
bDc,0,0,SRCCOPY
invoke EndPaint,hWnd,addr ps
xor eax,eax
ret
jDESTROY:
invoke DeleteDC,bDc ; Delete Buffer DC
invoke DeleteObject,hBm ; Delete Buffer Bitmap
invoke PostQuitMessage,NULL ; Quit App
ret
WinProc ENDP
ALIGN 4
InitDoubleBuffer Proc
LOCAL bih:BITMAPINFOHEADER
invoke DeleteDC,bDc ; Delete Old DC
invoke DeleteObject,hBm ; Delete Old Bitmap
; In order to set up a back bufer you need to create a DC. You then need to fill out a
; BITMAPINFOHEADER adn use CreateDIBSection to create a DIB Section. You can then select
; the DIB Section into the Back Buffers DC and from that you can BitBlt it.
invoke CreateCompatibleDC,0 ; Create the Backbuffer DC
mov bDc,eax
lea edx,bih ; edx point to BITMAPINFOHEADER memory
mov [edx].BITMAPINFOHEADER.biSize,sizeof(BITMAPINFOHEADER)
mov eax,rect.right
mov (BITMAPINFOHEADER ptr [edx]).biWidth, eax ; Set width to that of main window
mov eax,rect.bottom
mov [edx].BITMAPINFOHEADER.biHeight,eax ; And match Heights
mov [edx].BITMAPINFOHEADER.biPlanes,1
mov [edx].BITMAPINFOHEADER.biBitCount,32 ; Set 32bit colors, ie dwords
mov [edx].BITMAPINFOHEADER.biCompression,BI_RGB ; Pixel storage format
mov [edx].BITMAPINFOHEADER.biSizeImage,0
mov [edx].BITMAPINFOHEADER.biXPelsPerMeter,0
mov [edx].BITMAPINFOHEADER.biYPelsPerMeter,0
mov [edx].BITMAPINFOHEADER.biClrUsed,0
mov [edx].BITMAPINFOHEADER.biClrImportant,0
invoke CreateDIBSection,bDc,edx,DIB_RGB_COLORS,addr pBb,0,0 ; Here pBb will be set with
mov hBm,eax ; a pointer to bitmap bits
invoke SelectObject,bDc,eax
ret
InitDoubleBuffer EndP
Rnd3Bit Proc ; This procedure generates 3 random bits. A slight change can be made to
.data ; alter this value up to at least 20bits.
RndInit dd 0A2F59C2Eh
.code
mov edx,RndInit
mov eax,3; <- Here's where it's set to 3 bits
rl: rol edx,1
jnc rs
xor edx,0ah
rs: dec eax
jne rl
mov eax,edx
rcr edx,1
mov RndInit,edx
ret
Rnd3Bit EndP
RenderFractal Proc
; This procdure renders the image of the fractal, Pascals Triangle. Perhaps the best example
; of perfect order out of absolutly random chaos.
; The fractal is generated by starting at any point, then for each iteration of the loop you
; pick one of the three points at random and move to a position half way between current point
; and the chosen corner. You then plot a pixel at that location.
; The method of selecting the postion half way is optimised so I'll explain it. The obvious
; method is to get the distance from the current point to the corner, half that value and add
; it to the current point. So that equation for x would be:
; CurX + (CornerX - CurX)/2
; Those who like maths may sopt that this can be shortened to:
; (2CurX + CornerX - CurX)/2 => (CurX + CornerX)/2
; An identical equation works for the y coords.
; Note that in a DIB Section the origion (0,0) is the bottom left corner. Not the top left
; as in most windows GDI functions.
mov eax,rect.right ; eax = window width.
shr eax,1 ; eax = width/2.
mov TriPoint[0].x,eax ; x coord of first point = eax = witdh/2.
lea eax,[eax*2][-5] ; eax = (eax*2)-5 = width-5.
mov TriPoint[8].x,eax ; x coord of 2nd point = eax, i.e. 5 pixels from right side.
mov TriPoint[16].x,5 ; x coord of 3rd point = 5, i.e. 5 pixels from left side.
mov eax,rect.bottom ; eax = height.
sub eax,5 ; eax = height-5.
mov TriPoint[0].y,eax ; y coord of 1st point = eax = height-5. i.e. 5 from top.
mov TriPoint[8].y,5 ; y coord of 2nd point 5 from bottom.
mov TriPoint[16].y,5 ; y coord of 3rd point 5 from bottom.
mov ebx,TriPoint[0].x ; ebx will hold current x throughout loop, initalise to point 1.
mov ecx,TriPoint[0].y ; ebx will hold current y throughout loop.
mov edi,pBb ; edi points to bitmap bits.
mov esi,100000 ; esi acts as loop counter. Note higher esi = better image & slower
rLp:call Rnd3Bit ; Get random 3 bit number.
and eax,3 ; convert to num between 0-3.
jz rLp ; if 0 then get new number. (Only 3 points, not 4)
add ebx,TriPoint[eax*8][-8].x ; CurX = CurX + CornerX
shr ebx,1 ; CurX = (CurX + CornerX)/2
add ecx,TriPoint[eax*8][-8].y ; CurY = CurY + CornerY
shr ecx,1 ; CurY = (CurY + CornerY)/2
mov eax,rect.right
xor edx,edx
mul ecx ; eax = CurY * width
add eax,ebx ; eax = eax + Cur X = (CurY * width) + CurX
mov dword ptr [edi][eax*4],0FFFFFFh ; Set Pixel to White
dec esi ; decrement counter
jnz rLp ; repeat loop if unfinished
ret
RenderFractal EndP
ALIGN 4
Start:
lea edi,wc
xor eax,eax
mov ecx,(sizeof WNDCLASSEX)/4
rep stosd ; Zero wc WNDCLASSEX Struct
invoke GetModuleHandle,eax
mov gIst,eax
mov wc.hInstance,eax
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style,CS_OWNDC or CS_HREDRAW or CS_VREDRAW
mov wc.lpszClassName,offset ClassName
mov wc.lpfnWndProc,offset WinProc
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
mov wc.hbrBackground,COLOR_WINDOW+1
invoke RegisterClassEx,ADDR wc
xor eax,eax
invoke CreateWindowEx,0,ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,\
10,10,300,200,eax,eax,gIst,eax
mov gWnd,eax ; Store handle in ase its needed later.
push eax
push SW_SHOWNORMAL
push eax
call ShowWindow
call UpdateWindow
ml: xor eax,eax
lea edi,msg
invoke GetMessage,edi,eax,eax,eax
test eax,eax
jz qm
push edi
push edi
call TranslateMessage
call DispatchMessage
jmp ml
ALIGN 4
qm: mov eax,msg.wParam
invoke ExitProcess,eax
END Start
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -