#[1]dc0d32 - Atom [2]dc0d32 - RSS [3]dc0d32 - Atom [4]dc0d32 Tuesday, June 15, 2010 Real mode in C with gcc : writing a bootloader Usually the x86 boot loader is written in assembler. We will be exploring the possibility of writing one in C language (as much as possible) compiled with gcc, and runs in real mode. Note that you can also use the 16 bit bcc or TurboC compiler, but we will be focusing on gcc in this post. Most open source kernels are compiled with gcc, and it makes sense to write C bootloader with gcc instead of bcc as you get a much cleaner toolchain :) As of today (20100614), gcc 4.4.4 officially only emits code for protected/long mode and does not support the real mode natively (this may [5]change in future). Also note that we will not discuss the very fundamentals of booting. This article is fairly advanced and assumes that you know what it takes to write a simple boot-loader in assembler. It is also expected that you know how to write gcc inline assembly. Not everything can be done in C! getting the tool-chain working .code16gcc As we will be running in 16 bit real mode, this tells gas that the assembler was generated by gcc and is intended to be run in real mode. With this directive, gas automatically adds addr32 prefix wherever required. For each C file which contains code to be run in real mode, this directive should be present at the top of effectively generated assembler code. This can be ensured by defining in a header and including it before any other. #ifndef _CODE16GCC_H_ #define _CODE16GCC_H_ __asm__(".code16gcc\n"); #endif This is great for bootloaders as well as parts of kernel that must run in real mode but are desired written in C instead of asm. In my opinion C code is a lot easier to debug and maintain than asm code, at expense of code size and performance at times. Special linking As bootloader is supposed to run at physical 0x7C00, we need to tell that to linker. The mbr/vbr should end with the proper boot signature 0xaa55. All this can be taken care of by a simple linker script. ENTRY(main); SECTIONS { . = 0x7C00; .text : AT(0x7C00) { _text = .; *(.text); _text_end = .; } .data : { _data = .; *(.bss); *(.bss*); *(.data); *(.rodata*); *(COMMON) _data_end = .; } .sig : AT(0x7DFE) { SHORT(0xaa55); } /DISCARD/ : { *(.note*); *(.iplt*); *(.igot*); *(.rel*); *(.comment); /* add any unwanted sections spewed out by your version of gcc and flags here */ } } gcc emits elf binaries with sections, whereas a bootloader is a monolithic plain binary with no sections. Conversion from elf to binary can be done as follows: $ objcopy -O binary vbr.elf vbr.bin The code With the toolchain set up, we can start writing our hello world bootloader! vbr.c (the only source file) looks something like this: /* * A simple bootloader skeleton for x86, using gcc. * * Prashant Borole (boroleprashant at Google mail) * */ /* XXX these must be at top */ #include "code16gcc.h" __asm__ ("jmpl $0, $main\n"); #define __NOINLINE __attribute__((noinline)) #define __REGPARM __attribute__ ((regparm(3))) #define __NORETURN __attribute__((noreturn)) /* BIOS interrupts must be done with inline assembly */ void __NOINLINE __REGPARM print(const char *s){ while(*s){ __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)) ; s++; } } /* and for everything else you can use C! Be it traversing the filesystem, or ve rifying the kernel image etc.*/ void __NORETURN main(){ print("woo hoo!\r\n:)"); while(1); } compile it as $ gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o vbr.o vbr.c $ ld -static -Tlinker.ld -nostdlib --nmagic -o vbr.elf vbr.o $ objcopy -O binary vbr.elf vbr.bin and that should have created vbr.elf file (which you can use as a symbols file with gdb for source level debugging the vbr with gdbstub and qemu/bochs) as well as 512 byte vbr.bin. To test it, first create a dummy 1.44M floppy image, and overwrite it's mbr by vbr.bin with dd. $ dd if=/dev/zero of=floppy.img bs=1024 count=1440 $ dd if=vbr.bin of=floppy.img bs=1 count=512 conv=notrunc and now we are ready to test it out :D $ qemu -fda floppy.img -boot a and you should see the message! Once you get to this stage, you are pretty much set with respect to the tooling itself. Now you can go ahead and write code to read the filesystem, search for next stage or kernel and pass control to it. Here is a simple example of a floppy boot record with no filesystem, and the next stage or kernel written to the floppy immediately after the boot record. The next image LMA and entry are fixed in a bunch of macros. It simply reads the image starting one sector after boot record and passes control to it. There are many obvious holes, which I left open for sake of brevity. /* * A simple bootloader skeleton for x86, using gcc. * * Prashant Borole (boroleprashant at Google mail) * */ /* XXX these must be at top */ #include "code16gcc.h" __asm__ ("jmpl $0, $main\n"); #define __NOINLINE __attribute__((noinline)) #define __REGPARM __attribute__ ((regparm(3))) #define __PACKED __attribute__((packed)) #define __NORETURN __attribute__((noreturn)) #define IMAGE_SIZE 8192 #define BLOCK_SIZE 512 #define IMAGE_LMA 0x8000 #define IMAGE_ENTRY 0x800c /* BIOS interrupts must be done with inline assembly */ void __NOINLINE __REGPARM print(const char *s){ while(*s){ __asm__ __volatile__ ("int $0x10" : : "a"(0x0E00 | *s), "b"(7)) ; s++; } } #if 0 /* use this for the HD/USB/Optical boot sector */ typedef struct __PACKED TAGaddress_packet_t{ char size; char :8; unsigned short blocks; unsigned short buffer_offset; unsigned short buffer_segment; unsigned long long lba; unsigned long long flat_buffer; }address_packet_t ; int __REGPARM lba_read(const void *buffer, unsigned int lba, unsigned short blocks, unsigned char bios_drive){ int i; unsigned short failed = 0; address_packet_t packet = {.size = sizeof(address_packet_t), .blocks = blocks, .buffer_offset = 0xFFFF, .buffer_segment = 0xFFFF, .lba = lba, .flat_b uffer = (unsigned long)buffer}; for(i = 0; i < 3; i++){ packet.blocks = blocks; __asm__ __volatile__ ( "movw $0, %0\n" "int $0x13\n" "setcb %0\n" :"=m"(failed) : "a"(0x4200), "d"(bios_drive), "S "(&packet) : "cc" ); /* do something with the error_code */ if(!failed) break; } return failed; } #else /* use for floppy, or as a fallback */ typedef struct { unsigned char spt; unsigned char numh; }drive_params_t; int __REGPARM __NOINLINE get_drive_params(drive_params_t *p, unsigned char bios_drive){ unsigned short failed = 0; unsigned short tmp1, tmp2; __asm__ __volatile__ ( "movw $0, %0\n" "int $0x13\n" "setcb %0\n" : "=m"(failed), "=c"(tmp1), "=d"(tmp2) : "a"(0x0800), "d"(bios_drive), "D"(0) : "cc", "bx" ); if(failed) return failed; p->spt = tmp1 & 0x3F; p->numh = tmp2 >> 8; return failed; } int __REGPARM __NOINLINE lba_read(const void *buffer, unsigned int lba, uns igned char blocks, unsigned char bios_drive, drive_params_t *p){ unsigned char c, h, s; c = lba / (p->numh * p->spt); unsigned short t = lba % (p->numh * p->spt); h = t / p->spt; s = (t % p->spt) + 1; unsigned char failed = 0; unsigned char num_blocks_transferred = 0; __asm__ __volatile__ ( "movw $0, %0\n" "int $0x13\n" "setcb %0" : "=m"(failed), "=a"(num_blocks_transferred) : "a"(0x0200 | blocks), "c"((s << 8) | s), "d"((h << 8) | bios_driv e), "b"(buffer) ); return failed || (num_blocks_transferred != blocks); } #endif /* and for everything else you can use C! Be it traversing the filesystem, or ve rifying the kernel image etc.*/ void __NORETURN main(){ unsigned char bios_drive = 0; __asm__ __volatile__("movb %%dl, %0" : "=r"(bios_drive)); /* the B IOS drive number of the device we booted from is passed in dl register */ drive_params_t p = {}; get_drive_params(&p, bios_drive); void *buff = (void*)IMAGE_LMA; unsigned short num_blocks = ((IMAGE_SIZE / BLOCK_SIZE) + (IMAGE_SIZE % BLOCK_SIZE == 0 ? 0 : 1)); if(lba_read(buff, 1, num_blocks, bios_drive, &p) != 0){ print("read error :(\r\n"); while(1); } print("Running next image...\r\n"); void* e = (void*)IMAGE_ENTRY; __asm__ __volatile__("" : : "d"(bios_drive)); goto *e; } removing __NOINLINE may result in even smaller code in this case. I had it in place so that I could figure out what was happening. Concluding remarks C in no way matches the code size and performance of hand tuned size/speed optimized assembler. Also, because of an extra byte (0x66, 0x67) wasted (in addr32) with almost every instruction, it is highly unlikely that you can cram up the same amount of functionality as assembler. Global and static variables, initialized as well as uninitialized, can quickly fill those precious 446 bytes. Changing them to local and passing around instead may increase or decrease size; there is no thumb rule and it has to be worked out on per case basis. Same goes for function in-lining. You also need to be extremely careful with various gcc optimization flags. For example, if you have a loop in your code whose number of iterations are small and deducible at compile time, and the loop body is relatively small (even 20 bytes), with default -Os, gcc will unroll that loop. If the loop is not unrolled (-fno-tree-loop-optimize), you might be able to shave off big chunk of bytes there. Same holds true for frame setups on i386 - you may want to get rid of them whenever not required using -fomit-frame-pointer. Moral of the story : you need to be extra careful with gcc flags as well as version update. This is not much of an issue for other real mode modules of the kernel where size is not of this prime importance. Also, you must be very cautious with assembler warnings when compiling with .code16gcc. Truncation is common. It is a very good idea to use --save-temp and analyze the assembler code generated from your C and inline assembly. Always take care not to mess with the C calling convention in inline assembly and meticulously check and update the clobber list for inline assembly doing BIOS or APM calls (but you already knew it, right?). It is likely that you want to switch to protected/long mode as early as possible, though. Even then, I still think that maintainability wins over asm's size/speed in case of a bootloader as well as the real mode portions of the kernel. It would be interesting if someone could try this with c++/java/fortran. Please let me know if you do! at [6]June 15, 2010 [7]Email This[8]BlogThis![9]Share to Twitter[10]Share to Facebook[11]Share to Pinterest Labels: [12]assembler, [13]bootloader, [14]c, [15]gas, [16]gcc, [17]kernel, [18]osdev 25 comments: 1. [19]Girija[20]Tuesday, June 15, 2010 at 6:12:00 PM GMT+5:30 Dokyaawarun 10 foot.. kiwwa jaastach. :-| Reply[21]Delete Replies Reply 2. [22]descent[23]Tuesday, December 21, 2010 at 1:10:00 PM GMT+5:30 Hi, Thank you for your sharing. in void __NOINLINE __REGPARM print(const char *s) I change the print function to access pointer, like this: videoram[0]='H'; but I got the warning message: /tmp/cc5qsy9l.s:33: Warning: 00000000000b8000 shortened to 0000000000008000 Do I miss something? Reply[24]Delete Replies Reply 3. [25]descent[26]Tuesday, December 21, 2010 at 2:05:00 PM GMT+5:30 Hi, I use gcc-3.4 to compile again. I see no warning message, but in qemu, I still cannot see char H. videoram is static variable. static unsigned char *videoram = (unsigned char *) 0xb8000; Reply[27]Delete Replies Reply 4. [28]descent[29]Tuesday, December 21, 2010 at 3:16:00 PM GMT+5:30 Hi, I got something. In 16bit mode, the pointer is 16bit length. So 0xb8000 shortened to 0x8000. I write a c file and a function, void put_char() { unsigned char *videoram = (unsigned char *) 0xb8000; videoram[0]='H'; videoram[2]='H'; videoram[40]='H'; } no include code16gcc.h, I think the pointer is 32bits length, but I still can not see the H character. Reply[30]Delete Replies Reply 5. [31]Prashant[32]Tuesday, December 21, 2010 at 7:16:00 PM GMT+5:30 @descent: check the '--save-temps' preserved assembler version of the C function. This article assumes that the reader has low level programming experience with x86. To access the vidmem with b8000h, you have 2 options: 1. write inline assembly to set es to b800h, and di to the address in the real mode segment. Then write byte/word to es:di. 2. Enter unreal mode. Then you can use the full 4G memory, one-to-one mapped. I personally would not recommend any of these methods for printing - BIOS int 10h is pretty good. Remember - do not try and do anything fancy in the (m/v)br; do it in the next stage instead as you have pretty much unconstrained image size in later stages. Reply[33]Delete Replies Reply 6. [34]descent[35]Wednesday, December 22, 2010 at 9:41:00 AM GMT+5:30 Hi Prashant, Thank you for your explanation. Because in protected mode, I can use C, and direct access 0xb8000, so I am confused. real/protect mode, gcc/gas 16/32 bit also confuse me. They are very complicate. Reply[36]Delete Replies Reply 7. [37]Sebastian[38]Saturday, March 12, 2011 at 6:26:00 PM GMT+5:30 you are a genius! Reply[39]Delete Replies Reply 8. [40]Unknown[41]Sunday, April 17, 2011 at 5:48:00 AM GMT+5:30 I've got that infamous runtime error... bootloader.exe has encountered a problem and needs to close. We are sorry for the inconvenience. Reply[42]Delete Replies Reply 9. [43]Unknown[44]Saturday, May 21, 2011 at 2:39:00 AM GMT+5:30 Managed to do it in C++. Code is the same. Linker file needs to discard eh_frame. When building on x86-64 add -m32 to g++ and -melf_i386 on ld command line. Trying to rewrite it in a more c++-ish style. My e-mail is boskovits@cogito-top.hu . Reply[45]Delete Replies Reply 10. [46]Prashant[47]Saturday, May 21, 2011 at 3:02:00 AM GMT+5:30 @abraker95: are you trying to run the MZ/PE image in windows? that is like sinning and then spitting on the devil when in hell. @boskov1985: cool man! let us know how it goes :D Reply[48]Delete Replies Reply 11. Anonymous[49]Friday, November 25, 2011 at 2:50:00 AM GMT+5:30 It's easier to to this without objcopy. Modern ld versions support --oformat=binary , so just one line does the direct compilation job. gcc -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -static -nostdlib -Wl,-Tlinker.ld -Wl,--nmagic -Wl,--oformat=binary -o loader.bin loader.c Reply[50]Delete Replies Reply 12. [51]Prashant[52]Friday, November 25, 2011 at 8:01:00 AM GMT+5:30 I can't verify right now whether it works, but thanks for letting us know, rpfh! Reply[53]Delete Replies Reply 13. [54]descent[55]Sunday, December 4, 2011 at 9:42:00 PM GMT+5:30 Hi, The c code uses function call, why need not set stack (ss:esp)? Reply[56]Delete Replies Reply 14. [57]Prashant[58]Tuesday, December 6, 2011 at 10:18:00 AM GMT+5:30 good point @decent. I guess you will need to set up the stack first in main, probably in assembler. Reply[59]Delete Replies Reply 15. [60]descent[61]Saturday, December 24, 2011 at 8:02:00 PM GMT+5:30 I change %ss:%esp to 0x07a0:0000, Is any side effect? void __NORETURN main(){ __asm__ ("mov %cs, %ax\n"); __asm__ ("mov %ax, %ds\n"); __asm__ ("mov $0x07a0, %ax\n"); __asm__ ("mov %ax, %ss\n"); __asm__ ("mov $0, %esp\n"); print("woo hoo!\r\n:)"); while(1); } Reply[62]Delete Replies Reply 16. [63]descent[64]Monday, July 30, 2012 at 8:16:00 AM GMT+5:30 Hi, I test c bootloader in real machine, in my eeepc 904, need add some code to setup stack. http://descent-incoming.blogspot.tw/2012/05/x86-bootloader-hello-wo rld.html The article is written by Chinese, but the code, picture can give some reference. cppb.cpp is cpp version (compile by g++), it can work, I test it in real machine(eeepc 904). Reply[65]Delete Replies Reply 17. [66]axiomfinity[67]Saturday, April 20, 2013 at 10:46:00 AM GMT+5:30 linker fails whats up with it..? Reply[68]Delete Replies Reply 18. [69]Prashant[70]Sunday, April 21, 2013 at 9:34:00 AM GMT+5:30 Fails how? Can you please elaborate? Reply[71]Delete Replies Reply 19. [72]Unknown[73]Wednesday, November 13, 2013 at 12:51:00 PM GMT+5:30 Thank you for detaile explanation Linker failed nt sure why..ld: error: load segment overlap [0x7c00 -> 0x7e50] and [0x7dfe -> 0x7e00] Reply[74]Delete Replies Reply 20. [75]osdev[76]Saturday, May 31, 2014 at 1:35:00 AM GMT+5:30 someone here? I need to test, but... "c"((s << 8) | s) <-- duplicate s in CH and CL? c = lba / (p->numh * p->spt); <-- 'c' is never used... maybe -> "c"((c << 8) | s) Reply[77]Delete Replies Reply 21. [78]Unknown[79]Thursday, February 5, 2015 at 8:39:00 PM GMT+5:30 Thank you for your nice post! I'm trying to run it on my x86-64 linux box, but gcc reports errors like "bad register name rax", I'm a little confused by the various compiler options here, could you please give me suggestions on how to compile the C source file on x86-64 machines? Thanks Reply[80]Delete Replies 1. [81]Jose Fernando Lopez Fernandez[82]Friday, January 20, 2017 at 2:56:00 PM GMT+5:30 rax is a 64 bit register. A bootloader is running in 16 bits, so you cannot use rax (64 bit) or eax (32 bit). You have to use ax. Also, you said your computer is an x86-64. Which one is it? x86 (32 bit) or 64 (64 bit)? If you have an x86, it will have no idea what rax is, since it has no knowledge of 64 bit registers. I'm just speculating as to your problem here, though. If anything here is incorrect/misguided by all means let me know, I'm only a beginner too [83]Delete Replies Reply 2. [84]Jose Fernando Lopez Fernandez[85]Friday, January 20, 2017 at 2:57:00 PM GMT+5:30 @Jing Peng rax is a 64 bit register. A bootloader is running in 16 bits, so you cannot use rax (64 bit) or eax (32 bit). You have to use ax. Also, you said your computer is an x86-64. Which one is it? x86 (32 bit) or 64 (64 bit)? If you have an x86, it will have no idea what rax is, since it has no knowledge of 64 bit registers. I'm just speculating as to your problem here, though. If anything here is incorrect/misguided by all means let me know, I'm only a beginner too [86]Delete Replies Reply Reply 22. [87]Unknown[88]Thursday, February 5, 2015 at 8:40:00 PM GMT+5:30 Thank you for your nice post! I'm trying to run it on my x86-64 linux box, but gcc reports errors like "bad register name rax", I'm a little confused by the various compiler options here, could you please give me suggestions on how to compile the C source file on x86-64 machines? Thanks Reply[89]Delete Replies Reply 23. [90]Unknown[91]Sunday, February 7, 2016 at 8:43:00 PM GMT+5:30 hello i ma atif Reply[92]Delete Replies Reply Add comment Load more... [93]Newer Post [94]Older Post [95]Home Subscribe to: [96]Post Comments (Atom) * [97]Real mode in C with gcc : writing a bootloader Usually the x86 boot loader is written in assembler. We will be exploring the possibility of writing one in C language (as much as possible)... * [98]Writing kernel in Windows with Visual Studio C/C++ Most hobby osdev projects prefer *nix+gcc combination these days, primarily because there are a bunch of nice tutorials and examples availab... * [99]Debugging kernel with qemu and gdb Assuming that you have your (or Linux/*BSD/Solaris/Windows or any other) kernel on a bootable device, you can debug the kernel and also the ... Blog Archive * [100]|> [101]2012 (1) + [102]|> [103]Feb 2012 (1) * [104]v [105]2010 (7) + [106]v [107]Jun 2010 (2) o [108]Cold boot attack o [109]Real mode in C with gcc : writing a bootloader + [110]|> [111]May 2010 (2) + [112]|> [113]Apr 2010 (1) + [114]|> [115]Mar 2010 (1) + [116]|> [117]Feb 2010 (1) * [118]|> [119]2009 (12) + [120]|> [121]Dec 2009 (1) + [122]|> [123]Nov 2009 (2) + [124]|> [125]Sep 2009 (1) + [126]|> [127]Aug 2009 (1) + [128]|> [129]Jul 2009 (2) + [130]|> [131]Feb 2009 (2) + [132]|> [133]Jan 2009 (3) * [134]|> [135]2008 (9) + [136]|> [137]Nov 2008 (2) + [138]|> [139]Oct 2008 (3) + [140]|> [141]Aug 2008 (1) + [142]|> [143]Jun 2008 (3) Labels [144]linux [145]kernel [146]8800 [147]FreeBSD [148]gdb [149]nvidia [150]osdev [151]windows 7 [152]bochs [153]boot [154]bootloader [155]debug [156]dual boot [157]gas [158]gcc [159]overclock [160]pidgin [161]windows [162]windows server 2008 [163]2k8 [164]3DMark [165]3DMark vantage [166]820 [167]DRAM [168]Directx 10 [169]Dirext 11 [170]Java [171]OpenJDK [172]OpenOffice [173]Pentium D [174]RAID [175]Sun [176]UUID [177]Unicode [178]VirtualBox [179]X [180]Xorg [181]ageis [182]assembler [183]authentication [184]bash [185]c [186]coolbits [187]dx10 [188]fedora [189]fortune [190]gdm [191]ghostscript [192]gnome [193]google [194]gs [195]gtalk [196]heat sink [197]invisible [198]jabber [199]kde [200]latex [201]lvm [202]lyx [203]mount [204]networked audio [205]networked sound [206]nvclock [207]oolatex [208]ooolatex [209]perl [210]phonon [211]physics [212]physx [213]picasa [214]plugin [215]proxy [216]pulseaudio [217]qemu [218]rsync [219]rtp [220]scp [221]scp stdin [222]security [223]server [224]shell [225]squid [226]ssh [227]sync [228]tar [229]udev [230]unix [231]xdm [232]xfce [233]xmpp [234]xorg.conf [235]zsh [236]visit counter for blogspot Theme images by [237]5ugarless. Powered by [238]Blogger. References Visible links: 1. http://dc0d32.blogspot.com/feeds/posts/default 2. http://dc0d32.blogspot.com/feeds/posts/default?alt=rss 3. http://dc0d32.blogspot.com/feeds/6370208028763486595/comments/default 4. http://dc0d32.blogspot.com/ 5. http://gcc.gnu.org/ml/gcc/1999-07n/msg00483.html 6. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html 7. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=email 8. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=blog 9. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=twitter 10. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=facebook 11. https://www.blogger.com/share-post.g?blogID=35813921&postID=6370208028763486595&target=pinterest 12. http://dc0d32.blogspot.com/search/label/assembler 13. http://dc0d32.blogspot.com/search/label/bootloader 14. http://dc0d32.blogspot.com/search/label/c 15. http://dc0d32.blogspot.com/search/label/gas 16. http://dc0d32.blogspot.com/search/label/gcc 17. http://dc0d32.blogspot.com/search/label/kernel 18. http://dc0d32.blogspot.com/search/label/osdev 19. https://www.blogger.com/profile/06904019980664523275 20. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1276605767623#c7537756629084768590 21. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7537756629084768590 22. https://www.blogger.com/profile/17992312956580227764 23. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292917257855#c7916645211913421716 24. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7916645211913421716 25. https://www.blogger.com/profile/17992312956580227764 26. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292920505936#c6914976194912758237 27. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=6914976194912758237 28. https://www.blogger.com/profile/17992312956580227764 29. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292924802000#c3509490007866551116 30. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=3509490007866551116 31. https://www.blogger.com/profile/15716533043357974705 32. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292939196737#c8552773997968662641 33. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8552773997968662641 34. https://www.blogger.com/profile/17992312956580227764 35. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1292991102048#c3691472389082213083 36. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=3691472389082213083 37. https://www.blogger.com/profile/04546527990311411722 38. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1299934567958#c8861407369344586215 39. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8861407369344586215 40. https://www.blogger.com/profile/13931402888317484377 41. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1302999537204#c1796379189090357880 42. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1796379189090357880 43. https://www.blogger.com/profile/10664008816666619973 44. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1305925792707#c309698377277262219 45. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=309698377277262219 46. https://www.blogger.com/profile/15716533043357974705 47. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1305927124224#c7619831240140737017 48. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7619831240140737017 49. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1322169605658#c1693276418345545837 50. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1693276418345545837 51. https://www.blogger.com/profile/15716533043357974705 52. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1322188282688#c6259496576598783959 53. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=6259496576598783959 54. https://www.blogger.com/profile/17992312956580227764 55. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1323015134989#c3945832952459710949 56. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=3945832952459710949 57. https://www.blogger.com/profile/15716533043357974705 58. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1323146939454#c2066813635755540091 59. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=2066813635755540091 60. https://www.blogger.com/profile/17992312956580227764 61. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1324737140263#c7908397772486068687 62. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7908397772486068687 63. https://www.blogger.com/profile/17992312956580227764 64. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1343616406999#c8117194716929362278 65. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8117194716929362278 66. https://www.blogger.com/profile/00410755183408310829 67. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1366435009449#c1258130037332531147 68. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1258130037332531147 69. https://www.blogger.com/profile/15716533043357974705 70. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1366517094365#c8123329091843779139 71. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=8123329091843779139 72. https://www.blogger.com/profile/17234059656421576642 73. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1384327289704#c4134298820836763034 74. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=4134298820836763034 75. https://www.blogger.com/profile/16683260877229099988 76. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1401480336214#c455729903293178418 77. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=455729903293178418 78. https://www.blogger.com/profile/07765096042053323038 79. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1423148995473#c7126019925062815723 80. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7126019925062815723 81. https://www.blogger.com/profile/01833111909520604012 82. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1484904386672#c7038618115198897417 83. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=7038618115198897417 84. https://www.blogger.com/profile/01833111909520604012 85. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1484904424918#c1284220459583274955 86. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=1284220459583274955 87. https://www.blogger.com/profile/07765096042053323038 88. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1423149010339#c2287827836063649127 89. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=2287827836063649127 90. https://www.blogger.com/profile/17596900636592437710 91. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html?showComment=1454858010555#c4198004625201390279 92. https://www.blogger.com/delete-comment.g?blogID=35813921&postID=4198004625201390279 93. http://dc0d32.blogspot.com/2010/06/cold-boot-attack.html 94. http://dc0d32.blogspot.com/2010/05/how-not-to-look-like-fool-on-facebook.html 95. http://dc0d32.blogspot.com/ 96. http://dc0d32.blogspot.com/feeds/6370208028763486595/comments/default 97. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html 98. http://dc0d32.blogspot.com/2012/02/writing-kernel-in-windows-with-visual.html 99. http://dc0d32.blogspot.com/2010/03/debugging-kernel-with-qemu-and-gdb.html 100. javascript:void(0) 101. http://dc0d32.blogspot.com/2012/ 102. javascript:void(0) 103. http://dc0d32.blogspot.com/2012/02/ 104. javascript:void(0) 105. http://dc0d32.blogspot.com/2010/ 106. javascript:void(0) 107. http://dc0d32.blogspot.com/2010/06/ 108. http://dc0d32.blogspot.com/2010/06/cold-boot-attack.html 109. http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html 110. javascript:void(0) 111. http://dc0d32.blogspot.com/2010/05/ 112. javascript:void(0) 113. http://dc0d32.blogspot.com/2010/04/ 114. javascript:void(0) 115. http://dc0d32.blogspot.com/2010/03/ 116. javascript:void(0) 117. http://dc0d32.blogspot.com/2010/02/ 118. javascript:void(0) 119. http://dc0d32.blogspot.com/2009/ 120. javascript:void(0) 121. http://dc0d32.blogspot.com/2009/12/ 122. javascript:void(0) 123. http://dc0d32.blogspot.com/2009/11/ 124. javascript:void(0) 125. http://dc0d32.blogspot.com/2009/09/ 126. javascript:void(0) 127. http://dc0d32.blogspot.com/2009/08/ 128. javascript:void(0) 129. http://dc0d32.blogspot.com/2009/07/ 130. javascript:void(0) 131. http://dc0d32.blogspot.com/2009/02/ 132. javascript:void(0) 133. http://dc0d32.blogspot.com/2009/01/ 134. javascript:void(0) 135. http://dc0d32.blogspot.com/2008/ 136. javascript:void(0) 137. http://dc0d32.blogspot.com/2008/11/ 138. javascript:void(0) 139. http://dc0d32.blogspot.com/2008/10/ 140. javascript:void(0) 141. http://dc0d32.blogspot.com/2008/08/ 142. javascript:void(0) 143. http://dc0d32.blogspot.com/2008/06/ 144. http://dc0d32.blogspot.com/search/label/linux 145. http://dc0d32.blogspot.com/search/label/kernel 146. http://dc0d32.blogspot.com/search/label/8800 147. http://dc0d32.blogspot.com/search/label/FreeBSD 148. http://dc0d32.blogspot.com/search/label/gdb 149. http://dc0d32.blogspot.com/search/label/nvidia 150. http://dc0d32.blogspot.com/search/label/osdev 151. http://dc0d32.blogspot.com/search/label/windows%207 152. http://dc0d32.blogspot.com/search/label/bochs 153. http://dc0d32.blogspot.com/search/label/boot 154. http://dc0d32.blogspot.com/search/label/bootloader 155. http://dc0d32.blogspot.com/search/label/debug 156. http://dc0d32.blogspot.com/search/label/dual%20boot 157. http://dc0d32.blogspot.com/search/label/gas 158. http://dc0d32.blogspot.com/search/label/gcc 159. http://dc0d32.blogspot.com/search/label/overclock 160. http://dc0d32.blogspot.com/search/label/pidgin 161. http://dc0d32.blogspot.com/search/label/windows 162. http://dc0d32.blogspot.com/search/label/windows%20server%202008 163. http://dc0d32.blogspot.com/search/label/2k8 164. http://dc0d32.blogspot.com/search/label/3DMark 165. http://dc0d32.blogspot.com/search/label/3DMark%20vantage 166. http://dc0d32.blogspot.com/search/label/820 167. http://dc0d32.blogspot.com/search/label/DRAM 168. http://dc0d32.blogspot.com/search/label/Directx%2010 169. http://dc0d32.blogspot.com/search/label/Dirext%2011 170. http://dc0d32.blogspot.com/search/label/Java 171. http://dc0d32.blogspot.com/search/label/OpenJDK 172. http://dc0d32.blogspot.com/search/label/OpenOffice 173. http://dc0d32.blogspot.com/search/label/Pentium%20D 174. http://dc0d32.blogspot.com/search/label/RAID 175. http://dc0d32.blogspot.com/search/label/Sun 176. http://dc0d32.blogspot.com/search/label/UUID 177. http://dc0d32.blogspot.com/search/label/Unicode 178. http://dc0d32.blogspot.com/search/label/VirtualBox 179. http://dc0d32.blogspot.com/search/label/X 180. http://dc0d32.blogspot.com/search/label/Xorg 181. http://dc0d32.blogspot.com/search/label/ageis 182. http://dc0d32.blogspot.com/search/label/assembler 183. http://dc0d32.blogspot.com/search/label/authentication 184. http://dc0d32.blogspot.com/search/label/bash 185. http://dc0d32.blogspot.com/search/label/c 186. http://dc0d32.blogspot.com/search/label/coolbits 187. http://dc0d32.blogspot.com/search/label/dx10 188. http://dc0d32.blogspot.com/search/label/fedora 189. http://dc0d32.blogspot.com/search/label/fortune 190. http://dc0d32.blogspot.com/search/label/gdm 191. http://dc0d32.blogspot.com/search/label/ghostscript 192. http://dc0d32.blogspot.com/search/label/gnome 193. http://dc0d32.blogspot.com/search/label/google 194. http://dc0d32.blogspot.com/search/label/gs 195. http://dc0d32.blogspot.com/search/label/gtalk 196. http://dc0d32.blogspot.com/search/label/heat%20sink 197. http://dc0d32.blogspot.com/search/label/invisible 198. http://dc0d32.blogspot.com/search/label/jabber 199. http://dc0d32.blogspot.com/search/label/kde 200. http://dc0d32.blogspot.com/search/label/latex 201. http://dc0d32.blogspot.com/search/label/lvm 202. http://dc0d32.blogspot.com/search/label/lyx 203. http://dc0d32.blogspot.com/search/label/mount 204. http://dc0d32.blogspot.com/search/label/networked%20audio 205. http://dc0d32.blogspot.com/search/label/networked%20sound 206. http://dc0d32.blogspot.com/search/label/nvclock 207. http://dc0d32.blogspot.com/search/label/oolatex 208. http://dc0d32.blogspot.com/search/label/ooolatex 209. http://dc0d32.blogspot.com/search/label/perl 210. http://dc0d32.blogspot.com/search/label/phonon 211. http://dc0d32.blogspot.com/search/label/physics 212. http://dc0d32.blogspot.com/search/label/physx 213. http://dc0d32.blogspot.com/search/label/picasa 214. http://dc0d32.blogspot.com/search/label/plugin 215. http://dc0d32.blogspot.com/search/label/proxy 216. http://dc0d32.blogspot.com/search/label/pulseaudio 217. http://dc0d32.blogspot.com/search/label/qemu 218. http://dc0d32.blogspot.com/search/label/rsync 219. http://dc0d32.blogspot.com/search/label/rtp 220. http://dc0d32.blogspot.com/search/label/scp 221. http://dc0d32.blogspot.com/search/label/scp%20stdin 222. http://dc0d32.blogspot.com/search/label/security 223. http://dc0d32.blogspot.com/search/label/server 224. http://dc0d32.blogspot.com/search/label/shell 225. http://dc0d32.blogspot.com/search/label/squid 226. http://dc0d32.blogspot.com/search/label/ssh 227. http://dc0d32.blogspot.com/search/label/sync 228. http://dc0d32.blogspot.com/search/label/tar 229. http://dc0d32.blogspot.com/search/label/udev 230. http://dc0d32.blogspot.com/search/label/unix 231. http://dc0d32.blogspot.com/search/label/xdm 232. http://dc0d32.blogspot.com/search/label/xfce 233. http://dc0d32.blogspot.com/search/label/xmpp 234. http://dc0d32.blogspot.com/search/label/xorg.conf 235. http://dc0d32.blogspot.com/search/label/zsh 236. http://www.statcounter.com/blogger/ 237. http://www.istockphoto.com/portfolio/5ugarless?platform=blogger 238. https://www.blogger.com/ Hidden links: 240. https://www.blogger.com/post-edit.g?blogID=35813921&postID=6370208028763486595&from=pencil 241. https://www.blogger.com/comment/frame/35813921?po=6370208028763486595&hl=en