⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mirrors.asm

📁 汇编语言实现一个小小的镜子
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;------------------------------------------------------------
;  Mirrors
;  -------
;
;  Orthogonal circle creation and circle inversion demo               
;  ----------------------------------------------------
;										
;  The program creates several orthogonal circles around a base circle. 
;  Each orthogonal circle is then used as a mirror circle to mathematically 
;  invert (reflect) all the other orthogonal circles. This creates more 
;  orthogonal circles and the process is repeated a second time on these new 
;  circles to extend the set of orthogonal circles and thereby build a
;  beautiful graphic.   

;	by   Ron Thomas 30/7/99
; 	
;	Ron_Thom@Compuserve.com & www.rbtmomas.freeserve.co.uk	
;-------------------------------------------------------------

.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

ClassName db "SimpleWinClass",0
AppName   db "It's all done by mirrors !",0

; **** To change the model alter the variables NOC and NoLevels as required.
;      ---------------------------------------------------------------------

NoLevels	EQU	2	; Nesting level for circle inversion

NOC		EQU	5  ; No of orthogonal circles to be built around the base circle
                           ; valid for 2 to 10 circles only.
Total_no_circles EQU    (1 + NOC + NOC*(NOC-1) + NOC*(NOC-1)*(NOC*(NOC-1)-1))
	
		; Above 4 terms are only for 2 of levels inversion
		; e.g for 4 initial orthogonals & 2 levels we get: 1 + 4 + 4*3 + 4*3*11 = 149
		; 	The 3rd level is a little impractical at 17590 circles !
		; 	Beyond that the number is too many to consider !!

deg2rad		DQ	3f91df46a2529d39h	; 2 * pi / 360 (conversion factor for radians)
count		dw	1	; Controls inversion nesting; 1 gives 2 levels, 2 gives 3 etc
first		DD	16	; Index to first circle to be inverted

.data?

hInstance HINSTANCE ?
CommandLine LPSTR ?

;	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	?	; 
Radius	real4	?	; Radius 
Colour	DD	?	; Circle colour

Circle$	ENDS		; End of circle structure

circles	Circle$	Total_no_circles DUP ({})	; Provide storage for circle data

base_circle_diameter	real4	?
delta_X		real4	?
delta_Y		real4	?	; Storage for computational constants
first_orthog_Y	real4	?	; Computed value for 1st orthog circle (Y coord)
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)
theta		real4	?	; Required rotation in degrees
math_X_Coord	real4	?	;
math_Y_Coord	real4	?	; Math space coordinates
	
hdc		HDC	?

cxClient	DD	?
cyClient	DD	?
bluepen		DD	?	; Pen handle

x1		DD	?
x2		DD	?
y1		DD	?
y2		DD	?
temp		DD	?	; Temporary variable
last		DD	?	;	" last	"	"	"
circles_made	DD	?	; (No of circles made by inversion)*4

.const

frac_screen	real4	0.666666	; Set base circle to this fraction of cyClient 
two		real4	2.0E0

; Arbitrary factor used to derive 1st orthog Y coord, adjust if necessary for your system
Pfact		real4	1.0,1.0,5.0,2.002,1.417,1.238,1.156,1.112,1.085,1.066,1.054  
;-------------------------------------------------------------------------------------------

;Macros 

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

CIRCLE	MACRO	xc,yc,rad, col	;; x & y centre coords, the radius and the colour 

	  fld	xc
	  fsub	rad
	  fistp	x1				;; x1 boundary
	
	  fld	yc
	  fsub	rad
	  fistp	y1				;; y1 boundary
	
	  fld	xc
	  fadd	rad
	  fistp	x2				;; x2 boundary
	
	  fld	yc
	  fadd	rad
	  fistp	y2				;; y2 boundary

	  invoke SelectObject, hdc, col	
	  invoke Ellipse, hdc, x1, y1, x2, y2	; Fill circle with colour
 
	ENDM
 
CIRCLECOLOUR	MACRO red,green,blue, n		;; Set initial orthogonal circle colours
 
	  RGB red, green, blue			;; Set RGB colour
	  invoke CreateSolidBrush, eax
	  mov	 circles.Colour[n*16],eax

	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 ps:PAINTSTRUCT, msg:MSG

	mov   eax,uMsg
	  
 	.IF eax==WM_CREATE

	  finit						; Initialise coprocessor
	  invoke CreatePen, PS_SOLID, 1, 0FF0000h	; Solid, thin & blue 
	  mov	bluepen,eax

