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.
The gdb debugger is designed for interactive use. gdb is started with the command gdbFor 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 run set disassembly-flavor intel disassemble main x/90xb main info registers print/x $rsp print/x $rax nexti print/x $rsp print/x $rax next info float info stack q y Additional commands after "run" to get more on screen: layout asm layout regs si si 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 run 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 nexti 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. next 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 q And, gdb requires the confirmation to quit, using a "y". 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 http://gnu.org/licenses/gpl.html 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: http://www.gnu.org/software/gdb/bugs/>... 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
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
Last updated 2/25/2015