質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.62%

  • アセンブリ言語

    105questions

    アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

引数を使ったプログラム(nasm)

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 584

binary

score 14

自分はubuntuで動くアセンブリ言語のプログラムを作りましたが予想したように動かず質問させて頂きます。アセンブリはnasmです
【プログラムの説明】PSP(プログラムセグメントプリフィックス)に格納されている文字列の引数を読み込み再び出力するプログラムです。
【利用した考え方】
・まずPSPの80H番地に引数の文字数が格納されている
・82H番地から引数が文字列として格納されている
【実行方法】
端末にて
nasm -f elf64 filename.asm
ld -s -o filename filename.o
./filename abcd ←abcdが文字引数として格納されますよね?

これを実行するとコアダンプが起こります

【プログラム 及びその説明】
section .bss
buffer: resb 1024h
nub: resb 1h

section .text
global _start

_start:
mov edx, 80h
mov ecx, [edx]
mov edx, 82
mov ebx, buffer
mov [nub], ecx

cope:        ;引数をbufferに格納している コピーは文字引数の数を参考している
mov eax, [edx]
mov [ebx], eax
xor eax, eax
inc edx
inc ebx
loop cope

print0:
mov edx, [nub]
mov eax, 4
mov ebx, 1
mov ecx, buffer
int 80h

end:
mov eax,1
int 80h

改善法やもし誤った認識があれば教えてください
よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yohhoy

    2017/09/28 01:25

    LinuxにはPSPが存在しないハズですが...

    キャンセル

  • fuzzball

    2017/09/28 09:18

    以前からDOSとLinuxの情報がごちゃ混ぜになっているようなので、今回もそれっぽいですね。

    キャンセル

  • binary

    2017/09/28 09:28

    linuxでも意図したとおりに動かしたい場合はどうすればいいでしょうか?回答よろしくお願いします

    キャンセル

  • fuzzball

    2017/09/28 09:33

    ググって見つからないような情報でもないと思うのですが、勘違いしていたのだから、もう一度探してみては?

    キャンセル

回答 2

checkベストアンサー

+1

有益な回答を先にいただいていたのでちょっと遠慮したのですが、
サンプルプロを書いていたのでせっかくなので回答させてもらいます。
nasm用に書いたものです。プログラムへの引数はC言語での
main(int argc, *argv[]) でイメージされるようになっていて、
少なくとも本サンプルの実行時は espレジスターで指し示すスタック領域から
高位のアドレスに向けて、4バイトずつ、argc, argv[0], argv[1], argv[2]… と続いていきます。

argc は実行時のコマンドラインを含めた引数の数、
argv[0]はコマンドライン、argv[1]は引数1, argv[2]は引数2。。。と続きます。
4バイトづつなのは、簡単に言えば、32ビットのアドレスだからです。

サンプルではargv[2] までを取得して、標準出力にプリントします。
引数の数(argc)は終了コードとして返します。
コードとしては冗長で、一部危険な使い方のままですが、サンプル用として、あえてベタに書いています。

;hoge.asm
; $ ./hoge arg1 arg2

section .data
    ARGC dd 0
    ARGV0 dd 0
    ARGV1 dd 0
    ARGV2 dd 0

section .text

global _start:

_start:
    mov eax, [esp]

    ; argc
    mov [ARGC], eax 

    ; argv[0]
    mov eax, [esp + 4]
    mov [ARGV0], eax 

    ; argv[1]
    mov eax, [esp + 8]
    mov [ARGV1], eax 

    ; argv[2]
    mov eax, [esp + 12]
    mov [ARGV2], eax 

    mov eax, 4
    mov ebx, 1
    mov ecx, [ARGV0]
    ; 6bytes for './hoge'
    mov edx, 6
    int 80h 

    mov eax, 4
    mov ebx, 1
    mov ecx, [ARGV1]
    ; 4bytes for 'arg1'
    mov edx, 4
    int 80h 

    mov eax, 4
    mov ebx, 1
    mov ecx, [ARGV2]
    ; 4bytes for 'arg2'
    mov edx, 4
    int 80h 

.exit:
    mov eax, 1
    mov ebx, [ARGC]
    int 80h
    ret

コード

