无法将用户输入与数字,nasm elf64进行比较

时间:2012-12-02 08:21:36

标签: assembly 64-bit nasm

我发誓我今天已经阅读了20多页,从NASM的手册到大学的指南,到维基百科,以及介于两者之间的所有内容但是我无法绕过这个,我写了一个程序来比较用户输入使用0或1然后根据它行动(我应该使用数组,一旦我在程序集中得到它们的挂起),但现在这样做。

问题是,我的检查永远不会工作,他们总是直接找到错误的标签,我看着x86 NASM Assembly - Problems with Input看起来很相似,但它不太相同,我真的不喜欢不需要存储用户的输入,只需检查它是什么并对其作出反应。

这是我的代码的缩小版本,它应该在输入两个连续的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'的变量,但似乎没什么可做的。

我是大会的新手,所以如果我在这里真的很蠢,如果你指出它,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

假设你试图在64位AMD64 linux上运行它,你需要确保使用正确的方法将参数传递给内核(调用约定)。

对于linux / x64上的64位应用程序,它如下:

  • rax - 系统调用ID
  • rdi - 参数1
  • rsi - 参数2
  • rdx - 参数3
  • r10 - 参数4
  • arg 5和6位于 r9 r8
  • 系统调用不会保留
  • rcx r11 值,但所有其他寄存器都不会被破坏。

此外,Paul R的回答也是正确的。 ASCII表示'0'不是十进制零。另一个问题是默认情况下stdin在缓冲模式下运行,因此在按Enter键之前,您实际上不会获得任何数据。下面的代码将两个字节读入tmp缓冲区(由rsi指向)并将第一个字节与ascii-zero进行比较。第二个字节是我们并不特别感兴趣的换行符。

; 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

答案 1 :(得分:1)

您需要比较字符,而不是整数值。变化:

cmp rcx,0

cmp byte [rcx],'0'

与1比较同上。