質問編集履歴

10

追記

2020/03/29 07:38

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
@@ -1 +1 @@
1
- set_gate関数IDT設定 関数が思うように動作しない。
1
+ 解決しました。:set_gate関数IDT設定 関数が思うように動作しない。
test CHANGED
File without changes

9

追記

2020/03/29 07:38

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -857,3 +857,29 @@
857
857
 
858
858
 
859
859
  この場合エラーになります。(内容に関係なしに)
860
+
861
+
862
+
863
+
864
+
865
+ アセンブリ言語内で定義した関数は割り込みハンドラとして登録し実行することができる。
866
+
867
+ これを利用して解決案として
868
+
869
+ アセンブリ言語内で割り込みハンドラを登録。
870
+
871
+ そのハンドラ内でC言語関数アドレスに向けてJMPする。
872
+
873
+
874
+
875
+ ・・・この方法を試そうと思いましたが
876
+
877
+ アセンブリ言語で書かれたブートローダーと
878
+
879
+ C言語で書かれたカーネルをそれぞれ
880
+
881
+ 別々にリンクしrawバイナリ形式にしたところで繋げているのでこの方法は使えません・・・。
882
+
883
+
884
+
885
+ なんか解決策はないでしょうか?

8

ついき

2020/03/27 07:13

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -819,3 +819,41 @@
819
819
  ブートローダーで上記のプログラムでIDTに登録したところうまくできましたが
820
820
 
821
821
  カーネル以降での登録はまだうまくいっていません。
822
+
823
+
824
+
825
+ ブートローダーはアセンブリ言語で書き
826
+
827
+ カーネル以降はC言語で記述しており
828
+
829
+
830
+
831
+ アセンブリ言語で定義した関数を登録しソフトウエア割り込みで呼び出す分には何も問題なく作動するのですが
832
+
833
+ カーネルつまりC言語で定義された関数を登録すると呼び出した時点でエラー・暴走が起こります。
834
+
835
+ 呼び出した時点で暴走するので関数から復帰する際に~ってわけではなさそうです。
836
+
837
+
838
+
839
+ void function(){}
840
+
841
+
842
+
843
+ なにもしなってのはこのようなやつです。
844
+
845
+
846
+
847
+ _set_gate(idt_address,14,0,ブートローダーアセンブリ言語レベルで定義した関数アドレス,0x08);
848
+
849
+
850
+
851
+ この場合はうまくいき
852
+
853
+
854
+
855
+ _set_gate(idt_address,14,0,カーネルCC言語レベルで定義すた関数アドレス,0x08);
856
+
857
+
858
+
859
+ この場合エラーになります。(内容に関係なしに)

7

追記

2020/03/27 01:13

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -793,3 +793,29 @@
793
793
  そもそもIDTにトラップゲートを設置する以前に何か設定するものでもあるのでしょうか?
794
794
 
795
795
  何か知っておられましたら教えていただけると助かります。
796
+
797
+
798
+
799
+ ```
800
+
801
+ lidt [IDTR]
802
+
803
+ mov eax,int_handler
804
+
805
+ mov [IDT+49*8],ax
806
+
807
+ mov word [IDT+49*8+2],0x08
808
+
809
+ mov word [IDT+49*8+4],0x8E00
810
+
811
+ shr eax,16
812
+
813
+ mov [IDT+49*8+6],ax
814
+
815
+ int 49
816
+
817
+ ```
818
+
819
+ ブートローダーで上記のプログラムでIDTに登録したところうまくできましたが
820
+
821
+ カーネル以降での登録はまだうまくいっていません。

6

追記

