ページ 1 / 1
アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 02:04
by 黒船
nasmを学習しています。
環境はlinux(mint)です。
以下のプログラムのように
message db 'hello, world', 0x0a
を.textで定義するとアセンブルできるのですが、
実行すると
Segmentation fault
と表示されてしまいます。
なぜなのですか?
あと .textでも定義できるようになるにはどうしたらいいのですか。
よろしくおねがいします。
コード:
section .data ; データセクションの定義
section .text
global _start ; エントリーポイント
jmp _main ; ジャンプ
_start:
message db 'hello, world', 0x0a
mov edx, 13 ; スタックにバッファを設定
mov eax, 4 ; 出力(sys_write)
mov ebx, 1 ; ファイルハンドル(1=標準出力 > ディスプレィに表示)
_main:
mov ecx, message ; 文字列
int 0x80 ; システムコール,出力する
mov eax, 1 ; sys.exit
mov ebx, 0 ; 終了ステータスコード
int 0x80 ; システムコール,終了する
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 12:17
by softya(ソフト屋)
jmp _main ; ジャンプ
が意味不明なのですが、どんな意図が?
【追記】
_start:
message db 'hello, world', 0x0a
で今回の問題ですが、コレがマズイと思います。
それに関連して上に書いたjmpを入れる場所が問題です。
あるいはmessage を置く場所を変えるかです。
アセンブラでは命令コードとデータは自分でちゃんと分けてやらないといけませんが、それが出来ていないのが問題なのと、エントリーポイントの意味をちゃんと理解していないのも問題かと思います。
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 12:35
by 黒船
これといった意図はないです。
このコードは
サイトにあるものを自分が少し変更を加えただけのものですから、
変な箇所が出てしまいました。
以後気をつけます。
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 12:38
by softya(ソフト屋)
黒船 さんが書きました:これといった意図はないです。
このコードは
サイトにあるものを自分が少し変更を加えただけのものですから、
変な箇所が出てしまいました。
以後気をつけます。
追記で書きましたが、問題点は理解出来ましたでしょうか?
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 13:06
by 黒船
すこし 話が変わるのですが、
今 サーバから送られてきたデータをメモリ上に展開し、
実行するというプログラムを作っています。
うまく説明できませんが
実行ファイルがなくても実行できるプログラム(クラウド アプリケーション?)
を作りたいと思っています。
しかし、そのためには純粋なアセンブリで開発しなければいけなくて、
(余計なヘッダや、.idataがあるとうまく実行できないので ・・・この認識が間違っていたらご指摘おねがいします。)
どうしても.textに文字列を埋め込みたいです。
softyaさんの
>アセンブラでは命令コードとデータは自分でちゃんと分けてやらないといけません
は理解していますが、先にあげたような理由があったので
ひょっとしたら何か良い方法が他にあるのではと思って質問しました。
なのでそこのところはある程度わかっています。
ただ、エントリーポイントの箇所はいまいちわかっていません。
jmp _mainと_mainを消してエントリーポイントの問題は解決したと思っています。
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 13:53
by YuO
黒船 さんが書きました:今 サーバから送られてきたデータをメモリ上に展開し、
実行するというプログラムを作っています。
うまく説明できませんが
実行ファイルがなくても実行できるプログラム(クラウド アプリケーション?)
を作りたいと思っています。
それはクラウドアプリケーションではないですし,データ領域上のプログラムコードを実行することは,通常許されません。
データ領域のページのNXビットは少なくとも最近の64bit OSでは通常デフォルトで有効だと思いますが……。
ダウンロードしてテンポラリに書き出して実行する,インタプリタとして実行する,などのことをする必要があります。
ダウンロードしてテンポラリに書き出したなら,セキュリティを考えて本来ならサンドボックス作らないといけませんけどね。
まぁ,JavaなどでJITがないと使い物にならないので,何らかの対応方法があるとは思いますが……。
# Windowsでは
VirtualAllocExのflProtectに
PAGE_EXECUTE系の値を渡す,という形です。Linux系は探したがわからなかった……。
オフトピック
クラウドアプリケーションというと,クラウド環境下で実行されるアプリケーションが想像されます。
原則的にクラウドサーバー側にアプリケーションがあり,クライアント側は主にブラウザか,専用アプリケーションでもViewと自身のマネージメントを行う程度の機能しかないイメージです。
e.g.) Google Apps, Office Web Apps等。
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年5月19日(日) 14:04
by softya(ソフト屋)
黒船 さんが書きました:すこし 話が変わるのですが、
今 サーバから送られてきたデータをメモリ上に展開し、
実行するというプログラムを作っています。
うまく説明できませんが
実行ファイルがなくても実行できるプログラム(クラウド アプリケーション?)
を作りたいと思っています。
しかし、そのためには純粋なアセンブリで開発しなければいけなくて、
(余計なヘッダや、.idataがあるとうまく実行できないので ・・・この認識が間違っていたらご指摘おねがいします。)
どうしても.textに文字列を埋め込みたいです。
既に書かれている通り、データ領域にあるコードを実行するために色々工夫が必要です。
うっかりするとウィルス対策ソフトにウイルス扱いされるかも。
Linuxの実行権は詳しくないのでコメントできません。
黒船 さんが書きました:
softyaさんの
>アセンブラでは命令コードとデータは自分でちゃんと分けてやらないといけません
は理解していますが、先にあげたような理由があったので
ひょっとしたら何か良い方法が他にあるのではと思って質問しました。
なのでそこのところはある程度わかっています。
ただ、エントリーポイントの箇所はいまいちわかっていません。
jmp _mainと_mainを消してエントリーポイントの問題は解決したと思っています。
エントリーポイントは、実行ファイルとして扱った時に一番最初にプログラムカウンタが設定されるアドレスです。
特殊な使い方をされるようなので、エントリーポイント自体が無意味だと思います。
それとデータは命令の後に書けば命令コードとして実行されないので、そこに書いてください。
ただし、リロケーターブルなアドレッシングの命令だけで書かれていないと実行するのは困難です。
あと
mov ecx, message ; 文字列
がリロケータブルな命令に展開されるのかnasmの機能を確認してください。
コンパイルオプションでも変わるかもしれません。
Re: アセンブリで.textに文字列を定義したい
Posted: 2013年6月12日(水) 00:10
by 黒船
ずいぶん返信が遅くなってしまいました。
皆様のアドバイスを元に勉強しなおし、
アセンブルし、デバッグすることによって
mov ecx, message ; 文字列
はリロケータブルではないことがわかりました。
なので、callを使って実現することになりました。
以下のような感じで実現しました。
動作確認済みです。
この質問はここで解決にさせて頂きます。
ありがとうございました。
コード:
section .text
global _start ; エントリーポイント
_start:
starter:
call data
mov eax, 4 ; 出力(sys_write)
mov ebx, 1 ; ファイルハンドル(1=標準出力 > ディスプレィに表示)
pop ecx
mov edx, 16 ; スタックにバッファを設定
int 0x80 ; システムコール,出力する
jmp short dummy
nop
data:
call [esp]
db 'AAAAAAAAAAAAAAA', 0x0a
ender:
mov eax, 1 ; sys.exit
mov ebx, 0 ; 終了ステータスコード
int 0x80 ; システムコール,終了する