Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing character array as parameter (C kernel code)

I'm trying to print something on screen using my print function.

I've stumbled on a small problem - when I pass the character array like this:

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

It works fine, but when i call it like this there is no effect.

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 by 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 of kernel.o

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

Disassembly of section .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:

Since this might be something with the way I am initilising the enviroment, here are the 2 files responsible:

pmode.asm -initializes segments, and jumps to start of 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

here is how I build the 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
like image 372
Bartlomiej Lewandowski Avatar asked Aug 11 '13 20:08

Bartlomiej Lewandowski


People also ask

How do you pass a char array to an argument?

A whole array cannot be passed as an argument to a function in C++. You can, however, pass a pointer to an array without an index by specifying the array's name. In C, when we pass an array to a function say fun(), it is always treated as a pointer by fun().

Can C have character array?

In C programming, the collection of characters is stored in the form of arrays. This is also supported in C++ programming. Hence it's called C-strings. C-strings are arrays of type char terminated with null character, that is, \0 (ASCII value of null character is 0).

What is a char * in C?

In C, char* means a pointer to a character. Strings are an array of characters eliminated by the null character in C.

How do you pass a character to a function?

In C, if you need to amend a string in a called function, pass a pointer to the first char in the string as an argument to the function. If you have allocated storage for the string outside the function, which you cannot exceed within the function, it's probably a good idea to pass in the size.


1 Answers

I have found the answer, after looking at a disassembly with a much bigger string.

The reason was the way I linked the kernel. These were the commands I was advised to use:

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

but since I had a windows gcc, and my asm and C files were in elf format, I had to use this trick:

ld -o kernel.out -Ttext 0x1000 $^ 
objcopy -O binary -j .text kernel.out $@

This copied only the text part of the object, so I was left with the binary version. Since I only copied the .text part of the object, my strings that were kept in the .rdata sections were lost. So it was simply a matter of adding this to objcopy:

objcopy -O binary -j .text -j .rdata kernel.out $@
like image 65
Bartlomiej Lewandowski Avatar answered Oct 13 '22 02:10

Bartlomiej Lewandowski