# Char vergleichen



## üäpöol (19. März 2012)

Hi,

ist nur ne kleine Sache. Ich möchte in C ein Char mit etwas vergleichen, im konkreten Fall:

```
if (szString[i] == '\0')
```
Leider funktioniert das nicht. Soweit ich mich entsinnen kann, darf man das auch so nicht machen. Dafür gibt es glaube ich strcmp(). Ich darf nur leider keine Bibliotheke includieren. Muss ich dafür extra eine Assemblerfunktion schreiben, oder geht das auch anders?


----------



## DexXxtrin (19. März 2012)

Bist du sicher dass dieser Teil nicht funktioniert?
Meines Wissens nach sollte dies so gehen...


----------



## üäpöol (19. März 2012)

Ich bin mir nicht ganz sicher, aber irgendwann endet doch jedes CharArray, oder?
Hier mehr Code:

```
int printString(char* szString) {
	int i=0;
	int finished=0;
	while (finished != 1)
	{
		if (szString[i] == '\0') {
			finished=1;
		}
		else {
			print(szString[i]);
			i=i+1;
		}
	}
	return 0;
}
```
Die Funktion print() funktioniert im Prinzip auch.
Ich habe das Problem schon so eingeschränkt, dass 
	
	
	



```
if (szString[i] == '\0')
```
 leider nie richtig ist, dadurch wird dann auch nicht zurückgesprungen.

Tut mir Leid, ich habe mich getäuscht. i wird nicht inkrementiert. Ich weiß leider nicht, warum.


----------



## sheel (19. März 2012)

Hi

print gibt also eine einzelnen char (keinen Pointer oder so) aus?
Dann müsste das funktionieren.
Geht zwar einfacher, aber sollte so auch passen.

(strcmp ist zum Vergleichen von zwei kompletten Strings.
Jeden char einzeln mit = so wie hier passt schon.)

Prüf mal, was als szString übergeben wird.
Ob das überhaupt eine \0 hat.


----------



## üäpöol (19. März 2012)

Print ist eine Assemblerfunktion, die das einzele Char ausgibt. Es muss an dem 'i' liegen, weil das nicht inkrementiert wird. Hm. Ich weiß nicht, wie ich überprüfen soll, was ankommt. Ich übergebe printString("Ha"); Aber C hängt doch automatisch ein Nullzeichen an, oder?


----------



## ibafluss (19. März 2012)

Gib am besten einmal den ganzen Code an. 
Ja, C hängt automatisch das Nullzeichen an.

Lg


----------



## üäpöol (19. März 2012)

Hi,

print.asm

```
[BITS 16]
global print

print:
	push bp
	mov bp, sp
	mov al, [bp+4]
	mov ah, 0x0E
	int 0x10
	pop bp
	ret
```

Und die C Datei

```
extern void print();
extern void restart();
extern char read();
int printString(char* szString);

short i=0;
short finished=0;

int main() {
	printString("Ha");
	while(read() != 'r');
	restart();
	return 0;
}

int printString(char* szString) {
    int i=0;
    int finished=0;
    while (finished != 1)
    {
        if (szString[i] == '\0') {
            finished=1;
        }
        else {
            print(szString[i]);
            i=i+1;
        }
    }
    return 0;
}
```

Ist alles 16 bit.


----------



## ibafluss (19. März 2012)

Also ich habe statt dem print() ein printf() genommen (ich kenne mich bei Assembler nicht aus) und alles hat funktioniert. Entweder liegt der Fehler am print(), oder in der main-Umgebung. 

Lg


----------



## üäpöol (19. März 2012)

Ich schreibe ein kleines OS. Deshalb kann ich keine Funktionen benutzen. print('X') funktioniert perfekt. Ich benutze GCC MinGW als Crosscompiler. Kann es daran liegen?


----------



## ibafluss (19. März 2012)

Was passiert eigentlich, wenn du die Funktion aufrufst? Also gibt es eine Endlosschleife, wird überhaupt etwas ausgegeben?

Lg


----------



## üäpöol (19. März 2012)

Es wird nichts ausgegeben, aber auch nicht returned. Es ist ein ewiges while...


----------



## ibafluss (19. März 2012)

Das kann gar nicht sein. Entweder muss das if oder das else betreten werden, aber keines ist nicht möglich. Funktionen kannst du gar keine aufrufen? Du müsstest am Ende des if-else ein system("pause") oder so in der Art platzieren, nur als Indikator, ob die Schleife wiederholt wird. 
Ich vermute, dass die Schleife nicht betreten wird. 

Oder könnte es sein, dass er in der Schleife im main hängt? Die mit read(), an der ist ein ; am Ende, das sieht mir auch relativ verdächtig aus.

Lg


----------



## üäpöol (19. März 2012)

Ich habe das ganze jetzt mal disassembliert. Das ganze while() funktioniert nicht. Ich springe an eine leere Position. Ich muss das anders lösen; Ich bin für jeden Vorschlag dankbar!


