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

📄 pi.rc

📁 计算圆周率π,用asm汇编
💻 RC
字号:
;***********************************************************************************************************
;计算原理:
;PI=PI=16x(1/5-1/(5^3/3)+1/(5^5/5)-1/(5^7/7)+...)-4x(1/239-1/(239^3/3)+1/(239^5/5)-1/(239^7/7)+...)
;PI=4x(4x5/25-239/57121)/1-4x(4x5/25^2-239/57121^2)/3+4x(4x5/25^3-239/57121^3)/5-...
;每一个dword型数据只能放9位十进制数,用N个dword数存储9N位计算结果
;y=(4*4*5/25^a),z=(4*239/57121^a),c=(y-z)/a,x+=c 或 x-=c,a+=2(a初始为1),循环计算直到y=0结束
;***********************************************************************************************************
;“计算圆周率.Asm”文件

.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive

include 计算圆周率.inc

.code

start:
invoke InitCommonControls
invoke GetModuleHandle,NULL
invoke DialogBoxParam,eax,IDD_DIALOG_MAIN,NULL,addr DlgProc,NULL
invoke ExitProcess,0

;########################################################################

_CalPI proc uses edi esi ebx
LOCAL @hMemX,@pMemX,@hMemY,@pMemY,@hMemZ,@pMemZ,@hMemC,@pMemC
LOCAL @dwDigit,@dwCalLen,@dwA,@dwI,@dwTime

invoke GetDlgItemInt,hWndDlg,IDC_DIGIT,0,0
.if eax<1
invoke SetDlgItemInt,hWndDlg,IDC_DIGIT,1000,0
mov eax,1000
.endif
add eax,4
mov @dwDigit,eax ;要计算的位数

;mov ecx,eax
;shr ecx,7
;add eax,ecx ;要多算几位,因为最后若干位不准确
mov ecx,DATALEN ;要多算几位,因为最后若干位不准确
add eax,ecx
div ecx ;每四字节存放 DATALEN 位十进制的结果
test edx,edx
jz @F
inc eax
@@: shl eax,2
mov @dwCalLen,eax ;内存数组的大小

add eax,4
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,eax
mov @hMemY,eax
invoke GlobalLock,eax
mov @pMemY,eax
mov dword ptr[eax],04C4B400h;4*4*5*DATAMAX/1000,不能写成mov dword ptr[eax],4*4*5*DATAMAX/1000,编译器有bug??
mov ecx,@dwCalLen
inc dword ptr[eax+ecx] ;此为计算结束的标志

invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,ecx
mov @hMemZ,eax
invoke GlobalLock,eax
mov @pMemZ,eax
mov dword ptr[eax],038FB6700h;4*239*DATAMAX/1000 同上,编译器有bug??

invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,@dwCalLen
mov @hMemC,eax
invoke GlobalLock,eax
mov @pMemC,eax

invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,@dwCalLen
mov @hMemX,eax
invoke GlobalLock,eax
mov @pMemX,eax

xor eax,eax
mov @dwI,eax ;循环计数器初始化
inc eax
mov @dwA,eax ;A初始化
invoke GetTickCount
mov @dwTime,eax

;**************************************************************************
CAL_START:
mov ebx,DATAMAX ;开始计算Y/=25
mov esi,25
xor edx,edx
mov ecx,@dwI
mov edi,@pMemY
CAL_Y:
mov eax,edx
mul ebx
add eax,dword ptr[edi+ecx]
adc edx,0
div esi
mov dword ptr[edi+ecx],eax
add ecx,4
cmp ecx,@dwCalLen
jb CAL_Y

mov ecx,@dwI
CAL_SETPOS:
cmp dword ptr[edi+ecx],0
jnz CAL_ISEND
add ecx,4
jmp CAL_SETPOS
CAL_ISEND:
cmp ecx,@dwCalLen
jae CAL_END

mov @dwI,ecx

mov esi,57121 ;开始计算Z/=57121
xor edx,edx
mov edi,@pMemZ
CAL_Z:
mov eax,edx
mul ebx
add eax,dword ptr[edi+ecx]
adc edx,0
div esi
mov dword ptr[edi+ecx],eax
add ecx,4
cmp ecx,@dwCalLen
jb CAL_Z

clc ;开始计算C=Y-Z
mov esi,@pMemC
mov ebx,@pMemY
CAL_C:
lahf
sub ecx,4
cmp ecx,@dwI
jl CAL_CCF
sahf
mov eax,dword ptr[ebx+ecx]
sbb eax,dword ptr[edi+ecx]
jnc CAL_CC
add eax,DATAMAX
stc
CAL_CC:
mov dword ptr[esi+ecx],eax
jmp CAL_C
CAL_CCF:
;sahf
;jc CAL_CDIVA
;dec dword ptr[esi+ecx]
CAL_CDIVA:
xor edx,edx ;开始计算C/=A
mov ecx,@dwI
mov edi,@dwA
mov ebx,DATAMAX
CAL_CA:
mov eax,edx
mul ebx
add eax,dword ptr[esi+ecx]
adc edx,0
div edi
mov dword ptr[esi+ecx],eax
add ecx,4
cmp ecx,@dwCalLen
jb CAL_CA 

