CHARLES UNIVERSITY IN PRAGUE
http://d3s.mff.cuni.cz/~jezek
faculty of mathematics and physics
Principles of Computers17th Lecture
Pavel Ježek, [email protected]
Selected Faults/Traps/Exceptions of x86 ISA
CPU Exception Interrupt vector(all push IP of faulting instruction)
Invalid opcode 6
Divide by zero (DIV0) 0
Alignment check 17 ($11)
General Protection Fault 13 ($0D)
Page Fault 14 ($0E)
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image ... ... ... ... call P.EXE entrypoint ... ... main program of P.EXE ...
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... main program of P.EXE ...
Dependency Walker (depends.exe)
Process Explorerwww.sysinternals.com
Really Dynamic DLL Loading Example
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefree
... free
... free
... free9 free8 A data7 A data6 A data5 A code4 A code3 A code2 A code1 A codePT ...
→ call procedure at address 4000 (= in page 3 for 1kB pages)
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
→ read variable at address 8200 (= in page 8 for 1kB pages)
A’s entrypoint
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefree
... free
... free
... free9 free8 A data (guard)7 A data (guard)6 A data (guard)5 A code (guard)4 A code (guard)3 A code (guard)2 A code (guard)1 A codePT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
A’s entrypoint
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefree
... free
... free
... free9 free8 A data (guard)7 A data (guard)6 A data (guard)5 A code (guard)4 A code (guard)3 A code (guard)2 A code (guard)1 A codePT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
A’s entrypoint
→ call procedure at address 4000 (= in page 3 for 1kB pages)
page fault
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefree
... free
... free
... free9 free8 A data (guard)7 A data (guard)6 A data (guard)5 A code (guard)4 A code (guard)3 A code2 A code (guard)1 A codePT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
A’s entrypoint
→ call procedure at address 4000 (= in page 3 for 1kB pages)
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefree
... free
... free
... free9 free8 A data (guard)7 A data (guard)6 A data (guard)5 A code (guard)4 A code (guard)3 A code2 A code (guard)1 A codePT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
A’s entrypoint
→ call procedure at address 4000 (= in page 3 for 1kB pages)
→ read variable at address 8200 (= in page 8 for 1kB pages)
page fault
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefree
... free
... free
... free9 free8 A data7 A data (guard)6 A data (guard)5 A code (guard)4 A code (guard)3 A code2 A code (guard)1 A codePT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
A’s entrypoint
→ call procedure at address 4000 (= in page 3 for 1kB pages)
→ read variable at address 8200 (= in page 8 for 1kB pages)
page fault
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... main program of P.EXE ...
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) ... ... ... (never here = rest of P.EXE main program) ... ... ret goto
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) ... ret ... should not get here ... ... ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → ExecExit syscallarguments
SP →return address
Exit → P main........................
IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images (A.DLL, B.DLL) ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) ... ret ... P.EXE’s main program continues ... ... ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Exec
SP →Exit syscallarguments
return addressExit → P main
...
...
...
...
...
...
...
...
IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... ... ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → ExecExit syscallarguments
SP →return address
Exit → P main........................
IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... ... ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
arguments
SP →return address
P main → ExecExit syscallarguments
return addressExit → P main
...
...
...
...
...
...
...
...
IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images ... ... call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... ... ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shell
SP →P.EXE’s entrypoint
argumentsreturn address
P main → ExecExit syscallarguments
return addressExit → P main
...
...
...
...
...
...
...
...
IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID ret goto
context switch
context switch
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... AllocMem → for currentPID = 2 call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) ret goto
context switch to PID 2
context switch back to PID 1
1) Allocated memory (pages)
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... AllocMem → for currentPID = 2 call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) ret goto
context switch to PID 2
context switch back to PID 1
1) Allocated memory (pages)2) CPU fault → kernel interrupt handler →
call procTable[currentPID].faultHandlers[faultID]
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... AllocMem → for currentPID = 2 call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) ret goto
context switch to PID 2
context switch back to PID 1
1) Allocated memory (pages)2) CPU fault → kernel interrupt handler →
call procTable[currentPID].faultHandlers[faultID]3) Open files – e.g. ReadFile(fileDesc, ...):
read from procTable[currentPID].fileDescTable[fileDesc]
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... AllocMem → for currentPID = 2 call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) ret goto
context switch to PID 2
context switch back to PID 1
1) Allocated memory (pages)2) CPU fault → kernel interrupt handler →
call procTable[currentPID].faultHandlers[faultID]3) Open files – e.g. ReadFile(fileDesc, ...):
read from procTable[currentPID].fileDescTable[fileDesc]
4) Current path – e.g. OpenFile(path, ...)if path startsWith ‘/’ or ‘\’ then open file at (path)else open file at (procTable[currentPID].workingDir + path)
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... AllocMem → for currentPID = 1 repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID (1) currentPID := AllocateNewPID; (2) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... AllocMem → for currentPID = 2 call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID (1) ret goto
context switch to PID 2
context switch back to PID 1
1) Allocated memory (pages)2) CPU fault → kernel interrupt handler →
call procTable[currentPID].faultHandlers[faultID]3) Open files – e.g. ReadFile(fileDesc, ...):
read from procTable[currentPID].fileDescTable[fileDesc]
4) Current path – e.g. OpenFile(path, ...)if path startsWith ‘/’ or ‘\’ then open file at (path)else open file at (procTable[currentPID].workingDir + path)
5) List of loaded DLLs
Further Options How to Take Advantage of Processes …
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInitshell local & temporary
variables Exec syscall
argumentsreturn address
Exec → shellExec local & temporary
variablesP.EXE’s entrypoint
arguments
SP →return address
P main → Exec???SP →
P main local & temporary variables
Exit syscallarguments
return addressExit → P main
SP →Exit local & temporary
variables........................
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
f2 in P.EXE functionarguments
return addressf2 → f1Exit syscallarguments
SP →return addressExit → f2
...
...
...
...IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
f2 in P.EXE functionarguments
SP →return addressf2 → f1Exit syscallarguments
return addressExit → f2
...
...
...
...IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of f2) ... f1 execution continues ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
SP →f2 in P.EXE function
argumentsreturn addressf2 → f1Exit syscallarguments
return addressExit → f2
...
...
...
...
IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; procTable[currentPID].oldSP := SP call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := procTable[currentPID].oldSP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
f2 in P.EXE functionarguments
return addressf2 → f1Exit syscallarguments
SP →return addressExit → f2
...
...
...
...IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; procTable[currentPID].oldSP := SP call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := procTable[currentPID].oldSP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
arguments
SP →return address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
f2 in P.EXE functionarguments
return addressf2 → f1Exit syscallarguments
return addressExit → f2
...
...
...
...IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; procTable[currentPID].oldSP := SP – sizeof(entrypoint’s stack frame) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := procTable[currentPID].oldSP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
argumentsreturn address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
f2 in P.EXE functionarguments
return addressf2 → f1Exit syscallarguments
SP →return addressExit → f2
...
...
...
...IP
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; procTable[currentPID].oldSP := SP – sizeof(entrypoint’s stack frame) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := procTable[currentPID].oldSP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto
...
...shell’s entrypoint
argumentsreturn address
shell → kernelInit Exec syscall
argumentsreturn address
Exec → shellP.EXE’s entrypoint
arguments
SP →return address
P main → Execf1 in P.EXE function
argumentsreturn addressf1 → P main
f2 in P.EXE functionarguments
return addressf2 → f1Exit syscallarguments
return addressExit → f2
...
...
...
...IP
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefreefreefreefreefreefreefreefreefreefreefreeA dataA code
PT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefreefreefreefreefreefreefreefreefreefreeA heapA dataA code
PT ...
→ Pascal runtime’s call of syscall (OS API) AllocMem
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefreefreefreefreefreefreefreefreeA heapA heapA heapA dataA code
PT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
PT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
...
kerneldata
IVTproc table...
page tbl kernel code
kernel codestackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
PT ...
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
... B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
... B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
... B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
... B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
... B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
kernel initcall Exec(‘shell.exe’) load shell.exe call shell.exe entrypoint ... repeat ... until key <> ENTER call Exec(‘P.EXE’) load P.EXE load & relocate EXE image load & relocate DLL images push currentPID currentPID := AllocateNewPID; procTable[currentPID].pageTable := InitilizeNewPageTable; CR3 := procTable[currentPID].pageTable; procTable[currentPID].oldSP := SP – sizeof(entrypoint’s stack frame) call A.DLL entrypoint call B.DLL entrypoint call P.EXE entrypoint ... call f1 in P.EXE ... call f2 in P.EXE ... call Exit clean up (release resources) SP := procTable[currentPID].oldSP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID CR3 := procTable[currentPID].pageTable; ret goto
context switch back to PID 1
context switch to PID 2
context switch to PID 2
1) Allocated memory (pages)2) CPU fault → kernel interrupt handler
call procTable[currentPID].faultHandlers[faultID]3) Open files – e.g. ReadFile(fileDesc, ...):
read from procTable[currentPID].fdt[fileDesc]4) Current path – e.g. OpenFile(path, ...)
if path startsWith ‘/’ or ‘\’ then open file at (path)else open file at (procTable[currentPID].workingDir + path)
5) List of loaded DLLs6) Page table (state of the address space)
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
... B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
nil = address 0= pointer(0)
CPU (x86/IA-32)...
kerneldata
...proc tableB page tbl
A page tbl
kernel codekernel code
stackstack
guard pagefreefreefreefreefreefreefreefreefreefreeB heapB dataB codeB codeA heapA heapA heapA dataA code
A PT
page 0 B PT
31 0EIP
31 0ESP
31 page table base 0CR3
Non-presentKernel/SupervisorUser Read/OnlyUser Read/Write
nil = address 0= pointer(0)
How a Debugger Works?
Visual Studio 2015 CommunityVisual Studio 2015 Enterprise
google: mff dreamspark
...
...
...
...
... ...
...
...
...
...
...
...
... $01000000
...
...006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
...
...
...
...
... ...
...
...
...
...
...
...
... $01000000
...
...006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
...
...
...
...
... ...
...
...
...
...
...
...
... $01000000
...
...006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
...
...
...
...
... ...
...
...
...
...
...
...
... $01000000
...
...006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
...
...
...
...
... ...
...
...
...
...
...
...
... $01000000
...
...006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
...
...
... 685B10B90068...
........................ $01000000......006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s code
...
...
... 685B10B90068... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A01 $00B9100700FFF015FF $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
call [0100FFF0h]
JMP to entrypoint
...
...
... 685B10B90068... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A01 $00B9100700FFF015FF $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
call [0100FFF0h]
JMP to entrypoint EIP
...
...
... 685B10B90068... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A01 $00B9100700FFF015FF $00B91002406A $00B91000...
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
call [0100FFF0h]
JMP to entrypoint
EIP
...
...
... 685B10B90068... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A01 $00B9100700FFF015FF $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
call [0100FFF0h]
JMP to entrypoint
EIP
...
...
... 685B10B90068... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A01 $00B9100700FFF015FF $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
call [0100FFF0h]
JMP to entrypoint
EIP
...
...
... 685B10B90068... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
EIP
...
...
... 681A10B9006A... $0100FFF0
........................ $01000000......006A $00B9100C00B9101A68 $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
EIP
...
...
... 681A10B9006A... $0100FFF0
........................ $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
EIP
call [0100FFF0h]
...
...
... 681A10B9006A... $0100FFF0
RET..................... $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
EIP
call [0100FFF0h]
restore state of application & jump back
...
...
... 681A10B9006A... $0100FFF0
RET..................... $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
call [0100FFF0h]
restore state of application & jump backEIP
...
...
... 681A10B9006A... $0100FFF0
RET..................... $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
call [0100FFF0h]
restore state of application & jump back
EIP
...
...
... 681A10B9006A... $0100FFF0
RET..................... $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
call [0100FFF0h]
restore state of application & jump back
EIP
...
...
... 681A10B9006A... $0100FFF0
RET..................... $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
call [0100FFF0h]
restore state of application & jump back
EIP
...
...
... 681A10B9006A... $0100FFF0
RET..................... $01000000......0001 $00B9100C00FFF015FF $00B9100700B9105B68 $00B91002406A $00B91000...
Execute main debugger loop (Update/Draw cycle to display UI)
save state of application (e.g. push all registers to stack)
push dword ptr [00B9105Bh]
push dword 40h
push dword ptr [00B9105Bh]
push dword 0
code and data of debugged application (=
debugee)
code and data of DEBUGGER
variable holding copy of original app’s codevariable address of debugger step function
JMP to entrypoint
call [0100FFF0h]
restore state of application & jump back
EIP
Stepping in Higher Level Programming Language (e.g. Pascal)
A.pasC1C2C3
A.exeI1I2I3I4I5I6
Stepping in Higher Level Programming Language (e.g. Pascal)
A.pasC1C2C3
A.exeI1I2I3I4I5I6
Stepping in Higher Level Programming Language (e.g. Pascal)
A.pasC1C2C3
A.exeI1I2I3I4I5I6
Typical ISA Arithmetic Instructions
MIPS: a := b op cx86, 6502: a := a op b
6502 Registers (Accumulator Architecture)
7 0A
7 0X
7 0Y
0000 0001 7 0S
P
15 0PC
7 0
Load Value Into Register (6502)LDA #$xx
LDA $xxxx
A := xx
A := ($xxxx)^
Load Value Into AccumulatorLDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDA ($xx,X)
LDA ($xx),Y
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
A := ( (^word($00xx + X))^)^
A := ( (^word($00xx))^ + Y)^
Load Value Into RegisterLDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDX imm/addr
LDY imm/addr
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
X := imm/addr
X := imm/addr
& Store Value From RegisterLDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDX imm/addr
LDY imm/addr
STA $xxxx
STA $xxxx,X
STA $xxxx,Y
STX addr
STY addr
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
X := imm/addr
X := imm/addr
($xxxx)^ := A
($xxxx + X)^ := A
($xxxx + Y)^ := A
addr := X
addr := Y
Move (Transfer) Value Between RegistersLDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDX imm/addr
LDY imm/addr
STA $xxxx
STA $xxxx,X
STA $xxxx,Y
STX addr
STY addr
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
X := imm/addr
X := imm/addr
($xxxx)^ := A
($xxxx + X)^ := A
($xxxx + Y)^ := A
addr := X
addr := Y
TAX
TXA
TAY
TYA
TSX
TXS
X := A
A := X
Y := A
A := Y
X := S
S := X
Push To Stack & Pop (Pull) From Stack LDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDX imm/addr
LDY imm/addr
STA $xxxx
STA $xxxx,X
STA $xxxx,Y
STX addr
STY addr
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
X := imm/addr
X := imm/addr
($xxxx)^ := A
($xxxx + X)^ := A
($xxxx + Y)^ := A
addr := X
addr := Y
TAX
TXA
TAY
TYA
TSX
TXS
X := A
A := X
Y := A
A := Y
X := S
S := X
PHP
PLP
PHA
PLA
push P (flags)
pop P (flags)
push A
pop A
Setting FlagsLDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDX imm/addr
LDY imm/addr
STA $xxxx
STA $xxxx,X
STA $xxxx,Y
STX addr
STY addr
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
X := imm/addr
X := imm/addr
($xxxx)^ := A
($xxxx + X)^ := A
($xxxx + Y)^ := A
addr := X
addr := Y
TAX
TXA
TAY
TYA
TSX
TXS
X := A
A := X
Y := A
A := Y
X := S
S := X
PHP
PLP
PHA
PLA
push P (flags)
pop P (flags)
push A
pop A
P.Negative := target.7
if target = 0 then P.Zero := 1else P.Zero := 0;
P N... ..Z.7654 3210
Setting FlagsLDA #$xx
LDA $xxxx
LDA $xxxx,X
LDA $xxxx,Y
LDX imm/addr
LDY imm/addr
STA $xxxx
STA $xxxx,X
STA $xxxx,Y
STX addr
STY addr
A := xx
A := ($xxxx)^
A := ($xxxx + X)^
A := ($xxxx + Y)^
X := imm/addr
X := imm/addr
($xxxx)^ := A
($xxxx + X)^ := A
($xxxx + Y)^ := A
addr := X
addr := Y
TAX
TXA
TAY
TYA
TSX
TXS
X := A
A := X
Y := A
A := Y
X := S
S := X
PHP
PLP
PHA
PLA
push P (flags)
pop P (flags)
push A
pop A
P.Negative := target.7
if target = 0 then P.Zero := 1else P.Zero := 0;
CLC
SEC
P.Carry := 0
P.Carry := 1
P N... ..Z.7654 3210
Bitwise OperationsORA imm/addr
AND imm/addr
EOR imm/addr
? NOT
ASL A
LSR A
A := A BitwiseOr imm/addr
A := A BitwiseAnd imm/addr
A := A BitwiseXor imm/addr
EOR #$FF
A := A shl 1
A := A shr 1
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
Oring 16-bit Numbers (e.g. Little Endian)
A7 A6 A5 A4 A3 A2 A1 A0A15A14A13A12A11A10 A9 A8
LSB of A stored at $A000MSB of A stored at $A001
B7 B6 B5 B4 B3 B2 B1 B0B15B14B13B12B11B10 B9 B8
LSB of B stored at $B000MSB of B stored at $B001
or
=
C7 C6 C5 C4 C3 C2 C1 C0C15C14C13C12C11C10 C9 C8
LSB of C stored at $C000MSB of C stored at $C001
Oring 16-bit Numbers (e.g. Little Endian)
A7 A6 A5 A4 A3 A2 A1 A0A15A14A13A12A11A10 A9 A8
LSB of A stored at $A000MSB of A stored at $A001
B7 B6 B5 B4 B3 B2 B1 B0B15B14B13B12B11B10 B9 B8
LSB of B stored at $B000MSB of B stored at $B001
or
=
C7 C6 C5 C4 C3 C2 C1 C0C15C14C13C12C11C10 C9 C8
LSB of C stored at $C000MSB of C stored at $C001
or
=
LDA $A000ORA $B000STA $C000
LDA $A001ORA $B001STA $C001
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
Integer OperationsADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
P N... ..ZC7654 3210
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
Integer Operations (Adding 8-bit Numbers)
ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
P N... ..ZC7654 3210
A7 A6 A5 A4 A3 A2 A1 A0
LSB of A stored at $A000
B7 B6 B5 B4 B3 B2 B1 B0
LSB of B stored at $B000+
=
C7 C6 C5 C4 C3 C2 C1 C0
LSB of C stored at $C000
C8carry
0carry
+
=
LDA $A000CLCADC $B000STA $C000
Adding 16-bit Numbers (e.g. Little Endian)
A7 A6 A5 A4 A3 A2 A1 A0A15A14A13A12A11A10 A9 A8
LSB of A stored at $A000MSB of A stored at $A001
B7 B6 B5 B4 B3 B2 B1 B0B15B14B13B12B11B10 B9 B8
LSB of B stored at $B000MSB of B stored at $B001
+
=
C7 C6 C5 C4 C3 C2 C1 C0C15C14C13C12C11C10 C9 C8
LSB of C stored at $C000MSB of C stored at $C001
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
Adding 16-bit Numbers (e.g. Little Endian)ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
A7 A6 A5 A4 A3 A2 A1 A0
LSB of A stored at $A000
B7 B6 B5 B4 B3 B2 B1 B0
LSB of B stored at $B000+
=
C7 C6 C5 C4 C3 C2 C1 C0
LSB of C stored at $C000
C8carry
0carry
+
=
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
Adding 16-bit Numbers (e.g. Little Endian)ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
A7 A6 A5 A4 A3 A2 A1 A0
LSB of A stored at $A000
B7 B6 B5 B4 B3 B2 B1 B0
LSB of B stored at $B000+
=
C7 C6 C5 C4 C3 C2 C1 C0
LSB of C stored at $C000
C8carry
0carry
+
=
LDA $A000CLCADC $B000STA $C000
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
Adding 16-bit Numbers (e.g. Little Endian)ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
A7 A6 A5 A4 A3 A2 A1 A0
A15A14A13A12A11A10 A9 A8
LSB of A stored at $A000
MSB of A stored at $A001
B7 B6 B5 B4 B3 B2 B1 B0
B15B14B13B12B11B10 B9 B8
LSB of B stored at $B000
MSB of B stored at $B001
+
=
C7 C6 C5 C4 C3 C2 C1 C0
C15C14C13C12C11C10 C9 C8
LSB of C stored at $C000
MSB of C stored at $C001
C8carry
+
=
0carry
+
=
C16carry
=
LDA $A000CLCADC $B000STA $C000
+
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
Adding 16-bit Numbers (e.g. Little Endian)ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
A7 A6 A5 A4 A3 A2 A1 A0
A15A14A13A12A11A10 A9 A8
LSB of A stored at $A000
MSB of A stored at $A001
B7 B6 B5 B4 B3 B2 B1 B0
B15B14B13B12B11B10 B9 B8
LSB of B stored at $B000
MSB of B stored at $B001
+
=
C7 C6 C5 C4 C3 C2 C1 C0
C15C14C13C12C11C10 C9 C8
LSB of C stored at $C000
MSB of C stored at $C001
C8carry
+
=
0carry
+
=
C16carry
=
LDA $A000CLCADC $B000STA $C000
LDA $A001ADC $B001STA $C001
+
Adding 16-bit Numbers (e.g. Little Endian)
LDA $A000CLCADC $B000STA $C000LDA $A001ADC $B001STA $C001
A7 A6 A5 A4 A3 A2 A1 A0A15A14A13A12A11A10 A9 A8
LSB of A stored at $A000MSB of A stored at $A001
B7 B6 B5 B4 B3 B2 B1 B0B15B14B13B12B11B10 B9 B8
LSB of B stored at $B000MSB of B stored at $B001
+
=
C7 C6 C5 C4 C3 C2 C1 C0C15C14C13C12C11C10 C9 C8
LSB of C stored at $C000MSB of C stored at $C001
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
ADC imm/addr
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
Integer Operations – Subtraction? Via Two’s Complement
ADC imm/addr result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
A := value – A↓INC ANOT AADD value
A := value – A↓CLCADC #1EOR #$FFCLCADC value
Integer Operations – Subtraction? Subtract with Borrow
ADC imm/addr
SBC imm/addr
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
result := A – imm/addr – not(P.Carry)P.Carry := not(result.7)A := result.7 … result.0
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
Other Integer Operations
ADC imm/addr
SBC imm/addr
INXINYDEXDEY
result := A + imm/addr + P.CarryP.Carry := result.8A := result.7 … result.0
result := A – imm/addr – not(P.Carry)P.Carry := not(result.7)A := result.7 … result.0
X := X + 1Y := Y + 1X := X – 1Y := Y - 1
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
P.Negative := A.7
if A = 0 then P.Zero := 1else P.Zero := 0;
P.Negative := X/Y.7
if X/Y = 0 then P.Zero := 1else P.Zero := 0;