0

I'm learning programming in Assembly x86 using the GNU Assembler "as". I'm trying to write a simple program which first asks user for input (a one-digit number), increments that number, then prints it out.

This is what I tried:

# AT&T Syntax used.

inout:                    # subroutine: inout
  movq $0, %rsi
  movq $request, %rdi
  call printf             # Prints: "Enter a number please"

  movq %rsp, %rbp
  subq $8, %rsp
  leaq -8(%rbp), %rsi
  movq $formatstr, %rdi
  movq $0, %rax
  call scanf              # Scan for input
  movq -8(%rbp), %rax     # copy the number from the stack to a register
  incq %rax               # increment it


  movq %rbp, %rsp
  popq %rbp             # reset the stack


  movq $0, %rsi
  movq %rax, %rbx
  movq $result, %rcx
  call printf             # print the string: "The result is: %d\n"

  ret

.text                     # variables

  string: .asciz "inout\n"
  request: .asciz "Enter a number please\n"
  formatstr: .asciz "%1d"
  result: .asciz "The result is: %d\n"


.global main              # Subrountine : main

 main:                    

   movq $0, %rax
   movq $string, %rdi
   call printf            # print string "inout"

   call inout

 end:                    # end of program

   mov $0, %rdi
   call exit

Then I compile and run using the following two commands:

gcc -o inout.o inout.s -no-pie
./inout.o

I get the first two lines printed, I enter a number (1), then I get segmentation fault:

 "inout
 Enter a numbers please"
 1
 Segmentation fault

Could you please check what I am doing wrong? Thanks in advance.

Othman H
  • 75
  • 2
  • 9
  • Use a debugger (like gdb) to find out where you crash. If it's inside a library function, use `bt` to print a backtrace. See the bottom of the x86 tag wiki for debugging tips: https://stackoverflow.com/tags/x86/info. It's hard to know where to look for problems if you don't know which instruction it crashed on, so a debugger is (almost) essential for asm. Maybe you passed a bad address, or maybe you broke the stack or tried to `ret` when `rsp` wasn't pointing to your return address. – Peter Cordes Dec 11 '17 at 13:54
  • @PeterCordes I read that page. The debug instructions themselves need instructions for a beginner like me. I'm programming using AT&T Syntax which was mentioned to be avoided. Any suggestions? – Othman H Dec 11 '17 at 14:04
  • Your problem is that you are not properly ensuring that the point at which calls are made to the _C_ libraries that the stack is 16 byte aligned. This is a requirement of the 64-bit System V ABI. Things like `printf` are failing because they are assuming proper alignment. – Michael Petch Dec 11 '17 at 14:15
  • @MichaelPetch Didn't I do that when I resetted the stack? – Othman H Dec 11 '17 at 14:16
  • @OthmanH: To gdb defaults to AT&T syntax. If want to use it, leave out the step that suggests `set disassembly-flavor intel`, and follow all the rest of the instructions. I made an example of using gdb for asm in another answer, see the bottom of https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit-int-0x80-linux-abi-in-64-bit-code. – Peter Cordes Dec 11 '17 at 14:20
  • You need to ensure the stack is aligned at the top of each of your functions. So `main` needs to make sure things are 16-byte aligned when it calls functions and then the same needs to be done for `inout`. I haven't ben to bed and I'm too tired to explain this. Here is a version of your code that should at least deal with the alignment issue: http://www.capp-sysware.com/misc/stackoverflow/47754414.s – Michael Petch Dec 11 '17 at 14:27
  • 2
    To make things easy you should set up a stack frame at the beginning and end of your function and allocate space on the stack for local variables right after setting up the stack frame. Before returning from the function you do the reverse. Doing it in the middle can make things hard to read and follow and can make keeping stack alignment more difficult to manage. – Michael Petch Dec 11 '17 at 14:29
  • @MichaelPetch The code you added worked in successfully showing output but the output was the same number "1" not incremented. By the way I didn't get what you mentioned about the stack. Could you explain it a bit simpler? I'm a beginner in Assembly. – Othman H Dec 11 '17 at 19:45
  • 2
    I didn't attempt fix any bugs beyond the genepal protection fault you were getting. There are logic issues with the code, but you didn't ask about those. You wanted to know about the segfault and I responded. With that out of the way you should be able to use a debugger (like GDB) to find out your other mistakes.. – Michael Petch Dec 11 '17 at 19:48
  • @MichaelPetch Thank you. I couldn't find any simple and clear guide to install GDB on windows. – Othman H Dec 11 '17 at 20:02
  • @MichaelPetch I installed the package from the GDB website. extracted the .gz file and didn't know how to proceed. – Othman H Dec 11 '17 at 20:03
  • If on Windows what are you using. Ubuntu for Windows (Windows Subsystem for Linux)? MinGW? Cygwin? Something else? – Michael Petch Dec 11 '17 at 20:32
  • I'm using a linux virtual machine on windows 10. I'm reading the readme file of the GDB debugger but it's so complicated. No direct installation. – Othman H Dec 11 '17 at 20:36
  • 1
    If you are using linux `gdb` is usually installed. If it is Ubuntu based distro you should simply be able to install it with `sudo apt-get install gdb` if it wasn't already installed. On Debian distros you can leave off the `sudo` – Michael Petch Dec 11 '17 at 22:13
  • It's Debian 9. Do I just type `apt-get install gdb` in the terminal anywhere? By the way thanks for your help, I managed to fix the program and it works now. Here it is: (https://codepaste.net/fw2nua) . I just swapped registers' names and I still don't know what's the difference. Would it be okay if I send you a couple of basic questions about registers as a private message? Don't worry they won't be long. I'm only trying to get an overview of the basics in this language. – Othman H Dec 11 '17 at 23:04
  • Inside the VM you have linux OS. In its terminal you can use apt-get to manage installed packaged. There's ton of SW available to you, in every common distro, including Debian. So yes, in the terminal in that virtualized linux inside VM. (terminal/console of windows will not work of course, doesn't have apt-get program). – Ped7g Dec 12 '17 at 00:19
  • @Ped7g Thanks. I followed this tutorial on how to install gdb on linux: http://www.gdbtutorial.com/tutorial/how-install-gdb , However, in the last step: `$ make install` I get errors. – Othman H Dec 12 '17 at 13:47
  • wait, if you have Debian installed, why don't you use their repository to install the pre-packaged thing? It's very rare to compile SW nowadays on common linux distro, as almost everything is available in distro-repositories... what kind of problems did you hit with normal installation `apt-get install gdb`? – Ped7g Dec 12 '17 at 14:05
  • @Ped7g I get multiple errors in the last step: `$ make install`. You can check them here: codepaste.net/iOwbn7 – Othman H Dec 13 '17 at 21:19

0 Answers0