I know that this question was asked some time ago, but here comes the solution working on Windows.
Note: See the last section of this answer to get the solution for other systems and architectures.
x86 32 bit files
OllyDbg2 is the tool that can be used for logging every single assembly instruction along with memory reads and writes. A short guide how to log it is presented below:
- Run OllyDbg.
- Select
Options
->Options...
(or use Alt
+o
shortcut). The options window will show up.
- Search for
Run trace
section and select options specified on image below:

Of course, if you don't want Olly to log all string instructions or code in system DLLs, you may just select two relevant boxes. Additionally, you may choose smaller trace buffer size if you want to dump the log to a file.
- Now, open your target application, but don't start it yet.
- Select
View
->Run trace
.
- Right click on a window that appeared and select memory and register options you want to have in the trace.

- Right click on that window once again and select
Log to file...
option and choose the file where you want to write entire run trace.
- Press
Ctrl
+F11
to start tracing.
- When you want it to stop, click pause button (or
F12
) to pause execution.
- You will see the instructions logged in
Run trace
window.
- Right click on
Run trace
window and select Stop logging
option. This will close and save the trace file.
That's it! You may now open and analyse the file (it will be probably huge nonetheless).
The small excerpt of such a file is presented below (it shows only modified registers and doesn't enter system DLLs):
main <ModuleEntryPoint> JMP SHORT 00401012
main 00401012 MOV EAX,[DWORD DS:4F61EF] [004F61EF]=0 EAX=00000000
main 00401017 SHL EAX,2
main 0040101A MOV [DWORD DS:4F61F3],EAX [004F61F3]=0
main 0040101F PUSH EDX [0019FF80]=0 ESP=0019FF80
main 00401020 PUSH 0 [0019FF7C]=0 ESP=0019FF7C
main 00401022 CALL <JMP.&KERNEL32.GetModuleHandleA> EAX=00400000, ECX=DC5CD787, ESP=0019FF80
main 00401027 MOV EDX,EAX EDX=00400000
main 00401029 CALL 004E7210 ESP=0019FF7C
main 004E7210 MOV EAX,EDX
main 004E7212 CMP [BYTE DS:4F61E0],0 [004F61E0]=00
main 004E7219 JNE SHORT 004E7240
main 004E721B CMP [BYTE DS:4F61E1],0 [004F61E1]=00
main 004E7222 JE SHORT 004E7238
main 004E7238 MOV ECX,[DWORD DS:57D7D4] [0057D7D4]=ollydbg.0061B108 ECX=0061B108
main 004E723E MOV [DWORD DS:ECX],EAX [0061B108]=0
main 004E7240 MOV EAX,[DWORD DS:57D7D8] [0057D7D8]=ollydbg.0061B131 EAX=0061B131
main 004E7245 MOV [BYTE DS:EAX],1 [0061B131]=00
DOS executables
DOSBox Debugger will log everything you want when you are analysing DOS executable.
- Download it from here for example.
- Start application by dragging and dropping the executable on DOSBox Debugger icon.
- Press
Alt
+Pause
at the moment you want to start logging the execution trace - application will freeze.
- Switch to debugger window. You will see something like this:

- Type
logl n
, where n
is a (hexadecimal) number of instructions to log; for example: logl ffff
.
- The log file has been created and should be located in the same directory as DOSBox debugger - it will have
LOGCPU.txt
name.
Several lines of resulting file are given below:
01A2:00004654 mov ax,si 8B C6 EAX:0000002A EBX:0000002A ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007293 CR0:00000000
01A2:00004656 mov dx,000E BA 0E 00 EAX:00000004 EBX:0000002A ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007293 CR0:00000000
01A2:00004659 imul dx F7 EA EAX:00000004 EBX:0000002A ECX:00000A00 EDX:0000000E ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007293 CR0:00000000
01A2:0000465B mov bx,ax 8B D8 EAX:00000038 EBX:0000002A ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:0 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
01A2:0000465D cmp word [bx+56F6],0001 ds:[572E]=0000 83 BF F6 56 01 EAX:00000038 EBX:00000038 ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:0 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
01A2:00004662 jne 00004678 ($+14) (down) 75 14 EAX:00000038 EBX:00000038 ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
01A2:00004678 inc si 46 EAX:00000038 EBX:00000038 ECX:00000A00 EDX:00000000 ESI:00000004 EDI:00000004 EBP:0000FFE2 ESP:0000FFDE DS:26EF ES:A000 FS:0000 GS:0000 SS:26EF CF:1 ZF:0 SF:1 OF:0 AF:1 PF:1 IF:1 TF:0 VM:0 FLG:00007296 CR0:00000000
Every or almost every architectures and systems
radare2 is the tool that may be used for your purpose regardless the system and architecture (complete list of them is given here).
- Run
r2 -c aei -d programToDebug
.
- Put a breakpoint at the address where you want to start tracing (using
db address_in_hex
for example).
- Run
dc
to continue until the breakpoint is hit.
- Type
e dbg.trace=1
and press enter.
- Run
des N
to step N
instructions (for example des 10
).
- Use
dtd > log1
to print instructions traced to log1
file.
- Use
dte > log2
to print all memory and register accesses to log2
file.
Sample contents of these files are given below:
Instructions:
And some corresponding memory accesses:

Of course, it will be nicer to have these outputs listed in such a way as OllyDbg does, for example, but it just requires to write a script that links these two files together and displays the information in more convenient way. Like so, for instance:

Python script for creating such an output from these files is available here. Usage:
./prettyTraceLog.py file1 file2
, where log1
and log2
are default values. If you find any bug, or want to modify it for some other reason, feel free to do it.
Thanks @pancake for telling me how to do tracing in radare2
.
PIN_SafeCopy
(not used in the example) to access the memory, and you're done.