Ich empfehle doch FASM. Eine EXE lässt sich sofort aus dem Quell-Code erstellen; ohne (extra) Compiler und Linker. Tests (von Teilstücken) lassen sich bei Bedarf bequem mit PB austesten. Der Quellcode ist mit jedem x-beliebigen Text-Editor erstellbar, wenn die FASM-eigene Umgebung (sehr spartanisch, aber funktionell) nicht zusagt. Und: Der Quellcode sieht mMn wirklich nach Assembler aus
Da ich meist auch gern ein Beispiel liefere und Du wohl welche suchst, hier ein etwas älterer Primzahlen-Test mit der Divisions-Methode. Älter, weil ich sonst nur noch 64-Bit-Progs erstelle (Rücksicht auf Dein System).
Ich habe auch die Kommentare nicht verändert; der Code ist verbesserungsbedürftig, aber erfüllt seinen Zweck. Und: Die Exe ist schlappe 3KB groß!
Es ist auch egal, ob dies auf einem 32-oder 64-Bit-System ausgeführt wird; die EXE ist 32-Bit (auch ein Vorteil von FASM!).
Code: Alles auswählen
;Von flatassembler.net die aktuelle Windows-Version herunterladen, entpacken, bei include für "...\Include\win32a.inc" den Pfad anpassen und los gehts!
;Es wird auch unter 64-Bit-Windows eine 32-Bit-Exe erstellt!
;flat assembler 1.70.03
;Kein Multi-Threading
;28.07.2012, Ergebnis für i7-3770K @4.1GHz, Win7/64-Bit, nur Core2: Endwert=100000, Zeit=1310ms
;Viel Spaß wünscht Helle
format PE GUI 4.0
include 'C:\Codes\FAsm\Programm\Include\win32a.inc' ;Pfad anpassen!
entry start
section '.text' code readable executable
start:
invoke GetModuleHandle,0
mov [hInstance],eax
invoke RegisterClass,wc
invoke CreateWindowEx,0,_class,_text1,WS_VISIBLE+WS_OVERLAPPEDWINDOW,100,150,1000,500,NULL,NULL,[hInstance],NULL ;100=X-Pos., 150=Y-Pos., 1000=Breite, 500=Höhe
mov [hWnd],eax
;======================================================================================================================
;Anfang Test-Code, hier incl. Bildschirm-Ausgabe von unsigned Integers
;======================================================================================================================
;hier ist der Bereich für eigenen Test-Code; das Ergebnis steht in EINEM String!
invoke CreateThread,NULL,0,thread_test,0,0,0 ;für den Testcode wird ein Thread erzeugt
mov [hThread],eax
;---> CORE-ZUORDNUNG, selber testen!
invoke SetThreadAffinityMask,[hThread],100b ;0b=keine Zuordnung, 1b=Core0, 10b= Core1, 100b= Core2 usw. Bei Zuweisung von mehreren (oder keine) Cores verteilt Windows!
;--->
jmp End_Selbst
proc thread_test
;Startzeit nehmen
invoke QueryPerformanceCounter,Start
;hier ein Test für DIV mit Primzahl-Ermittlung
;---> ENDWERT, selber testen!
mov [Endwert],100000 ;bis dahin Primzahlen ermitteln, ist hier nur ein Testwert
;--->
invoke VirtualAlloc,0,Endwert/2,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE ;Speicher für die Dezimal-Zahlen der Ausgabe reservieren
mov [Ergebnis],eax ;Buffer-Adresse
invoke VirtualAlloc,0,Endwert+512,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE ;Speicher für die Hex-Prim-Zahlen reservieren, 512 als Sicherheits-Buffer für kleinen Endwert; Pi mal Daumen
mov [AdrPrime],eax ;Buffer-Adresse
mov edi,eax ;AdrPrime, Anfangs-Adresse Buffer Primzahlen
xor ebx,ebx ;PrimeCounter, Anzahl Primzahlen
mov dword[edi],2 ;Startwert muss ungerade sein, deshalb wird vereinfachend "2" direkt in die Primzahl-Liste geschrieben
inc ebx
add edi,4 ;es werden Double-Words geschrieben
mov ecx,3 ;Startwert
Prim0: ;Beginn eigentliche Primzahl-Ermittlung
mov esi,2 ;Divisor
@@:
xor edx,edx ;reicht für unsigned
mov eax,ecx ;Dividend
div esi
inc esi
or edx,edx ;Divisionsrest Null?
jnz @b
cmp esi,ecx
jb @f ;Primzahl ist, die nur durch 1 und sich selbst teilbar ist
mov [edi],ecx ;gefundene Primzahl in Speicher schreiben für Anzeige
add edi,4 ;Double-Words
inc ebx
@@:
add ecx,2
cmp ecx,[Endwert]
jb Prim0 ;Ende eigentliche Primzahl-Ermittlung
;Berechnung beendet, Endzeit nehmen
invoke QueryPerformanceCounter,Ende
invoke QueryPerformanceFrequency,Freq
fninit ;hier FPU, weil Werte (Integer-)Quads sind
fild qword[Ende] ;Zeit = (Ende - Start) / Freq
fild qword[Start]
fsubp st1,st0
fmul qword[Tausend]
fild qword[Freq]
fdivp st1,st0
fistp dword[edi] ;ist Zeit in ms
add edi,4
mov [edi],ebx ;PrimeCounter
add edi,4
mov eax,[Endwert]
mov [edi],eax
add ebx,3 ;Zeit, Startwert und PrimeCounter sollen mit in Dezimal umgewandelt werden
;Konvertierung Hex in Ausgabe-String, hier eigene Routine, evtl. vorher Abschätzung auf Länge Dezimal-String
mov [PrimeCounter],ebx
mov edi,[Ergebnis] ;Anfangs-Adresse String-Buffer
mov esi,[AdrPrime] ;Anfangs-Adresse zu konvertierende Hex-Zahlen
mov dword[AnzChars],0 ;Zeichenzähler für Zeilenlänge
Konv0:
xor edx,edx ;DL=Ziffer
xor ebx,ebx ;Pointer in Dezi-Tabelle
mov dword[LeadNull],0 ;Merker führende Null(en)
mov eax,[Dezi+ebx] ;Wert aus Dezi-Tabelle
mov [DeziWert],eax
mov eax,[esi]
mov ecx,eax
Konv1:
sub eax,[DeziWert]
jc @f
inc dl
mov ecx,eax
jmp Konv1
@@:
cmp dl,byte[LeadNull] ;führende Nullen ausblenden
je @f
mov byte[LeadNull],0ffh ;blöd, mal sehen
or dl,30h ;Dezimal-Ziffer schreiben
mov [edi],dl
inc dword[AnzChars] ;Zeichenzähler
inc edi ;Pointer in String-Buffer
@@:
add ebx,4
mov eax,[Dezi+ebx]
mov [DeziWert],eax
or eax,eax
jz @f ;Ende erreicht
mov eax,ecx
xor edx,edx
jmp Konv1
@@:
or cl,30h ;letzte Ziffer
mov [edi],cl
inc dword[AnzChars]
dec dword[PrimeCounter] ;Zähler Hex-Werte
jz Schluss
inc edi
mov byte[edi],20h ;Leerzeichen schreiben
cmp dword[AnzChars],135 ;max.Zeichen pro Zeile, je nach Lust und Laune und Fensterbreite (s.o.)
jb @f
inc edi ;ja, nächste Zeile
mov byte[edi],0dh
inc edi
mov byte[edi],0ah
mov dword[AnzChars],0
@@:
inc dword[AnzChars]
add esi,4
inc edi
jmp Konv0
Schluss: ;fertig mit Konvertierung Hex-Werte -> String
;Werte in Windows-Titel schreiben, hier direkt in vorhandenen String reinschreiben
;das Ganze ist grauselig schlecht programmiert und nicht weiter vorzeigenswert; es soll hier nur seinen Zweck erfüllen
lea eax,[_text2] ;Text mit hoffentlich genügend Freizeichen ;-)
add eax,75 ;Pi mal Daumen
@@:
mov dl,[edi] ;Endwert
cmp dl,20h ;Leerzeichen oder CR/LF
jbe @f
dec eax
mov byte[eax],dl
mov byte[edi],0
dec edi
jmp @b
@@:
dec edi
mov dl,[edi]
cmp dl,20h ;Leerzeichen oder CR/LF
jbe @b
lea eax,[_text2]
add eax,87
@@:
mov dl,[edi] ;PrimeCounter
cmp dl,20h ;Leerzeichen oder CR/LF
jbe @f
dec eax
mov byte[eax],dl
mov byte[edi],0
dec edi
jmp @b
@@:
lea eax,[_text2]
add eax,115
@@:
dec edi
mov dl,[edi]
cmp dl,20h ;Leerzeichen oder CR/LF
jbe @b
@@:
mov dl,[edi] ;Zeit
cmp dl,20h ;Leerzeichen oder CR/LF
jbe @f
dec eax
mov byte[eax],dl
mov byte[edi],0
dec edi
jmp @b
@@:
invoke SetWindowText,[hWnd],_text2
invoke SendMessage,[edithwnd],WM_SETTEXT,0,[Ergebnis] ;Ausgabe des Ergebnis-Strings
ret
endp
End_Selbst:
;======================================================================================================================
;Ende Test-Code incl. Bildschirm-Ausgabe von unsigned Integers
;======================================================================================================================
;--------------------------------------------------------------------------
msg_loop:
invoke GetMessage,msg,NULL,0,0
cmp eax,1
jb end_loop
jne msg_loop
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp msg_loop
end_loop:
invoke ExitProcess,[msg.wParam]
proc WindowProc hwnd,wmsg,wparam,lparam
cmp [wmsg],WM_CREATE
je .wmcreate
cmp [wmsg],WM_DESTROY
je .wmdestroy
.defwndproc:
invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
jmp .finish
.wmcreate:
invoke GetClientRect,[hwnd],client
invoke CreateWindowEx,WS_EX_CLIENTEDGE,_edit,0,WS_VISIBLE+WS_CHILD+WS_HSCROLL+WS_VSCROLL+ES_AUTOHSCROLL+ES_AUTOVSCROLL+ES_MULTILINE,[client.left],[client.top],[client.right],[client.bottom],[hwnd],0,[hInstance],NULL
mov [edithwnd],eax
invoke CreateFont,14,0,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH+FF_DONTCARE,NULL
mov [editfont],eax
invoke SendMessage,[edithwnd],WM_SETFONT,eax,FALSE
jmp .finish
.wmdestroy:
invoke DeleteObject,[editfont]
invoke PostQuitMessage,0
.finish:
ret
endp
;----------------------------------------------------------------------------------------------------------------------
section '.data' data readable writeable
;======================================================================================================================
;Anfang Test-Daten
;======================================================================================================================
Dezi dd 1000000000 ;für Konvertierung Hex in Dezimal-String für Ausgabe
dd 100000000
dd 10000000
dd 1000000
dd 100000
dd 10000
dd 1000
dd 100
dd 10
dd 0
Endwert dd ?
AdrPrime dd ?
Ergebnis dd ?
PrimeCounter dd ?
AnzChars dd ?
LeadNull dd ?
DeziWert dd ?
_text1 TCHAR 'Warte, warte noch ein Weilchen...',0
_text2 TCHAR 'CPU-DIV-Test 32-Bit (Primzahl-Ermittlung): Anzahl Primzahlen bis : ; Benötigte Zeit : ms',0
;======================================================================================================================
;Ende Test-Daten
;======================================================================================================================
wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class
Align 8 ;muss sein!
Freq dq ? ;für Zeit-Messung
Start dq ?
Ende dq ?
Tausend dq 1000.0 ;Float DP
hWnd dd ?
hInstance dd ?
hThread dd ?
edithwnd dd ?
editfont dd ?
msg MSG
client RECT
_class TCHAR 'Ausgabe',0
_edit TCHAR 'edit',0
;----------------------------------------------------------------------------------------------------------------------
section '.idata' import data readable writeable
library kernel,'KERNEL32.DLL',\
user,'USER32.DLL',\
gdi,'GDI32.DLL'
import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess,'ExitProcess',\
SetThreadAffinityMask,'SetThreadAffinityMask',\
CreateThread,'CreateThread',\
VirtualAlloc,'VirtualAlloc',\
QueryPerformanceFrequency,'QueryPerformanceFrequency',\
QueryPerformanceCounter,'QueryPerformanceCounter'
import user,\
RegisterClass,'RegisterClassA',\
CreateWindowEx,'CreateWindowExA',\
DefWindowProc,'DefWindowProcA',\
TranslateMessage,'TranslateMessage',\
DispatchMessage,'DispatchMessageA',\
GetClientRect,'GetClientRect',\
SendMessage,'SendMessageA',\
PostQuitMessage,'PostQuitMessage',\
GetMessage,'GetMessageA',\
SetWindowText,'SetWindowTextA'
import gdi,\
CreateFont,'CreateFontA',\
DeleteObject,'DeleteObject'