----------



## ibafluss (19. März 2012)

Warum springst du auf eine leere Position? Also, welche Anweisung ist dafür verantwortlich?

Lg


----------



## üäpöol (19. März 2012)

Der Funktionsaufruf printChar.


----------



## sheel (19. März 2012)

Es gibt keine leeren Positionen.
Und der Code ist nunmal korrekt.
gcc macht auch sehr sehr sicher nichts falsch beim Kompilieren.
...
Wie fügt sich das Programm überhaupt ins Betriebssytem ein?
main?


----------



## üäpöol (19. März 2012)

Ich habe mich falsch ausgedrückt. Die Position ist natürlcih nicht leer, sondern einfach nur 'NUL'.


----------



## saftmeister (19. März 2012)

Ich habe mal eine Frage: Kann es sein, dass dein OS von einem Bootloader geladen wird, der in den Protected-Mode umschaltet?


----------



## üäpöol (19. März 2012)

Leider stimmt das nur zur Hälfte. Mein OS wird von einem Bottloader geladen, beim PM bin ich leider noch nicht ganz.


----------



## saftmeister (19. März 2012)

Ich frage nur deshalb, weil BIOS-Interrupts im PM nicht gerufen werden dürfen. Versuch doch mal, den Video-Speicher direkt anzusprechen: http://www.lowlevel.eu/wiki/Textausgabe#Protected_Mode


----------



## DexXxtrin (20. März 2012)

Du definierst einmal short i=0 und short finished=0 und in der funktion die gleichen Namen nochmals mit dem Typ int... ändere da mal was, vielleicht gehts dann.


----------



## ibafluss (20. März 2012)

Nein, es wird bei gleichen Namen immer die lokalste Variable angesprochen, das bedeutet die globalen Variablen mit gleichen Namen stören den Compiler nicht.


----------



## DexXxtrin (20. März 2012)

Ich hab das Ganze mal mit dem selben Compiler ausprobiert, einfach folgendermassen:


```
#include <stdio.h>
int printString(char* szString);
 
short i=0;
short finished=0;
 
int main() {
    printString("Ha");
    while(read() != 'r');
    return 0;
}
 
int printString(char* szString) {
    int i=0;
    int finished=0;
    while (finished != 1)
    {
        if (szString[i] == '\0') {
            finished=1;
        }
        else {
			printf("%c", szString[i]);
			i=i+1;
        }
    }
    return 0;
}
```

Ich weiss dass du stdio.h nicht verwenden kannst. Aber die Tatsache, dass es so funktioniert lässt darauf schliessen, dass die print() Routine nicht funktioniert...
Oder kannst du sagen wo genau das Programm hängen bleibt?


----------



## sheel (20. März 2012)

Und falls es wirklich nicht print sein sollte, üäpöol, nocheinmal:
Welche Rolle/Position hat dieses Programm in deinem OS?
Das main weckt den Verdacht auf Missverständnisse...

Wie kompilierst du genau?
Wie wird das Ganze mit dem Asm-Teil zusammengehängt?
Wie von Asm aus aufgerufen...?


----------



## üäpöol (20. März 2012)

Das Problem ist print(). Ich muss die Funktion nochmal verändern. Ich kompiliere das C Programm mit gcc ins elf-Format. Die Asm-Dateien werden auch ins elf-Format assembliert und am Ende wird alles zusammen ins binäre gelinkt.

EDIT:
Genauer gesagt ist das Problem mit print, dass ich es nur einmal aufrufen kann und danach alles abstürzt. Ich vermute, dass das am Stack liegt.


----------



## DexXxtrin (20. März 2012)

Ich hätte auch auf ein Problem mit dem Stack oder so getippt.

Noch etwas. Weiss gerade nicht mehr wie das verarbeitet wird. Du übergibst ja "Ha" und hast danach nur noch ein Pointer zu diesem String, welcher temporär abgespeichert wird.
Kann es sein dass dieses "Ha" nicht mehr am existiert (an diesem Speicherplatz) nachdem du print() aufgerufen hast? Wenn ja, übergib mal ne Variabel...
Aber eben, mit ist nicht mehr bewusst wie das verarbeitet wird vom PC


----------



## deepthroat (20. März 2012)

üäpöol hat gesagt.:


> Genauer gesagt ist das Problem mit print, dass ich es nur einmal aufrufen kann und danach alles abstürzt. Ich vermute, dass das am Stack liegt.


Evtl. solltest du einfach mal den gesicherten Stackpointer wieder zurückschreiben?


DexXxtrin hat gesagt.:


> Noch etwas. Weiss gerade nicht mehr wie das verarbeitet wird. Du übergibst ja "Ha" und hast danach nur noch ein Pointer zu diesem String, welcher temporär abgespeichert wird.
> Kann es sein dass dieses "Ha" nicht mehr am existiert (an diesem Speicherplatz) nachdem du print() aufgerufen hast?


