C Funktion ohne Stack

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

C Funktion ohne Stack

Beitrag von Dirty Oerti » Fr Mär 26, 2010 3:49 pm

Tag zusammen :)

Gibt es eine Möglichkeit, dass der folgende Code, der ja nun eigentlich wirklich keinen Stack braucht, vom gcc (bzw jedem anderen) C-Compiler auch ohne Stack kompiliert wird, oder muss ich auf Assembler zurückgreifen?

Code: Alles auswählen

INTO_SECTION( void switchtask(IRQ_Information *r), ".linked" )
{
	if (*MyPriorityLeft > 0) {
		(*MyPriorityLeft)--;
	} else {
		asm volatile("mov %%esp, %0" : "=r"(*My_esp));
		*My_eip = read_eip();
		if (*My_eip == 0x123) {
			return;
		}
		*MyPriorityLeft = *MyPriority;
		enable_paging(*NextTask_cr3);
		asm volatile("cli");
		asm volatile("mov %0, %%ecx" : : "r"(*My_eip));
		asm volatile("mov %0, %%esp" : : "r"(*My_esp));
		asm volatile("mov $0x123, %eax");
		asm volatile("sti");
		asm volatile("jmp *%ecx");
	}
} 
Dieser Code wird kompiliert zu:

Code: Alles auswählen

ffc00000 <switchtask>:
ffc00000:	55                   	push   %ebp
ffc00001:	89 e5                	mov    %esp,%ebp
ffc00003:	53                   	push   %ebx
ffc00004:	83 ec 14             	sub    $0x14,%esp
ffc00007:	a1 ac 06 c0 ff       	mov    0xffc006ac,%eax
ffc0000c:	8b 00                	mov    (%eax),%eax
ffc0000e:	85 c0                	test   %eax,%eax
ffc00010:	74 0e                	je     ffc00020 <switchtask+0x20>
ffc00012:	a1 ac 06 c0 ff       	mov    0xffc006ac,%eax
ffc00017:	8b 10                	mov    (%eax),%edx
ffc00019:	83 ea 01             	sub    $0x1,%edx
ffc0001c:	89 10                	mov    %edx,(%eax)
ffc0001e:	eb 60                	jmp    ffc00080 <switchtask+0x80>
ffc00020:	a1 b8 06 c0 ff       	mov    0xffc006b8,%eax
ffc00025:	89 e2                	mov    %esp,%edx
ffc00027:	89 10                	mov    %edx,(%eax)
ffc00029:	8b 1d bc 06 c0 ff    	mov    0xffc006bc,%ebx
ffc0002f:	e8 73 06 00 00       	call   ffc006a7 <read_eip>
ffc00034:	89 03                	mov    %eax,(%ebx)
ffc00036:	a1 bc 06 c0 ff       	mov    0xffc006bc,%eax
ffc0003b:	8b 00                	mov    (%eax),%eax
ffc0003d:	3d 23 01 00 00       	cmp    $0x123,%eax
ffc00042:	74 3b                	je     ffc0007f <switchtask+0x7f>
ffc00044:	a1 ac 06 c0 ff       	mov    0xffc006ac,%eax
ffc00049:	8b 15 b0 06 c0 ff    	mov    0xffc006b0,%edx
ffc0004f:	8b 12                	mov    (%edx),%edx
ffc00051:	89 10                	mov    %edx,(%eax)
ffc00053:	a1 b4 06 c0 ff       	mov    0xffc006b4,%eax
ffc00058:	8b 00                	mov    (%eax),%eax
ffc0005a:	89 04 24             	mov    %eax,(%esp)
ffc0005d:	e8 0f 04 00 00       	call   ffc00471 <enable_paging>
ffc00062:	fa                   	cli    
ffc00063:	a1 bc 06 c0 ff       	mov    0xffc006bc,%eax
ffc00068:	8b 00                	mov    (%eax),%eax
ffc0006a:	89 c1                	mov    %eax,%ecx
ffc0006c:	a1 b8 06 c0 ff       	mov    0xffc006b8,%eax
ffc00071:	8b 00                	mov    (%eax),%eax
ffc00073:	89 c4                	mov    %eax,%esp
ffc00075:	b8 23 01 00 00       	mov    $0x123,%eax
ffc0007a:	fb                   	sti    
ffc0007b:	ff e1                	jmp    *%ecx
ffc0007d:	eb 01                	jmp    ffc00080 <switchtask+0x80>
ffc0007f:	90                   	nop
ffc00080:	83 c4 14             	add    $0x14,%esp
ffc00083:	5b                   	pop    %ebx
ffc00084:	5d                   	pop    %ebp
ffc00085:	c3                   	ret    
Und das erscheint mir doch etwas umständlich.
Außerdem zählt hier wirklich jede Anweisung weniger, da dieser Code nunmal 100 - 10000 mal pro Sekunde aufgerufen wird.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C Funktion ohne Stack

Beitrag von Xin » Fr Mär 26, 2010 3:54 pm

