Running nasm and gdb

Specifically for nasm on Linux, X86-64, with gcc


  • assembling and running nasm code
  • running the debugger, gdb
  • hello_64.asm
  • nasmdoc.txt manual, a little old
  • assembling and running nasm

    There are many ways to run nasm. This section chooses to
    use only one way for one system. Modify to suit your needs.
    This is for nasm running on Linux on an Intel X86-64 computer.
    gcc, the "C" compilation system and
    libraries are used. The next section will cover gdb, the
    debugger that comes with gcc.
    Use your favorite editor to create a nasm assembly language file.
    e.g. hello.asm shown below.
    Type the command:
       nasm -g -f elf64 -l hello_64.lst  hello_64.asm
    If your program had no assembly time errors, nothing displays.
    If you had assembly time errors, fix them and repeat the command.
    Two files are created by the command  hello_64.o  and  hello_64.lst
    Verify this by typing the command
       ls -l
    Type the command:
       gcc -m64 -o hello_64  hello_64.o
    If your program had no link time errors, nothing displays.
    If you had link time errors, fix the  .asm  file and repeat the command.
    There is now an executable file   hello_64
    Verify this by typing the command
       ls -l
    Execute (run) your program by typing the command:
       hello_64 or ./hello_64
    The output should be displayed.
    That is all there is to do, assuming your output is what you
    expected. Most of the time, the output will be wrong.
    Start by finding the first error in your output, then look
    in the  .asm  file to check the code that was supposed to
    generate the good output. You may also want to check the  .lst
    file in the same area. The  .lst file shows addresses.
    instructions and data as numbers. This is harder to read, yet
    may explain the error.
    If you can not find the error (bug) then use the next section,
    gdb, to help debug your program.

    running the debugger, gdb

    The gdb debugger is designed for interactive use.
    gdb is started with the command
    For this session, the intarith.asm  from the samples is bring used.
    The commands for a sample session are shown, as typed, then explained.
    gdb intarith_64
    break main
    set disassembly-flavor intel
    disassemble main
    x/90xb main
    info registers
    print/x $rsp
    print/x $rax
    print/x $rsp
    print/x $rax
    info float
    info stack
    Additional commands after "run" to get more on screen:
    layout  asm
    layout  regs
          each  "si"  runs an instruction and updates 
    For all of the samples in this WEB page, "main" is used because
    it is the standard gcc name for the main program. The debugger
    works for "C" programs, best if the  -g3  option is used.
    At the time this WEB page was prepared nasm would not add
    debugging information, even with the  -g  option.
    The first command to gdb,  when the (gdb)  prompt appears is
       break main
    This sets a breakpoint on the address of "main" the start of
    the program being debugged.
    The next command runs the program until the breakpoint is reached
    For use with nasm, it is best to set the flavor to intel
       set disassembly-flavor intel
    Then, the disassembly can be seen
       disassemble main
    To see the raw bytes in storage that are the program
       x/90xb main
    The number 90 is just a sample. By looking at the disassembly,
    the number of bytes  main  could be determined.
    To see what is in the integer registers
       info registers
    Note that both hexadecimal and integer values are shown
    To look at specific registers, use  print/x or print/d with
    a dollar sign in front of the register name.
       print/x $rsp
       print/x $rax
    To step one instruction
    Then look at registers again
       print/x $rsp
       print/x $rax
    If there were line number debug information in the executable file,
    then  "next"  would setp one line, rather than one instruction.
    For this case, "next" runs the program to completion.
    For demonstration, the floating point registers may be displayed
       info float
    The stack can be displayed
       info stack
    To quit gdb, the single letter "q" is the complete command
    And, gdb requires the confirmation to quit, using a "y".
    The output from the above, slightly edited to fit on lines
    and with a blank line before each command,is intarith.gdb
    the source file is intarith_64.asm
    the assembler list file is intarith_64.lst
    Note that the assembler list file is the most useful file to have
    when running the debugger. Note extra  "-g"
    Assemble:	  nasm -g -f elf64 -l intarith_64.lst  intarith_64.asm
    Link:		  gcc -m64 -o intarith_64  intarith_64.o
    gdb intarith_64 > intarith_64.gdb
    GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-51.el7
    Copyright (C) 2013 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-redhat-linux-gnu".
    For bug reporting instructions, please see:>...
    Reading symbols from /home/csee1/squire/cs313/intarith_64...done.
    (gdb) break main
    Breakpoint 1 at 0x400530
    (gdb) run
    Starting program: /home/csee1/squire/cs313/intarith_64 
    Breakpoint 1, 0x0000000000400530 in main ()
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-55.el7_0.5.x86_64
    (gdb) set disassembly-flavor intel
    (gdb) disassemble main
    Dump of assembler code for function main:
    => 0x0000000000400530 <+0>:	push   rbp
    End of assembler dump.
    (gdb) x/90xb main
    0x400530 <main>:	0x55	0xb8	0x05	0x00	0x00	0x00	0x48	0x89
    0x400538 <lit5+7>:	0x04	0x25	0x80	0x10	0x60	0x00	0x48	0xbf
    0x400540 <lit5+15>:	0x44	0x10	0x60	0x00	0x00	0x00	0x00	0x00
    0x400548 <lit5+23>:	0x48	0xbe	0x5d	0x10	0x60	0x00	0x00	0x00
    0x400550 <lit5+31>:	0x00	0x00	0x48	0x8b	0x14	0x25	0x34	0x10
    0x400558 <lit5+39>:	0x60	0x00	0x48	0x8b	0x0c	0x25	0x3c	0x10
    0x400560 <lit5+47>:	0x60	0x00	0x4c	0x8b	0x04	0x25	0x80	0x10
    0x400568 <lit5+55>:	0x60	0x00	0xb8	0x00	0x00	0x00	0x00	0xe8
    0x400570 <lit5+63>:	0x9c	0xfe	0xff	0xff	0x48	0x8b	0x04	0x25
    0x400578 <addb+4>:	0x34	0x10	0x60	0x00	0x48	0x03	0x04	0x25
    0x400580 <addb+12>:	0x3c	0x10	0x60	0x00	0x48	0x89	0x04	0x25
    0x400588 <addb+20>:	0x80	0x10
    (gdb) info registers
    rax            0x400530	4195632
    rbx            0x0	0
    rcx            0x4006c0	4196032
    rdx            0x7fffffffe008	140737488347144
    rsi            0x7fffffffdff8	140737488347128
    rdi            0x1	1
    rbp            0x0	0x0
    rsp            0x7fffffffdf18	0x7fffffffdf18
    r8             0x7ffff7dd6e80	140737351872128
    r9             0x0	0
    r10            0x7fffffffdda0	140737488346528
    r11            0x7ffff7a3ca00	140737348094464
    r12            0x400440	4195392
    r13            0x7fffffffdff0	140737488347120
    r14            0x0	0
    r15            0x0	0
    rip            0x400530	0x400530 <main>
    eflags         0x246	[ PF ZF IF ]
    cs             0x33	51
    ss             0x2b	43
    ds             0x0	0
    es             0x0	0
    fs             0x0	0
    gs             0x0	0
    (gdb) print/x $rsp
    $1 = 0x7fffffffdf18
    (gdb) print/x $rax
    $2 = 0x400530
    (gdb) nexti
    0x0000000000400531 in lit5 ()
    (gdb) print/x $rsp
    $3 = 0x7fffffffdf10
    (gdb) print/x $rax
    $4 = 0x400530
    (gdb) next
    Single stepping until exit from function lit5,
    which has no line number information.
    c=5  , a=3, b=4, c=5
    c=a+b, a=3, b=4, c=7
    c=a-b, a=3, b=4, c=-1
    c=a*b, a=3, b=4, c=12
    c=c/a, a=3, b=4, c=4
    [Inferior 1 (process 19708) exited normally]
    (gdb) info float
    (gdb) info stack
    (gdb) q

    hello_64.asm complete program

      The nasm source code is hello_64.asm
      This demonstrates basic text output to a screen.
    ; hello_64.asm    print a string using printf
    ; Assemble:	  nasm -f elf64 -l hello_64.lst  hello_64.asm
    ; Link:		  gcc -m64 -o hello_64  hello_64.o
    ; Run:		  ./hello_64 > hello_64.out
    ; Output:	  cat hello_64.out
    ; Equivalent C code
    ; // hello.c
    ; #include <stdio.h>
    ; int main()
    ; {
    ;   char msg[] = "Hello world\n";
    ;   printf("%s\n",msg);
    ;   return 0;
    ; }
    ; Declare needed C  functions
            extern	printf		; the C function, to be called
            section .data		; Data section, initialized variables
    msg:	db "Hello world", 0	; C string needs 0
    fmt:    db "%s", 10, 0          ; The printf format, "\n",'0'
            section .text           ; Code section.
            global main		; the standard gcc entry point
    main:				; the program label for the entry point
            push    rbp		; set up stack frame, must be aligned
    	mov	rdi,fmt
    	mov	rsi,msg
    	mov	rax,0		; or can be  xor  rax,rax
            call    printf		; Call C function
    	pop	rbp		; restore stack
    	mov	rax,0		; normal, no error, return value
    	ret			; return

    Go to top

    Last updated 2/25/2015