c - Bootloader - Display String Runtime Error -


i going write first "hello world" bootloader program.i found article on codeproject website.here link of it. http://www.codeproject.com/articles/664165/writing-a-boot-loader-in-assembly-and-c-part up-to assembly level programming going well, when wrote program using c,same given in article, faced runtime error. code written in .c file below.

__asm__(".code16\n"); __asm__("jmpl $0x0000,$main\n");  void printstring(const char* pstr) {         while(*pstr)         {               __asm__ __volatile__("int $0x10": :"a"(0x0e00|*pstr),"b"(0x0007));               ++pstr;         } }  void main() {         printstring("akatsuki9"); } 

i created image file floppy.img , checking output using bochs. displaying

booting floppy... s 

it should akatsuki9. don't know did mistake? can 1 me find why facing runtime error?

brief answer: problem gcc (in fact, specific application of generated code) , not c program itself. it's hidden in assembly code.

long answer: longer (more elaborate) explanation specific details of problem:
(it helpful have assembly code. can obtained using -s switch of gcc or use 1 got gcc; i've attached @ end). if don't know opcode-prefixing, c-parameter passing in assembly, etc. have @ following background information section. looking @ assembly source, it's evident it's 32bit code. gcc '.code16' produces 16bit code 32bit-mode processor (using operand-size prefixes). when same exact code run in real (i.e. 16bit) mode, treated 32bit code. not issue (80386 , later processors can execute such, previous processors ignore operand-size prefix). problem occurs because gcc calculates offsets based on 32bit-mode of (processor) operation, not true (by default) when executing boot-code.

some background information (experienced assembly language programmers should skip this):
1. operand-size prefix: in x86, prefix bytes (0x66, 0x67, etc.) used obtain variants of instruction. 0x66 operand-size prefix obtain instruction non-default operand size; gas uses technique produce code '.code16'. example, in real (i.e. 16bit) mode, 89 d8 corresponds movw %bx,%ax while 66 89 d8 corresponds movl %ebx,%eax. relationship gets reversed in 32bit mode.
2. parameter passing in c: parameters passed on stack , accessed through ebp register.
3. call instruction: call branching operation next instruction's address saved on stack (for resuming). near call saves ip (when in 16bit mode) or eip ( when in 32bit mode). far call saves cs (code-segment register) along ip/eip.
4. push operation: saves value on stack. size of object subtracted esp.


exact problem

start @
movl %esp, %ebp in main: {{ %ebp set equal %esp }}
pushl $.lc0 subtracts 4 stack pointer {{ .lc0 addresses char* "akatsuki9"; getting saved on stack (to accessed printstring function) }}
call printstring subtracts 2 stack pointer (16bit mode; ip 2bytes)
pushl %ebp in printstring: {{ 4 subtracted %esp }}
movl %esp, %ebp {{ %ebp , %esp @ 2+4(=6) bytes char *pstr }}
pushl %ebx changes %esp not %ebp
movl 8(%ebp), %edx {{ accessing 'pstr' @ %ebp+8 ??? }}

accessing 'pstr' @ %ebp+8 instead of %ebp+6 (gcc had calculated offset of 8, assuming 32bit eip); program has obtained invalid pointer , it's going cause problem when program dereferences later: movsbl (%edx), %eax.

fix

as of don't know of fix work gcc. writing boot-sector code, native 16bit code-generator, think, more effective (size-limit & other quirks explained above). if insist on using gcc generates code 32bit mode, fix avoid passing function parameters. more information, refer gcc , gas manuals. , please let me know if there workaround or option works gcc.

edit

i have found fix program make work desired purpose while still using gcc. kinda hackish & not-recommended. why post then? well, sort of proof of concept. here is: (just replace printstring function one)

void printstring(const char* pstr) {   const char *hackptr = *(const char**)((char *)&pstr-2);   while(*hackptr)   {     __asm__ __volatile__("int $0x10": :"a"(0x0e00|*hackptr),"b"(0x0007));     ++hackptr;   } } 

i invite @akatsuki , others (interested) verify works. above answer , added c-pointer arithmetic, can see why should.

my assembly-source file

    .file   "bootl.c" #app     .code16      jmpl $0x0000,$main  #no_app     .text     .globl  printstring     .type   printstring, @function printstring: .lfb0:     .cfi_startproc     pushl   %ebp     .cfi_def_cfa_offset 8     .cfi_offset 5, -8     movl    %esp, %ebp     .cfi_def_cfa_register 5     pushl   %ebx     .cfi_offset 3, -12     movl    8(%ebp), %edx     movl    $7, %ebx .l2:     movsbl  (%edx), %eax     testb   %al, %al     je  .l6     orb $14, %ah #app # 8 "bootl.c" 1     int $0x10 # 0 "" 2 #no_app     incl    %edx     jmp .l2 .l6:     popl    %ebx     .cfi_restore 3     popl    %ebp     .cfi_restore 5     .cfi_def_cfa 4, 4     ret     .cfi_endproc .lfe0:     .size   printstring, .-printstring     .section    .rodata.str1.1,"ams",@progbits,1 .lc0:     .string "akatsuki9"     .section    .text.startup,"ax",@progbits     .globl  main     .type   main, @function main: .lfb1:     .cfi_startproc     pushl   %ebp     .cfi_def_cfa_offset 8     .cfi_offset 5, -8     movl    %esp, %ebp     .cfi_def_cfa_register 5     pushl   $.lc0     call    printstring     popl    %eax     leave     .cfi_restore 5     .cfi_def_cfa 4, 4     ret     .cfi_endproc .lfe1:     .size   main, .-main     .ident  "gcc: (ubuntu 4.8.2-19ubuntu1) 4.8.2"     .section    .note.gnu-stack,"",@progbits 

Comments

Popular posts from this blog

python - mat is not a numerical tuple : openCV error -

c# - MSAA finds controls UI Automation doesn't -

wordpress - .htaccess: RewriteRule: bad flag delimiters -