0

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)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Hunkerjr
  • 83
  • 1
  • 6

1 Answers1

1

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • I am not sure I understand. When typing "1 + ENTER", that is passing the info the terminal so the 1 and 0xA is passed, but how does it get appended at the end of the 2nd string? Looking at strace, my 2nd write is totally different than yours : `write(1, "What is the second number ? \32\0\0\0"..., 6291948) = 2048` – Hunkerjr Nov 16 '19 at 01:33
  • Regarding the output, I think I had some garbage in my .asm file. I deleted it, copied/paste above code, recompile/link, and it works just fine ... I will assume I did something wrong and couldn't see it :) – Hunkerjr Nov 16 '19 at 01:47
  • @Hunkerjr: Your strace output shows you were passing some huge garbage value (`6291948`) in RDX as the length to `write` so you're actually printing both messages at once with the first `write`. Unless that was only for the 2nd prompt? It returns 2048 because is presumably hit the end of a page at that point and the next page was unmapped. Your question was not at all clear about what's actually printed. The code in your question is bug-free and works when copy/pasted and assembled with YASM. Anyway, this is one of many reasons why `strace` is amazingly useful. – Peter Cordes Nov 16 '19 at 01:57
  • Thank you very much. May I ask, could you point me to some good documentation to learn? It's pretty obvious that all I am trying to do with the above is prompt for 2 numbers then perform an arithmetic operation then display the result. I am getting really confuse about variable size, bit, byte and register to use. Had 4 hours night (6 months old daughter!), time to crash and continue tomorrow ;) – Hunkerjr Nov 16 '19 at 03:13
  • @Hunkerjr: Think about the task in a higher-level language like C, or in the abstract in terms of what processing steps have to happen to your data. Then look for instructions or system calls that you can build that out of. Or write it in C or C++ and look at compiler output for hints. [How to remove "noise" from GCC/clang assembly output?](//stackoverflow.com/q/38552116). For your specific thing: https://stackoverflow.com/tags/x86/info has a section on multi-digit numbers. See [NASM Assembly convert input to integer?](//stackoverflow.com/a/49548057) – Peter Cordes Nov 16 '19 at 03:47