Previous Next Contents Index Doc Set Home

Debugging at the Machine- Instruction Level


This chapter describes how to use event management and process control commands at the machine-instruction level, how to display the contents of memory at specified addresses, and how to display source lines along with their corresponding machine instructions. The next, step, stop and trace commands each support a machine-instruction level variant: nexti, stepi, stopi, and tracei. The regs command can be used to print out the contents of machine registers or the print command can be used to print out individual registers.

This chapter is organized into the following sections:

Examining the Contents of Memory

page 167

Stepping and Tracing at Machine-Instruction Level

page 173

Setting Breakpoints at Machine-Instruction Level

page 175

Using the adb Command

page 176

Using the regs Command

page 176

Examining the Contents of Memory

Using addresses and the examine or x command, you can examine the content of memory locations as well as print the assembly language instruction at each address. Using a command derived from adb(1), the assembly language debugger, you can query for:

You can print the assembly commands using the dis and listi commands.

Using the examine or x Command

Use the examine command, or its alias x, to display memory contents or addresses.

Use the following syntax to display the contents of memory starting at addr for count items in format fmt. The default addr is the next one after the last address previously displayed. The default count is 1. The default fmt is the same as was used in the previous examine command, or X if this is the first command given.

The syntax for the examine command is:

examine [addr] [/ [count] [fmt]]

To display the contents of memory from addr1 through addr2 inclusive, in format fmt:

examine addr1, addr2 [/ [fmt]]

Display the address, instead of the contents of the address in the given format:

examine addr = [fmt]

To print the value stored at the next address after the one last displayed by examine:

examine +/ i

To print the value of an expression, enter the address as an expression:

examine addr=format
examine addr=


The addr is any expression resulting in or usable as an address. The addr may be replaced with a + (plus sign) which displays the contents of the next address in the default format.

Example addresses are:


An absolute address


Address of a function


Offset from a function address


Address of a variable


A pointer-value variable pointing to a string

Symbolic addresses used to display memory are specified by preceding a name with an ampersand (&). Function names can be used without the ampersand; &main is equal to main. Registers are denoted by preceding a name with a dollar sign($).


The fmt is the address display format in which dbx displays the results of a query. The output produced depends on the current display fmt. To change the display format, supply a different fmt code.

Set the fmt specifier to tell dbx how to display information associated with the addresses specified.

The default format set at the start of each dbx session is X, which displays an address/value as a 32-bit word in hexadecimal. The following memory display formats are legal.


Display as an assembly instruction


Display as a halfword in decimal


Display as a word in decimal


Display as a half-word in octal.


Display as a word in octal.


Display as a halfword in hexadecimal.


Display as a word in hexadecimal. (default format)


Display as a byte in octal


Display as a wide character


Display as a wide character.


Display as a string of characters terminated by a null byte.


Display as a wide character.


Display as a single-precision floating point number.

F, g

Display as a double-precision floating point number.


Display as an extended-precision floating point number.

ld, lD

Display as a decimal (4 bytes, same as D)

lo, lO

Display as an octal (4 bytes, same as O)

lx, LX

Display as a hexadecimal (4 bytes, same as X)

Ld, LD

Display as a decimal (8 bytes)

Lo, LO

Display as an octal (8 bytes)

Lx, LX

Display as a hexadecimal (8 bytes)


The count is a repetition count in decimal. The increment size depends on the memory display format.


The following examples show how to use an address with count and fmt options to display five successive disassembled instructions starting from the current stopping point.


