无法将用户输入与数字进行比较,nasm elf64 [英] can't compare user input with number, nasm elf64

查看:18
本文介绍了无法将用户输入与数字进行比较,nasm elf64的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发誓我今天已经阅读了 20 多页,从 NASM 的手册到大学的指南再到维基百科之间的所有内容,但我无法理解这一点,我编写了一个程序来比较用户输入使用 0 或 1,然后根据它采取行动(一旦我在 Assembly 中掌握了它们的窍门,我可能应该使用数组),但现在就可以了.

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.

问题是,我的检查从不工作,他们总是直接进入错误标签,我查看了x86 NASM Assembly - 输入问题 看起来很相似但并不完全相同,我真的不需要存储用户的输入,只需检查它是什么并对此做出反应.

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.

这是我的代码的简化版本,它应该在输入两个连续的 0 后退出,显然我无法测试它,因为我无法弄清楚用户输入了什么.

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

我在这里阅读 http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html#stack 输入不是真正的整数,而是一个字符,所以我尝试创建只存储1"或0"的变量,但是似乎没有什么可以解决问题.

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.

我是 Assembly 的超级新手,所以如果我在这里做的真的很愚​​蠢,如果您指出,我将不胜感激.

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

推荐答案

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

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).

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

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

  • rax - 系统调用 ID
  • rdi - 参数 1
  • rsi - 参数 2
  • rdx - 参数 3
  • r10 - 参数 4
  • arg 5 和 6 在 r9r8
  • rcxr11 值不会跨系统调用保留,但不会破坏所有其他寄存器.
  • 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.

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

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

这篇关于无法将用户输入与数字进行比较,nasm elf64的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