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 IA-32 computer, e.g. 386, 486, pentium. 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 -f elf -l hello.lst hello.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.o and hello.lst Verify this by typing the command ls -l Type the command: gcc -o hello hello.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 Verify this by typing the command ls -l Execute (run) your program by typing the command: hello 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 break main run set disassembly-flavor intel disassemble main x/90xb main info registers print/x $esp print/x $eax nexti print/x $esp print/x $eax next info float info stack q y 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 $esp print/x $eax To step one instruction nexti Then look at registers again print/x $esp print/x $eax 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.asm the assembler list file is intarith.lst Note that the assembler list file is the most useful file to have when running the debugger. >gdb intarith > intarith.gdb GNU gdb Red Hat Linux (5.2-2) Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) break main Breakpoint 1 at 0x8048370 (gdb) run Starting program: /afs/umbc.edu/users/s/q/squire/home/cs313/intarith Breakpoint 1, 0x08048370 in main () (gdb) set disassembly-flavor intel (gdb) disassemble main Dump of assembler code for function main: 0x8048370 : mov eax,0x5 0x8048375 : mov ds:0x8049624,eax 0x804837a : push ds:0x8049624 0x8048380 : push ds:0x80494e8 0x8048386 : push ds:0x80494e4 0x804838c : push 0x8049502 0x8048391 : push 0x80494ec 0x8048396 : call 0x8048298 0x804839b : add esp,0x14 End of assembler dump. (gdb) x/90xb main 0x8048370 : 0xb8 0x05 0x00 0x00 0x00 0xa3 0x24 0x96 0x8048378 : 0x04 0x08 0xff 0x35 0x24 0x96 0x04 0x08 0x8048380 :0xff 0x35 0xe8 0x94 0x04 0x08 0xff 0x35 0x8048388 :0xe4 0x94 0x04 0x08 0x68 0x02 0x95 0x04 0x8048390 :0x08 0x68 0xec 0x94 0x04 0x08 0xe8 0xfd 0x8048398 :0xfe 0xff 0xff 0x83 0xc4 0x14 0xa1 0xe4 0x80483a0 : 0x94 0x04 0x08 0x03 0x05 0xe8 0x94 0x04 0x80483a8 :0x08 0xa3 0x24 0x96 0x04 0x08 0xff 0x35 0x80483b0 :0x24 0x96 0x04 0x08 0xff 0x35 0xe8 0x94 0x80483b8 :0x04 0x08 0xff 0x35 0xe4 0x94 0x04 0x08 0x80483c0 :0x68 0x08 0x95 0x04 0x08 0x68 0xec 0x94 0x80483c8 :0x04 0x08 (gdb) info registers eax 0x1 1 ecx 0x42130f28 1108545320 edx 0xbffffc0c -1073742836 ebx 0x4213030c 1108542220 esp 0xbffffb9c 0xbffffb9c ebp 0xbffffbd8 0xbffffbd8 esi 0x40013020 1073819680 edi 0xbffffc04 -1073742844 eip 0x8048370 0x8048370 eflags 0x296 662 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x0 0 fctrl 0x37f 895 fstat 0x0 0 ftag 0xffff 65535 fiseg 0x0 0 fioff 0x0 0 foseg 0x0 0 fooff 0x0 0 fop 0x0 0 xmm0 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm1 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm2 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm3 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm4 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm5 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm6 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm7 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} mxcsr 0x1f80 8064 orig_eax 0xffffffff -1 (gdb) print/x $esp $1 = 0xbffffb9c (gdb) print/x $eax $2 = 0x1 (gdb) nexti 0x08048375 in main () (gdb) print/x $esp $3 = 0xbffffb9c (gdb) print/x $eax $4 = 0x5 (gdb) next Single stepping until exit from function main, which has no line number information. 0x42017589 in __libc_start_main () from /lib/i686/libc.so.6 (gdb) info float R7: Empty 0x00000000000000000000 R6: Empty 0x00000000000000000000 R5: Empty 0x00000000000000000000 R4: Empty 0x00000000000000000000 R3: Empty 0x00000000000000000000 R2: Empty 0x00000000000000000000 R1: Empty 0x00000000000000000000 =>R0: Empty 0x00000000000000000000 Status Word: 0x0000 TOP: 0 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0xffff Instruction Pointer: 0x00:0x00000000 Operand Pointer: 0x00:0x00000000 Opcode: 0x0000 (gdb) info stack #0 0x42017589 in __libc_start_main () from /lib/i686/libc.so.6 (gdb) q The program is running. Exit anyway? (y or n) y
The nasm source code is hello.asm This demonstrates basic text output to a screen. ; hello.asm a first program for nasm for Linux, Intel, gcc ; ; assemble: nasm -f elf -l hello.lst hello.asm ; link: gcc -o hello hello.o ; run: hello ; output is: Hello World SECTION .data ; data section msg: db "Hello World",10 ; the string to print, 10=cr len: equ $-msg ; "$" means "here" ; len is a value, not an address SECTION .text ; code section global main ; make label available to linker main: ; standard gcc entry point mov edx,len ; arg3, length of string to print mov ecx,msg ; arg2, pointer to string mov ebx,1 ; arg1, where to write, screen mov eax,4 ; write command to int 80 hex int 0x80 ; interrupt 80 hex, call kernel mov ebx,0 ; exit code, 0=normal mov eax,1 ; exit command to kernel int 0x80 ; interrupt 80 hex, call kernel
Last updated 10/10/03