can't compare user input with number, nasm elf64

核能气质少年 提交于 2020-07-31 04:29:47

问题


I swear I've read more than 20 pages today, from NASM's manual to Universities' guides to Wikipedia to everything in between but I just can't wrap my head around this, I wrote a single program to compare the user input with either a 0 or a 1 and then act based on that (I should probably use an array once I get the hang of them in Assembly), but this will do for now.

Problem is, my checks never work, they always go straight to the err label, I looked at x86 NASM Assembly - Problems with Input which seemed similar but it wasn't quite the same, I really don't need to store the user's input, just check what it was and react on it.

Here's a reduce version of my code, it's supposed to exit after two consecutive 0's have been entered, clearly I haven't been able to test it, since I can't figure out what the user entered.

I'm sorry if this is a silly question but this week Assembly has gotten the best of me.

; 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

I read here http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html#stack that the input is not truly an int, but a character, so I tried creating variables that just store '1' or '0' but nothing seems to do the trick.

I'm a super new to Assembly so if I'm doing really stupid here, I would appreciate if you point it out.


回答1:


Assuming you're trying to run this on 64 bit AMD64 linux, you need to make sure you use the right way of passing parameters to the kernel (the calling convention).

For a 64 bit app on linux/x64, it is as follows:

  • rax - system call id
  • rdi - argument 1
  • rsi - argument 2
  • rdx - argument 3
  • r10 - argument 4
  • arg 5 and 6 are in r9 and r8
  • rcx and r11 values are not preserved across syscall, but all other registers will not be clobbered.

In addition, Paul R's answer is also correct. The ASCII representation of '0' is not decimal zero. Another gotcha is that the stdin operates in buffered mode by default, so you won't actually get any data until you press enter. The code below reads two bytes into the tmp buffer (pointed to by rsi) and compares the first with ascii-zero. The second byte is a newline character that we're not particularly interested in.

; 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



回答2:


You need to compare characters, not integer values. Change:

cmp rcx,0

to

cmp byte [rcx],'0'

Ditto for the comparison with 1.



来源:https://stackoverflow.com/questions/13667620/cant-compare-user-input-with-number-nasm-elf64

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!