Autor Thema: Kleiner Assembler Thread  (Gelesen 14271 mal)

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #20 am: 14. August 2009, 15:59 »
Nun, so war es auch...
 
Ich habe das geändert, allerdings funktioniert es nicht. Auch habe ich noch eine Frage.
Wenn ich "mov eax, [GlobaleVariable]" schreibe, heißt das doch eigentlich hole den Inhalt von "GlobaleVariable" und schiebe ihn nach eax. Oder ist das falsch?
 
Hier der Code zum ausgeben eines Zeichens:
video_write_char:
push ebp
mov ebp, esp
; save later used registers
push eax
push edi

; ToDo: Calculate position for edi
mov esi, 0xb8000

mov eax, [video_cursor_y]
mov ebx, 80
mul ebx
add eax, [video_cursor_x]
mul esi
mov eax, esi

; Read parameter and print out character
mov al, FUNCTION_PARAMETER_1 ; <-- Character
mov ah, 0x0F ; <-- black background white fontcolor
stosw
; ToDo: Set new Cursor positions
mov eax, [video_cursor_x]
inc eax
mov [video_cursor_x], eax

; Move Cursor;
call video_move_cursor

; restore register
pop edi
pop eax

mov esp, ebp
pop ebp
ret 4
Am Ende der Datei sind folgende Daten reserviert worden:
[SECTION .data]
video_cursor_x dw 0
video_cursor_y dw 0
video_address dd 0xb8000

 
EDIT:
Noch eine kleine Frage nebenbei: Muss ich für die Shift-Operator wirklich lokale Variablen anlegen, oder kann man das auch anders lösen, da z.B. folgendes Konstrukt nicht funktioniert:
out dx, [ebx >> 8]
« Letzte Änderung: 14. August 2009, 16:08 von ChristianF »

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #21 am: 14. August 2009, 16:17 »
Wenn ich "mov eax, [GlobaleVariable]" schreibe, heißt das doch eigentlich hole den Inhalt von "GlobaleVariable" und schiebe ihn nach eax.
Genau.
 
Zitat
video_write_char:
push ebp
mov ebp, esp
; save later used registers
push eax
push edi

; ToDo: Calculate position for edi
mov esi, 0xb8000

mov eax, [video_cursor_y]
mov ebx, 80
mul ebx
add eax, [video_cursor_x]
mul esi
mov eax, esi
Was machst du denn hier?
eax = (video_cursor_y * 80 + video_cursor_x) * 0xb8000;
eax = 0xb8000;

BTW verwendest du hier ebx, und esi, die du nicht sicherst. Wobei du das esi aber druch edi ersetzen solltest, dem stosw zu liebe  :wink:
Zitat
; Read parameter and print out character
mov al, FUNCTION_PARAMETER_1 ; <-- Character
mov ah, 0x0F ; <-- black background white fontcolor
stosw

; ToDo: Set new Cursor positions
mov eax, [video_cursor_x]
inc eax
mov [video_cursor_x], eax

; Move Cursor;
call video_move_cursor

; restore register
pop edi
pop eax

mov esp, ebp
pop ebp
ret 4
Am Ende der Datei sind folgende Daten reserviert worden:
[SECTION .data]
video_cursor_x dw 0
video_cursor_y dw 0
video_address dd 0xb8000
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #22 am: 14. August 2009, 17:29 »
Eigentlich sollte das auch edi sein, anscheinend hatte ich da wegen irgendwas edi im Kopf.
Wie dem auch sei, ebx, edi und eax werden nun gesichert, wie es sein soll.
 
Was ich allerdings noch nicht verstehe ist, warum jeder 2. Buchstabe "verschluckt" wird. Anscheinend wird der 2. Buchstabe immer als Wert für Hintergrundfarbe und Schriftfarbe verwendet...
 
Was ich geändert habe ist die Berechnung von edi, die ja wie folgt ist:
eax = (video_cursor_y * 80 + video_cursor_x) + 0xb8000;
und esi wurde in edi umbenannt.
 
Der Aufruf aus write_string sieht wie folgt aus:
.printloop:
lodsb
test al, al
jz .printdone

; call function to print out current character
push eax
call video_write_char

jmp .printloop
.printdone:
Merkwürdig ist auch, dass bei einem "push ax" anstatt dem "push eax" ein triple fault ausgelöst wird. Ist das so normal?

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #23 am: 14. August 2009, 17:39 »
Was ich allerdings noch nicht verstehe ist, warum jeder 2. Buchstabe "verschluckt" wird. Anscheinend wird der 2. Buchstabe immer als Wert für Hintergrundfarbe und Schriftfarbe verwendet...
 
Was ich geändert habe ist die Berechnung von edi, die ja wie folgt ist:
eax = (video_cursor_y * 80 + video_cursor_x) + 0xb8000;
und esi wurde in edi umbenannt.
das hab ich ganz übersehen, natürlich brauchst du für jedes Zeichen 2 Bytes du musst also die Cursorposition mit 2 multiplizieren. das müsste so ungefähr gehen:
mov eax, [video_cursor_y]
mov ebx, 80
mul ebx
add eax, [video_cursor_x]
lea edi, [0xb8000 + eax*2]

Zitat
Merkwürdig ist auch, dass bei einem "push ax" anstatt dem "push eax" ein triple fault ausgelöst wird. Ist das so normal?
Ja. Weil ein 'push ax' pushed tatsächlich nur 2 byte auf den Stuck, und du räumst mit dem 'ret 4' 4 wieder ab, machst also irgendwas kaputt.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #24 am: 14. August 2009, 18:54 »
Mmmhhh...
Stimmt. C macht das ja automatisch...
 
