カーネルすべてをアセンブリ言語で作成するのは嫌なのでC言語ファイルとアセンブリ言語ファイルを
くっつけたい。
C言語コード→GCC
アセンブリ言語コード→NASM
C言語コードをGCCでアセンブルしてアセンブリに変換して
もともとのアセンブリ言語ファイルと合併させる方法を思いついたが
書式が違うのでそれはできない・・・と思っていたができる方法があるらしいです。
;オブジェクトファイルを生成します。 gcc -fno-asynchronous-unwind-tables -s -c struct_offsetof.c -o s3.obj
;objconvでnasm形式のアセンブリファイルに変換する objconv -fnasm s3.obj
さっそくobjconvをインストールして試してみました。
objconvはこちらで簡単に手に入れられた。
C言語コード
c
1int aaa (void){ 2 int i,j; 3 for(i=1;i<21;i++) 4 j= i + 100; 5 return 0; 6 } 7
上記2つのコマンドを実行しました。
以下、NASM形式に変換されたであろう(たぶん)アセンブリコード
s
1; Disassembly of file: sample.obj 2; Thu Mar 5 15:20:20 2020 3; Mode: 32 bits 4; Syntax: YASM/NASM 5; Instruction set: 80386 6 7 8global _aaa: function 9 10 11SECTION .text align=4 execute ; section number 1, code 12 13.text: ; Local function 14 15_aaa: 16 push ebp ; 0000 _ 55 17 mov ebp, esp ; 0001 _ 89. E5 18 sub esp, 16 ; 0003 _ 83. EC, 10 19 mov dword [ebp-4H], 1 ; 0006 _ C7. 45, FC, 00000001 20 jmp ?_002 ; 000D _ EB, 0D 21 22?_001: mov eax, dword [ebp-4H] ; 000F _ 8B. 45, FC 23 add eax, 100 ; 0012 _ 83. C0, 64 24 mov dword [ebp-8H], eax ; 0015 _ 89. 45, F8 25 add dword [ebp-4H], 1 ; 0018 _ 83. 45, FC, 01 26?_002: cmp dword [ebp-4H], 20 ; 001C _ 83. 7D, FC, 14 27 jle ?_001 ; 0020 _ 7E, ED 28 mov eax, 0 ; 0022 _ B8, 00000000 29 leave ; 0027 _ C9 30 ret ; 0028 _ C3 31 32 nop ; 0029 _ 90 33 nop ; 002A _ 90 34 nop ; 002B _ 90 35 36 37SECTION .data align=4 noexecute ; section number 2, data 38 39 40SECTION .bss align=4 noexecute ; section number 3, bss 41 42 43SECTION .rdata$zzz align=4 noexecute ; section number 4, const 44 45 db 47H, 43H, 43H, 3AH, 20H, 28H, 4DH, 69H ; 0000 _ GCC: (Mi 46 db 6EH, 47H, 57H, 2EH, 6FH, 72H, 67H, 20H ; 0008 _ nGW.org 47 db 47H, 43H, 43H, 2DH, 38H, 2EH, 32H, 2EH ; 0010 _ GCC-8.2. 48 db 30H, 2DH, 33H, 29H, 20H, 38H, 2EH, 32H ; 0018 _ 0-3) 8.2 49 db 2EH, 30H, 00H, 00H ; 0020 _ .0.. 50 51 52
この元C言語コードをアセンブリ言語本体のプログラム(カーネル)に
%include "../16_protect_mode/sample.asm"
これでのっけて、正常にコンパイルできるかやってみたところ
../16_protect_mode/sample.asm:11: warning: ignoring unknown section attribute: "execute" [-w+other] ../16_protect_mode/sample.asm:37: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:40: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:43: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:11: warning: ignoring unknown section attribute: "execute" [-w+other] ../16_protect_mode/sample.asm:37: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:40: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:43: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:11: warning: ignoring unknown section attribute: "execute" [-w+other] ../16_protect_mode/sample.asm:37: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:40: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:43: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:11: warning: ignoring unknown section attribute: "execute" [-w+other] ../16_protect_mode/sample.asm:15: error: binary format does not support any special symbol types ../16_protect_mode/sample.asm:37: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:40: warning: ignoring unknown section attribute: "noexecute" [-w+other] ../16_protect_mode/sample.asm:43: warning: ignoring unknown section attribute: "noexecute" [-w+other]
生成されたアセンブリコードのうち
s
1_aaa: 2 push ebp ; 0000 _ 55 3 mov ebp, esp ; 0001 _ 89. E5 4 sub esp, 16 ; 0003 _ 83. EC, 10 5 mov dword [ebp-4H], 1 ; 0006 _ C7. 45, FC, 00000001 6 jmp ?_002 ; 000D _ EB, 0D 7 8?_001: mov eax, dword [ebp-4H] ; 000F _ 8B. 45, FC 9 add eax, 100 ; 0012 _ 83. C0, 64 10 mov dword [ebp-8H], eax ; 0015 _ 89. 45, F8 11 add dword [ebp-4H], 1 ; 0018 _ 83. 45, FC, 01 12?_002: cmp dword [ebp-4H], 20 ; 001C _ 83. 7D, FC, 14 13 jle ?_001 ; 0020 _ 7E, ED 14 mov eax, 0 ; 0022 _ B8, 00000000 15 leave ; 0027 _ C9 16 ret ; 0028 _ C3 17 18 nop ; 0029 _ 90 19 nop ; 002A _ 90 20 nop ; 002B _ 90 21
これ以外は邪魔な情報が入っているのではないか?と考え上記以外は消して再度コンパイルしたところ
エラーなくしてコンパイルできました。
(実際にカーネル内でcall aaaをしてもエラーはでなかった。)
それで質問なのですが
上記のやり方でプログラムは正しく動くのでしょうか?
たまたまうまくいっているように見えるだけでしょうか?
不明点1 インラインアセンブラが反映されていない?
LinuxカーネルのIDT登録関数を持ってきました。
s
1#define _set_gate(gate_addr,type,dpl,addr,seg) \ 2do { \ 3 int __d0, __d1; \ 4 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \ 5 "movw %4,%%dx\n\t" \ 6 "movl %%eax,%0\n\t" \ 7 "movl %%edx,%1" \ 8 :"=m" (*((long *) (gate_addr))), \ 9 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \ 10 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \ 11 "3" ((char *) (addr)),"2" ((seg) << 16)); \ 12} while (0) 13 14 15/* 16 * This needs to use 'idt_table' rather than 'idt', and 17 * thus use the _nonmapped_ version of the IDT, as the 18 * Pentium F0 0F bugfix can have resulted in the mapped 19 * IDT being write-protected. 20 */ 21void set_intr_gate(unsigned int n, void *addr) 22{ 23 _set_gate(0,14,0,0,0); 24/* 注意 値は適当です*/ 25}
s
1_set_intr_gate:; Function begin 2 push ebp ; 0025 _ 55 3 mov ebp, esp ; 0026 _ 89. E5 4 push ebx ; 0028 _ 53 5 sub esp, 16 ; 0029 _ 83. EC, 10 6 mov ecx, 0 ; 002C _ B9, 00000000 7 mov ebx, 4 ; 0031 _ BB, 00000004 8 mov edx, 0 ; 0036 _ BA, 00000000 9 mov eax, 0 ; 003B _ B8, 00000000 10 mov ax, dx ; 0040 _ 66: 89. D0 11; Note: Length-changing prefix causes delay on Intel processors 12 mov dx, 36352 ; 0043 _ 66: BA, 8E00 13 mov dword [ecx], eax ; 0047 _ 89. 01 14 mov dword [ebx], edx ; 0049 _ 89. 13 15 mov dword [ebp-8H], eax ; 004B _ 89. 45, F8 16 mov dword [ebp-0CH], edx ; 004E _ 89. 55, F4 17 nop ; 0051 _ 90 18 add esp, 16 ; 0052 _ 83. C4, 10 19 pop ebx ; 0055 _ 5B 20 pop ebp ; 0056 _ 5D 21 ret ; 0057 _ C3 22; _set_intr_gate End of function 23
中身で_set_gate関数を呼び出していないばかりか
_set_gate関数自体ない気がするのですが・・・
_set_gateを定義しないまま上記からコンパイルしようとしたところ
cmd
1../16_protect_mode/sample.asm:13: error: symbol `__set_gate' undefined 2../16_protect_mode/sample.asm:19: error: label `_set_system_intr_gate' changed during code generation [-w+error=label-redef-late] 3../16_protect_mode/sample.asm:28: error: symbol `__set_gate' undefined
と出たのでどこかしらに_set_gateがあるはずなのだが・・・