2013-08-11 14 views
6

Ich versuche, etwas auf dem Bildschirm mit meiner Druckfunktion zu drucken.Übergeben von Zeichen-Array als Parameter (C-Kernel-Code)

Ich habe auf ein kleines Problem gestoßen - wenn ich den Charakter Array wie folgt passieren:

char s[] = "abc"; 
print(s); 

Es funktioniert gut, aber wenn ich es so nennen es keine Wirkung.

print("abc"); 

Hier ist meine Funktion Erklärung

//print function 
void print(char* message); 

bin ich etwas fehlt? printf funktioniert genauso, und Sie können die Zeichenfolge auf dem zweiten Weg übergeben.

EDIT:

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); 
} 

EDIT2: 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 

EDIT3:

Da dies könnte etwas mit der Art und Weise, die ich die Umwelt am initilising, hier sind die 2-Dateien verantwortlich:

pmode.asm Segmente -initializes, und springt von Kernel

[bits 16] 
switch_to_pm: 

    cli  ; switch interuppts off 
    lgdt [gdt_descriptor] ; load global descriptor table 

    mov eax, cr0 ; set control registers first bit to protected mode 
    or eax, 0x1 
    mov cr0, eax 

    jmp CODE_SEG:init_pm ;flush cache by far jump 

[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 

hier zu starten ist, wie ich das gdt baue:

; GDT

gdt_start: 

gdt_null: ; the mandatory null descriptor 
    dd 0x0  ; ' dd ' means define double word (i.e. 4 bytes) 
    dd 0x0 

gdt_code: ; the code segment descriptor 
    ; base =0 x0 , limit =0 xfffff , 
    ; 1 st flags : (present)1 (privilege)00 (descriptor type)1 -> 1001 b 
    ; type flags : (code)1 (conforming)0 (readable)1 (accessed)0 -> 1010 b 
    ; 2 nd flags : (granularity)1 (32- bit default)1 (64- bit seg)0 (AVL)0 -> 1100 b 
    dw 0xffff  ; Limit (bits 0-15) 
    dw 0x0   ; Base (bits 0-15) 
    db 0x0   ; Base (bits 16-23) 
    db 10011010b ; 1 st flags , type flags 
    db 11001111b ; 2 nd flags , Limit (bits 16-19) 
    db 0x0   ; Base (bits 24-31) 
gdt_data: ; the data segment descriptor 
    ; Same as code segment except for the type flags : 
    ; type flags : (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010 b 
    dw 0xffff  ; Limit (bits 0-15) 
    dw 0x0   ; Base (bits 0-15) 
    db 0x0   ; Base (bits 16-23) 
    db 10010010b ; 1 st flags , type flags 
    db 11001111b ; 2 nd flags , Limit (bits 16-19) 
    db 0x0   ; Base (bits 24-31) 

gdt_end: ; The reason for putting a label at the end of the 
      ; GDT is so we can have the assembler calculate 
      ; the size of the GDT for the GDT decriptor (below) 
      ; GDT descriptior 
gdt_descriptor: 
    dw gdt_end - gdt_start - 1 ; Size of our GDT , always less one 
           ; of the true size 
    dd gdt_start    ; Start address of our GDT 

    ; Define some handy constants for the GDT segment descriptor offsets , which 
    ; are what segment registers must contain when in protected mode. For example , 
    ; when we set DS = 0 x10 in PM , the CPU knows that we mean it to use the ; segment described at offset 0 x10 (i.e. 16 bytes) in our GDT , which in our 
    ; case is the DATA segment (0 x0 -> NULL ; 0 x08 -> CODE ; 0 x10 -> DATA) 
    CODE_SEG equ gdt_code - gdt_start 
    DATA_SEG equ gdt_data - gdt_start 
+0

Und wie ist Ihre Funktion ** definiert ** (d. H. Implementiert)? –

+0

@ H2CO3 hinzugefügt Definitionen –

+0

Sie sollten 'const char *' verwenden, aber das ist wahrscheinlich nicht verwandt. – Dave

Antwort

1

Ich habe die Antwort gefunden, nachdem ich eine Demontage mit einer viel größeren Schnur betrachtet habe.

Der Grund war die Art, wie ich den Kernel verband. Dies waren die Befehle, die ich geraten wurde, zu verwenden:

ld -o kernel.bin -Ttext 0x1000 $^ --oformat binary 

aber da ich ein Fenster gcc hatte, und meine asm und C-Dateien waren in elf Format, ich hatte diesen Trick zu verwenden:

ld -o kernel.out -Ttext 0x1000 $^ 
objcopy -O binary -j .text kernel.out [email protected] 

Dies kopierte nur den Textteil des Objekts, so dass ich mit der binären Version übrig blieb. Da ich nur den .Text Teil des Objekts kopiert habe, gingen meine Strings verloren, die in den .RData Sektionen gehalten wurden.Also war es einfach eine Sache, dies zu objcopy hinzuzufügen:

objcopy -O binary -j .text -j .rdata kernel.out [email protected] 
-1

Wenn Sie print (s) sagen, übergeben Sie es als Char-Array, weil Sie "s" deklariert haben. Aber wenn Sie als Druck übergeben ("abc"). Was ist der Typ von "abc"? Es ist nicht definiert. Ich schätze, das ist dein Problem. Ich würde dir auch empfehlen, deine Chars [] in char * s zu ändern. Hoffe das hilft.

+0

Der Datentyp von "abc" (eine literale Zeichenfolge) ist eindeutig als Zeichenzeiger definiert. Es gibt nichts Undefiniertes. Und es gibt keinen Unterschied zwischen char s [] und char * s; – amrith

+0

@amrith: char s [] und char * sind eigentlich nicht gleich. Bitte gehen Sie einige Referenzen durch. Hier ist ein Beispiel. Schau mal. Prost !! char * s = "hallo", hier kann s eine andere Zeichenfolge zur Laufzeit zeigen Ich meine, es ist kein konstanter Zeiger Sie können einen anderen Wert zur Laufzeit p = "Nishant" zuweisen, während s [] hier s ist konstant Zeiger .... Es kann keine andere Zeichenkette neu zugewiesen werden, aber wir können bei s [index] einen anderen Zeichenwert zuweisen. – Sunny

+0

Der Unterschied hier ist, dass char * s = "Hallo Welt"; wird Hallo Welt in den schreibgeschützten Teilen des Speichers platzieren und einen Zeiger darauf machen, was jeden Schreibvorgang in diesem Speicher illegal macht. Dabei: char s [] = "Hallo Welt"; setzt die literale Zeichenfolge in den Nur-Lese-Speicher und kopiert die Zeichenfolge in neu zugewiesenen Speicher auf dem Stapel. Herstellung s [0] = 'J'; legal. – Sunny

Verwandte Themen