Nein, das kann nicht sein. Der String ist die ganze Programmlaufzeit über verfügbar.

Gruß


----------



## üäpöol (20. März 2012)

deepthroat hat gesagt.:


> Evtl. solltest du einfach mal den gesicherten Stackpointer wieder zurückschreiben?



Wie meinst du das genau? Wie ist der Stackpointer denn gesichert, oder soll ich ihn erst sichern?


----------



## saftmeister (20. März 2012)

Ich bin jetzt nicht so der ASM-Profi, aber könnte das nicht so funktionieren:


```
[BITS 16]
global print
 
print:
    push bp
    mov bp, sp
    mov al, [bp+4]
    mov ah, 0x0E
    int 0x10
    mov sp, bp
    pop bp
    ret
```


----------



## üäpöol (20. März 2012)

Wow, das ist ja genial! Zumindest stürzt das Programm jetzt nicht mehr (zumindest wenn ich print() selbst mehrfach aufrufe) ab, aber den Paramter bekomme ich leider nur beim ersten Aufruf der print() - vielleicht wird die Funktion auch nur einmal aufgerufen - und die Funktion printString gibt nur Müll aus, wonach alles wieder abstürzt.
Aber ich glaube, das geht in die richtige Richtung! Vielen Dank, saftmeister!

EDIT:
Ich habe jetzt herausgefunden, dass print() nicht mehrfach aufgerufen wird. Ich habe keinen Schimmer, warum nicht. Ich hoffe ihr könnt mir nochmal helfen.


----------



## saftmeister (21. März 2012)

Ich glaube so langsam, das es am GCC liegt, der 32Bit-Code erzeugt. Zu mindest wird das Thema hier http://forum.osdev.org/viewtopic.php?f=13&t=14157&start=0 behandelt.

Ich denke, du fährst besser, wenn du gleich in den Protected-Mode wechselst und 32-Bit-Code verwendest. So schwer ist das auch nicht, GrUB als Bootloader nimmt dir da einiges ab.

Edit: Hier gibts noch eine Erklärung, wie man mit GCC 16Bit-Code erzeugt: http://forum.lowlevel.eu/index.php?topic=1288.0

Meine Vermutung ist, das dein Code das derzeit nicht ist. Was gibt objdump auf das .o-File deines C-Codes aus?


----------



## üäpöol (21. März 2012)

Hm. Ich bin mir sicher, dass es am GCC liegt. Der 16-bit Trick funktioniert leider auch nicht, es funktioniert nichts mehr; ich kann keine Funktion aufrufen. Ich versuche jetzt mal in den PM zu wechseln.


----------



## üäpöol (24. März 2012)

Wow! Inzwischen funktionert der Trick!
Meine Funktion sieht so aus:

```
int printString(char* szString) {
	int i=0;
	int finished=0;

	while (finished != 1)
	{
		if (szString[i] != '\0') {
			print(szString[i]);
			i++;
		}
		else {
			finished=1;
		}
	}
	return 0;
}
```
und ich rufe sie so auf:

```
char szString[] = "Hallo Welt!";
printString(szString);
```
Leider stoppt die Funktion jetzt nie und es wird ewig Hallo Welt! ausgegeben... Ich verstehe leider nicht, warum. Ich hoffe mir kann jemand helfen. 

EDIT:
printString("Hallo Welt!") funktioniert nicht, weil der String nicht übergegeben wird.

EDIT2:
Ich benutze zurzeit asm(".code16gcc\n");.
Wenn ich asm(".code16\n"); stattdessen schreibe, werden mit 11 leere Zeichen ausgegeben. Ich fürchte hinter dem Problem steckt doch noch ein bisschen mehr.


----------



## saftmeister (24. März 2012)

Ist es möglich, das du in den Graphics-Mode gewechselt hast, bevor du Zeichen darstellen willst? Laut Ralf Brown-Liste müsstest du dann in das bl-Register noch einen Wert für Vordergrundfarbe kopieren. Das 0-Byte dürfte bewirken, das ein schwarzer Text ausgegeben wird.

Hier die Links: 

http://www.delorie.com/djgpp/doc/rbinter/id/11/1.html
http://en.wikipedia.org/wiki/INT_10H


----------



## üäpöol (24. März 2012)

Leider stimmt das nicht. Ich kann ganz normal Buchstaben ausgeben (mit mov al, 'X'). Deshalb kann es kaum am 10er Interrupt liegen. Hast du noch andere Ideen?

EDIT:
Ich glaube, ich spinne:

```
int printString(char* szString) {
	int i=0;
	while (i != 2)
	{
		print(szString[i]);
		i=i+1;
	}
	return 0;
}
```
Dieser Code gibt ewig HaHaHaHa usw. aus.
Ich versteh's nicht. Vielleicht will der Computer mich ja auslachen.


----------



## saftmeister (24. März 2012)

Wie gesagt, ich bin kein ASM-Profi, ich klau mir auch die Sachen aus dem Netz zusammen ;-)