mov edi,@pMemX
test @dwA,2 ;判断(A/2)是奇数还是偶数
jz CAL_AO

CAL_A1:
lahf ;开始计算X-=C  (A/2)是奇数时
sub ecx,4
cmp ecx,@dwI
jl CAL_ACF1
sahf
mov eax,dword ptr[edi+ecx]
sbb eax,dword ptr[esi+ecx]
jnc CAL_AA1
add eax,ebx
stc
CAL_AA1:
mov dword ptr[edi+ecx],eax
jmp CAL_A1
CAL_ACF1:
sahf
jnc CAL_NEXTA
dec dword ptr[edi+ecx]
jmp CAL_NEXTA

CAL_AO:
lahf ;开始计算X+=C  (A/2)是偶数时
sub ecx,4
cmp ecx,@dwI
jl CAL_ACFO
sahf
mov eax,dword ptr[edi+ecx]
adc eax,dword ptr[esi+ecx]
cmp ebx,eax
ja CAL_AAO
sub eax,ebx
stc
CAL_AAO:
mov dword ptr[edi+ecx],eax
jmp CAL_AO
CAL_ACFO:
sahf
jnc CAL_NEXTA
inc dword ptr[edi+ecx]

CAL_NEXTA:
add @dwA,2
jmp CAL_START
;**************************************************************************

CAL_END:
invoke GetTickCount
xor edx,edx
sub eax,@dwTime
mov ecx,1000
div ecx
mov ecx,@dwA
shr ecx,1
inc ecx
invoke wsprintf,@pMemC,addr lpStr,ecx,eax,edx

invoke SetDlgItemText,hWndDlg,IDC_TIME,@pMemC
invoke GlobalUnlock,@pMemC
invoke GlobalFree,@hMemC
invoke GlobalUnlock,@pMemY 
invoke GlobalFree,@hMemY
invoke GlobalUnlock,@pMemZ 
invoke GlobalFree,@hMemZ 

mov eax,@dwDigit
add eax,DATALEN
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,eax
mov @hMemC,eax
invoke GlobalLock,eax
mov @pMemC,eax

mov edi,eax
mov ecx,@dwDigit
add ecx,DATALEN-1
mov al,030h
rep stosb

mov edi,@pMemC
mov ecx,10
mov esi,@pMemX
xor edx,edx
mov @dwI,edx
mov ebx,DATALEN
SHOW_DATA:
mov eax,dword ptr[esi] ;显示X中计算结果
SHOW_CHAR:
div ecx
dec ebx
add byte ptr[edi+ebx],dl
xor edx,edx
test eax,eax
jnz SHOW_CHAR

mov eax,@dwI
cmp eax,@dwDigit
jae OK 
add esi,4
mov ebx,DATALEN
add @dwI,ebx
add edi,ebx
jmp SHOW_DATA

OK:
mov ecx,@dwDigit
mov edi,@pMemC
mov byte ptr[edi+ecx-1],0
mov cl,byte ptr[edi+2]
mov byte ptr[edi+1],cl
mov byte ptr[edi+2],'.'
invoke GlobalUnlock,@pMemX 
invoke GlobalFree,@hMemX
inc edi
invoke SetDlgItemText,hWndDlg,IDC_PI,edi

invoke GlobalUnlock,@pMemC
invoke GlobalFree,@hMemC

ret

_CalPI endp
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

mov eax,uMsg
.if eax==WM_INITDIALOG
mov eax,hWin
mov hWndDlg,eax
.elseif eax==WM_COMMAND
mov eax,wParam 
.if lParam!=0 
mov edx,eax
shr edx,16 
.if dx==BN_CLICKED ;按钮消息处理
.if ax==IDC_CAL ;计算
call _CalPI
.endif
.endif
.endif
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
jmp @F
.endif
mov eax,TRUE
@@:
ret

DlgProc endp

end start

;***********************************************************************************
;“计算圆周率.Inc”文件

include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc

includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib

DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM

.const

DATALEN equ 9
DATAMAX equ 1000000000
;计算圆周率.dlg
IDD_DIALOG_MAIN equ 101
IDC_GRP1 equ 1003
IDC_STC1 equ 1001
IDC_DIGIT equ 1002
IDC_CAL equ 1004
IDC_TIME equ 1005
IDC_PI equ 1006

;计算圆周率.Rc
MY_ICON equ 10

;#########################################################################

.data?
hWndDlg HWND ?

;#########################################################################

.data
lpStr db '计算%d次,用时%d.%d秒',0

⌨️ 快捷键说明

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