I am pretty new to Assembly and I am following some tutorials that I found on google / youtube (Mostly this).
I am trying to fly on my own and write my own little program, but obviously, it doesn't go as it goes while following a tutorial ;)
I am trying to understand why I am not getting the output that I am expecting and also, how can I debug to understand where/what my error is/are.
I am using : - yasm 1.3.0 - Ubuntu 18.04.3 LTS (Bionic Beaver)
I am compiling with following options :
yasm -Worphon-labels -g dwarf2 -f elf64 <my_file.asm> -l my_file.lst
ld -g -o my_file my_file.o
Here's my code :
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
I am expecting the following output :
Number One ? <waiting for input> ; when provided, next line
Number Two ? <waiting for input> ; when provided, next line
<program exit>
But I am getting the following :
Number One ? <waiting for input> ; say we type in 1
Number Two ? 1
_cursor is now here_ ; say we type in 1
<program exit>
There are few things that confuse me :
- Why is there a new line if I did not provide 0xA between both string display?
- Why is the '1' on the 2nd prompt appearing and why is the cursor on 3rd line?
- How can I debug my exec to try to figure out what is going on ?
I tried to use edb GUI. I knwo how to set a breakpoint / step into but I can't figure out what I am looking for and where?
I also try the classic gdb but I'm clueless how to get some debug information, other than "run, next, next, next ... program completed".
(In case you are wondering, I am learning Assembly by pure curiosity! Next in the pipeline is C :D)
When you run this program with input connected to a terminal (instead of redirected from a file or something), the terminal is still in "echo" mode, with line editing provided by the kernel. So the newline typed by the user affects the cursor.
When I run it, the final result in my terminal after typing 1 enter twice:
peter@volta:/tmp$ ./foo
Number One ? 1
Number Two ? 2
peter@volta:/tmp$
If I used control-D to "submit" text (so read would return) without typing a newline, output looks like this:
peter@volta:/tmp$ ./foo
Number One ? 1Number Two ? 1peter@volta:/tmp$
To learn more about this stuff, google POSIX TTY and terminal input.
Debugging:
For GDB, use layout reg
to show registers while you single step. Also you can run strace ./my_program
to trace system calls. See the bottom of https://stackoverflow.com/tags/x86/info for debugging tipes.
Strace output, recorded to a file with -o
so it doesn't mix with the actual terminal output:
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 +++
Notice that your prompts included a 0
byte. In a terminal it prints as zero-width but it's still a bad idea. write
takes a pointer + length and works on arbitrary binary bytes. You should just leave out the terminating zero because you have explicit-length strings.