Ich versuche, etwas auf dem Bildschirm mit meiner Druckfunktion auszudrucken.
Ich bin auf ein kleines Problem gestoßen - wenn ich das Zeichenarray so übergebe:
char s[] = "abc";
print(s);
Funktioniert es gut, aber wenn ich es so aufrufe, gibt es keinen Effekt.
print("abc");
Hier ist meine Funktionsdeklaration
//Druckfunktion
void print(char* message);
Feht mir etwas? printf funktioniert genauso, und man kann den String auf die zweite Weise übergeben.
BEARBEITEN:
Definitionen
void print_at(char* message, int col, int row){
if(col >= 0 && row >= 0){
set_cursor(get_screen_offset(col,row));
}
int i = 0;
while(message[i] != 0){
print_char(message[i++],-1,-1,WHITE_ON_BLACK);
}
}
void print(char* message){
print_at(message, -1,-1);
}
BEARBEITEN2: objdump von kernel.o
void start(){
clear_screen();
char s[] = "abc";
print("abc");
print(s);
while(1);
}
Disassembly des Abschnitts .text:
00000000 <_start>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 ec 28 sub esp,0x28
6: e8 00 00 00 00 call b <_start+0xb> //clear_screen()
b: c7 45 f4 61 62 63 00 mov DWORD PTR [ebp-0xc],0x636261 //"bca"
12: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
19: e8 00 00 00 00 call 1e <_start+0x1e> //print()
1e: 8d 45 f4 lea eax,[ebp-0xc]
21: 89 04 24 mov DWORD PTR [esp],eax
24: e8 00 00 00 00 call 29 <_start+0x29> //print()
29: eb fe jmp 29 <_start+0x29>
2b: 90 nop
BEARBEITEN3:
Da dies möglicherweise etwas mit der Art und Weise ist, wie ich die Umgebung initialisiere, sind hier die 2 Dateien verantwortlich:
pmode.asm -initialisiert Segmente und springt zum Start des Kernels
[bits 16]
switch_to_pm:
cli ; schalte die Unterbrechungen aus
lgdt [gdt_descriptor] ; global descriptor table laden
mov eax, cr0 ; setze die Steuerregister auf den ersten Bit im geschützten Modus
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:init_pm ;leeren Cache durch einen weit entfernten Sprung
[bits 32]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
call BEGIN_PM
so baue ich die gdt:
; GDT
gdt_start:
gdt_null: ; der obligatorische Null-Descriptor
dd 0x0 ; ' dd ' bedeutet define double word ( d.h. 4 Bytes )
dd 0x0
gdt_code: ; der Code-Segment-Descriptor
; Basis =0 x0 , Grenze =0 xfffff ,
; 1. Flags : ( vorhanden )1 ( Privileg )00 ( Deskriptortyp )1 -> 1001 b
; Typen-Flags : ( Code )1 ( konform )0 ( lesbar )1 ( zugegriffen )0 -> 1010 b
; 2. Flags : ( Granularität )1 ( 32- Bit-Standard )1 ( 64- Bit-Seg )0 ( AVL )0 -> 1100 b
dw 0xffff ; Grenze ( Bits 0-15)
dw 0x0 ; Basis ( Bits 0-15)
db 0x0 ; Basis ( Bits 16-23)
db 10011010b ; 1. Flags , Typen-Flags
db 11001111b ; 2. Flags , Grenze ( Bits 16-19)
db 0x0 ; Basis ( Bits 24-31)
gdt_data: ; der Datensegment-Descriptor
; Wie das Code-Segment, jedoch für die Typenflaggen :
; Typen-Flags : ( Code )0 ( expand down )0 ( beschreibbar )1 ( zugegriffen )0 -> 0010 b
dw 0xffff ; Grenze ( Bits 0-15)
dw 0x0 ; Basis ( Bits 0-15)
db 0x0 ; Basis ( Bits 16-23)
db 10010010b ; 1. Flags , Typen-Flags
db 11001111b ; 2. Flags , Grenze ( Bits 16-19)
db 0x0 ; Basis ( Bits 24-31)
gdt_end: ; Der Grund, warum wir ein Label am Ende der
; GDT setzen, ist, dass der Assembler dann die Größe der
; GDT für den GDT-Deskriptor berechnen kann ( unten )
; GDT-Deskriptor
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; Größe unserer GDT, immer eins weniger als die tatsächliche Größe
dd gdt_start ; Startadresse unserer GDT
; Definiere einige praktische Konstanten für die GDT-Segment-Deskriptor-Offsets, die
; anzeigen, welche Werte die Segmentregister im geschützten Modus enthalten müssen. Zum Beispiel,
; wenn wir DS = 0 x10 in PM setzen, weiß die CPU, dass wir wollen, dass sie das ; Segment an Offset 0 x10 ( d.h. 16 Bytes ) in unserer GDT verwenden soll, das in unserem
; Fall das DATA-Segment ist (0 x0 -> NULL ; 0 x08 -> CODE ; 0 x10 -> DATA )
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start