我对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)
当您在输入连接到终端(而不是从文件或其他东西重定向)的情况下运行该程序时,终端仍处于“ 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
采用指针+长度,并处理任意二进制字节。您应该只保留结尾的零,因为您有显式长度的字符串。