关于终端上的读取系统调用期间光标移动的问题

问题描述 投票:0回答:1

我对Assembly很陌生,我正在遵循在google / youtube(Mostly this)上找到的一些教程。我试图独自飞行并编写自己的小程序,但是很显然,在学习教程时,它并没有如愿以偿;)我试图了解为什么我没有得到期望的输出,并且也如何调试以了解错误的位置/原因。

我正在使用:-Yasm 1.3.0-Ubuntu 18.04.3 LTS(Bionic Beaver)

我正在使用以下选项进行编译:

yasm -Worphon-labels -g dwarf2 -f elf64 <my_file.asm> -l my_file.lst
ld -g -o my_file my_file.o

这是我的代码:

section .data
  msgOne   db   "Number One ? ", 0x0
  msgOne_len equ $-msgOne

  msgTwo   db   "Number Two ? ", 0x0
  msgTwo_len equ $-msgTwo

section .bss
  numOne resb 8
  numTwo resb 8

section .text
global _start
_start
  mov rax, 1
  mov rdi, 1
  mov rsi, msgOne
  mov rdx, msgOne_len
  syscall

  mov rax, 0
  mov rdi, 0
  mov rsi, numOne
  mov rdx, 8
  syscall

  mov rax, 1
  mov rdi, 1
  mov rsi, msgTwo
  mov rdx, msgTwo_len
  syscall

  mov rax, 0
  mov rdi, 0
  mov rsi, numTwo
  mov rdx, 8
  syscall

  mov rax, 60
  mov rdi, 0
  syscall

我期待以下输出:

Number One ? <waiting for input> ; when provided, next line
Number Two ? <waiting for input> ; when provided, next line
<program exit>

但是我得到以下内容:

Number One ? <waiting for input> ; say we type in 1
Number Two ? 1
_cursor is now here_             ; say we type in 1
<program exit>

几乎没有什么让我感到困惑的:-如果在两个字符串显示之间都未提供0xA,为什么会有新行?-为什么第二个提示上出现“ 1”,为什么光标位于第三行上?-如何调试我的执行程序以试图弄清到底是怎么回事?

我尝试使用edb GUI。我知道如何设置断点/进入,但我不知道自己在寻找什么,在哪里?我也尝试了经典的gdb,但是我不知道如何获取一些调试信息,而不是“运行,下一步,下一步,下一步...程序已完成”。

((如果您想知道,我是出于好奇而学习汇编!下一个管道是C:D)

assembly terminal x86-64 nasm yasm
1个回答
0
投票

当您在输入连接到终端(而不是从文件或其他东西重定向)的情况下运行该程序时,终端仍处于“ echo”模式,内核提供了行编辑功能。因此,用户键入的换行符会影响光标。

当我运行它时,两次输入1 enter后,最终结果出现在我的终端中:

peter@volta:/tmp$ ./foo 
Number One ? 1
Number Two ? 2
peter@volta:/tmp$ 

如果我使用control-D来“提交”文本(这样读将返回)而没有键入换行符,则输出看起来像这样:

peter@volta:/tmp$ ./foo 
Number One ? 1Number Two ? 1peter@volta:/tmp$ 

要了解有关此内容的更多信息,请使用google POSIX TTY和终端输入。


调试:

对于GDB,单步执行时,请使用layout reg显示寄存器。您也可以运行strace ./my_program来跟踪系统调用。请参阅https://stackoverflow.com/tags/x86/info的底部以获取调试提示。

Strace输出,使用-o记录到文件中,因此不会与实际的终端输出混合:

peter@volta:/tmp$ strace -o foo.tr ./foo 
Number One ? 1
Number Two ? 1
peter@volta:/tmp$ cat foo.tr
execve("./foo", ["./foo"], 0x7fffbac22f80 /* 54 vars */) = 0
write(1, "Number One ? \0", 14)         = 14
read(0, "1\n", 8)                       = 2
write(1, "Number Two ? \0", 14)         = 14
read(0, "1\n", 8)                       = 2
exit(0)                                 = ?
+++ exited with 0 +++

注意,您的提示中包含0字节。在终端中,它打印为零宽度,但这仍然不是一个好主意。 write采用指针+长度,并处理任意二进制字节。您应该只保留结尾的零,因为您有显式长度的字符串。

© www.soinside.com 2019 - 2024. All rights reserved.