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などで
実行してみて下さい)。