At times it is useful to figure out exactly where some oops happened, or to figure out exactly what some C code is compiling to. objdump -d objectfile.o will send to standard output the disassembled objectfile.o. In particular, objdump -d vmlinuz in the root of the kernel tree will dissassemble the whole kernel. You can search for addresses (look for the eip value in the oops), or for function names. Note that the numbers given after a symbol name in an oops (e.g., svc_authorise+0x1f/0x80)) are the offset within the function of the instruction where the oops happened, followed by the total length of the function. So as a sanity check, you should be able to see in the disassembled output that the named function does have the length reported. You can also do obdump -d -S vmlinuz and objdump will attempt to intersperse lines from the C source with the assembly. And make path/to/file.lst in the root of the linux kernel tree is supposed to do this for you, putting the result in file.lst. I've never had much luck with either. Reading the assembly ^^^^^^^^^^^^^^^^^^^^ gas/whatever syntax. Each line has the format address (raw binary) opcode first operand, second operand The operations generally modify the second operand, where such exists. So, for example, "xor" puts the xor of the two operands into the second operand (in particular, "xor something, something" sets "something" to zero). "mov" moves the contents of operand1 to operand2. The operands can be prefaced by a $, in which case they are literal constants, or by a %, in which case they are registers. Anything else is a memory address. An operand like 0x20(%ebx) means the value at offset 32 from the address in the register ebx. More generally, a(b,c,d) means (??).... There are 8 registers you care about, with the following uses: EAX - Function return value EBX ECX EDX EBP - Stack frame pointer ESP - Stack pointer ESI EDI http://www.unixwiz.net/techtips/win32-callconv-asm.html has a pretty basic explanation of the __cdecl calling convention. A short summary: EBX, EBP, ESI, and EDI must never change across a function call, so functions must save and restore them if necessary; the return value is always left in eax; the caller is responsible for pushing arguments onto the stack before calling, last argument first, and popping them off (at its convenience) sometime afterwards. The stack grows downwards, and the last items pushed on the stack are the EIP and the EBP (the EIP automatically by the "call" operation, and the EBP explicitly by the callee). So (assuming 4-byte arguments) the first argument will be at 0x8(%ebp), the second at 0xc(%ebp), etc. But the first few arguments may also be passed on the stack--see http://en.wikipedia.org/wiki/X86_calling_conventions for variations. Conditionals: Conditional branching is done by a test operation followed by a conditional jump. The test operation modifies bits in the special EFLAGS register. One common example: test %ebx,%ebx #sets the ZF bit of EFLAGS to 1 iff the and of its #arguments is 0 (so iff %ebx is 0 in this case) je c042bb2f #jumps to c042bb2f if ZF is set. cmpl? lea?? Sources: intel architecture manuals: test: 3-450 (480) cmp: 3-61 (91) sub (3-448 (478) info gas ? It's often easier to follow an assembly listing if you know some structure offsets. You can figure them out by hand, or use gdb (though there must be a more elegant way of doing this...): bfields@puzzle:linux-2.6.12-rc1$ gdb vmlinux GNU gdb 6.3-debian Copyright 2004 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-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) print &((struct dentry *)0)->d_parent $1 = (struct dentry **) 0x24 (gdb) Note that these offsets vary depending on the exact kernel version and the config options it was built with. (For example, the d_parent pointer above would be at a much lower offset on a non-SMP kernel, since the preceding d_lock field would have size zero.) See also http://marc.info/?l=linux-kernel&m=119976288709741&w=2