📄 invcircs.asm
字号:
;-----------------------------------------------
; Inversion of a rectangular array of circles
; by Ron Thomas
; Ron_Thom@Compuserve.com 15/7/99
;-----------------------------------------------
.386 ; 32 bit when .386 appears before .MODEL
.MODEL FLAT,STDCALL
include windows.inc
include user32.inc
include kernel32.inc
include gdi32.inc
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
WinMain PROTO :DWORD, :DWORD, :DWORD, :SDWORD
.data
inverted = FALSE
numCols EQU 16
numRows EQU 11
Total_no_circles EQU numRows*numCols*2+1 ; 2 * # in rectangular matrix + 1 (inversion circle)
ClassName db "SimpleWinClass",0
AppName db "Circle Inversion: Press any key to see the transform",0
; Set up a structure to hold data for all created circles
; Floating point numbers are used so that precision is not lost by
; rounding action as in the case of integer computation of radii etc
Circle$ STRUCT 4 ; Align for fastest speed
X_Coord real4 ? ; X and Y coordinates for the circle centre
Y_Coord real4 ? ;
Fradius real4 ? ; Radius
Ccolour DD ? ; Circle colour
Circle$ ENDS ; End of circle template
circles Circle$ Total_no_circles DUP ({}) ; Provide storage for circle data
circles_made DW 0 ; (No of circles made by inversion)*4
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
delta_X real4 ?
delta_Y real4 ? ; Storage for computational constants
sin_beta real4 ? ;
cos_beta real4 ? ;
SL_prime real4 ? ;
SM_prime real4 ? ;
radius_cos_beta real4 ? ; radius*cos(beta)
radius_sin_beta real4 ? ; radius*sin(beta)
cxClient DD ?
cyClient DD ?
colour DD ?
x1 DD ?
x2 DD ?
y1 DD ?
y2 DD ?
cDiam DD ?
temp DD ?
XC DW ? ; Screen centre location
YC DW ?
last dw ?
tmp dw ?
.const
two real4 2.0
three DW 3
first DW 16 ; Offset to 1st circle in the rectangular array
;MACRO's
LOWORD MACRO bigword ;; Retrieves the low word from double word argument
mov eax,bigword
and eax,0FFFFh ;; Set to low word
ENDM
HIWORD MACRO bigword ;; Retrieves the high word from double word argument
mov ebx,bigword
shr ebx,16 ;; Shift 16 for high word to set to high word
ENDM
RGB MACRO red, green, blue ;; Get composite number from red green and blue bytes
mov al,blue ;; ,,,blue
shl eax,8 ;; ,,blue,
add al,green ;; ,,blue,green
shl eax,8 ;; ,blue,green,
add al,red ;; ,blue,green,red
and eax,0FFFFFFh ;; Mask out top byte to complete COLORREF dword
ENDM
CIRCOLOUR MACRO red, green, blue ;; Set the circle colours for any one row
RGB red, green, blue
invoke CreateSolidBrush, eax
mov esi,0
.WHILE esi < numCols
mov circles.Ccolour[ebx],eax
add ebx,16
inc esi
.ENDW
ENDM
;----------------------------------------------------------------------------
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,0
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc uses ebx esi edi, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC, ps:PAINTSTRUCT, msg:MSG, whiteBrush:HBRUSH, redBrush:HBRUSH
mov eax,uMsg
.IF eax==WM_CREATE
RGB 255, 0, 0 ; Colour red
invoke CreateSolidBrush, eax
mov redBrush,eax
; Set colour for each row of circles
mov ebx,16 ; Initialise to 1st circle on 1st row
CIRCOLOUR 255, 0, 0 ; Red row
CIRCOLOUR 0, 255, 0 ; Green
CIRCOLOUR 0, 0, 255 ; Blue
CIRCOLOUR 255, 255, 0 ; Yellow
CIRCOLOUR 0, 255, 255 ; Cyan
CIRCOLOUR 255, 0, 255 ; Magenta
CIRCOLOUR 255, 0, 125
CIRCOLOUR 128, 255, 128
CIRCOLOUR 255, 128, 128
CIRCOLOUR 128, 128, 255
CIRCOLOUR 255, 255, 128
.ELSEIF eax==WM_SIZE
LOWORD lParam
mov cxClient,eax
shr eax,4 ; Set diameter to 1/16 of screen width
mov cDiam,eax
HIWORD lParam
mov cyClient,ebx
mov eax,cxClient
shr eax,1 ; Set inversion circle at centre of screen
mov XC,ax ; and save integer coordinates
shr ebx,1 ;
mov YC,bx ;
finit ; Initialise the coprocessor
fild XC
fstp circles.X_Coord ; Store FP values for base circle centre
fild YC ; coordinates
fstp circles.Y_Coord
mov ax,YC
shl ax,1 ; Sets R(b)=2/3 screen
xor dx,dx ;
div three ;
mov tmp,ax ;
fild tmp
fstp circles.Fradius ; Store radius of base circle as a real number
.ELSEIF eax==WM_PAINT
invoke InvalidateRect, hWnd, NULL, TRUE ; Request a full repaint
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
mov y1,0
mov y2,0
mov ebx,16 ; set circle index to 1st colomn of row 1
mov edi,0 ; Row index
.WHILE edi <= numRows-1
mov x1,0 ; Start on left hand side
mov eax,cDiam
.IF edi==0
inc eax
.ENDIF
add y2,eax ; Set y2 boundary
mov esi,1 ; Column index
.WHILE esi <= numCols
mov eax,cDiam ; Get circle diameter
mov edx,0
mul esi
.IF esi != numCols
inc eax ; boundary to just touch
.ENDIF
mov x2,eax ; Set x2 boundary
invoke SelectObject, hdc, circles.Ccolour[ebx]
invoke Ellipse, hdc, x1, y1, x2, y2
mov eax,x1
add eax,x2
mov temp,eax
fild temp
fdiv two
fstp circles.X_Coord[ebx] ; circle-centre x-coord
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -