diff options
Diffstat (limited to 'doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt')
-rw-r--r-- | doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt | 892 |
1 files changed, 892 insertions, 0 deletions
diff --git a/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt b/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt new file mode 100644 index 0000000..6834acd --- /dev/null +++ b/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt @@ -0,0 +1,892 @@ + #[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 |