Was mir allerdings noch aufgefallen ist: Der Datentyp int ist in der Regel 32bit groß. Versuch mal statt dessen short.

Hast du mal das Objekt-File deines C-Sources disassembliert? Wenn da irgendwelche 32bit-Register vorkommen, ist das natürlich ungünstig.

Edit: Kannst du mal den Code zeigen, der "printString" aufruft? Also alles, was so da drum rum ist.


----------



## üäpöol (24. März 2012)

short oder int ändert nichts. Ich hab das ganze disassembliert, und es werden 32bit Register verwendet. Hier ist der gesamte Sourcecode:

```
asm(".code16gcc\n");
extern void print();
extern void restart();
extern char read();
int printString(char* szString);

int main() {
	char szString[] = "Hallo Welt!";
	printString(szString);
	while(read() != 'r');
	restart();
	return 0;
}

int printString(char* szString) {
	short i=0;
	while (i != 2)
	{
		print(szString[i]);
		i=i+1;
	}
	return 0;
}
```
Wie gesagt, ich verstehe nicht, warum das Programm nicht aus der Funktion zurückkehrt.

EDIT:
Das ist übrigens das disassemblierte:

```
00000210  6653              push ebx
00000212  6683EC14          sub esp,byte +0x14
00000216  67668B5C241C      mov ebx,[dword esp+0x1c]
0000021C  67660FBE03        movsx eax,byte [ebx]
00000221  6650              push eax
00000223  E87A00            call word 0x2a0
00000226  67660FBE4301      movsx eax,byte [ebx+0x1]
0000022C  6766890424        mov [dword esp],eax
00000231  E86C00            call word 0x2a0
00000234  66B800000000      mov eax,0x0
0000023A  6683C418          add esp,byte +0x18
0000023E  665B              pop ebx
00000240  C3                ret
00000241  67668D4C2404      lea ecx,[dword esp+0x4]
00000247  6683E4F0          and esp,byte -0x10
0000024B  6766FF71FC        push dword [ecx-0x4]
00000250  6655              push ebp
00000252  6689E5            mov ebp,esp
00000255  6651              push ecx
00000257  6683EC20          sub esp,byte +0x20
0000025B  6766C745EC48616C  mov dword [ebp-0x14],0x6c6c6148
         -6C
00000264  6766C745F06F2057  mov dword [ebp-0x10],0x6557206f
         -65
0000026D  6766C745F46C7421  mov dword [ebp-0xc],0x21746c
         -00
00000276  67668D45EC        lea eax,[ebp-0x14]
0000027B  6650              push eax
0000027D  E890FF            call word 0x210
00000280  6683C410          add esp,byte +0x10
00000284  E82900            call word 0x2b0
00000287  3C72              cmp al,0x72
00000289  75F9              jnz 0x284
0000028B  E83200            call word 0x2c0
0000028E  66B800000000      mov eax,0x0
00000294  67668B4DFC        mov ecx,[ebp-0x4]
00000299  C9                leave
0000029A  67668D61FC        lea esp,[ecx-0x4]
```


----------



## saftmeister (24. März 2012)

Ok, anscheinend ist das mit den 32-Bit-Registern doch in Ordnung, wenn man diesem Forum-Eintrag folgt: http://forum.osdev.org/viewtopic.php?f=13&t=14157&start=0

Insbesondere dieser Post ist dabei interessant: http://forum.osdev.org/viewtopic.php?p=98340#p98340

Welchen Kompiler (Version, Cross-Compiler-Fähigkeiten, etc.) verwendest du eigentlich genau? Hast du ein Makefile oder eine Batch-Datei zum kompilieren/linken? Welche Compile-/Link-Flags verwendest du?


----------



## üäpöol (24. März 2012)

Für Compiler/Linker, bin ich dieser Seite gefolgt: http://www.lowlevel.eu/wiki/Crosscompiler_für_Windows.
Ich benutze eine Batch zum Erstellen.
So sieht sie aus:

```
nasm\NASM.exe -f bin -o bootloader.bin bootloader.asm
nasm\NASM.exe -f bin -o padding.bin padding.asm
nasm\NASM.exe -f elf -o kernelA.elf kernel.asm
nasm\NASM.exe -f elf -o functions/read.elf functions/read.asm
nasm\NASM.exe -f elf -o functions/restart.elf functions/restart.asm
nasm\NASM.exe -f elf -o functions/print.elf functions/print.asm
compiler_linker\bin\i586-elf-gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o kernelB.elf kernel.c
compiler_linker\bin\i586-elf-ld.exe -T link.ld -o kernel.bin kernelA.elf kernelB.elf functions/print.elf functions/read.elf functions/restart.elf
copy bootloader.bin+kernel.bin+padding.bin OS.img
mkisofs\mkisofs.exe -b OS.img -o OS.iso OS.img
PAUSE
```


----------



## üäpöol (24. März 2012)

