1

NASMのマニュアルから大学のガイド、ウィキペディア、そしてその間のすべてまで、今日20ページ以上読んだことを誓いますが、これに頭を悩ませることはできません。ユーザー入力を次のいずれかと比較する単一のプログラムを作成しました。 0または1を選択し、それに基づいて動作します(Assemblyでコツをつかんだら、おそらく配列を使用する必要があります)が、今のところはこれで十分です。

問題は、私のチェックが機能しないことです。それらは常にerrラベルに直接移動します。x86NASMアセンブリを調べました-入力の問題は似ているように見えましたが、まったく同じではありませんでした。ユーザーの入力を保存する必要はありません。 、それが何であったかを確認し、それに反応するだけです。

これが私のコードの縮小版です。2つの連続した0が入力された後に終了することになっています。ユーザーが何を入力したかわからないため、明らかにテストできませんでした。

これがばかげた質問であるならば申し訳ありませんが、今週の議会は私の最善を尽くしました。

; constants
section .data
  lblZero:      db    'Zero';
  lblOne:       db    'One ';
  lblNumLength: db    0x4;
  tmp:          db    0;

; code
section .text
  global _start

; linker needs this, 'main'
_start:

loop:
  ; user was already prompted for a single digit
  ; store user's input ; read
  mov rax, 0 ;
  mov rbx, 19 ;
  mov rcx, tmp ;
  mov rdx, 10 ;
  syscall
  ; series of IFs
  cmp   rcx, 0    ; is input 0? 00 exits the program
  je    isZero
  cmp   rcx, 1    ; is input 1?
  je    isOne  
  jmp   exit  

; user typed 0
isZero:
  inc   rcx               ; flag for 0
  cmp   rcx, 2            ; checking if this is the 2nd zero
  je    exit              ; if so, we are outta here
  mov   rsi, lblZero ;
  mov   rcx, -1 ;
  jmp  print ;

; user typed 1
isOne:
  mov   rsi, lblOne ;
  mov   rcx, -1 ;
  jmp  print ;

; prints the string into the screen ; sys_write
print:
  mov   rax, 1 ;           
  mov   rdi, 1 ;         
  mov   rdx, lblNumLength ;       
  syscall
  jmp   loop

; displays an error message
err:
  ; sys_write, not relevant to the Q     
  syscall
  jmp loop

; shutsdown program ; sys_write ; sys_exit
exit:
  ; not relevant to the Q, code always ends here

http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html#stackで、入力は実際にはintではなく文字であると読んだので、'1を格納するだけの変数を作成してみました。 'または'0'ですが、何もうまくいかないようです。

私はAssemblyにとても慣れていないので、ここで本当にばかげているのであれば、指摘していただければ幸いです。

4

2 に答える 2

3

これを64ビットAMD64Linuxで実行しようとしていると仮定すると、パラメーターをカーネルに渡す正しい方法(呼び出し規約)を使用していることを確認する必要があります。

linux / x64上の64ビットアプリの場合、次のようになります。

  • rax-システムコールID
  • rdi-引数1
  • rsi-引数2
  • rdx-引数3
  • r10-引数4
  • arg5と6はr9r8にあります
  • rcxr11の値は、syscall全体で保持されませんが、他のすべてのレジスタが破壊されることはありません。

さらに、ポールRの答えも正しいです。'0'のASCII表現は10進数のゼロではありません。もう1つの落とし穴は、stdinがデフォルトでバッファモードで動作するため、Enterキーを押すまで実際にはデータを取得しないことです。以下のコードは、2バイトをtmpバッファー(rsiが指す)に読み込み、最初のバイトをascii-zeroと比較します。2番目のバイトは、特に関心のない改行文字です。

; constants
section .data
  lblZero:      db    'Not zero, try again', 0xa;
  tmp:          db    0,0;
; code

section .text
BITS 64
  global _start
_start: 
  mov rax, 0   ; sys_read(int fd, void *ptr, int count)
  mov rdi, 0   ; 0 = stdin 
  mov rsi, tmp ; @ tmp
  mov rdx, 2   ; 2 bytes (one for our number, another to store newline)
  syscall
  cmp byte[rsi], '0' ; is input '0' (or decimal 48) ? 
  je  done
  mov rax, 1            ; sys_write(int fd, void *ptr, int count)
  mov rdi, 1            ; 1 = stdout
  mov rsi, lblZero      ; @lblZero
  mov rdx, 20           ; 20 bytes
  syscall
  jmp _start

done:   
  mov rax, 60 ; sys_exit
  mov rdi, 0
  syscall
于 2012-12-05T21:10:20.000 に答える
2

整数値ではなく、文字を比較する必要があります。変化する:

cmp rcx,0

cmp byte [rcx],'0'

1との比較のための同上。

于 2012-12-02T09:07:02.217 に答える