无法将用户输入的数字与nasm elf64进行比较 [英] can't compare user input with number, nasm elf64
问题描述
我发誓今天我已经读了20多个页面,从NASM的手册到大学的Wikipedia指南,以及介于两者之间的所有内容,但我对此无能为力,我编写了一个程序来比较用户输入用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.
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在 r9 和 r8 中
- rcx 和 r11 的值不会在整个系统调用中保留,但所有其他寄存器都不会被破坏.
- 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的答案也是正确的. ASCII表示的'0'不是十进制的零.另一个陷阱是,标准输入默认情况下在缓冲模式下运行,因此,除非您按Enter键,否则实际上不会获得任何数据.下面的代码将两个字节读入tmp缓冲区(由rsi指向),并将第一个字节与ascii-零进行比较.第二个字节是换行符,我们对此并不特别感兴趣.
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屋!