Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/floppy/doc/dc0d32.blogspot.com_2010_06_real-mode-in-c-with-gcc-writing.txt
blob: 6834acd76864244753ae18a0025e542d48186483 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
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