Ich komme dem Problem auf die Schliche.
Wenn ich das print() weglasse funktionierts (mit der .code16gcc Variante). Aber erklären kann ich mir das immer noch nicht.


----------



## saftmeister (24. März 2012)

Ich bin mir grad nicht so sicher, ob der Prototyp für print() richtig ist:


```
extern void print();
```

Möglicherweise optimiert der GCC da was weg. Mach doch mal ein


```
extern void print(char);
```

draus.


----------



## üäpöol (24. März 2012)

Ich habe das Problem gelöst.  In der print.asm muss ich o32 statt ret schreiben. Bisher funktioniert jetzt alles.


----------



## saftmeister (24. März 2012)

Das ist schön, was macht o32 denn? Ich finde auf die Schnelle keine x86 instruction list, in der das erklärt wird.


----------



## üäpöol (25. März 2012)

Das weiß ich leider auch nicht so genau. Ich habe das ganze nur disassembliert und gesehen, dass bei asm(".code16"); das o32 automatisch eingefügt wird. Das habe ich so manuell gemacht.

Hi,
ich habe das nächste Problem mit GCC.

```
//...
testfunc('a');
//...
void testfunc(char test) {
	print(test);
	print(test);
	print(test);
}
```
Gibt das a nur einmal aus. Das ist bei jeder Funktion so. Die Paramter kommen nur beim ersten Aufruf an. Eine Puffervariable, also char testvar=test; bringt auch nichts. Die Funktion print() wird aber definitiv dreimal aufgerufen. Wer sich den restlichen Code etc. mal anschauen möchte, kann ja hier vorbeischauen: http://www.tutorials.de/c-c/385923-char-vergleichen.html
Was ist nur mit diesem GCC los?!
Danke im Voraus.

EDIT:


> Jedenfalls denke ich kaum, dass an meinem Code funktioniert, da dieses Problem nur in einer Funktion und nicht einfach so auftritt. Ändere ich die Funktion print() so, dass immer der selbe Buchstabe angezeigt wird gibt es kein Problem und wenn ich print() einfach so dreimal im Code aufrufe, wird auch dreimal der übergebene Buchstabe angezeigt.


----------



## FSA (26. März 2012)

Könnte es sein, dass das weg optimiert wird? Wäre aber sehr eigenartig. Kannst du die Optimierungsfunktion an aus schalten? Probiere mal printf("a");
MfG


----------



## deepthroat (26. März 2012)

Hi.

Das o32 ist nur eine Meta-Anweisung für den Assembler, dass die darauffolgende Instruktion im 32 Bit Modus assembliert werden soll. üäpöol hat sich schlecht ausgedrückt, er hat o32 nicht statt ret genommen sondern o32 vor das ret gesetzt.

Wenn der GCC einen 32bit CALL macht (und EIP pusht), dann sollte man natürlich in der Funktion auch einen 32bit RET durchführen.

Wenn du allerdings im .code16 Modus (ohne gcc) kompilierst, dann erzeugt der Assembler auch nur ein 16bit CALL.

@üäpöol: Warum machst du denn ein neues Thema auf? Anscheinend funktioniert es ja doch nicht so wirklich... Und am GCC liegt es höchstwahrscheinlich nicht, sondern an deinem Code.

Gruß


----------



## üäpöol (26. März 2012)

Hi,
ich wollte ein neues Thema aufmachen, weil das imho wirklich nichts mehr mit Chars vergleichen zu tun hat, aber vielleicht ist sheel ja so nett und löscht das Thema wieder, wenn er deiner Meinung ist. Wie auch immer. Jedenfalls denke ich kaum, dass an meinem Code funktioniert, da dieses Problem nur in einer Funktion und nicht einfach so auftritt. Ändere ich die Funktion print() so, dass immer der selbe Buchstabe angezeigt wird gibt es kein Problem und wenn ich print() einfach so dreimal im Code aufrufe, wird auch dreimal der übergebene Buchstabe angezeigt. Ich weiß nicht, ob das hilft.

edit:
Hm. Das hilft leider nichts. Es wird einmal ein leeres (\0) Zeichen ausgegeben.


----------



## sheel (26. März 2012)

Beide Themen zusammengefügt.


----------



## üäpöol (26. März 2012)

Danke, sheel. Ich habe die Funktion print() (und andere, die mit Paramtern arbeitern) in verschiedenen Situationen überprüft, aber der Paramter der Funktion testfunc() kommt jedesmal nur einmal an. Komisch, dass auch eine Puffervariable nichts bringt. Hat jemand eine Idee?


----------



## deepthroat (27. März 2012)

Hi.

Wie sieht denn dein Code momentan genau aus? Hast du code16 oder code16gcc verwendet?

Wie stellst du denn fest, ob die Funktion 3 Mal aufgerufen wird? Hast du dir das im Debugger angesehen?

Gruß


----------



## üäpöol (27. März 2012)

Hi,

ich verwende asm(".code16gcc\n");.
Wenn die print() so aussieht, wird dreimal b ausgegeben.

