Linuxアセンブリプログラムを書くときそこには多くの可能性があります。はじめに
どのアセンブラを使うか選べます。GAS(AS)を使うのがよいでしょう。gasは
ほとんどのLinuxディストリビューションの標準となっているアセンブラです。
gasの欠点はgasがAT&T-syntax
を使っていることです。これは
Intel-syntax
と大きく違っています。
DOSユーザーはほとんどがIntel-syntax
を使っています。
AT&T-syntax
についてのより詳細な情報は
infoファイルにあります。このinfoファイルをhtmlフォーマットに変換しました。
Intel互換のsyntaxを参照する時はnasmでプログラムを書くことができます。
from the 80xxx-fidonet-area :
= deze bewaar ik : asm =================================================keepit= from : james vahn 17-apr-97 15:20:22 1:346/15.1 to : jan wagemakers 2:292/8133.23 subj : nasm & linux =======================================================================rem_asm=
* 80xxx からの引用 jw> デモがありますが、見ている範囲ではcプログラムから呼び出すように jw> 書かれています。nasmとlinuxで 100% アセンブリプログラムをどのように jw> 書くのか知りたいです。 バグフィックスされたnasm-0.94を使って、ソースを以下のようにアセンブルします。 nasm -f elf hello.asm gcc hello.o -o hello strip hello 学ぶことがたくさんあります :-)
;-------------nasm's standalone hello-world.asm for linux -------- section .text extern puts global main main: push dword msg ;stash the location of msg on the stack. call puts ;call the 'puts' routine (libc?) add esp, byte 4 ;clean the stack? ret ;exit. msg: db "hello world!",0
--- timed 1.01 * origin: james vahn (jvahn@short.circuit.com) (1:346/15.1) ===============================================================================この例ではputsの呼び出しは画面にテキストを表示するのに使われます。putsは cからのもので、Linuxでロードされるライブラリの標準表示です。しかし アセンブリでこれを行う方法もあります。
interrupts
です。
Linuxカーネルの今後のバージョンで変更されるかもしれないのでこの割り込み
(interrupts)を使うのはお奨めしません。
アセンブラ.028から優れたサンプルをpieter de jong
氏が出しました。
例1) putsの呼び出しを使った例
.text message: .ascii "hello world!\0" .align 4 .globl main main: pushl %ebp movl %esp,%ebp #call ___main pushl $message call puts addl $4,%esp xorl %eax,%eax movl %ebp,%esp popl %ebp ret
as hello.s -o hello.o gcc hello.o -o helloとコンパイルします。
例2) int 80h
を使う
.text message: .ascii "hello, world!\12\0" .align 4 .globl _hw _hw: movl $4, %eax movl $1, %ebx movl $message, %ecx movl $15, %edx int $0x80 movl $1, %eax movl $0, %ebx int $0x80
as hello.s -o hello.o ld hello.o -e _hw -o hello (_hw = エントリポイント)とコンパイルします。
changed on : 5 Jul 1997
マクロを使うことによってプログラミングの複雑さをすくなくできます。ある ドキュメントで、GASはマクロを解釈できずアセンブリでマクロを使うにはGASPを 使わねばならないということを読みました。
しかし.. いくつかテストしてみたりGNU-C info
ファイルを読んだところ
GAS(as)を使ってアセンブリプログラムにマクロを加えることができることを
発見しました。
以下、私が行ったテストを紹介します。GAS と マクロ の可能性を試みています
(訳注:dummy.dummy
というファイルがあるかチェックするプログラムです)。
test_fopen.s
のソース:
.include "include.asm" .globl main main: _print hallo # タイトル表示 _open bestand mode # ファイル'dummy.dummy'を開く cmp $0,%eax # Success? je file_error # だめ。エラーメッセージの表示 _close %eax # ファイルを閉じる _print bestaat # 'exist'と表示 jmp einde # プログラム終了 file_error: _print bestaat_niet # 'doesn't exist'と表示する einde: ret # The End ;-) hallo: .string "Test Linux Program ;-) \n" bestaat: .string "The file dummy.dummy exists..." bestaat_niet: .string "The file dummy.dummy doesn't exist..." bestand: .string "dummy.dummy" mode: .string "r" .END
include.asm
.MACRO _print message # start _print message pushl $\message call puts addl $4,%esp # end _print message .ENDM .MACRO _open file mode # start _open ファイルモード pushl %ebp movl %esp,%ebp pushl $\mode pushl $\file call fopen addl $8,%esp movl %eax,-4(%ebp) # %eax = ファイルハンドル # - %eax = 0 ならファイルはない # - %eax >< 0 %eax ならファイルハンドル popl %ebp # end _open ファイルモード .ENDM .MACRO _close filehandle # start _close ファイルハンドル pushl \filehandle call fclose addl $4,%esp # end _close ファイルハンドル .ENDM
as test_fopen.s -o test_fopen.o gcc test_fopen.o -o test_fopenのようにコンパイルします。
1997年7月21日 変更:
Ncurses はテキストベースのLinuxプログラムを書くときに使う関数の ライブラリです。
以下、ピュアなアセンブリプログラムからncurseesをどのように呼び出すか見る ためにサンプルプログラムを挙げます。ちゃんとしたものではないかもしれませんが 動作をみるにはよいと思います :-) 。
sat_color.s
.include "/home/jan/assembler/include/ncurses.asm" .globl main main: _initscr _start_color _init_pair $1,$2,$4 _init_pair $2,$0,$6 _init_pair $3,$3,$4 _init_pair $4,$4,$4 # Hide the flashing cursor call cls # clear screen/init colors. _use_pair $0x00000200 # 00 00(NORMAL) 02(PAIR) 00 _locate $1,$0 _printw $titel _locate $46,$0 _printw $pd _use_pair $0x00200100 # 00 20(BOLD) 01(PAIR) 00 _locate $32,$12 _printw $world _use_pair $0x00200300 # 00 20(BOLD) 03(PAIR) 00 movl $0,%esi lus: movb tabel(%esi),%dl # %dl = X(%esi) incl %esi movb tabel(%esi),%cl # %cl = Y(%esi) incl %esi cmpb $242,%cl jne n242_1 movl $0,%esi jmp lus n242_1: movl %esi,%edi redo: movb tabel(%edi),%dh # %dh = X(%esi + 1) incl %edi movb tabel(%edi),%ch # %ch = Y(%esi + 1) cmpb $242,%ch jne n242_2 movl $0,%edi jmp redo n242_2: movl $leeg,%ebp call print_item movl $linux,%ebp movb %ch,%cl movb %dh,%dl call print_item pushl $160000 # C : usleep(....); call usleep # Wait-loop addl $4,%esp _refresh jmp lus _endwin ret print_item: pushal movzbl %cl,%eax movzbl %dl,%ebx _locate %ebx,%eax _printw %ebp popal ret cls: _use_pair $0x00000200 # 00 00(NORMAL) 02(PAIR) 00 # Color of the first line movb $0,%cl movb $0,%dl cls_lus: movl $chr32,%ebp call print_item incb %dl cmpb $79,%dl jna cls_lus pushal _use_pair $0x00000400 # 00 00(NORMAL) 04(PAIR) 00 # Color of the rest of the screen popal xorb %dl,%dl incb %cl cmpb $25,%cl jna cls_lus ret linux: .string "Linux" leeg: .string " " chr32: .string " " world: .string "World Domination" titel: .string "sat_color.s - 1997 Jan Wagemakers -" pd: .string "Donated to the Public Domain :-)" tabel: .include "cirkel.dat" .byte 242,242 .END
cirkel.dat
.byte 72 , 12 .byte 71 , 13 .byte 69 , 15 .byte 66 , 17 .byte 62 , 18 .byte 56 , 20 .byte 51 , 21 .byte 44 , 21 .byte 38 , 21 .byte 31 , 21 .byte 24 , 21 .byte 18 , 20 .byte 13 , 19 .byte 8 , 17 .byte 5 , 16 .byte 3 , 14 .byte 2 , 12 .byte 2 , 10 .byte 3 , 8 .byte 6 , 7 .byte 10 , 5 .byte 15 , 4 .byte 20 , 3 .byte 27 , 2 .byte 33 , 2 .byte 40 , 2 .byte 47 , 2 .byte 53 , 3 .byte 59 , 4 .byte 63 , 5 .byte 67 , 7 .byte 70 , 8 .byte 71 , 10
/home/jan/assembler/include/ncurses.asm
# ncurses.asm - donated to the public domain by Jan Wagemakers - # derived of the following C-program # #include # # int main(void) # { # initscr(); /* cursesライブラリの初期化 */ # move(10, 2); /* カーソルを X: 2, Y: 10 に置く */ # printw("Hello, World !"); /* 表示するもの */ # refresh(); /* 物理画面に "Hello, World !" を置く */ # getch(); /* キーが押されるのを待つ */ # endwin(); /* deinit the curses libraries. */ # return 0; # } # # Cについてよく知らないので以下は違うこともあります。 # 修正するときはためらわずやって下さい。 # ncursesを使って画面に何か書きたいという時は以下のマクロを呼び出します。 # 1. _initscr # 2. _locate x y (x,y = 画面の座標) # 3. _printw message # 4. _refresh # 5. _endwin (winの終り.... なにかいい響きですね ;-) .MACRO _initscr # start _initscr call initscr # end _initscr .ENDM .MACRO _locate x y # start _locate x y pushl \x pushl \y movl stdscr,%eax pushl %eax call wmove addl $12,%esp # end _locate x y .ENDM .MACRO _printw message # start _print message pushl \message call printw addl $4,%esp # end _printw message .ENDM .MACRO _refresh # start _refresh movl stdscr,%eax pushl %eax call wrefresh addl $4,%esp # end _refresh .ENDM .MACRO _endwin # start _endwin call endwin # end _endwin .ENDM # Colors と ncurses. (15/07/97) # - After _initscr , call _start_color # - Init with _init_pair a color-pair. # - With _use_pair select a color-pair. .MACRO _start_color # start _start_color call start_color # end _start_color .ENDM .MACRO _init_pair pair foreground background # start _init_pair pushl \background pushl \foreground pushl \pair call init_pair addl $12,%esp # end _init_pair .ENDM .MACRO _use_pair pair # start _use_pair movl \pair,%eax # | | %ah | %al | # %eax = xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx # | | # | | # | +----> 使いたいカラーペア(color-pair)番号 # +-------------> 00 = ノーマル , 20 = BOLD pushl %eax movl stdscr,%eax pushl %eax call wattr_on addl $8,%esp #end _use_pair .ENDM
as sat_color.s -o sat_color.o gcc sat_color.o -o sat_color -lncursesとコンパイルし、
./sat_color
で実行します(訳注:このプログラムを
実行すると青い背景の画面中央に緑文字で「World Domination」、その周り
を黄色文字「Linux」がぐるぐる回るデモが見れます。color_xterm
などで
実行してみて下さい)。