A mai gépek miért nem tudnak a másodperc tört része alatt 0..2147483647 értékig elszámolni?
Nekem fura az, hogy nem tudják ezt a műveletet a másodperc tört része alatt végrehajtani a mai gépek.
Bár Ryzen 7 vagy Core i7 esetén nem próbáltam, Ryzen 5 3600 gépen igen és meglepő a 3-4 másodperc, ami e művelethez kell.
Esetleg párhuzamosítani kellene processzormagonként az ilyen bonyolult műveleteket? (mondjuk ahhoz nem mintha értenék).
Miért lehetséges ez?
BITS 32
CPU pentium
EXTERN fpc_get_output
EXTERN fpc_write_text_shortstr
EXTERN fpc_iocheck
EXTERN fpc_writeln_end
EXTERN fpc_initializeunits
EXTERN fpc_do_exit
EXTERN INIT$_$SYSTEM
EXTERN INIT$_$FPINTRES
EXTERN THREADVARLIST_$SYSTEM$indirect
; Begin asmlist al_procedures
SECTION .text
ALIGN 16
GLOBAL PASCALMAIN
PASCALMAIN:
GLOBAL _main
_main:
push ebp
mov ebp,esp
push ebx
call fpc_initializeunits
mov dword [U_$P$SZAMOLASPELDA_$$_SZAM],0
jmp ..@j4
ALIGN 8
..@j3:
add dword [U_$P$SZAMOLASPELDA_$$_SZAM],1
..@j4:
cmp dword [U_$P$SZAMOLASPELDA_$$_SZAM],2147483647
jl ..@j3
jmp ..@j5
..@j5:
call fpc_get_output
mov ebx,eax
mov ecx,dword _$SZAMOLASPELDA$_Ld1
mov edx,ebx
mov eax,0
call fpc_write_text_shortstr
call fpc_iocheck
mov eax,ebx
call fpc_writeln_end
call fpc_iocheck
mov dword [U_$P$SZAMOLASPELDA_$$_SZAM],-1
ALIGN 8
..@j6:
mov eax,dword [U_$P$SZAMOLASPELDA_$$_SZAM]
lea eax,[eax+1]
mov dword [U_$P$SZAMOLASPELDA_$$_SZAM],eax
cmp dword [U_$P$SZAMOLASPELDA_$$_SZAM],2147483647
jge ..@j8
jmp ..@j6
..@j8:
call fpc_get_output
mov ebx,eax
mov ecx,dword _$SZAMOLASPELDA$_Ld2
mov edx,ebx
mov eax,0
call fpc_write_text_shortstr
call fpc_iocheck
mov eax,ebx
call fpc_writeln_end
call fpc_iocheck
call fpc_do_exit
pop ebx
mov esp,ebp
pop ebp
ret
; End asmlist al_procedures
; Begin asmlist al_globals
SECTION .bss
ALIGNB 4
U_$P$SZAMOLASPELDA_$$_SZAM: RESB 4
SECTION .data
ALIGN 4,DB 0
GLOBAL INITFINAL
INITFINAL DD 2,0,INIT$_$SYSTEM,0,INIT$_$FPINTRES,0
SECTION .data
ALIGN 4,DB 0
GLOBAL FPC_THREADVARTABLES
FPC_THREADVARTABLES DD 1,THREADVARLIST_$SYSTEM$indirect
SECTION .data
ALIGN 4,DB 0
GLOBAL FPC_RESOURCESTRINGTABLES
FPC_RESOURCESTRINGTABLES DD 0
SECTION .data
ALIGN 4,DB 0
GLOBAL FPC_WIDEINITTABLES
FPC_WIDEINITTABLES DD 0
SECTION .data
ALIGN 4,DB 0
GLOBAL FPC_RESSTRINITTABLES
FPC_RESSTRINITTABLES DD 0
SECTION .fpc
ALIGN 16,DB 0
__fpc_ident DB "FPC 3.2.0 [2020/06/04] for i386 - Win32"
SECTION .data
ALIGN 4,DB 0
GLOBAL __heapsize
__heapsize DD 0
SECTION .data
ALIGN 4,DB 0
GLOBAL __fpc_valgrind
__fpc_valgrind DB 0
; End asmlist al_globals
; Begin asmlist al_typedconsts
SECTION .rodata
ALIGN 4,DB 0
_$SZAMOLASPELDA$_Ld1:
DB 10,"while vege",0
SECTION .rodata
ALIGN 4,DB 0
_$SZAMOLASPELDA$_Ld2:
DB 15,"for ciklus vege",0
; End asmlist al_typedconsts
holott, elég lett volna ennyi:
xor EAX,EAX
loop:
inc EAX
cmp EAX,2147483647
jnz loop
de a kérdésedben szereplő óhaj teljesül kevesebbel is:
xor EAX,EAX
loop:
inc EAX
jmp loop
Sajnos, nem tudok assembly-ben programozni, valamint az Fpc fordítóját se tudom megregulázni, hogy "gyors assembler kódot generáljon".
Egyébként a nasm-mel is próbáltam fordítani. :)
Hát, ehhez nem kell tudni assemblyben programozni.
Az eax egy 32 bites regiszter, amelynek a bitszélessége éppen megegyezik az általad határértékként definiált szám bitszélességével.
- Az xor kinullázza az EAX regisztert
- az INC egyel növeli az utána lévő regiszter (esetünkben az EAX) tartalmát.
- A CMP összehasonlítja a regiszter (EAX) tartalmát adott értékkel (2147483647) és aha a kettő azonos, akkor bebillenti a ZERO felag-et.
- a JNZ pedig ennek a flag-nek a vizsgálata után ugrik a 'loop' cimkével megfeleltetett címre, ha a flag <> mint zero.
Köszi, hogy elmagyaráztad.
A C fordító ugyanezt az "O3" optimalizációval meg tudja csinálni? Mivel ezt alkalmazva a másodperc tört része alatt fut a kód.
Feltételezem, hogy képes erre, de nem tudom, hogy milyen c fordítóval erőlködsz és azt sem, hogy milyen kódot kivánnál lefordíttatni vele.
A pure nasm nem tudom, miért nem felel meg?
Annyit tudni kell, hoghy a példámban szereplő "loop" címke valós asm forrásban nem fog működni, mert a "loop" az x86 assemblynek egy foglalt szava.
Cseréld ki a loop-ot eloop-ra, vagy bármi másra és akkor jó lesz.
Köszi a magyarázatokat.
Az fpc fordítónak adtam, hogy a nasm-mel fordítsa a kódot, hasonló soksoros assembler-kimenet lett belőle és eltérő .exe. Én meg nem értek hozzá. :)
C esetén Linux alatt a sima GCC-vel fordítottam.
#include <stdio.h>
void main() {
for (int i=0; i<2147483647;i++) { }
}
Ha C-ben írsz egy ciklust, hogy
for(int i=0; i < 2147483647; ++i);
azt O2-nél nagy valószínűséggel egy nop-ra cseréli. Ugyan nem számol el semeddig, de gyors, és a program eredménye szempontjából nem változik semmi.
Utánanéztem hogyan lehet nasm-mel futtatható exe-t gyártani. Olyan 2 mp alatt fut le.
Biztos hogy nálam van a probléma.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!