ただ、コマンドラインや引数が実行時にどのように自分に渡されるかは、
リンカーのオプションやリンクされたスタートアップルーチンに影響されるはずなので、
上記の情報は鵜呑みにはしないでください。今回のケースに限定してください。

これ以上はメモリの概念とレジスターによる間接アドレッシング等を理解していないと厳しいです。
int80hのx86 linuxシステムコールを理解する為には先のご回答でも言及されていたように、
C言語の知識もほぼ必須です。少なくとも知っていると理解がスムーズなのは確かです。
※Linux はC言語で書かれたPOSIX互換のOSだ、と言うことが大きいです。

実行にあたっては最初はコアダンプ必至だと思うので、必ずデバッガーが必要になります。

Ubuntu 17.04 x86版での実行結果です。
$ ./hoge arg1 arg2 
で3つの引数が本体のプログラムに渡ります。終了後、$? で3が終了コードとして帰っているのが分かります。

イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/02 08:11

    サンプルプログラム付きの解説ありがとうございます。

    キャンセル

+1

アセンブリ言語でプログラムを組む場合、該当環境のABI(Application Binary Interface)を参照する必要があります。

Linux(ELF)環境のIntel x86アセンブラであれば、https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI にある "Intel386 psABI" を参照ください。一通り目を通されることを強くお勧めします。


上記ドキュメントの 2.3 Process Initialization - 2.3.1 Initial Stack and Register State を参照ください。espレジスタを介してあなたの望む情報にアクセスできます。

・まずPSPの80H番地に引数の文字数が格納されている
・82H番地から引数が文字列として格納されている

これはLinuxのABIではありません。PSP(Program Segment Prefix)はDOS OS向けABIです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/28 10:21 編集

    蛇足:アセンブリ言語以外のシステムプログラミング言語(C言語など)の経験はありますか?いきなりアセンブリ言語への入門は難易度が高すぎるかと思います。まずはC言語ソースコードから変換されるアセンブリの対比を見ていく、といった学習法の方がずっと効率的かもしれません。アセンブリ言語では言語そのものにエラー処理サポートなど存在しないため、間違ったプログラムでコアダンプが起きるのは当然です(即座にSEGVしないこともあります)。デバッガの使い方も合わせて学習すべきです。

    キャンセル

  • 2017/10/02 08:10

    学習方法などのプログラミング上達方法を教えていただきありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    アセンブリ言語のレジスタに64bitのアドレスを入れる方法

    x86_64系のアセンブリ言語を勉強しています。 レジスタの中にmovでメモリアドレスを直接代入したい場合などはどうすればよろしいのでしょうか? mov rax,0x000

  • 解決済

    アセンブリ言語の基本

    疑問に思ったところがあります。 前回の質問とちょっと前に質問したものなんですが・・・ アセンブリのコンパイルができません。 スタック領域の順番が同じになってしまいます。 ス

  • 解決済

    アセンブリ言語で読めない箇所があります。

    ポインタを使用するプログラムです。 1 #include<stdio.h> 2 #include<ctype.h> 3 4 char *test(char *

  • 解決済

    ダイナミックリンカローダーについて

    ダイナミックリンカローダについてです。 動的なリンカ 動的なリンカ/ローダ ELFファイルフォーマットの先頭には _startがあります。.textセクションに入っているやつで

  • 解決済

    nasm システムコールの疑問

    自分はnasm 16bit のプログラミングを勉強したものです 今はnasm 32bitをubuntuの端末で動かそうとしているのですが nasm16bitではシステムコールがin

  • 解決済

    ただファイルを開くだけのプログラム

    Ubuntuの端末で動くアセンブリ言語のただファイルを開くだけのシステムを作ってみましたが実行コアダンプが発生します。 具体的には開くだけのシステム+開けたかどうか表示をするプログ

  • 解決済

    アセンブリプログラムの解説

    アセンブリ言語のプルグラムに関する質問です。 ある本でアセンブリを勉強をしているのですがわからない部分があります。 横幅が4の倍数協会にない場合のダミーデータを計算するようなのです

  • 解決済

    nasm 擬似命令 orgについて

    nasmでは擬似命令orgによってプログラムを格納するメモリーアドレスを指定できますよね? GAS(gcc )にはnasmのorgのようなプログラムを格納するアドレスを指定するよう

同じタグがついた質問を見る

  • アセンブリ言語

    105questions

    アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。