2020/03/24 12:22

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -789,3 +789,7 @@
789
789
  ```
790
790
 
791
791
  こちらも結果は同様に変わりませんでした。(1万文字をこえるので変更点以外は省略しました。)
792
+
793
+ そもそもIDTにトラップゲートを設置する以前に何か設定するものでもあるのでしょうか?
794
+
795
+ 何か知っておられましたら教えていただけると助かります。

5

追記yg7いg789

2020/03/23 17:32

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -392,18 +392,6 @@
392
392
 
393
393
  void protect_puts(char*,int,int,int);
394
394
 
395
- void KBC_sendready();
396
-
397
- int in_kbc(int);
398
-
399
- void out_kbc(int,int);
400
-
401
- void set_keyboard();
402
-
403
- void set_mouse();
404
-
405
- void set_PIC_Hardware_interrupt();
406
-
407
395
  void set_intr_gate();
408
396
 
409
397
  void aaa();
@@ -424,14 +412,6 @@
424
412
 
425
413
 
426
414
 
427
- set_PIC_Hardware_interrupt();
428
-
429
- set_keyboard();
430
-
431
- set_mouse();
432
-
433
-
434
-
435
415
  __asm__(
436
416
 
437
417
  "int $0x32\n\t"
@@ -690,157 +670,9 @@
690
670
 
691
671
 
692
672
 
693
- /* PIC ハードウエア割り込みと割り込み処理ルーチンを結び付ける。 */
694
-
695
-
696
-
697
- void set_PIC_Hardware_interrupt(void){
698
-
699
- out_kbc(0x21,0xff); /* マスタPIC 割り込みマスクレジスタ https://books.google.co.jp/books?id=ilSvAgAAQBAJ&pg=PA698&lpg=PA698&dq=30%E6%97%A5os+PIC0_IMR&source=bl&ots=k2QAHG49WB&sig=ACfU3U1p8v00GRN-FGlY4vhikh3HChjXvQ&hl=ja&sa=X&ved=2ahUKEwj-le-m86LoAhXFfd4KHXJ1DzUQ6AEwAHoECAoQAQ#v=onepage&q=30%E6%97%A5os%20PIC0_IMR&f=false */
700
-
701
- out_kbc(0xa1,0xff); /* スレーブPIC 割り込みマスクレジスタ http://softwaretechnique.jp/OS_Development/kernel_development03.html*/
702
-
703
-
704
-
705
- out_kbc(0x20,0x11);
706
-
707
- out_kbc(0x20,0x20); /* IRQ0~IRQ7 INT20~INT27 */
708
-
709
- out_kbc(0x21,1<<2);
710
-
711
- out_kbc(0x21,0x01);
712
-
713
-
714
-
715
- out_kbc(0xa0,0x11);
716
-
717
- out_kbc(0xa0,0x28); /* IRQ8~IRQ15 INT28~INT2f */
718
-
719
- out_kbc(0xa1,2);
720
-
721
- out_kbc(0xa1,0x01);
722
-
723
-
724
-
725
- /* out_kbc(0x21,0xfb);
726
-
727
- out_kbc(0xa1,0xff); */
728
-
729
- }
730
-
731
-
732
-
733
- /* マウス有効化関数 */
734
-
735
-
736
-
737
- void set_mouse(void){
738
-
739
- KBC_sendready();
740
-
741
- out_kbc(0x64,0xd4); /* 0xd4??? */
742
-
743
- KBC_sendready();
744
-
745
- out_kbc(0x60,0xf4);
746
-
747
- }
748
-
749
-
750
-
751
- /* キーボード初期化・有効化関数 */
752
-
753
-
754
-
755
- void set_keyboard(void){
756
-
757
- KBC_sendready();
758
-
759
- out_kbc(0x64,0x60); /* 0x60 ??? */
760
-
761
- KBC_sendready();
762
-
763
- out_kbc(0x64,0x47); /* 0x47 ??? */
764
-
765
- }
766
-
767
-
768
-
769
- /* KBCコントローラーへデータを送れるかどうかを判断する。 */
770
-
771
-
772
-
773
- void KBC_sendready(void){
774
-
775
- for(;;){
776
-
777
- if((in_kbc(0x64)) == 0){
778
-
779
- break;
780
-
781
- }
782
-
783
- }
784
-
785
- }
786
-
787
-
788
-
789
- /* IN KBC ステータスレジスタなど取得関数 */
790
-
791
-
792
-
793
- int in_kbc(int in_number){
794
-
795
- int return_status = 0;
796
-
797
- __asm__ __volatile__(
798
-
799
- "mov %0,%%edx\n\t"
800
-
801
- "xor %%eax,%%eax\n\t"
802
-
803
- "in %%dx,%%al\n\t"
804
-
805
- "mov %%al,%0\n\t"
806
-
807
- :"=m" (return_status)
808
-
809
- :"m" (in_number)
810
-
811
- );
812
-
813
- return return_status;
814
-
815
- }
816
-
817
-
818
-
819
- /* OUT KBC */
820
-
821
-
822
-
823
- void out_kbc(int out_number,int data){
824
-
825
- __asm__ __volatile__(
826
-
827
- "mov %2,%%edx\n\t"
828
-
829
- "mov %3,%%eax\n\t"
830
-
831
- "out %%al,%%dx\n\t"
832
-
833
- :"=m" (out_number),
834
-
835
- "=m" (data)
836
-
837
- :"m" (out_number),
838
-
839
- "m" (data)
840
-
841
- );
842
-
843
- }
673
+
674
+
675
+
844
676
 
845
677
 
846
678
 
@@ -866,8 +698,94 @@
866
698
 
867
699
 
868
700
 
869
- 省略の全コードです。main_kernelから処理がスタートします。
701
+ 文字制限のためPIC初期化関数とかは省略しました。main_kernelから処理がスタートします。
870
702
 
871
703
  INT 0x32(10進数50)でaaa関数を呼び出そうとしています。
872
704
 
873
705
  (何やら長いですが原因が全く分からないのでお願いします・・・。)
706
+
707
+
708
+
709
+ **やってみたこと**
710
+
711
+
712
+
713
+ IDTアドレスの指定が間違えている可能性がある。
714
+
715
+ なので・・・
716
+
717
+ ブートローダーからカーネルへ制御が移行する際に
718
+
719
+
720
+
721
+ push IDT
722
+
723
+
724
+
725
+ とすることでスタックにIDTアドレスを保管し
726
+
727
+ カーネルに制御が移ったらスタックに積まれたアドレスを回収する。
728
+
729
+ ```c
730
+
731
+ /* プロトタイプ宣言 0x1060 */
732
+
733
+ void loop();
734
+
735
+ void protect_puts(char*,int,int,int);
736
+
737
+ void set_intr_gate(int);
738
+
739
+ void aaa();
740
+
741
+ void test();
742
+
743
+
744
+
745
+
746
+
747
+ /* メイン関数 */
748
+
749
+
750
+
751
+ void main_kernel(){
752
+
753
+ int idt_address = 0x00000000;
754
+
755
+ __asm__(
756
+
757
+ "mov 4(%%esp),%%eax\n\t"
758
+
759
+ "mov %%eax,%1\n\t"
760
+
761
+ :"=m" (idt_address)
762
+
763
+ :"m" (idt_address)
764
+
765
+ );
766
+
767
+
768
+
769
+ set_intr_gate(idt_address);
770
+
771
+ }
772
+
773
+
774
+
775
+ void set_intr_gate(int idt_address)
776
+
777
+ {
778
+
779
+ void(* a)() = aaa;
780
+
781
+ _set_gate(idt_address,14,0,&a,0x08); /* 0x8600 */
782
+
783
+ }
784
+
785
+
786
+
787
+
788
+
789
+ ```
790
+
791
+ こちらも結果は同様に変わりませんでした。(1万文字をこえるので変更点以外は省略しました。)

4

追記

2020/03/23 17:21

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
File without changes

3

追記

2020/03/23 14:25

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -381,3 +381,493 @@
381
381
  アセンブリ言語でいうところのret命令みたいのが必要なのでしょうか?
382
382
 
383
383
  (いや、それだったらエラーになるはずだが・・・)
384
+
385
+
386
+
387
+ ```c
388
+
389
+ /* プロトタイプ宣言 0x1060 */
390
+
391
+ void loop();
392
+
393
+ void protect_puts(char*,int,int,int);
394
+
395
+ void KBC_sendready();
396
+
397
+ int in_kbc(int);
398
+
399
+ void out_kbc(int,int);
400
+
401
+ void set_keyboard();
402
+
403
+ void set_mouse();
404
+
405
+ void set_PIC_Hardware_interrupt();
406
+
407
+ void set_intr_gate();
408
+
409
+ void aaa();
410
+
411
+
412
+
413
+ /* メイン関数 */
414
+
415
+
416
+
417
+ void main_kernel(){
418
+
419
+
420
+
421
+ set_intr_gate();
422
+
423
+
424
+
425
+
426
+
427
+ set_PIC_Hardware_interrupt();
428
+
429
+ set_keyboard();
430
+
431
+ set_mouse();
432
+
433
+
434
+
435
+ __asm__(
436
+
437
+ "int $0x32\n\t"
438
+
439
+ );
440
+
441
+
442
+
443
+ loop();
444
+
445
+
446
+
447
+ }
448
+
449
+
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+ void aaa(){
458
+
459
+ char ptr[] = "abcdefghigk";
460
+
461
+ char *a = ptr;
462
+
463
+ protect_puts(a,11,5,5);
464
+
465
+
466
+
467
+ }
468
+
469
+
470
+
471
+ /* 文字表示関数 */
472
+
473
+
474
+
475
+ void protect_puts(char *char_address,int bytes,int side_size,int height_size){ /* 1=文字アドレス,2=バイト */
476
+
477
+
478
+
479
+
480
+
481
+ int vram_address = 0xA0000;
482
+
483
+ int font_address = 0x0500;
484
+
485
+ int byte_count = bytes;
486
+
487
+ int yoko = side_size;
488
+
489
+ int tate = height_size;
490
+
491
+ char *ptrr = char_address;
492
+
493
+
494
+
495
+ __asm__ __volatile__(
496
+
497
+ /* 横設定 */
498
+
499
+ "mov %7,%%eax\n\t"
500
+
501
+ "mov %5,%%ebx\n\t"
502
+
503
+ "add %%eax,%%ebx\n\t"
504
+
505
+ "mov %%ebx,%2\n\t"
506
+
507
+
508
+
509
+
510
+
511
+ "mov %8,%%eax\n\t"
512
+
513
+ "mov $1280,%%ebx\n\t"
514
+
515
+ "mul %%ebx\n\t"
516
+
517
+ "mov %5,%%ebx\n\t"
518
+
519
+ "add %%eax,%%ebx\n\t"
520
+
521
+ "mov %%ebx,%2\n\t"
522
+
523
+
524
+
525
+
526
+
527
+ "mov %6,%%eax\n\t" /* eax = 文字があるアドレス */
528
+
529
+ "mov %3,%%ebx\n\t" /* %0 ebx = バイト数 */
530
+
531
+ ".protect_puts_loop2:\n\t"
532
+
533
+ "cmp $0,%%ebx\n\t"
534
+
535
+ "jz .endd\n\t"
536
+
537
+
538
+
539
+ "xor %%esi,%%esi\n\t"
540
+
541
+ "mov (%%eax),%%esi\n\t" /* esiレジスタにASCII1文字 */
542
+
543
+ /* "mov $97,%%esi\n\t" */
544
+
545
+ "and $0b00000000000000000000000011111111,%%esi\n\t"
546
+
547
+ "shl $4,%%esi\n\t"
548
+
549
+
550
+
551
+ "xor %%ebx,%%ebx\n\t"
552
+
553
+ "mov %4,%%ebx\n\t"
554
+
555
+ "add %%ebx,%%esi\n\t"
556
+
557
+
558
+
559
+
560
+
561
+ "mov %5,%%edi\n\t"
562
+
563
+
564
+
565
+ "mov $16,%%ecx\n\t" /* 1文字 縦16bitだから */
566
+
567
+
568
+
569
+ ".protect_puts_loop:\n\t"
570
+
571
+ "movsb\n\t"
572
+
573
+ "add $80 - 1,%%edi\n\t"
574
+
575
+ "loop .protect_puts_loop\n\t"
576
+
577
+
578
+
579
+ "inc %%eax\n\t"
580
+
581
+
582
+
583
+ "xor %%ebx,%%ebx\n\t"
584
+
585
+
586
+
587
+ "mov %5,%%ebx\n\t"
588
+
589
+ "add $1,%%ebx\n\t"
590
+
591
+ "mov %%ebx,%2\n\t"
592
+
593
+
594
+
595
+ "mov %3,%%ebx\n\t" /* バイトカウント 0かどうか確認 */
596
+
597
+ "sub $1,%%ebx\n\t"
598
+
599
+ "mov %%ebx,%0\n\t"
600
+
601
+ "mov %3,%%ebx\n\t"/* 変更 */
602
+
603
+
604
+
605
+ "jmp .protect_puts_loop2\n\t"
606
+
607
+
608
+
609
+
610
+
611
+ ".endd:\n\t"
612
+
613
+
614
+
615
+
616
+
617
+ : "=m" (byte_count), /* %0 バイト数 */
618
+
619
+ "=m" (font_address),
620
+
621
+ "=m" (vram_address)
622
+
623
+
624
+
625
+ : "m" (byte_count), /* %0 バイト数 %4*/
626
+
627
+ "m" (font_address),
628
+
629
+ "m" (vram_address),
630
+
631
+ "m" (ptrr),
632
+
633
+ "m" (yoko),
634
+
635
+ "m" (tate)
636
+
637
+ );
638
+
639
+
640
+
641
+ }
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+ /* IDT登録関数 */
650
+
651
+
652
+
653
+ #define _set_gate(gate_addr,type,dpl,addr,seg) \
654
+
655
+ do { \
656
+
657
+ int __d0, __d1; \
658
+
659
+ __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
660
+
661
+ "movw %4,%%dx\n\t" \
662
+
663
+ "movl %%eax,%0\n\t" \
664
+
665
+ "movl %%edx,%1" \
666
+
667
+ :"=m" (*((long *) (gate_addr))), \
668
+
669
+ "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
670
+
671
+ :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
672
+
673
+ "3" ((char *) (addr)),"2" ((seg) << 16)); \
674
+
675
+ } while (0)
676
+
677
+
678
+
679
+ void set_intr_gate()
680
+
681
+ {
682
+
683
+ void(* a)() = aaa;
684
+
685
+ _set_gate(0x8590,14,0,&a,0x08); /* 0x8600 */
686
+
687
+ }
688
+
689
+
690
+
691
+
692
+
693
+ /* PIC ハードウエア割り込みと割り込み処理ルーチンを結び付ける。 */
694
+
695
+
696
+
697
+ void set_PIC_Hardware_interrupt(void){
698
+
699
+ out_kbc(0x21,0xff); /* マスタPIC 割り込みマスクレジスタ https://books.google.co.jp/books?id=ilSvAgAAQBAJ&pg=PA698&lpg=PA698&dq=30%E6%97%A5os+PIC0_IMR&source=bl&ots=k2QAHG49WB&sig=ACfU3U1p8v00GRN-FGlY4vhikh3HChjXvQ&hl=ja&sa=X&ved=2ahUKEwj-le-m86LoAhXFfd4KHXJ1DzUQ6AEwAHoECAoQAQ#v=onepage&q=30%E6%97%A5os%20PIC0_IMR&f=false */
700
+
701
+ out_kbc(0xa1,0xff); /* スレーブPIC 割り込みマスクレジスタ http://softwaretechnique.jp/OS_Development/kernel_development03.html*/
702
+
703
+
704
+
705
+ out_kbc(0x20,0x11);
706
+
707
+ out_kbc(0x20,0x20); /* IRQ0~IRQ7 INT20~INT27 */
708
+
709
+ out_kbc(0x21,1<<2);
710
+
711
+ out_kbc(0x21,0x01);
712
+
713
+
714
+
715
+ out_kbc(0xa0,0x11);
716
+
717
+ out_kbc(0xa0,0x28); /* IRQ8~IRQ15 INT28~INT2f */
718
+
719
+ out_kbc(0xa1,2);
720
+
721
+ out_kbc(0xa1,0x01);
722
+
723
+
724
+
725
+ /* out_kbc(0x21,0xfb);
726
+
727
+ out_kbc(0xa1,0xff); */
728
+
729
+ }
730
+
731
+
732
+
733
+ /* マウス有効化関数 */
734
+
735
+
736
+
737
+ void set_mouse(void){
738
+
739
+ KBC_sendready();
740
+
741
+ out_kbc(0x64,0xd4); /* 0xd4??? */
742
+
743
+ KBC_sendready();
744
+
745
+ out_kbc(0x60,0xf4);
746
+
747
+ }
748
+
749
+
750
+
751
+ /* キーボード初期化・有効化関数 */
752
+
753
+
754
+
755
+ void set_keyboard(void){
756
+
757
+ KBC_sendready();
758
+
759
+ out_kbc(0x64,0x60); /* 0x60 ??? */
760
+
761
+ KBC_sendready();
762
+
763
+ out_kbc(0x64,0x47); /* 0x47 ??? */
764
+
765
+ }
766
+
767
+
768
+
769
+ /* KBCコントローラーへデータを送れるかどうかを判断する。 */
770
+
771
+
772
+
773
+ void KBC_sendready(void){
774
+
775
+ for(;;){
776
+
777
+ if((in_kbc(0x64)) == 0){
778
+
779
+ break;
780
+
781
+ }
782
+
783
+ }
784
+
785
+ }
786
+
787
+
788
+
789
+ /* IN KBC ステータスレジスタなど取得関数 */
790
+
791
+
792
+
793
+ int in_kbc(int in_number){
794
+
795
+ int return_status = 0;
796
+
797
+ __asm__ __volatile__(
798
+
799
+ "mov %0,%%edx\n\t"
800
+
801
+ "xor %%eax,%%eax\n\t"
802
+
803
+ "in %%dx,%%al\n\t"
804
+
805
+ "mov %%al,%0\n\t"
806
+
807
+ :"=m" (return_status)
808
+
809
+ :"m" (in_number)
810
+
811
+ );
812
+
813
+ return return_status;
814
+
815
+ }
816
+
817
+
818
+
819
+ /* OUT KBC */
820
+
821
+
822
+
823
+ void out_kbc(int out_number,int data){
824
+
825
+ __asm__ __volatile__(
826
+
827
+ "mov %2,%%edx\n\t"
828
+
829
+ "mov %3,%%eax\n\t"
830
+
831
+ "out %%al,%%dx\n\t"
832
+
833
+ :"=m" (out_number),
834
+
835
+ "=m" (data)
836
+
837
+ :"m" (out_number),
838
+
839
+ "m" (data)
840
+
841
+ );
842
+
843
+ }
844
+
845
+
846
+
847
+ /* ループ関数 */
848
+
849
+
850
+
851
+ void loop(){
852
+
853
+
854
+
855
+ for(; ; ) {
856
+
857
+
858
+
859
+ }
860
+
861
+ }
862
+
863
+
864
+
865
+ ```
866
+
867
+
868
+
869
+ 省略なしの全コードです。main_kernelから処理がスタートします。
870
+
871
+ INT 0x32(10進数50)でaaa関数を呼び出そうとしています。
872
+
873
+ (何やら長いですが原因が全く分からないのでお願いします・・・。)

2

追記

2020/03/23 14:22

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
@@ -1 +1 @@
1
- set_gate関数を使ってIDTにゲートディスクリプタを設置てみたい。
1
+ set_gate関数IDT設定 関数が思うよう動作い。
test CHANGED
@@ -1,6 +1,8 @@
1
+ (内容が乱雑だったので訂正しました。)
2
+
1
3
  IDTのゲートディスクリプタにはaaa関数を登録します。
2
4
 
3
- (一部)
5
+
4
6
 
5
7
  ```c