Danke für die Hilfe. Und noch ein kleines, wahrscheinlich wie vorher auch ein schnell behebbares, Problem. Und zwar versuche ich den blinkenden Cursor an die entsprechende Stelle zu schieben, also hinter das letzte Zeichen. Das Problem ist, dass der Cursor einfach verschwindet... Mein Versuch sieht wie folgt aus:
mov eax, [video_cursor_y]
mov ebx, 80
mul ebx
add eax, [video_cursor_x]
mov ebx, eax

mov dx, 0x3D4
mov al, 0xE
out dx, al

mov dx, 0x3D5
mov al, bl
out dx, al

mov dx, 0x3D4
mov al, 0xF
out dx, al

mov dx, 0x3D5
mov al, bh
out dx, al
Natürlich werden wie bei jeder Funktion, die verwendeten Register gesichert. Das sind eax, ebx und edx...
Muss ich hier auch die Position, die ich berechne (y * 80 + x) mit 2 multiplizieren, oder kann man das hier weglassen?

EDIT:
Soeben hat sich das Problem aufgelöst. Der Code wurde nur leicht verändert:
; ....
mov dx, 0x3D5
mov ax, bx
shr ax, 8
out dx, ax
; ...
mov dx, 0x3D5
mov ax, bx
out dx, ax
; ...
« Letzte Änderung: 14. August 2009, 19:00 von ChristianF »

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #25 am: 17. August 2009, 12:37 »
So...
ich habe meine Funktion zur Ausgabe eines einzelnen Zeichens etwas verfeinert und bin dabei auf einen komischen Fehler gestoßen. In kernel_main wird der selbe Text 2 mal hintereinander und dann noch ein % ausgegeben. (Zumindest sollte das passieren...):
;....
; print out some text
push dword string ; parameter 1 - string to print out
call video_write_string ; call function

push dword string ; parameter 1 - string to print out
call video_write_string ; call function

mov al, 0x25
push eax
call video_write_char
;....
string db "Hello World, From AsmOS",0x0A,0x0D,0

Allerdings wird der String in "string" nur beim ersten Aufruf von video_write_string ausgegeben. Sobald ich die globale Variable video_cursor_y verändere, wird nichts mehr ausgegeben. Hier die aktuelle Version der Funktion "video_write_char", die von "video_write_string" verwendet wird:
video_write_char:
push ebp
mov ebp, esp
; save later used registers
push eax
push ebx
push edi

; Calculate position for edi
mov eax, dword [video_cursor_y]
mov ebx, 80
mul ebx
add eax, dword [video_cursor_x]
lea edi, [0xb8000 + eax * 2]

; Read parameter and print out character
mov eax, FUNCTION_PARAMETER_1 ; <-- Character
mov ah, 0x0F ; <-- black background white fontcolor

cmp al, 0x20 ; <-- normal characters
jae .normal
cmp al, 0x0D ; <-- Carriage return
je .cr
cmp al, 0x0A ; <-- line feed
je .nl
jmp .cont

.cr:
mov dword [video_cursor_x], 0
jmp .cont

.nl:
; sobald dieser abschnitt ausgeführt wird, wird kein Text, oder der Text aus irgendeinem Grund schwarz auf schwarz ausgegeben.
;Jedenfalls sieht man nichts mehr.
inc dword [video_cursor_y]
jmp .cont

.normal:
stosw
; Set new cursor positions
inc dword [video_cursor_x]
jmp .cont

.cont:

mov ebx, 80
mov eax, dword [video_cursor_x]
cmp eax, ebx
jae .nl

; Scroll screen if needed ...
call video_scroll
; ... and move cursor
call video_move_cursor

; restore register
pop edi
pop ebx
pop eax

mov esp, ebp
pop ebp
ret 4
Die übergabe geschieht immer mittels "push eax", deswegen auch das ret 4. Das komische dabei ist, dass alle 3 Ausgaben angezeigt werden, sobald ich die Behandlung des Zeilenumbruchs ausklammere.
Des Weiteren kann ich eine Überschreibung der Ausgaben ausschließen, da man sonst zumindest das '%'-Zeichen sehen müsste. Was habe ich in dem Abschnitt zur Behandlung des Zeilenumbruchs falsch gemacht? Greife ich auf die Variable an sich falsch zu?
« Letzte Änderung: 17. August 2009, 15:57 von ChristianF »

SHyx0rmZ

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #26 am: 17. August 2009, 19:32 »
Zuerst, nein, ich hab das Problem noch nciht gefunden, du willst aber warscheinlich trotzdem die Endlosschleife  bei .cont entfernen. Wenn eax > 80 springt die Funktion nämlich immer wieder zwischen .nl und .cont hin und her.
@X="krJhbuaesrytre c a cnR.ohut";while@X[/(..)(.)/];@X=@X[3..-1]+$1;print$2;end
"Scheiß auf Perl, wir haben Kekse" - Emperor Ruby

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #27 am: 17. August 2009, 20:40 »
Ich habe zumindest diesen Fehler gefunden.
Es lag wohl daran, dass die Variablen für x und y "words" waren und ich diese beim Schreiben in "double words" konvertiert habe. Momentan kämpfe ich wieder mit der Funktion zum setzen des Cursors, da  der Cursor immer in der zweiten Zeile platziert wird. Ist nun auch behoben.
 
Danke für den Hinweis mit dem newline und den >80 Zeichen, das war mir bisher nicht aufgefallen und ist nun behoben.
 
Wenn ich eine "beliebig" lange Zahl ausgeben möchte, sagen wir mal 250, dann muss ich diese ja Zahl aufbrechen und dann bei jedem Zahlenteil die '0' hinzu addieren. Erst danach kann man den ganzen Krempel per String oder eben einzeln Zeichen für Zeichen ausgeben...
« Letzte Änderung: 17. August 2009, 20:59 von ChristianF »

 

Einloggen