```
[BITS 16]
global print

print:
	push ebp
	mov ebp, esp
	mov al, 'b'
	mov ah, 0x0E
	mov bl, 0x07
	int 0x10
	mov ebp, esp
	pop ebp
	o32 ret
```

(normalerweise steht [ebp+8] statt 'b' da).

Meine kernel.c sieht im Moment so aus:

```
asm(".code16gcc\n");
extern void print();
extern void restart();
extern char read();
void printString(char* szString);
void testfunc(char test);

int main() {
	char szWelcome[] = "Hello world, welcome to my OS. Please press a key to start.";
	printString(szWelcome);
	read();
	testfunc('a');
	read();
	char szRestart[] = "Press 'r' to restart your computer.";
	printString(szRestart);
	while(read() != 'r');
	restart();
	return 0;
}

void printString(char* szString) {
	short i=0;
	short x=0;
	while (x == 0) {
		print(szString[i]);
		i++;
		if (szString[i] == '\0') {
			x=1;
		}
	}
}

void testfunc(char test) {
    print(test);
    print(test);
    print(test);
}
```

So wird nur ein a ausgegeben. Mit Pixeln, die gezeichnet werden sollen ist es genauso.


----------



## DexXxtrin (27. März 2012)

```
mov ebp, esp
    pop ebp
```

Hast du da nicht was vertauscht?


```
mov esp, ebp
    pop ebp
```


Und ich kenn mich nicht Detailiert mit ASM aus, aber ESP und EBP sind doch die 32-Bit Namen...!?
Wieso steht oben von deinem ASM-Code noch das [BITS16]? Kann man das so mischen?


----------



## üäpöol (27. März 2012)

Ups. ebp und esp habe ich vertauscht. Hilft aber leider nichts. Ich weiß, dass ich 16 und 32 bit ziemlich wild mische, aber im Prinzip sollte das trotzdem funktioniert, weil GCC auch nicht wirklich 16 bit erzeugt. Ich versuche am Wochenende in den Protected Mode zu gehen, wonach die 16- und 32 bit Probleme erstmal beseitigt sein sollten.


----------



## üäpöol (28. März 2012)

So langsam versteh ich gar nichts mehr:

```
void testfunc(char test) {
    if (test == 'a') {
		print(test);
	}
	if (test == 'a') {
		print(test);
	}
	if (test == 'a') {
		print(test);
	}
}
```
gibt dreimal a aus. Das löst jetzt zwar mein Problem nicht, aber vielleicht hat ja jetzt einer eine Idee.

EDIT:

```
void testfunc(char test) {
	int x=0;
	if (test == 'a') {
		print(test);
	}
	if (test == 'a') {
		print(test);
	}
	if (x == 0) {
		print(test);
	}
}
```

Das hier gibt zweimal a aus...

EDIT2:

```
if (test != 'b') {
       print(test);
}
```
gibt a nicht aus. Das liegt aber schon am GCC, oder kann das an meinem Code liegen?


----------



## DexXxtrin (28. März 2012)

Hast es schonmal mit einem anderen Compiler versucht?
Dann wüsstest definitiv obs an dem liegt oder nicht (was ich eher nicht glaube...).


----------



## üäpöol (28. März 2012)

Nein, habe ich noch nicht. Ich wüsste aber auf Anhieb auch nicht mit welchem. Es muss halt ein 16 bit Crosscompiler sein. Da ist GCC eigentlich schon erste Wahl.


----------



## üäpöol (29. März 2012)

Vielleicht hilft ja disassemblieren:

```
00000200  8CC8              mov ax,cs
00000202  8ED8              mov ds,ax
00000204  8ED0              mov ss,ax
00000206  B8F0FF            mov ax,0xfff0
00000209  89C4              mov sp,ax
0000020B  E89500            call word 0x2a3
0000020E  0000              add [bx+si],al
00000210  6653              push ebx
00000212  6683EC08          sub esp,byte +0x8
00000216  678A5C2410        mov bl,[dword esp+0x10]
0000021B  80FB62            cmp bl,0x62
0000021E  742A              jz 0x24a
00000220  6683EC0C          sub esp,byte +0xc
00000224  660FBEC3          movsx eax,bl
00000228  6650              push eax
0000022A  66E820010000      call dword 0x350
00000230  6683C410          add esp,byte +0x10
00000234  80FB61            cmp bl,0x61
00000237  7511              jnz 0x24a
00000239  6683EC0C          sub esp,byte +0xc
0000023D  666A61            push dword 0x61
00000240  66E80A010000      call dword 0x350
00000246  6683C410          add esp,byte +0x10
0000024A  6683EC0C          sub esp,byte +0xc
0000024E  660FBEDB          movsx ebx,bl
00000252  6653              push ebx
00000254  66E8F6000000      call dword 0x350
0000025A  6683C418          add esp,byte +0x18
0000025E  665B              pop ebx
00000260  66C3              o32 ret
00000262  6657              push edi
00000264  6656              push esi
00000266  6653              push ebx
00000268  67668B7C2410      mov edi,[dword esp+0x10]
0000026E  66BE00000000      mov esi,0x0
00000274  6683EC0C          sub esp,byte +0xc
00000278  660FBFDE          movsx ebx,si
0000027C  67660FBE041F      movsx eax,byte [dword edi+ebx]
00000282  6650              push eax
00000284  66E8C6000000      call dword 0x350
0000028A  6646              inc esi
0000028C  660FBFDE          movsx ebx,si
00000290  6683C410          add esp,byte +0x10
00000294  67803C1F00        cmp byte [dword edi+ebx],0x0
00000299  75D9              jnz 0x274
0000029B  665B              pop ebx
0000029D  665E              pop esi
0000029F  665F              pop edi
000002A1  66C3              o32 ret
000002A3  67668D4C2404      lea ecx,[dword esp+0x4]
000002A9  6683E4F0          and esp,byte -0x10
000002AD  6766FF71FC        push dword [ecx-0x4]
000002B2  6655              push ebp
000002B4  6689E5            mov ebp,esp
000002B7  6657              push edi
000002B9  6656              push esi
000002BB  6651              push ecx
000002BD  6683EC78          sub esp,byte +0x78
000002C1  67668D7DAC        lea edi,[ebp-0x54]
000002C6  66BE00201000      mov esi,0x102000
000002CC  66B90F000000      mov ecx,0xf
000002D2  66F3A5            rep movsd
000002D5  67668D45AC        lea eax,[ebp-0x54]
000002DA  6650              push eax
000002DC  66E880FFFFFF      call dword 0x262
000002E2  66E888000000      call dword 0x370
000002E8  6766C70424610000  mov dword [dword esp],0x61
         -00
000002F1  66E819FFFFFF      call dword 0x210
000002F7  66E873000000      call dword 0x370
000002FD  67668D7D88        lea edi,[ebp-0x78]
00000302  66BE3C201000      mov esi,0x10203c
00000308  66B909000000      mov ecx,0x9
0000030E  66F3A5            rep movsd
00000311  67668D4588        lea eax,[ebp-0x78]
00000316  6766890424        mov [dword esp],eax
0000031B  66E841FFFFFF      call dword 0x262
00000321  6683C410          add esp,byte +0x10
00000325  66E845000000      call dword 0x370
0000032B  3C72              cmp al,0x72
0000032D  75F6              jnz 0x325
0000032F  66E8AB000000      call dword 0x3e0
00000335  66B800000000      mov eax,0x0
0000033B  67668D65F4        lea esp,[ebp-0xc]
00000340  6659              pop ecx
00000342  665E              pop esi
00000344  665F              pop edi
00000346  665D              pop ebp
00000348  67668D61FC        lea esp,[ecx-0x4]
0000034D  66C3              o32 ret
0000034F  006655            add [bp+0x55],ah
00000352  6689E5            mov ebp,esp
00000355  678A4508          mov al,[ebp+0x8]
00000359  B40E              mov ah,0xe
0000035B  B307              mov bl,0x7
0000035D  CD10              int 0x10
0000035F  6689ED            mov ebp,ebp
00000362  665D              pop ebp
00000364  66C3              o32 ret
00000366  0000              add [bx+si],al
00000368  0000              add [bx+si],al
0000036A  0000              add [bx+si],al
0000036C  0000              add [bx+si],al
0000036E  0000              add [bx+si],al
00000370  B400              mov ah,0x0
00000372  CD16              int 0x16
00000374  B400              mov ah,0x0
00000376  C3                ret
00000377  0000              add [bx+si],al
00000379  0000              add [bx+si],al
0000037B  0000              add [bx+si],al
0000037D  0000              add [bx+si],al
0000037F  006655            add [bp+0x55],ah
00000382  6689E5            mov ebp,esp
00000385  BB0700            mov bx,0x7
00000388  678B4D08          mov cx,[ebp+0x8]
0000038C  678B550C          mov dx,[ebp+0xc]
00000390  678A4510          mov al,[ebp+0x10]
00000394  B40C              mov ah,0xc
00000396  CD10              int 0x10
00000398  665D              pop ebp
0000039A  66C3              o32 ret
0000039C  0000              add [bx+si],al
0000039E  0000              add [bx+si],al
000003A0  B400              mov ah,0x0
000003A2  B012              mov al,0x12
000003A4  CD10              int 0x10
000003A6  66C3              o32 ret
000003A8  0000              add [bx+si],al
000003AA  0000              add [bx+si],al
000003AC  0000              add [bx+si],al
000003AE  0000              add [bx+si],al
000003B0  B90000            mov cx,0x0
000003B3  6655              push ebp
000003B5  6689E5            mov ebp,esp
000003B8  678B5D08          mov bx,[ebp+0x8]
000003BC  83F91E            cmp cx,byte +0x1e
000003BF  7413              jz 0x3d4
000003C1  89D0              mov ax,dx
000003C3  52                push dx
000003C4  F7F3              div bx
000003C6  5A                pop dx
000003C7  01D0              add ax,dx
000003C9  B302              mov bl,0x2
000003CB  52                push dx
000003CC  F6F3              div bl
000003CE  5A                pop dx
000003CF  89C2              mov dx,ax
000003D1  41                inc cx
000003D2  EBE8              jmp short 0x3bc
000003D4  665D              pop ebp
000003D6  C3                ret
```

Hier nochmal alle relevanten Dateien im Überblick:
kernel.asm:

```
[Bits 16]
[extern main]
[global start]

start:
	mov ax, cs
    mov ds, ax
    mov ss, ax 
    mov ax, 0xFFF0
    mov sp, ax 
    call main
```

kernel.c

```
asm(".code16gcc\n");
extern void print();
extern void restart();
extern char read();
void printString(char* szString);
void testfunc(char test);

int main() {
	char szWelcome[] = "Hello world, welcome to my OS. Please press a key to start.";
	printString(szWelcome);
	read();
	testfunc('a');
	read();
	char szRestart[] = "Press 'r' to restart your computer.";
	printString(szRestart);
	while(read() != 'r');
	restart();
	return 0;
}

void printString(char* szString) {
	short i=0;
	short x=0;
	while (x == 0) {
		print(szString[i]);
		i++;
		if (szString[i] == '\0') {
			x=1;
		}
	}
}

void testfunc(char test) {
	int x=0;
	if (test != 'b') {
		print(test);
	}
	if (test == 'a') {
		print(test);
	}
	if (x == 0) {
		print(test);
	}
}
```

read.asm

```
[BITS 16]
global read

read:
	mov ah, 0x0
	int 0x16
	mov ah, 0
	ret
```

print.asm

```
[BITS 16]
global print

print:
	push ebp
	mov ebp, esp
	mov al, [ebp+8]
	mov ah, 0x0E
	mov bl, 0x07
	int 0x10
	mov esp, ebp
	pop ebp
	o32 ret
```

restart.asm

```
[BITS 16]
global restart

restart:
	db 0Eah
	dw 0000h
	dw 0FFFFh
```

Ich linke das dann so:

```
i586-elf-ld.exe -T link.ld -o kernel.bin kernelA.elf kernelB.elf functions/print.elf functions/read.elf functions/restart.elf
```

Danke an alle, die helfen! 
Ich hoffe, es liegt irgendwie an meinem Code. Ich werde morgen noch ein paar Versuche anstellen.


----------



## üäpöol (30. März 2012)

So, es wird immer komischer:

```
void testfunc(char test, char test2, char test3, char test4) {
	print(test);
	print(test2);
	print(test3);
	print(test4);
}
```
lässt alles völlig abstürzen. Das hängt wohl wieder mit dem Linker zusammen (genügend Sektoren habe ich geladen).
Das

```
void testfunc(char test, char test2, char test3) {
	print(test);
	print(test2);
	print(test3);
}
```
gibt zweimal a aus, obwohl ich drei übergebe.
Ich habe das Gefühl, irgendetwas komplett falsch zu machen. Vielleicht ist es das 16- und 32 bit Mischen, aber es dauert wohl doch noch ein bisschen mit dem Protected Mode. Kann mir jemand helfen?


----------



## saftmeister (30. März 2012)

Ehrliche Meinung? Die Zeit, die du damit verschwendest, herauszufinden, woran dein Code scheitert, legst du besser darin an, einen PM-Kernel zu bauen. Evtl. ist hier auch keiner so tief in der Materie drin, um die ganzen Vorgänge zu überblicken. Ich schäme mich dir vorzuschlagen, mal beim Low-Level-Forum nachzufragen, aber vielleicht kann man dir dort weiterhelfen.

Ich befürchte aber fast, dass es so, wie du dir vorstellst nicht umzusetzen ist. Du wirst vermutlich immer wieder auf die gleichen Probleme stoßen. IMHO handelt es sich um ein Problem mit dem Stack, was aus dem Mischen des 16-/32bit-Codes resultiert. Ich bin aber kein Profi was das angeht und kann komplett daneben liegen.

Mit einem PM-Kernel wirst du jedenfalls mit komplett anderen Problemen zu kämpfen haben. Möglicherweise kann man dir dabei aber eher helfen als beim aktuellen Problem 

EDIT: Mit welchem Emu arbeitest du aktuell? Hast du schon mal einen Debugger an den Emu gehängt? Mit Bochs geht das ganz gut, mit Qemu soll es auch prima zubewerstelligen sein. Wäre zumindest mal interessant zu wissen, an welchen Punkt es genau knallt.


----------



## üäpöol (31. März 2012)

@saftmeister Ich denke du hast Recht. Ich melde mich wieder, wenn ich im PM bin und das selbe Problem haben sollte.


----------