6
8
 
@@ -10,6 +12,8 @@
10
12
 
11
13
  void aaa();
12
14
 
15
+ void loop();
16
+
13
17
 
14
18
 
15
19
  /* メイン関数 */
@@ -30,13 +34,25 @@
30
34
 
31
35
  );
32
36
 
33
-
37
+ loop();
34
-
38
+
39
+
40
+
35
- }
41
+ }
42
+
43
+
44
+
36
-
45
+ void loop(){
46
+
47
+
48
+
37
-
49
+ for(; ; ) {
50
+
51
+
52
+
38
-
53
+ }
54
+
39
-
55
+ }
40
56
 
41
57
 
42
58
 
@@ -264,19 +280,9 @@
264
280
 
265
281
  a = aaa;
266
282
 
267
- __asm__(
283
+
268
-
269
- "lidt IDTR\n\t"
284
+
270
-
271
- "IDTR:\n\t"
272
-
273
- ".word 0x0200\n\t"
274
-
275
- ".word 0x8400\n\t"
276
-
277
- );
278
-
279
- _set_gate(0x8400,14,0,*a,0x08);
285
+ _set_gate(0x8400,14,0,&a,0x08);
280
286
 
281
287
  }
282
288
 
@@ -284,382 +290,94 @@
284
290
 
