2013-08-11 7 views
6

मैं अपने प्रिंट समारोह का उपयोग कर स्क्रीन पर कुछ मुद्रित करने के लिए कोशिश कर रहा हूँ।पासिंग चरित्र सरणी

मैं एक छोटी सी समस्या पर ठोकर खाई है - जब मैं इस तरह चरित्र सरणी पारित:

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

यह ठीक काम करता है, लेकिन जब मैं इसे इस तरह कहते हैं कोई प्रभाव नहीं है।

print("abc"); 

यहाँ मेरी समारोह घोषणा

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

Am मैं कुछ याद आ रही है? printf एक ही तरीके से काम करता है, और आप दूसरी तरफ स्ट्रिंग पास कर सकते हैं।

संपादित करें:

परिभाषाओं

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:

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: kernel.o

void start(){ 
    clear_screen(); 
    char s[] = "abc"; 
    print("abc"); 
    print(s); 
    while(1); 
} 

अनुभाग .text के disassembly के objdump:

के बाद से इस तरह से मैं पर्यावरण initilising हूँ के साथ कुछ हो सकता है, यहां 2 फ़ाइलें उत्तरदायी हैं:

pmode.asm क्षेत्रों -initializes, और

[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 

यहाँ गिरी के शुरू करने के लिए कूदता है कैसे मैं GDT का निर्माण होता है:

; 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

और आपका फ़ंक्शन ** परिभाषित ** ** (i। ई लागू) कैसे है? –

+0

@ H2CO3 परिभाषाओं को जोड़ा गया –

+0

आपको 'const char *' का उपयोग करना चाहिए, लेकिन यह शायद असंबंधित है। – Dave

उत्तर

1

मुझे एक बहुत बड़ी स्ट्रिंग के साथ एक डिस्सेप्लर देखने के बाद जवाब मिला है।

कारण जिस तरह से मैं गिरी जुड़ा हुआ था। इन आदेशों मैं उपयोग करने के लिए सलाह दी गई थी थे:

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

लेकिन जब से मैं एक खिड़कियों जीसीसी था, और मेरी एएसएम और सी फाइलों योगिनी प्रारूप में थे, मैं इस चाल का इस्तेमाल किया था:

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

इसने ऑब्जेक्ट का केवल टेक्स्ट भाग कॉपी किया, इसलिए मुझे बाइनरी संस्करण के साथ छोड़ दिया गया। चूंकि मैंने केवल .text ऑब्जेक्ट का हिस्सा कॉपी किया है, मेरे स्ट्रिंग्स को में रखा गया था .rdata अनुभाग खो गए थे।तो यह केवल objcopy में जोड़ने का मामला था:

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

जब आप कहते हैं कि प्रिंट (रों), आप इसे के रूप में चार सरणी से गुजर रहे हैं क्योंकि आप "एस" घोषित किया है। लेकिन जब आप प्रिंट ("एबीसी") के रूप में पास करते हैं। "एबीसी" का प्रकार क्या है। यह परिभाषित नहीं है। मुझे लगता है कि यह तुम्हारी समस्या है। मैं आपको अपने char s [] से char * s को बदलने की भी सिफारिश करता हूं। उम्मीद है की यह मदद करेगा।

+0

"एबीसी" (एक शाब्दिक स्ट्रिंग) का डेटाटाइप स्पष्ट रूप से एक चरित्र सूचक होने के लिए परिभाषित किया गया है। इसके बारे में कुछ भी अपरिभाषित नहीं है। और char s [], और char * s के बीच कोई अंतर नहीं है; – amrith

+0

@amrith: char s [] और char * वास्तव में समान नहीं हैं। कृपया कुछ संदर्भों के माध्यम से जाओ। यहाँ एक उदाहरण है। जरा देखो तो। चीयर्स !! char * s = "हैलो", यहां रन टाइम पर किसी भी अन्य स्ट्रिंग को इंगित कर सकता है मेरा मतलब है कि यह निरंतर सूचक नहीं है, आप रन टाइम पी = "निशांत" पर एक और मान असाइन कर सकते हैं, जबकि एस [] यहां स्थिर है पॉइंटर .... इसे किसी अन्य स्ट्रिंग को पुन: असाइन नहीं किया जा सकता है लेकिन हम एस [इंडेक्स] पर एक और चरित्र मान असाइन कर सकते हैं। – Sunny

+0

यहां अंतर यह है कि char * s = "हैलो वर्ल्ड"; मेमोरी के केवल पढ़ने वाले हिस्सों में हैलो दुनिया को रखेगा और उस पर एक सूचक बना देगा, इस स्मृति पर किसी भी लेखन को अवैध बना देगा। करते समय: char s [] = "हैलो वर्ल्ड"; शाब्दिक स्ट्रिंग को केवल-पढ़ने वाली मेमोरी में रखता है और स्ट्रिंग पर नई आवंटित मेमोरी को स्ट्रिंग की प्रतिलिपि बनाता है। एस [0] = 'जे' बनाना; कानूनी। – Sunny

संबंधित मुद्दे