2

したがって、コンピュータ アーキテクチャ クラスの一環として、アセンブリに慣れる必要があります。または、少なくとも十分に慣れる必要があります。ユーザーへの入力を読み取ってから (当分の間) 再印刷しようとしています。これが私が試した方法です。これを疑似コードでレイアウトするには:

  1. msg 変数を宣言します (これは画面に出力されます)
  2. 十分な長さの値を持つ長さ変数 (sys_write 関数で使用される) を宣言します。
  3. スタックを一度ポップしてプログラム名を取得する
  4. スタックを再度ポップして、最初の引数を取得します
  5. スタックの現在の値を msg 変数に移動します
  6. msg を ECX に移動 (sys_write 引数)
  7. 長さを EDX に移動 (sys_write 引数)
  8. 標準出力を使用して sys_write を呼び出す
  9. カーネルコール
  10. sys_exit を呼び出して終了

これはこれまでの私のコードです

section .data
  msg:    db 'placeholder text',0xa;
  length: dw 0x123;

section .text
  global _start 

    _start: 
      pop rbx;
      pop rbx;
      ; this is not working when I leave it in I get this error:
      ; invalid combination of opcode and operands                                                                                            
      ;mov msg, rbx;
      mov ecx, msg;
      mov edx, length;

      mov eax, 4;
      mov ebx, 1;
      int 0x80;
      mov ebx, 0;
      mov eax, 1;
      int 0x80;

省略した場合 (引数を msg に移動しない場合)、この出力が得られます

placeholder text
#.shstrtab.text.data
                     �@�$�`��

私たちは NASM を本当に始めたばかりなので、どんな助けでも大歓迎ですsyscalls.kernelgrok.com/ http://www.nasm.us/doc/nasmdo11.htmlに一致するようにレジストリ名を私の理解の範囲内で適合させる例を適合させる

私は Ubuntu 12.04、64 ビット コンパイルを実行しています (これが正しい言葉であるかどうかさえわかりません) ELF64 で NASM を実行しています。このようなばかげた質問をして申し訳ありませんが、64 ビットを使用する NASM の十分に簡単なチュートリアルを見つけることができませんでした。 .

4

3 に答える 3

4

プログラムが呼び出されると、スタックは次のようになります。

+----------------+
| ...            | <--- rsp + 24
+----------------+
| argument 2     | <--- rsp + 16
+----------------+
| argument 1     | <--- rsp + 8
+----------------+
| argument count | <--- rsp
+----------------+

最初の引数はプログラムの名前で、2 番目の引数はユーザー入力です (ユーザーが引数として何かを入力した場合)。したがって、引数の数は少なくとも 1 です。

64 モードでのシステム コールの引数は、次のレジスタに格納されます。

  • rax (システムコール番号)
  • rdi (第 1 引数)
  • rsi (第 2 引数)
  • rdx (第 3 引数)
  • rcx (第 4 引数)
  • r8 (第 5 引数)
  • r9 (第 6 引数)

そして、システムコールは で呼び出されsyscallます。すべてのシステム コールの番号は、ここ で確認できます(はい、32 ビット モードの番号とは異なります)。

これはあなたのことをするべきプログラムです:

section .data
    msg:    db 'Requesting 1 argument!', 10  ; message + newline

section .text
    global  _start

_start:
    cmp     qword [rsp], 2    ; check if argument count is 2
    jne     fail              ; if not jump to the fail lable

    mov     rax, 1            ; sys_write
    mov     rdi, 1            ; stdout
    mov     rsi, [rsp+16]     ; get the address of the argument 
    mov     rdx, 1            ; one character (length 1)

loop:
    cmp     byte [rsi], 0     ; check if current character is 0
    je      exit              ; if 0 then jump to the exit lable
    syscall
    inc     rsi               ; jump to the next character
    jmp     loop              ; repeat

fail:
    mov     rax, 1            ; sys_write
    mov     rdi, 1            ; stdout
    lea     rsi, [rel msg]    ; move the address of the lable msg in rsi
    mov     rdx, 23           ; length = 23
    syscall

exit:
    mov     rax, 60           ; sys_exit
    mov     rdi, 0            ; with code 0
    syscall

コードは多くの点で完全ではないため、変更する必要がある場合があります。

于 2012-11-30T15:12:14.560 に答える
2

あなたは文字通り指示に従った - そしてこれは予想される出力です。

メッセージに書き込むスタック変数は、単なるバイナリ値です。正確には、コマンド ライン引数を含む文字列の配列へのポインタです。それを理解するには、これらの文字列を出力するか、ポインターを ascii 文字列に変換する必要があります。「0x12313132」。

于 2012-11-30T07:22:38.487 に答える
2

私のOSはUbuntu 64ビットです。コードをコンパイルすると、次のエラーが発生しました。

nasm print3.asm 

print3.asm:12: error: instruction not supported in 16-bit mode
print3.asm:13: error: instruction not supported in 16-bit mode

「pop rbx」が配置されている正確な場所。

asm ファイルの先頭に「BITS 64」を追加すると、問題が解決しました。

BITS 64

section .data
  msg:    db 'placeholder text',0xa;
  length: dw 0x123;

...
于 2015-02-12T02:30:17.310 に答える