285
291
  ```
286
292
 
287
- [こちらから持ってきました。](https://elixir.bootlin.com/linux/v2.6.17.8/source/arch/i386/kernel/traps.c#L1090)
288
-
289
-
290
-
291
- 前提してmain_kernel関数から処理がスタトします。するようにしている。)
292
-
293
- リンク先から持ってきたset_intr_gate関数を使用てIDTに
294
-
295
- aaa関数を示すゲートディスクリプタ(インデックス0 INT 0)を設置し
296
-
297
- ソフトウエア割り込みを起こしてaaa関数を呼び出したいです。
298
-
299
-
300
-
301
- ```c
302
-
303
- void set_intr_gate()
304
-
305
- {
306
-
307
- void(* a)();
308
-
309
- a = aaa;
310
-
311
- __asm__(
312
-
313
- "lidt IDTR\n\t"
314
-
315
- "IDTR:\n\t"
316
-
317
- ".word 0x0200\n\t"
318
-
319
- ".word 0x8400\n\t"
320
-
321
- );
322
-
323
- _set_gate(0x8400,14,0,*a,0x08);
324
-
325
- }
326
-
327
- ```
328
-
329
- もしくは
330
-
331
- ```c
332
-
333
- void set_intr_gate()
334
-
335
- {
336
-
337
- void(* a)();
338
-
339
- a = aaa;
340
-
341
- __asm__(
342
-
343
- "lidt IDTR\n\t"
344
-
345
- "IDTR:\n\t"
346
-
347
- ".word 0x0200\n\t"
348
-
349
- ".word 0x0000\n\t"
350
-
351
- ".word 0x8400\n\t"
352
-
353
- );
354
-
355
- _set_gate(0x8400,14,0,*a,0x08);
356
-
357
- }
358
-
359
- ```
360
-
361
-
362
-
363
- ① __asm__中身,念のた
364
-
365
- IDTの場所を再定義してみました。
366
-
367
-
368
-
369
- IDTスタート場所 0x8400
370
-
371
- IDTサイズ    0x200
372
-
373
-
374
-
375
- LIDTIDTRレジスタにIDT情報をセットます。
376
-
377
-
378
-
379
- ② _set_gate(0x8400,14,0,*a,0x08);
380
-
381
- _set_gate関数を呼び出しています。
382
-
383
-
384
-
385
- 「0x8400」・・・ IDTアドレス(INT 0x00で呼び出したいから一番最初にセットする。)
386
-
387
-
388
-
389
- 「0」・・・dpl
390
-
391
-
392
-
393
- 「*a」・・・aaa関数のポインタ
394
-
395
-
396
-
397
- 「0x08」・・・GDT セグメントディスクリプタ(コード)
398
-
399
-
400
-
401
- GDT:
402
-
403
- dq 0x00_0_0_0_0_000000_0000 ;NULLディスクリプタ―
404
-
405
- .cs: dq 0x00_C_F_9_A_000000_FFFF ;コードディスクリプター
406
-
407
- .ds: dq 0x00_C_F_9_2_000000_FFFF ;データディスクリプタ―
408
-
409
-
410
-
411
- 上から2番目のやつを使用したいのでオフセット0x08を選びました。
412
-
413
- (一応、0x01のパターンも試した)
414
-
415
-
416
-
417
- 上記の手順でIDTにゲートディスクリプタを設置しました。
418
-
419
- いざ、__asm__(
420
-
421
- "INT $0x00\n\t"
422
-
423
- );
424
-
425
- でソフトウエア割り込みを発生されるとプログラムが強制終了となります。
426
-
427
-
428
-
429
- 原因として
430
-
431
- 1 IDTRレジスタにIDTの情報を渡せていない。
432
-
433
- 2 そもそもset_gate関数が使えない
434
-
435
- 3 set_gate関数の引数が間違えており適切なゲートディスクリプタがIDTに設置できていない。
436
-
437
-
438
-
439
- とかがあると思いますが・・・
440
-
441
-
442
-
443
- しっかりプロトタイプ宣言もしていますし(マクロ関数は必要なのか・・・?)
444
-
445
- 呼び出し方もあっているはず(たぶん)
446
-
447
-
448
-
449
- どこが間違えているのでしょうか?
450
-
451
-
452
-
453
- ### 自分でIDT登録関数を作ってみた
454
-
455
- ゲートのフォーマット
456
-
457
- [リンク内容](http://softwaretechnique.jp/OS_Development/kernel_development02.html)
458
-
459
- ```c
460
-
461
- void set_intr_gate()
462
-
463
- {
464
-
465
- int b = 割り込み処理ルーチン先頭アドレス;
466
-
467
- __asm__(
468
-
469
- /* IDT再設定 */
470
-
471
- "lidt IDTR\n\t"
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
- "mov $IDTアドレス + 0,%%ebx\n\t" /* 下位16bitオフセット */
480
-
481
- "mov %1,%%eax\n\t"
482
-
483
- "mov %%ax,(%%ebx)\n\t"
484
-
485
-
486
-
487
- "mov $IDTアドレス + 0x10,%%ebx\n\t" /* セグメントセレクター */
488
-
489
- "mov $0x08,%%eax\n\t"
490
-
491
- "mov %%ax,(%%ebx)\n\t"
492
-
493
-
494
-
495
- "mov $IDTアドレス + 0x20,%%ebx\n\t" /* DPLとか・・・ */
496
-
497
- "mov $0b11110111100000000,%%eax\n\t"
498
-
499
- "mov %%ax,(%%ebx)\n\t"
500
-
501
-
502
-
503
- "mov $IDTアドレス + 0x30,%%ebx\n\t" /* 上位16bitオフセット */
504
-
505
- "mov %1,%%eax\n\t"
506
-
507
- "shr $16,%%eax\n\t"
508
-
509
- "mov %%ax,(%%ebx)\n\t"
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
- "jmp .end\n\t"
518
-
519
- "IDTR:\n\t"
520
-
521
- ".word 0xIDTサイズ\n\t"
522
-
523
- ".word 0x0000\n\t"
524
-
525
- ".word 0xIDTアドレス\n\t"
526
-
527
- ".end:\n\t"
528
-
529
- :"=m" (b)
530
-
531
- :"m" (b)
532
-
533
- );
534
-
535
- }
536
-
537
-
538
-
539
- ```
540
-
541
- 割り込み処理ルーチン
542
-
543
- ```s
544
-
545
- times (512 * 10) - ($ - $$) db 0x00
546
-
547
- jmp $
548
-
549
- ```
550
-
551
- 10セクター目に jmp $ を設置しました。これをソフトウエア割り込みで呼び出せるようにしたいです。
552
-
553
- (これで正しく動くかはわからないが・・・)
554
-
555
-
556
-
557
- 10セクターなので・・・
558
-
559
- 0x200(512)× 0x0A(10) + 0x7C00(ロードされるアドレス) = 0x9000
560
-
561
-
562
-
563
- IDT
564
-
565
- "lidt IDTR\n\t"
566
-
567
- "IDTR:\n\t"
568
-
569
- ".word 0x0200\n\t"
570
-
571
- ".word 0x8400\n\t"
572
-
573
-
574
-
575
- より、0x8400からIDTを開始させているつもりです。
576
-
577
-
578
-
579
- ```c
580
-
581
- void set_intr_gate()
582
-
583
- {
584
-
585
- void(* a)();
586
-
587
- a = aaa;
588
-
589
- int b = 0x9000;
590
-
591
- /* int b = 0x9C00; */
592
-
593
- __asm__(
594
-
595
- /* IDT再設定 */
596
-
597
- "lidt IDTR\n\t"
598
-
599
-
600
-
601
- /* ゲートディスクリプタを作成 */
602
-
603
-
604
-
605
- "mov $0x8400,%%ebx\n\t" /* 下位16bitオフセット */
606
-
607
- "mov %1,%%eax\n\t"
608
-
609
- "mov %%ax,(%%ebx)\n\t"
610
-
611
-
612
-
613
- "mov $0x8410,%%ebx\n\t" /* セグメントセレクター */
614
-
615
- "mov $0x08,%%eax\n\t"
616
-
617
- "mov %%ax,(%%ebx)\n\t"
618
-
619
-
620
-
621
- "mov $0x8420,%%ebx\n\t" /* DPLとか・・・ */
622
-
623
- "mov $0b11110111100000000,%%eax\n\t"
624
-
625
- "mov %%ax,(%%ebx)\n\t"
626
-
627
-
628
-
629
- "mov $0x8430,%%ebx\n\t" /* 上位16bitオフセット */
630
-
631
- "mov %1,%%eax\n\t"
632
-
633
- "shr $16,%%eax\n\t"
634
-
635
- "mov %%ax,(%%ebx)\n\t"
636
-
637
-
638
-
639
-
640
-
641
-
642
-
643
- "jmp .end\n\t"
644
-
645
- "IDTR:"
646
-
647
- ".word 0x0200\n\t"
648
-
649
- ".word 0x0000\n\t"
650
-
651
- ".word 0x8400\n\t"
652
-
653
- ".end:\n\t"
654
-
655
- :"=m" (b)
656
-
657
- :"m" (b)
658
-
659
- );
660
-
661
- ```
662
-
663
- 実行してみるものもまだエラーになります。
664
-
665
- IDT開始アドレスの定義がおかしいのか、それとも割り込み処理ルーチンアドレスの設定が間違えているのか・・・。
293
+ [LinuxカーネルからIDT登録関数を持ってきました。](https://elixir.bootlin.com/linux/v2.6.17.8/source/arch/i386/kernel/traps.c#L1090)
294
+
295
+
296
+
297
+ ブートローダープログラム上記のカネル?)プログラムをrawバイナリ形式変換
298
+
299
+ つけVirtualbox上で動かます。
300
+
301
+
302
+
303
+ _set_gate(0x8400,14,0,&a,0x08);
304
+
305
+
306
+
307
+ これでIDTにゲートディスクリプタの登録を行っています。
308
+
309
+ このプログラムを使ってaaa関数(ポインタaにaaa関数のアドレスが入っている。)
310
+
311
+ をソフトウエア割り込みで呼び出せるようにしたいです。
312
+
313
+
314
+
315
+ aaa関数の中で画面に文字を表示させる関数を読んでいるので
316
+
317
+
318
+
319
+ ソフトウエア割り込み(INT 0x00)
320
+
321
+
322
+
323
+ 登録したゲートディスクリプタ(aaa関数への)が参照されaaa関数が呼ばれる。
324
+
325
+
326
+
327
+ aaa関数内部で画面に文字が表示される関数が呼ばれ
328
+
329
+ 画面上に文字が表示される。
330
+
331
+
332
+
333
+ 以上のことを期待しています。
334
+
335
+
336
+
337
+ 試験的に メモリ0x8600上に
338
+
339
+ jmp $(無限ループ)
340
+
341
+ この命令を配置し、
342
+
343
+ _set_gate(0x8400,14,0,0x8600,0x08);
344
+
345
+ とやってINT 0x00でソフトウエア割り込みを起こしたところ正常に動作しました。
346
+
347
+
348
+
349
+ なので、・・・
350
+
351
+ void(* a)();
352
+
353
+ a = aaa;
354
+
355
+ _set_gate(0x8400,14,0,&a,0x08);
356
+
357
+
358
+
359
+ このようにしてaaa関数へのゲートディスクリプタを作成してINT 0x00で呼び出したのですが
360
+
361
+ エラーこそ起こらないものの画面に何も表示されず
362
+
363
+ 期待通りの動作になりません。
364
+
365
+
366
+
367
+ 0x8600に配置したループ処理が呼べたことから
368
+
369
+ 割り込み処理ルーチンアドレス設定は問題なくきているもと思われます。(ぶん)
370
+
371
+
372
+
373
+ なので、どちらかと言えば
374
+
375
+ aaa関数 あるいは aaa関数内で呼ばれているprotect_puts(文字表示関数)のほうに問題があると思うのですが・・・
376
+
377
+
378
+
379
+ 何がいけないんでしょうか?
380
+
381
+ アセンブリ言語いうところret命令みたいのが必要なのでょうか?
382
+
383
+ (いや、それだったらエラーになるはずだが・・・)

1

追記

2020/03/21 18:20

投稿

kazuyakazuya
kazuyakazuya

スコア193

test CHANGED
File without changes
test CHANGED
@@ -447,3 +447,219 @@
447
447
 
448
448
 
449
449
  どこが間違えているのでしょうか?
450
+
451
+
452
+
453
+ ### 自分でIDT登録関数を作ってみた
454
+
455
+ ゲートのフォーマット
456
+
457
+ [リンク内容](http://softwaretechnique.jp/OS_Development/kernel_development02.html)
458
+
459
+ ```c
460
+
461
+ void set_intr_gate()
462
+
463
+ {
464
+
465
+ int b = 割り込み処理ルーチン先頭アドレス;
466
+
467
+ __asm__(
468
+
469
+ /* IDT再設定 */
470
+
471
+ "lidt IDTR\n\t"
472
+
473
+
474
+
475
+
476
+
477
+
478
+
479
+ "mov $IDTアドレス + 0,%%ebx\n\t" /* 下位16bitオフセット */
480
+
481
+ "mov %1,%%eax\n\t"
482
+
483
+ "mov %%ax,(%%ebx)\n\t"
484
+
485
+
486
+
487
+ "mov $IDTアドレス + 0x10,%%ebx\n\t" /* セグメントセレクター */
488
+
489
+ "mov $0x08,%%eax\n\t"
490
+
491
+ "mov %%ax,(%%ebx)\n\t"
492
+
493
+
494
+
495
+ "mov $IDTアドレス + 0x20,%%ebx\n\t" /* DPLとか・・・ */
496
+
497
+ "mov $0b11110111100000000,%%eax\n\t"
498
+
499
+ "mov %%ax,(%%ebx)\n\t"
500
+
501
+
502
+
503
+ "mov $IDTアドレス + 0x30,%%ebx\n\t" /* 上位16bitオフセット */
504
+
505
+ "mov %1,%%eax\n\t"
506
+
507
+ "shr $16,%%eax\n\t"
508
+
509
+ "mov %%ax,(%%ebx)\n\t"
510
+
511
+
512
+
513
+
514
+
515
+
516
+
517
+ "jmp .end\n\t"
518
+
519
+ "IDTR:\n\t"
520
+
521
+ ".word 0xIDTサイズ\n\t"
522
+
523
+ ".word 0x0000\n\t"
524
+
525
+ ".word 0xIDTアドレス\n\t"
526
+
527
+ ".end:\n\t"
528
+
529
+ :"=m" (b)
530
+
531
+ :"m" (b)
532
+
533
+ );
534
+
535
+ }
536
+
537
+
538
+
539
+ ```
540
+
541
+ 割り込み処理ルーチン
542
+
543
+ ```s
544
+
545
+ times (512 * 10) - ($ - $$) db 0x00
546
+
547
+ jmp $
548
+
549
+ ```
550
+
551
+ 10セクター目に jmp $ を設置しました。これをソフトウエア割り込みで呼び出せるようにしたいです。
552
+
553
+ (これで正しく動くかはわからないが・・・)
554
+
555
+
556
+
557
+ 10セクターなので・・・
558
+
559
+ 0x200(512)× 0x0A(10) + 0x7C00(ロードされるアドレス) = 0x9000
560
+
561
+
562
+
563
+ IDT
564
+
565
+ "lidt IDTR\n\t"
566
+
567
+ "IDTR:\n\t"
568
+
569
+ ".word 0x0200\n\t"
570
+
571
+ ".word 0x8400\n\t"
572
+
573
+
574
+
575
+ より、0x8400からIDTを開始させているつもりです。
576
+
577
+
578
+
579
+ ```c
580
+
581
+ void set_intr_gate()
582
+
583
+ {
584
+
585
+ void(* a)();
586
+
587
+ a = aaa;
588
+
589
+ int b = 0x9000;
590
+
591
+ /* int b = 0x9C00; */
592
+
593
+ __asm__(
594
+
595
+ /* IDT再設定 */
596
+
597
+ "lidt IDTR\n\t"
598
+
599
+
600
+
601
+ /* ゲートディスクリプタを作成 */
602
+
603
+
604
+
605
+ "mov $0x8400,%%ebx\n\t" /* 下位16bitオフセット */
606
+
607
+ "mov %1,%%eax\n\t"
608
+
609
+ "mov %%ax,(%%ebx)\n\t"
610
+
611
+
612
+
613
+ "mov $0x8410,%%ebx\n\t" /* セグメントセレクター */
614
+
615
+ "mov $0x08,%%eax\n\t"
616
+
617
+ "mov %%ax,(%%ebx)\n\t"
618
+
619
+
620
+
621
+ "mov $0x8420,%%ebx\n\t" /* DPLとか・・・ */
622
+
623
+ "mov $0b11110111100000000,%%eax\n\t"
624
+
625
+ "mov %%ax,(%%ebx)\n\t"
626
+
627
+
628
+
629
+ "mov $0x8430,%%ebx\n\t" /* 上位16bitオフセット */
630
+
631
+ "mov %1,%%eax\n\t"
632
+
633
+ "shr $16,%%eax\n\t"
634
+
635
+ "mov %%ax,(%%ebx)\n\t"
636
+
637
+
638
+
639
+
640
+
641
+
642
+
643
+ "jmp .end\n\t"
644
+
645
+ "IDTR:"
646
+
647
+ ".word 0x0200\n\t"
648
+
649
+ ".word 0x0000\n\t"
650
+
651
+ ".word 0x8400\n\t"
652
+
653
+ ".end:\n\t"
654
+
655
+ :"=m" (b)
656
+
657
+ :"m" (b)
658
+
659
+ );
660
+
661
+ ```
662
+
663
+ 実行してみるものもまだエラーになります。
664
+
665
+ IDT開始アドレスの定義がおかしいのか、それとも割り込み処理ルーチンアドレスの設定が間違えているのか・・・。