I am trying to print something on the screen using my print function. A.
I came across a small problem - when I pass an array of characters as follows:
char s[] = "abc"; print(s);
It works fine, but when I call it, it does not affect.
print("abc");
Here is my function declaration
//print function void print(char* message);
Am I missing something? printf works the same way, and you can pass the string in the second way.
EDIT:
Definitions
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 kernel .o
void start(){ clear_screen(); char s[] = "abc"; print("abc"); print(s); while(1); }
Dismantling the .text section:
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:
Since this may be something with the way I initialize the environment, here are 2 files that are responsible:
pmode.asm - initializes segments and jumps to the beginning of the 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
this is how i build gdt:
; Gdt
gdt_start: gdt_null: ; the mandatory null descriptor dd 0x0 ; ' dd ' means define double word ( ie 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 ( ie 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