;-------------------------------------------------------------------------
;	Set some colours for the orthogonal circles around the base circle   (10 are set)
;-------------------------------------------------------------------------

	  CIRCLECOLOUR 255, 0, 0,      1	; Red
 	  CIRCLECOLOUR 0, 255, 255,    2	; Cyan
	  CIRCLECOLOUR 0, 0, 255,      3	; Blue
	  CIRCLECOLOUR 255, 0, 255,    4	; Magenta
	  CIRCLECOLOUR 255, 255, 0,    5	; Yellow
	  CIRCLECOLOUR 0, 255, 0,      6	; Green
	  CIRCLECOLOUR 255, 0, 125,    7
	  CIRCLECOLOUR 128, 255, 128,  8
	  CIRCLECOLOUR 255, 128, 128,  9
	  CIRCLECOLOUR 128, 128, 255, 10	; Extend if more orthogonal circles are to be
	 					; created about the base circle 
 	.ELSEIF eax==WM_SIZE

	  LOWORD lParam
	  mov	 cxClient,eax
	  shr	 eax,1
	  mov	 temp,eax 
	  fild	 temp
	  fstp   circles.X_Coord		; save base X-centre coord

	  HIWORD lParam
	  mov	cyClient,ebx
	  shr   ebx,1
	  mov	temp,ebx
	  fild	temp 
	  fst   circles.Y_Coord			; save base Y-centre coord
	  
	  fmul	frac_screen			; Set R(b) to fraction (2/3) of max possible
	  fst	circles.Radius			; save radius
	  fmul	two
	  fstp	base_circle_diameter

	  fild	cyClient
	  fdiv	two
	  fld	circles.Radius			; get base radius

	  mov	ebx,NOC
	  shl	ebx,2				; *4
	  fmul	Pfact[ebx]			; mult by abitrary factor (alter as required)
	  fsub					; & subtract to
	  fstp	first_orthog_Y			; get Y centre for 1st orthog circle   

	  mov	first,16			; Reset these if we have to redraw 
	  mov	count,1				;
	  mov	circles_made,0			;

        .ELSEIF eax==WM_PAINT

 	  invoke  BeginPaint,hWnd, ADDR ps
	  mov     hdc,eax

;	  Set the 4 boundaries and draw the base circle

	  invoke SelectObject, hdc, bluepen

;	  mov	esi,0				; Make sure its zero 

	  CIRCLE circles.X_Coord, circles.Y_Coord, circles.Radius, 0 	
	 
;---------------------------------------;
;	Build 1st orthogonal circle	; 	
;---------------------------------------;

	  fld	circles.X_Coord		; Start with a circle vertically above the base circle 	
	
	  fstp	circles.X_Coord[16]	; Set X coord for centre of 1st orthogonal circle

	  fld	first_orthog_Y		; Arbitrary value; changes appearance of the graphic
	  fstp	circles.Y_Coord[16]	; Store Y coord
  
;	Calculate the angle necessary to rotate the orthogonal circles
;	centre and obtain the sequence of symetrically placed circles

	  mov	temp,360
	  fild	temp			; Set 360 degrees into st
	  mov	temp,NOC		; # circles orthogonal to the base circle
	  fild	temp			; 
	  fdiv				; get reqd angle in degrees
	  fstp	theta			;   	

	  mov	 ebx,1*16			; esi is an index to the circles
	  
;	Calculate  P, which is the distance from the new centre to the
;	circumference of the base circle, (on a line joining the two centres),
;	using the equation:

;		P = -R(b) + SQRT( ((X(n)-X(b))**2 + ((Y(n)-Y(b))**2 )

;	where	R(b)	is the radius of the base circle
;		X(b)	is the X coordinate of the base circle
;		Y(b)	       Y	"	"	"
;		X(n)	       X	"   	"   orthogonal circle
;		Y(n)	       Y	"	"	"	"

	  fld	circles.X_Coord[ebx]	; Get difference in X coordinates
	  fsub	circles.X_Coord		;	X(n) - X(b)
	  fld	st			; Push copy onto the stack (in st(1))
	  fmul				; we have delta_X squared

	  fld	circles.Y_Coord[ebx]	; Get difference in Y coordinates
  	  fsub	circles.Y_Coord		;	Y(n) - Y(b)
	  fld	st			; Take copy

	  fmul				; delta_Y squared
	  fadd				; Add the squares

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -