Inline ASM GCC



  • Hallo,

    Ich bastel gerade, rein aus Interesse, an einem kleinen "Betriebssystem".
    Dazu habe ich einen C++ Kernel für GCC geschrieben. Nun habe ich ein kleines Problem:

    unsigned long asmin( unsigned long port )
    {
    	unsigned long result;
    	__asm__  ("in %%dx, %%al" : "=a" (result) : "d" (port));
    	return result;
    }
    
    void asmout( unsigned long port, unsigned long data )
    {
    	__asm__ ("out %%al, %%dx" : :"a" (data), "d" (port));
    }
    
    int GetCursor()
    {
    	unsigned long offset = 0;
    	asmout( 0x3D4, 14 );
    	offset = asmin( 0x3D5 ) << 8;
    	asmout( 0x3D4, 15 );
    	offset |= asmin( 0x3D5 );
    }
    
    void SetCursor( unsigned long offset )
    {
    	asmout( 0x3D4, 14 );
    	asmout( 0x3D5, (unsigned long)(offset >> 8) );
    	asmout( 0x3D4, 15 );
    	asmout( 0x3D5, (unsigned long)(offset) );
    }
    

    So dieser mit diesem Code möchte ich den Cursor auf dem Bildschirm bewegen. Problem ist jedoch, dass ich den Cursor nur bis zum offset 255 verschieben kann. Danach beginnt er wieder am Bildschirmanfang 😕 .
    Da ich mich nicht wirklich mit ASM (insbesondere GCC inline ASM) auskenne, schätze ich mal, dass es daran liegt, dass der offset auf in eine unsigned char Variable gequetsch wird ;). Weiß jemand wie ich das beheben kann ?

    Noch eine kleine weitere Frage:
    Ich benutze zZ dafür den DJGPP Compiler mit folgenden optionen:

    gcc -g -W -O2 -nostdinc -nostdlib -fwritable-strings -fno-builtin -fno-exceptions -c src\main.cpp -o obj\main.o
    

    Weiß jemand, wie ich diese Optionen auf de VC7 Compiler übertragen könnte ?
    Der wäre mir eigentlich wesentlich lieber.

    Vielen Dank
    Dennis



  • gar net, .NET macht nur Windowsporgramme



  • wie schaut es zufällig mit nem anderen MS Compiler aus ?
    mir liegt das GCC inline ASM nicht wirklich.



  • Schreib die Funktionen doch in ASM und lasse sie von NASM zu einer Objektdatei compilen.
    Dann kannst du diese mit deiner C-Datei linken und auf die Funktionen zugreifen.

    Ich mache das so, weil ich den Inline-ASM-Syntax von GCC zum kotzen finde.



  • Ja danke, werde ich so machen !
    Eine weitere Frage, da ich mich mit ASM noch nicht so gut auskenne.

    Ich muss für den OS Memory Manager herausfinden wie viel Speicher das System hat. Das soll nur über den int 15h gehen. d.h. ich muss das ganze machen, bevor ich in den Protected mode gehe, also noch im bootloader.
    ich habe also die Größe des speichers im AX register. Wie bekomme ich die jetzt gespeichert und in meinen C++ Kernel rein ?



  • www.sub--zero.de

    Da ist unter Code->Assembler eine Funktion GetMemSize.

    Die kannst du auch aus dem C-Kernel aufrufen.
    Da bekommst du einen unsigend int Wert zurück der die Anzahl MEGABYTES angibt die im System installiert sind.

    Mit dem Int15 des BIOS kannst du nur den Speicher bis zu einer bestimmten Grenze ermitteln.



  • ich hab das so gemacht, indem ich die speichergröße an einer bestimmten far adresse abgelegt hab. z.b. 00008500h, im os selbst hab ich dann einfach den wert an dieser stelle ausgelesen.
    genauso hab ichs auch mit der dog. RAM map from hell 😉 (bios memory map)
    gemacht, indem ich dann im os einfach das array von structs ausgelesen hab...
    ich hab ne speicheradresse genommen, auf die ich später eh nie zugreifen werde.
    ich verwende eh kein dynamisches speichermanagement, von dem her isses auch net schlimm für mich



  • Auf deiner Seite findet man wirkich noch einiges 🙂
    etwas anders. Ich versuche deine Funktion zu meinem kernel dazu zu linken. leider klappt das nicht so ganz:

    unsigned long GetMemSize();
    
    void mem::Initialize()
    {
    	unsigned long size = GetMemSize();
    }
    

    dazu habe ich dann in die datei mem.asm folgenden code gepackt:

    [Bits 32]
    global 	_GetMemSize
    
    _GetMemSize:
    	push 	ebp 	
    	mov 	ebp, esp 	
    	mov 	eax, 0 	;EAX ist Zähler für die MBs
    	mov 	edx, 0x1EFFFC 	;EDX auf 3 Bytes vor die 2 MB Grenze setzen
    .1:
    	inc 	eax 	
    	mov 	DWORD [edx], 0xAAAAAAAA 	;0xAAAAAAAA an die Speicherstelle schreiben
    	mov 	ebx, [edx] 	;Speicherstelle wieder lesen
    	add 	edx, 0x100000 	;Adresse um 1 MB erhöhen
    	cmp 	ebx, 0xAAAAAAAA 	;Stimmt gelesener Wert mit dem geschriebenen überein?
    	je 	.1 	
    	mov 	esp, ebp 	
    	pop 	ebp 	
    	ret
    

    Dann hab ich es kompiliert. alles ohne probleme.

    nasmw -f aout src\mem.asm -o obj\asmmem.o
    

    Aber leider gottes beschwert sich der linker:

    undefined reference to `GetMemSize()'

    Hier der Linkeraufruf (habe die restlichen .o dateien raus gekürzt)

    ld -g [...] obj\asmmem.o obj\mem.o
    

    Weißt jemand zufällig, warum das nicht klappt ?
    Danke


Anmelden zum Antworten