Afaik baucht "ret" den Stack und Du übergibst einen Pointer.
Damit Du auf den Stack verzichten kannst, müsste die Funktion inline sein. Inline gibt's aber erst ab C++.

Es bleibt also erstmal die Frage, ob die Funktion wirklich rufbar sein muss.
Ansonsten kannst Du in C ein Macro draus machen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C Funktion ohne Stack

Beitrag von Dirty Oerti » Fr Mär 26, 2010 4:08 pm

Hm, ich hab die Funktion etwas abgeändert (der Funktionsruf wurde sinnigerweise ersetzt), jetzt reserviert sich die Funktion schonmal nicht mehr so viel Speicher auf dem Stack.
Ziel wäre es, die Funktion soweit zu bringen, dass sie das push ebp und pop ebp weglassen kann, sprich kein eigener Stackframe angelegt wird.
?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C Funktion ohne Stack

Beitrag von Dirty Oerti » Fr Mär 26, 2010 4:16 pm

Würde es was bringen, wenn ich die Zeiger direkt dort mit den Werten, wohin sie zeigen angebe?
Die entsprechenden Zeiger sind wie folgt festgelegt:

Code: Alles auswählen

UINT *MyPriorityLeft		__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE000;
UINT *MyPriority			__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE004;
UINT *NextTask_cr3		__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE008;
UINT *My_esp			__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE00C;
UINT *My_eip			__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE010;
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C Funktion ohne Stack

Beitrag von Xin » Fr Mär 26, 2010 4:28 pm

Dirty Oerti hat geschrieben:Hm, ich hab die Funktion etwas abgeändert (der Funktionsruf wurde sinnigerweise ersetzt), jetzt reserviert sich die Funktion schonmal nicht mehr so viel Speicher auf dem Stack.
Was heißt, der Funktionsruf wurde ersetzt?
Dirty Oerti hat geschrieben:Würde es was bringen, wenn ich die Zeiger direkt dort mit den Werten, wohin sie zeigen angebe?
Die Zeiger werden wohl konstant sein, hm? Dann kann der Compiler sich den Zugriff auf die Variable sparen und einfach auf die Konstante zugreifen. So könnte es ja sein, dass jemand die Zeiger überschreibt.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C Funktion ohne Stack

Beitrag von Dirty Oerti » Fr Mär 26, 2010 4:53 pm

"enable_paging(*NextTask_cr3)" ist rausgeflogen, dafür steht jetzt

Code: Alles auswählen

asm volatile("mov %0, %%cr3":: "r"(*NextTask_cr3));
da, was sinnvoller ist.
Die Zeiger werden wohl konstant sein, hm? Dann kann der Compiler sich den Zugriff auf die Variable sparen und einfach auf die Konstante zugreifen. So könnte es ja sein, dass jemand die Zeiger überschreibt.
Genau das meine ich. Sinnigerweise lässt der gcc mich die Zeiger aber nicht als konstant deklarieren ...
Sprich die Zeiger zeigen IMMER auf diese Stelle im Speicher.
Die Werte darin ändern sich natürlich.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C Funktion ohne Stack

Beitrag von Xin » Fr Mär 26, 2010 4:59 pm

Dirty Oerti hat geschrieben:
Die Zeiger werden wohl konstant sein, hm? Dann kann der Compiler sich den Zugriff auf die Variable sparen und einfach auf die Konstante zugreifen. So könnte es ja sein, dass jemand die Zeiger überschreibt.
Genau das meine ich. Sinnigerweise lässt der gcc mich die Zeiger aber nicht als konstant deklarieren ...
Was ist daran sinnvoll!?
Dirty Oerti hat geschrieben:Sprich die Zeiger zeigen IMMER auf diese Stelle im Speicher.
Die Werte darin ändern sich natürlich.
Wie deklarierst Du Zeiger als konstant?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C Funktion ohne Stack

Beitrag von Dirty Oerti » Fr Mär 26, 2010 5:09 pm

Was ist daran sinnvoll!?
Nichts, deshalb war es ironisch gemeint :)
"ist" passt aber nicht, "war" passt besser.
Hab es nun nochmal mit const Zeigern versucht und es geht.
Entweder liegt es daran, dass bei meinem letzten Test mit const noch ein älterer gcc mit eventuellem Bug installiert war, oder, was ich für wahrscheinlicher halte, ich hatte einfach nicht den Zeiger als konstant deklariert, sondern den Wert, auf den der Zeiger zeigt, was ja Blödsinn wäre.
So funktioniert es auf jedenfall:

Code: Alles auswählen

UINT *const MyPriorityLeft		__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE000;
UINT *const MyPriority			__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE004;
UINT *const NextTask_cr3		__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE008;
UINT *const My_esp			__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE00C;
UINT *const My_eip			__attribute__ (( section(".linked_data"))) = (UINT *)0xFFFFE010;
Optimierung bringt das aber nicht, er schaut immer noch in der Speicherstelle für den Zeiger nach der Adresse, anstatt sie einfach direkt im Code zu verwenden.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Antworten