Другие языки программирования и технологии

Факториал tasm. Нужно вычислить факториал (не меньше 300!) и вывести результат на дисплей. Заранее спасибо.

300! = 306`057`512`216`440
`636`035`370`461`297`268`629`388`588`804`173`576`999`416`776`741`259`476`533`176
`716`867`465`515`291`422`477`573`349`939`147`888`701`726`368`864`263`907`759`003
`154`226`842`927`906`974`559`841`225`476`930`271`954`604`008`012`215`776`252`176
`854`255`965`356`903`506`788`725`264`321`896`264`299`365`204`576`448`830`388`909
`753`943`489`625`436`053`225`980`776`521`270`822`437`639`449`120`128`678`675`368
`305`712`293`681`943`649`956`460`498`166`450`227`716`500`185`176`546`469`340`112
`226`034`729`724`066`333`258`583`506`870`150`169`794`168`850`353`752`137`554`910
`289`126`407`157`154`830`282`284`937`952`636`580`145`235`233`156`936`482`233`436
`799`254`594`095`276`820`608`062`232`812`387`383`880`817`049`600`000`000`000`000
`000`000`000`000`000`000`000`000`000`000`000`000`000`000`000`000`000`000`000`000

Нужно сначала определить сколько нужно памяти для массива DWORD самого факториала и CHAR для строки его десятичного DWORD [n];// n = ceil( ln(X!) / ln(2^32) )
CHAR [ s ]; // s = ceil( ln(X!) / ln(10) )
А потом посчитать используя длинное умножение (массива DWORD на один DWORD)
Стобв напечатать нужно использовать длинное деление (массива DWORD на один DWORD)
Остаток от деления на 10 даст последнюю цифру, и так далее.

в MASM выглядит примерно так

.686
.model flat, stdcall
option casemap :none

.data

Count32 dd 0 ; число элементов массива DWORD
Count8 dd 0 ; число элементов массива CHAR
flags dw 0 ; флаги

fac32 dd 0 ; указатель массива DWORD
fac8 dd 0 ; указатель массива CHAR

.code

Counts32 PROC
mov eax, Count32
ret
Counts32 ENDP

Counts8 PROC
mov eax, Count8
ret
Counts8 ENDP

CreateCounts PROC, nX:DWORD

; считаем логарифм факториала
fldz
locLoop:
mov eax, dword ptr nX
cmp eax, 1
jle locBreak
fld1
fild dword ptr nX
fyl2x
fadd
dec eax
mov dword ptr nX, eax
jmp locLoop
locBreak:

; считаем количесnво DWORD
mov dword ptr nX, 32
fld st(0)
fild dword ptr nX
fdiv

; округляем вверх до целого
fstcw flags
and flags, 1111001111111111b
or flags, 0000100000000000b
fldcw flags
frndint
fistp dword ptr Count32

; считаем количество CHAR
fldl2t
fdiv
; округляем вверх до целого
frndint
fistp dword ptr Count8
; прибавляем 1 (на всякий случай)
inc dword ptr Count8

ret 4
CreateCounts ENDP

Clear PROC uses edi ecx, pData:DWORD, nCount:DWORD
mov edi, pData
mov ecx, nCount
xor eax, eax
cld
rep stosd
ret 8
Clear ENDP

LongMul PROC uses ebx ecx edi, pData:DWORD, nCount:DWORD, nX:DWORD
xor ebx, ebx
xor ecx, ecx
mov edi, pData
locLoop:
cmp ecx, nCount
jle locBreak
mov eax, dword ptr [edi + 4*ecx]
mul dword ptr nX
add eax, ebx
adc edx, 0
mov dword ptr [edi + 4*ecx], eax
mov ebx, edx
inc ecx
jmp locLoop
locBreak:
ret 12
LongMul ENDP

Factorial PROC uses edi esi ecx, nX:DWORD
; считаем размеры
mov eax, dword ptr nX
push eax
call CreateCounts

; делаем память для массива
shl eax, 2
push eax
call malloc
add esp, 4
mov dword ptr fac32, eax

; и обнуляем
push Count32
push eax
call Clear

; считаем
mov edi, dword ptr fac32
mov dword ptr [edi], 1
mov ecx, 2
locLoop:
cmp ecx, nX
jg locBreak
push ecx
push Count32
push fac32
call LongMul
inc ecx
jmp lpLoop
locBreak:

; LongDiv
Осталось написать LongDiv
делишь на 10, остаток запоминаешь, это будет очередная цифра
потом их нужно вывести в обратном порядке.

ret 4
Factorial ENDP
END
Амир Каймаразов
Амир Каймаразов
21 360
Лучший ответ
Если учишься на программиста, то и учись. И задания выполняй сама.
Юрий Васильев
Юрий Васильев
88 126
Факториал от 300?! Нигде ничего не лопнет, не треснет?
Используйте числа с плавающей точкой
Ulan Nazirov
Ulan Nazirov
2 833