Page 1 of 1
Problem with string literlals
Posted: Thu May 06, 2010 4:56 am
by Peterbjornx
I have just started working on a simple kernel, so far everything works except string literals,
when i try to print a string literal either i get a lot of nonsense characters , or it doesnt print anything, while i can print a manually filled char array using the same function:
Code: Select all
#include "init.h"
#include "text_video.h"
#include "x86.h"
void kmain( void* mbd, unsigned int magic ) {
char *hello_literal = "Hello\n\0";
char hello_array[7];
hello_array[0] = 'H';
hello_array[1] = 'e';
hello_array[2] = 'l';
hello_array[3] = 'l';
hello_array[4] = 'o';
hello_array[5] = '\n';
hello_array[6] = '\0';
init_video();
clear_video();
kputch('P');
kprint(hello_array);
kprint(hello_literal);
}
Output: PHello
My toolset is Microsoft Visual C++ Express Edition 2010 and MinGW32 objcopy to convert PE to flat binary
What could be the cause of this behaviour?
Re: Problem with string literlals
Posted: Thu May 06, 2010 6:12 am
by JamesM
Hi,
I honestly don't know about MS Visual Studio, but if this were GCC the problem would be to do with your linker script. String literals go in the .rodata section, which in some linker scripts doesn't get linked into .data properly.
Double check your linker script in case this applies to you.
James
Re: Problem with string literlals
Posted: Thu May 06, 2010 6:19 am
by Peterbjornx
visual studio doesnt use a link script, but the map file it generates is :
Code: Select all
Preferred load address is 00100000
Start Length Name Class
0001:00000000 00000796H .text CODE
0002:00000000 0000008cH .bss DATA
Address Publics by Value Rva+Base Lib:Object
0001:00000000 ___multiboot_entry__@0 00100400 f loader.obj
0001:00000040 ?get_BDA@@YGPAUbda_td@@XZ 00100440 f bios.obj
0001:00000050 ?init_descriptor_tables@@YGXXZ 00100450 f descriptor_tables.obj
0001:000001c0 ?kmain@@YGXPAXI@Z 001005c0 f init.obj
0001:000001f0 ?memcpy@@YGPAXPAXPBXI@Z 001005f0 f memcpy.obj
0001:00000240 ?memsetw@@YGPAXPAXHI@Z 00100640 f memsetw.obj
0001:00000280 ?strlen@@YGIPBD@Z 00100680 f strlen.obj
0001:000002c0 ?is_monochrome@@YGHXZ 001006c0 f text_video.obj
0001:000002e0 ?get_page_length@@YGHXZ 001006e0 f text_video.obj
0001:00000310 ?get_text_video_memory@@YGPCUsc_s@@XZ 00100710 f text_video.obj
0001:00000330 ?_putch@@YGXDPAUvci_s@@@Z 00100730 f text_video.obj
0001:000003b0 ?write_crtc_register@@YGXDD@Z 001007b0 f text_video.obj
0001:000003e0 ?handle_escape@@YGXD@Z 001007e0 f text_video.obj
0001:000003f0 ?move_cursor@@YGXXZ 001007f0 f text_video.obj
0001:00000430 ?switch_vc@@YGXH@Z 00100830 f text_video.obj
0001:00000490 ?__putch@@YGXDPAUvci_s@@@Z 00100890 f text_video.obj
0001:00000620 ?clear_video@@YGXXZ 00100a20 f text_video.obj
0001:00000660 ?kputch@@YGXD@Z 00100a60 f text_video.obj
0001:000006a0 ?kprint@@YGXPAD@Z 00100aa0 f text_video.obj
0001:000006e0 ?init_video@@YGXXZ 00100ae0 f text_video.obj
0001:00000780 ?cli@@YGXXZ 00100b80 f x86.obj
0001:00000790 ?sti@@YGXXZ 00100b90 f x86.obj
0002:00000000 ?gdt_ptr@@3Ugdt_ptr_struct@@A 00100c00 descriptor_tables.obj
0002:00000008 ?gdt_entries@@3PAUgdt_entry_struct@@A 00100c08 descriptor_tables.obj
0002:00000030 ?all_vcs@@3PAUvci_s@@A 00100c30 text_video.obj
0002:00000088 ?current_vc@@3PAUvci_s@@A 00100c88 text_video.obj
entry point at 0000:00000000
Static symbols
0001:00000060 ?init_gdt@@YGXXZ 00100460 f descriptor_tables.obj
0001:000000f0 ?gdt_flush@@YGXI@Z 001004f0 f descriptor_tables.obj
0001:00000120 ?gdt_set_gate@@YGXHIIEE@Z 00100520 f descriptor_tables.obj
0001:00000590 ?scroll@@YGXPAUvci_s@@@Z 00100990 f text_video.obj
and the assembly listing for another try at it is :
Code: Select all
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.21003.01
TITLE C:\Users\Peter Bosch\documents\visual studio 2010\Projects\Codename PBX\Codename PBX\init.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC ??_C@_0M@KPLPPDAC@Hello?5World?$AA@ ; `string'
PUBLIC ?kmain@@YGXPAXI@Z ; kmain
EXTRN ?kprint@@YGXPAD@Z:PROC ; kprint
EXTRN ?clear_video@@YGXXZ:PROC ; clear_video
EXTRN ?init_video@@YGXXZ:PROC ; init_video
; COMDAT ??_C@_0M@KPLPPDAC@Hello?5World?$AA@
; File c:\users\peter bosch\documents\visual studio 2010\projects\codename pbx\codename pbx\init.c
CONST SEGMENT
??_C@_0M@KPLPPDAC@Hello?5World?$AA@ DB 'Hello World', 00H ; `string'
; Function compile flags: /Odtp
CONST ENDS
; COMDAT ?kmain@@YGXPAXI@Z
_TEXT SEGMENT
_mbd$ = 8 ; size = 4
_magic$ = 12 ; size = 4
?kmain@@YGXPAXI@Z PROC ; kmain, COMDAT
; 4 : void kmain( void* mbd, unsigned int magic ) {
00000 55 push ebp
00001 8b ec mov ebp, esp
; 5 : init_video();
00003 e8 00 00 00 00 call ?init_video@@YGXXZ ; init_video
; 6 : clear_video();
00008 e8 00 00 00 00 call ?clear_video@@YGXXZ ; clear_video
; 7 : kprint("Hello World");
0000d 68 00 00 00 00 push OFFSET ??_C@_0M@KPLPPDAC@Hello?5World?$AA@
00012 e8 00 00 00 00 call ?kprint@@YGXPAD@Z ; kprint
; 8 : }
00017 5d pop ebp
00018 c2 08 00 ret 8
?kmain@@YGXPAXI@Z ENDP ; kmain
_TEXT ENDS
END
Re: Problem with string literlals
Posted: Thu May 06, 2010 6:55 am
by gerryg400
Code: Select all
CONST SEGMENT
??_C@_0M@KPLPPDAC@Hello?5World?$AA@ DB 'Hello World', 00H ; `string'
; Function compile flags: /Odtp
CONST ENDS
It looks like your string is going into the CONST segment. You need to make sure that segment is loaded.
- gerryg400
Re: Problem with string literlals
Posted: Thu May 06, 2010 1:50 pm
by Peterbjornx
How would i do that, i'm using GRUB and
Code: Select all
dd(0x1BADB002)
; magic
dd(1 << 16) ; flags - aout-kludge
dd(-(0x1BADB002 + (1 << 16))) ; checksum
dd(0x100000) ; header_addr
dd(0x100000) ; load_addr
dd(0x0) ; load_end_addr
dd(0x0) ; bss_end_addr
dd(0x100000 + 0x20) ; entry_addr
Re: Problem with string literlals
Posted: Thu May 06, 2010 9:06 pm
by neon
Hello,
Use the Bochs Debugger and make sure your string is where its expected to be at. I wonder how you are using objcopy to convert it to a flat binary - perhaps that might be where the problem is at.
Re: Problem with string literlals
Posted: Fri May 07, 2010 1:53 am
by Peterbjornx
i have a custom build step:
Code: Select all
objcopy.exe /I pe-i386 /O binary kernel.dll kernel.bin
, when i look in the kernel.bin with a hex editor i see my strings there so they are getting converted.
Re: Problem with string literlals
Posted: Fri May 07, 2010 2:34 am
by gerryg400
This problem will be simple for you to diagnose. But think about it your plan of attack.
e.g.
1. Create a simple version without any confusing code. e.g. only have one printk, only have one string so you can understand the code more easily.
2. Inspect the actual binary that you are loading code with a disassembler or debugger. Work through the logic line by line. Check all addresses in assembler code.
3. You cannot fix a problem unless you know what the problem is. 'String not appearing' is not a problem, it is a symptom. The problem might be 'The linker links to wrong address' OR 'the compiler puts the sting in the wrong segment'. When you know the problem you can fix it. It's even possible that there is a bug in your tool-chain.
Sometimes people on osdev will recognise a symptom and be able to give you a solution right away, but really, you need to learn how to diagnose these problems yourself. I can guarantee there will be many more problems. Any study you do now will not be wasted.
- gerryg400
Re: Problem with string literlals
Posted: Fri May 07, 2010 4:18 am
by Peterbjornx
What i found is that it nicely pushes the char * to the stack, with the right address (0x00101600), and that that mapping gets translated to binary fine
Re: Problem with string literlals
Posted: Fri May 07, 2010 3:45 pm
by Peterbjornx
Well, after i checked the bin file again i saw that instead of keeping the string at 0x101A00 objcopy moved it to 0x101600 without chainging the pointer, and i couldnt get that to work with ms linker so i made a build step for GNU ld in my visual studio system but the data section pointers are off by 4 bytes,any idea on how i could move a section up 4 bytes?
Re: Problem with string literlals
Posted: Fri May 07, 2010 4:48 pm
by neon
Hello,
I personally have never mixed the MSVC toolchain with GNU tools so I cannot offer help. However I do want to mention that you do not need to use a flat binary kernel in order for GRUB to boot it. Thus their are alternative methods to get this working.
Re: Problem with string literlals
Posted: Fri May 07, 2010 11:41 pm
by Peterbjornx
I know, but when i try to run a PE executable linked by the microsoft linker, i get a grub error that it tried to read a block outside of the partition
Re: Problem with string literlals
Posted: Sat May 08, 2010 6:19 am
by Gigasoft
The problem is in your Multiboot header. You have header_addr set to 0x100000, where the correct address is probably 0x100400. You should set both header_addr and entry_addr to the correct labels instead of writing out the physical addresses you think they'll be at.
It should be possible to skip the objcopy step if you use /ALIGN:16 when linking. An align value below 4096 will create a flat file which can be used directly. However, this also means that uninitialized data will be included in the file. You can remove the extra zeros manually and have your code check the section headers to find any uninitialized data which it should zero out. Or, you could write a program that finds the uninitialized part of the .data segment and places the correct size in the Multiboot header before you objcopy it.
Re: Problem with string literlals
Posted: Sat May 08, 2010 6:48 am
by Peterbjornx
of course i change 0x100000 to 0x100400, but thanks for the /ALIGN trick, ill try that once i get VS2010 installed on this pc