1

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

问题是,我的检查从来没有用过,它们总是直接进入错误标签,我查看了x86 NASM 程序集 - 输入问题,看起来很相似但并不完全相同,我真的不需要存储用户的输入,只需检查它是什么并对其做出反应。

这是我的代码的简化版本,它应该在输入两个连续的 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 位 AMD64 linux 上运行它,您需要确保使用正确的方式将参数传递给内核(调用约定)。

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

  • rax - 系统调用 ID
  • rdi - 参数 1
  • rsi - 参数 2
  • rdx - 参数 3
  • r10 - 参数 4
  • arg 5 和 6 在r9r8中
  • rcxr11值不会在系统调用中保留,但不会破坏所有其他寄存器。

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

; 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 回答