(dbx) stepi
stopped in main at 0x108bc
0x000108bc: main+0x000c: st    %l0, [%fp - 0x14]
(dbx) x 0x108bc/5i
0x000108bc: main+0x000c: st    %l0, [%fp - 0x14]
0x000108c0: main+0x0010: mov   0x1,%l0
0x000108c4: main+0x0014: or    %l0,%g0, %o0
0x000108c8: main+0x0018: call  0x00020b90 [unresolved PLT 8: 
0x000108cc: main+0x001c: nop

For Intel:

(dbx) x &main/5i
0x08048988: main       :  pushl  %ebp
0x08048989: main+0x0001:  movl   %esp,%ebp
0x0804898b: main+0x0003:  subl   $0x28,%esp
0x0804898e: main+0x0006:  movl   0x8048ac0,%eax
0x08048993: main+0x000b:  movl   %eax,-8(%ebp)

For PowerPC:

(dbx) x &malloc/5i
0x01f55088: malloc       :  mflr  %r0
0x01f5508c: malloc+0x0004:  stwu  %r1,0xffe0(%r1)
0x01f55090: malloc+0x0008:  stw   %r0,0x0024(%r1)
0x01f55094: malloc+0x000c:  stw   %r31,0x001c(%r1)
0x01f55098: malloc+0x0010:  stw   %r30,0x0018(%r1)

Using the dis Command

The dis command is equivalent to the examine command with i as the default display format.

Here is the syntax for the dis command:

dis addr /[count]

The dis command without arguments displays 10 instructions starting at the address +. With only a count, the dis command displays count instructions starting at the address +.

Using the listi Command

To display source lines along with their corresponding assembly instructions, use listi, which is equivalent to list -i. See the discussion of list -i in Chapter 3, "Viewing and Visiting Code".


(dbx) listi 13, 14
   13       i = atoi(argv[1]);
0x0001083c: main+0x0014:  ld      [%fp + 0x48], %l0
0x00010840: main+0x0018:  add     %l0, 0x4, %l0
0x00010844: main+0x001c:  ld      [%l0], %l0
0x00010848: main+0x0020:  or      %l0, %g0, %o0
0x0001084c: main+0x0024:  call    0x000209e8 [unresolved PLT 7: 
0x00010850: main+0x0028:  nop     
0x00010854: main+0x002c:  or      %o0, %g0, %l0
0x00010858: main+0x0030:  st      %l0, [%fp - 0x8]
   14       j = foo(i);
0x0001085c: main+0x0034:  ld      [%fp - 0x8], %l0
0x00010860: main+0x0038:  or      %l0, %g0, %o0
0x00010864: main+0x003c:  call    foo
0x00010868: main+0x0040:  nop     
0x0001086c: main+0x0044:  or      %o0, %g0, %l0
0x00010870: main+0x0048:  st      %l0, [%fp - 0xc]

For Intel:

(dbx) listi 13, 14
   13       i = atoi(argv[1]);
0x080488fd: main+0x000d:  movl   12(%ebp),%eax
0x08048900: main+0x0010:  movl   4(%eax),%eax
0x08048903: main+0x0013:  pushl  %eax
0x08048904: main+0x0014:  call   atoi <0x8048798>
0x08048909: main+0x0019:  addl   $4,%esp
0x0804890c: main+0x001c:  movl   %eax,-8(%ebp)
   14       j = foo(i);
0x0804890f: main+0x001f:  movl   -8(%ebp),%eax
0x08048912: main+0x0022:  pushl  %eax
0x08048913: main+0x0023:  call   foo <0x80488c0>
0x08048918: main+0x0028:  addl   $4,%esp
0x0804891b: main+0x002b:  movl   %eax,-12(%ebp)

For PowerPC:

(dbx) listi 13, 14
   13       i = atoi(argv[1]);
0x02000964: main+0x002c:  lwz  %r3,0xfff0(%r30)
0x02000968: main+0x0030:  addi %r3,%r3,0x0004
0x0200096c: main+0x0034:  lwz  %r3,000000(%r3)
0x02000970: main+0x0038:  bl   0x020110a4      [atoi [PLT]]
0x02000974: main+0x003c:  stw  %r3,0xffe8(%r30)
   14       j = foo(i);
0x02000978: main+0x0040:  lwz  %r3,0xffe8(%r30)
0x0200097c: main+0x0044:  bl   0x020008e0      [foo]
0x02000980: main+0x0048:  stw  %r3,0xffe4(%r30)

Stepping and Tracing at Machine-Instruction Level

Machine-instruction level commands behave the same as their source level counterparts except that they operate at the level of single instructions instead of source lines.

Single-Stepping the Machine-Instruction Level

To single-step from one machine-instruction to the next machine-instruction:

   Use nexti or stepi
nexti and stepi behave the same as their source-code level counterparts: nexti steps over functions, stepi steps into a function called from the next instruction (stopping at the first instruction in the called function). The command forms are also the same. See next and step for a description.

The output from nexti and stepi differs from the corresponding source level commands in two ways. First, the output includes the address of the instruction at which the program is stopped (instead of the source code line number); secondly, the default output contains the disassembled instruction.

For example:

(dbx) func
(dbx) nexti
ungrasp +0x18:  call support

Tracing at the Machine-Instruction Level

Tracing techniques at the machine instruction level work the same as at the source code level, except when you use tracei. For tracei, dbx executes a single instruction only after each check of the address being executed or the value of the variable being traced. tracei produces automatic stepi-like behavior: the program advances one instruction at a time, stepping into function calls.

When you use tracei, it causes the program to stop momentarily after each instruction while dbx checks for the address execution or the value of the variable or expression being traced. Using tracei can slow execution considerably.

For more information on trace and its event specifications and modifiers, see Chapter 7, "Setting Breakpoints and Traces."

Here is the general syntax for tracei:

tracei event-specification [modifier]

Commonly used forms of tracei are:

tracei step

Trace each instruction

tracei next

Trace each instruction, but skip over calls

tracei at address

Trace the given code address


(dbx) tracei next -in main 
(dbx) cont
0x00010814: main+0x0004:  clr     %l0
0x00010818: main+0x0008:  st      %l0, [%fp - 0x8]
0x0001081c: main+0x000c:  call    foo
0x00010820: main+0x0010:  nop     
0x00010824: main+0x0014:  clr     %l0
(dbx) tracei step -in foo -if glob == 0
(dbx) cont              
0x000107dc: foo+0x0004:  mov     0x2, %l1
0x000107e0: foo+0x0008:  sethi   %hi(0x20800), %l0
0x000107e4: foo+0x000c:  or      %l0, 0x1f4, %l0     ! glob
0x000107e8: foo+0x0010:  st      %l1, [%l0]
0x000107ec: foo+0x0014:  ba      foo+0x1c

Setting Breakpoints at Machine-Instruction Level

To set a breakpoint at machine-instruction level, use stopi. The command stopi accepts any event specification, using the syntax:

stopi event specification [modifier]

Commonly used forms of the stopi command are:

stopi [at address] [if cond]
stopi in function [if cond]

Setting a Breakpoint at an Address

To set a breakpoint at a specific address:

(dbx) stopi at address

For example:

(dbx) nexti
stopped in hand::ungrasp at 0x12638
(dbx) stopi at &hand::ungrasp
(3) stopi at &hand::ungrasp

Using the adb Command

The adb command allows you to enter commands in an adb(1) syntax. You may also enter adb mode which interprets every command as adb syntax. Most adb commands are supported.

For more information on the adb command, see the dbx online help.

Using the regs Command

The regs command lets you print the value of all the registers.

Here is the syntax for the regs command:

regs [-f] [-F]

-f includes floating point registers (single precision). -F includes floating point registers (double precision); this is a SPARC only option.


dbx[13] regs -F
current thread: t@1
current frame:  [1]
g0-g3    0x00000000 0x0011d000 0x00000000 0x00000000
g4-g7    0x00000000 0x00000000 0x00000000 0x00020c38
o0-o3    0x00000003 0x00000014 0xef7562b4 0xeffff420
o4-o7    0xef752f80 0x00000003 0xeffff3d8 0x000109b8
l0-l3    0x00000014 0x0000000a 0x0000000a 0x00010a88
l4-l7    0xeffff438 0x00000001 0x00000007 0xef74df54
i0-i3    0x00000001 0xeffff4a4 0xeffff4ac 0x00020c00
i4-i7    0x00000001 0x00000000 0xeffff440 0x000108c4
y        0x00000000
psr      0x40400086
pc       0x000109c0:main+0x4    mov     0x5, %l0
npc      0x000109c4:main+0x8    st      %l0, [%fp - 0x8]
f0f1     +0.00000000000000e+00
f2f3     +0.00000000000000e+00
f4f5     +0.00000000000000e+00
f6f7     +0.00000000000000e+00

Platform-specific Registers

The following tables list platform-specific register names for SPARC, Intel and PowerPC that can be used in expressions.

SPARC Register Information

The following register information is for SPARC systems.


$g0 through $g7

Global registers

$o0 through $o7

"out" registers

$l0 through $l7

"in" registers

$i0 through $i7

"local" registers


Frame pointer, equivalent to register $i6


Stack pointer, equivalent to register $o6


Y register


Processor state register


Window invalid mask register


Trap base register


Program counter


Next program counter

$f0 through $f31

FPU "f" registers


FPU status register


FPU queue

The $f0f1 $f2f3 ... $f30f31 pairs of floating point registers are treated as having C "double" type (normally $fN registers are treated as C "float" type).

The following additional registers are available on SPARC V9 and V8+ hardware:

$xg0 $xg1 through $xg7

$xo0 $xo1 through $xo7

$xfsr $tstate $gsr

$f32f33 $f34f35 through $f62f63

See the SPARC Architecture Reference Manual and the Sun-4 Assembly Language Reference Manual for more information on SPARC registers and addressing.

Intel Register Information

The following register information is for Intel systems.



Alternate data segment register


Alternate data segment register


Alternate data segment register


Data segment register


Destination index register


Source index register


Frame pointer


Stack pointer


General register


General register


General register


General register


Exception vector number


Error code for exception


Instruction pointer


Code segment register




User stack pointer


Stack segment register

Commonly used registers are also aliased to their machine independent names:


Stack pointer; equivalent of $uesp


Program counter; equivalent of $eip


Frame pointer; equivalent of $ebp

Registers for the 80386 lower halves (16 bits) are:


General register


General register


General register


General register


Source index register


Destination index register


Instruction pointer, lower 16 bits


Flags, lower 16 bits

The first four 80386 16-bit registers can be split into 8-bit parts:


Lower (right) half of register



Higher (left) half of register



Lower (right) half of register



Higher (left) half of register



Lower (right) half of register



Higher (left) half of register



Lower (right) half of register



Higher (left) half of register


Registers for the 80387 are:


Control register


Status register


Tag register


Instruction pointer offset


Code segment selector


Operand pointer offset


Operand pointer selector

$st0 through $st7

Data registers

PowerPC Register Information

The following register information is for PowerPC systems.


$r0 through $r31

General purpose registers

$f0 through $f31

Floating point (double precision) registers


Condition register


Link register


Program counter


Machine state register


Count register


Integer exception register


Multiply quotient/divide dividend register


FP status and control register


Equivalent to $r1

Previous Next Contents Index Doc Set Home