Source file: /~heha/hs/Kalenderpuzzle.zip/src/msc.c

// Normalerweise wäre _alloca(size_t) ein simples "sub esp,eax".
// Aber das Win32-Speicherlayout macht einen Strich durch die Rechnung und verlangt,
// dass der Stack Seite für Seite abwärts belegt wird.
// Sonst kommt eine Schutzverletzung.
// Oder man legt per Linker-Schalter ein reichliches Commit für den Stack fest. (Geht das??)
// Daher generiert der Compiler für _alloca() sowie für Funktionen mit mehr als 4 KByte
// lokale Variablen einen Aufruf dieser Funktion.
// Prinzipiell könnte diese eax/4 push-Befehle ausführen …
// PE: eax = Zu reservierende Bytes
// PA: esp = Anfang des Speicherbereiches
// VR: eax

#define PROC void _declspec(naked) _cdecl
void _cdecl _chkstk();

#if _MSC_VER >= 1400
// Umstandskasten MSVC2008: Unpassende stdio.h, unpassend zu msvcrt.dll
#include <stdio.h>
_CRTIMP extern FILE _iob[];	// msvcrt.dll bietet Datenexport: Zeiger auf 3× FILE-struct
static FILE*_cdecl my_iob() {return _iob;}	// stdio.h erwartet dito als Funktionsesport
// Einen Zeiger auf _iob_func() anbieten, Zeiger weil DLL-Bindung
const FILE*(_cdecl*_imp____iob_func)() = my_iob;

PROC _alloca_probe_16() {_asm{	// außerdem heißt's nicht _alloca_probe sondern _alloca_probe_16
	jmp	_chkstk		// und der Compiler generiert INT3 statt nichts
}}
#else
PROC _alloca_probe() {_asm{	// MSVC6 läuft ohne weiteren Opcode hinein? Nicht ohne /debug!
	jmp	_chkstk
}}
#endif
PROC _chkstk() {_asm{
	add	eax,3
	and	al,~3		// Teilbarkeit durch 4 sicherstellen
	push	ecx
	 lea	ecx,[esp]+8	// ecx = Endadresse auf Stack
	 jmp	short testpg
onepg:	 sub	ecx,4096
	 sub	eax,4096
	 test	dword ptr [ecx],eax	// seitenweise Speicherlesezyklus anstoßen
testpg:	 cmp	eax,4096
	 jae	short onepg
	 sub	ecx,eax		// ecx = Startadresse auf Stack
	 mov	eax,esp		// eax = Zeiger auf ursprüngliches ecx
	 test	dword ptr [ecx],eax	// nochmal Speicherlesezyklus
	 mov	esp,ecx		// esp = Startadresse (Rückgabewert)
	mov	ecx,[eax]	// ecx restaurieren
	jmp	dword ptr[eax+4]// Rücksprung zum Aufrufer
}}

PROC _aullshr() {_asm{
	btr	ecx,5
	jc	short l1	// Für Schiebelängen >= 32 ohne shrd
	shrd	eax,edx,cl
	shr	edx,cl
	ret
l1:	mov	eax,edx
	xor	edx,edx
	shr	eax,cl
	ret 
}}

PROC _allshl() {_asm{
	btr	ecx,5
	jc	short l1	// Für Schiebelängen >= 32 ohne shld
	shld	edx,eax,cl
	shl	eax,cl
	ret
l1:	mov	edx,eax
	xor	eax,eax
	shl	edx,cl
	ret
}}

PROC _allmul() {_asm{
	mov	eax,[esp+8]	// hi(f1)
	mov	ecx,[esp+16]	// hi(f2)
	or	ecx,eax
	mov	ecx,[esp+12]	// lo(f2)
	jnz	short l1
	mov	eax,[esp+4]	// lo(f1)
	mul	ecx		// edx:eax = lo(f2)×lo(f1)
	ret	16
l1:	push	ebx
	 mul	ecx		// (edx:)eax = lo(f2)×hi(f1)
	 mov	ebx,eax
	 mov	eax,[esp+8]	// lo(f1)
	 mul	dword ptr[esp+20]// (edx:)eax = lo(f1)×hi(f2)
	 add	ebx,eax
	 mov	eax,[esp+8]
	 mul	ecx		// edx:eax = lo(f2)×lo(f1)
	 add	edx,ebx
	pop	ebx
	ret	16
}}

// Hier: Nur für DWORD-Divisor!
PROC _aulldiv() {_asm{
	mov	eax,[esp+8]	//High-Teil Zähler
	mov	ecx,[esp+12]	//Nenner
	xor	edx,edx
	div	ecx		//EAX=Ergebnis, EDX=Rest
	push	eax
	 mov	eax,[esp+8]	//Low-Teil Zähler
	 div	ecx		//EAX=Ergebnis, EDX=Rest
	pop	edx		//Rest durch High-Teil ersetzen
	ret	16
}}
Detected encoding: UTF-80