Principles of Computers th 17 Lecture http://d3s.mff.cuni.cz/~jezek Pavel Ježek, Ph.D. pavel.jezek@d3s.mff.cuni.cz CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics 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 init call 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 init call 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 Explorer www.sysinternals.com Really Dynamic DLL Loading Example ... A’s entrypoint Non-present Kernel/Supervisor User Read/Only User Read/Write ... ... ... 9 8 7 6 5 4 3 2 1 PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free A data A data A data A code A code → read variable at address 8200 A code (= in page 8 for 1kB pages) A code → call procedure at address 4000 A code (= in page 3 for 1kB pages) ... ... A’s entrypoint Non-present Kernel/Supervisor User Read/Only User Read/Write ... ... ... 9 8 7 6 5 4 3 2 1 PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free A data (guard) A data (guard) A data (guard) A code (guard) A code (guard) A code (guard) A code (guard) A code ... ... A’s entrypoint Non-present Kernel/Supervisor User Read/Only User Read/Write ... ... ... 9 8 7 6 5 4 3 2 1 PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free A data (guard) A data (guard) A data (guard) A code (guard) A code (guard) A code (guard) page fault A code (guard) → call procedure at address 4000 A code (= in page 3 for 1kB pages) ... ... A’s entrypoint Non-present Kernel/Supervisor User Read/Only User Read/Write ... ... ... 9 8 7 6 5 4 3 2 1 PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free A data (guard) A data (guard) A data (guard) A code (guard) A code (guard) A code A code (guard) → call procedure at address 4000 A code (= in page 3 for 1kB pages) ... ... A’s entrypoint Non-present Kernel/Supervisor User Read/Only User Read/Write ... ... ... 9 8 7 6 5 4 3 2 1 PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free A data (guard) page fault A data (guard) A data (guard) A code (guard) A code (guard) → read variable at address 8200 A code (= in page 8 for 1kB pages) A code (guard) → call procedure at address 4000 A code (= in page 3 for 1kB pages) ... ... A’s entrypoint Non-present Kernel/Supervisor User Read/Only User Read/Write ... ... ... 9 8 7 6 5 4 3 2 1 PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free A data page fault A data (guard) A data (guard) A code (guard) A code (guard) → read variable at address 8200 A code (= in page 8 for 1kB pages) A code (guard) → call procedure at address 4000 A code (= in page 3 for 1kB pages) ... kernel init call 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 init call 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 init call 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) ... IP ret ... should not get here ... ... ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec Exit syscall arguments return address Exit → P main ... ... ... ... ... ... ... ... kernel init call 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 IP ... P.EXE’s main program continues ... ... ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec Exit syscall arguments return address Exit → P main ... ... ... ... ... ... ... ... kernel init call 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) IP SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of P.EXE main program) ... ... ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec Exit syscall arguments return address Exit → P main ... ... ... ... ... ... ... ... kernel init call 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) IP ret ... (never here = rest of P.EXE main program) ... ... ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec Exit syscall arguments return address Exit → P main ... ... ... ... ... ... ... ... kernel init call 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) ... IP ... ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec Exit syscall arguments return address Exit → P main ... ... ... ... ... ... ... ... kernel init call 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; context switch 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 context switch ret goto 1) Allocated memory (pages) kernel init call 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) context switch to PID 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) context switch back to PID 1 ret goto 1) Allocated memory (pages) 2) CPU fault → kernel interrupt handler → call procTable[currentPID].faultHandlers[faultID] kernel init call 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) context switch to PID 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) context switch back to PID 1 ret goto 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 init call 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) context switch to PID 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) context switch back to PID 1 ret goto kernel init call 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) 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) context switch to PID 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) context switch back to PID 1 ret goto kernel init call 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) 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 context switch to PID 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) context switch back to PID 1 ret goto Further Options How to Take Advantage of Processes … kernel init call 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 SP → ??? SP → SP → ... ... shell’s entrypoint arguments return address shell → kernelInit shell local & temporary variables Exec syscall arguments return address Exec → shell Exec local & temporary variables P.EXE’s entrypoint arguments return address P main → Exec P main local & temporary variables Exit syscall arguments return address Exit → P main Exit local & temporary variables ... ... ... ... ... ... ... ... kernel init call 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) IP SP := SP + sizeof(Exit stack frame) ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... kernel init call 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 IP ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... kernel init call 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) ... IP f1 execution continues ... pop currentPID ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... kernel init call 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 IP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... kernel init call 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 IP ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto SP → ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... kernel init call 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 SP → clean up (release resources) SP := procTable[currentPID].oldSP IP ret ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... kernel init call 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 SP → 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 IP ... (never here = rest of f2) ... ... (never here = rest of f1) ... pop currentPID ret goto ... ... shell’s entrypoint arguments return address shell → kernelInit Exec syscall arguments return address Exec → shell P.EXE’s entrypoint arguments return address P main → Exec f1 in P.EXE function arguments return address f1 → P main f2 in P.EXE function arguments return address f2 → f1 Exit syscall arguments return address Exit → f2 ... ... ... ... ... Non-present Kernel/Supervisor User Read/Only User Read/Write PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free free free free free free free A data A code ... ... Non-present Kernel/Supervisor User Read/Only User Read/Write PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free free free free free free A heap A data A code → Pascal runtime’s call of syscall (OS API) AllocMem ... ... Non-present Kernel/Supervisor User Read/Only User Read/Write PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free free free free free A heap A heap A heap A data A code ... ... Non-present Kernel/Supervisor User Read/Only User Read/Write PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... ... Non-present Kernel/Supervisor User Read/Only User Read/Write PT IVT kernel proc table data ... page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... ... Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 ... Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 ... Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 ... Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 ... Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 1) Allocated memory (pages) 2) CPU fault → kernel interrupt handler kernel init call procTable[currentPID].faultHandlers[faultID] call Exec(‘shell.exe’) 3) Open files – e.g. ReadFile(fileDesc, ...): load shell.exe read from procTable[currentPID].fdt[fileDesc] call shell.exe entrypoint 4) Current path – e.g. OpenFile(path, ...) ... if path startsWith ‘/’ or ‘\’ then repeat open file at (path) ... else until key <> ENTER open file at (procTable[currentPID].workingDir + path) call Exec(‘P.EXE’) 5) List of loaded DLLs load P.EXE 6) Page table (state of the address space) load & relocate EXE image load & relocate DLL images push currentPID context switch to PID 2 currentPID := AllocateNewPID; procTable[currentPID].pageTable := InitilizeNewPageTable; context switch to PID 2 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 context switch back to PID 1 CR3 := procTable[currentPID].pageTable; ret goto ... nil = address 0 = pointer(0) Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code ... B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 ... nil = address 0 = pointer(0) Non-present Kernel/Supervisor User Read/Only User Read/Write A PT ... kernel proc table data B page tbl A page tbl kernel code kernel code stack stack guard page free free free free free free free free free free B heap B data B code B code A heap A heap A heap A data A code page 0 B PT CPU (x86/IA-32) EIP 31 0 ESP 31 0 CR3 31 page table base 0 How a Debugger Works? Visual Studio 2015 Community Visual Studio 2015 Enterprise google: mff dreamspark code and data of DEBUGGER code and data of debugged application (= debugee) ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 00 6A 00 B9 10 1A 68 00 B9 10 5B 68 40 6A ... $01000000 $00B9100C push dword 0 push dword ptr [00B9105Bh] $00B91007 push dword ptr [00B9105Bh] $00B91002 $00B91000 push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 00 6A 00 B9 10 1A 68 00 B9 10 5B 68 40 6A ... $01000000 $00B9100C push dword 0 push dword ptr [00B9105Bh] $00B91007 push dword ptr [00B9105Bh] $00B91002 $00B91000 push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 00 6A 00 B9 10 1A 68 00 B9 10 5B 68 40 6A ... $01000000 $00B9100C push dword 0 push dword ptr [00B9105Bh] $00B91007 push dword ptr [00B9105Bh] $00B91002 $00B91000 push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 00 6A 00 B9 10 1A 68 00 B9 10 5B 68 40 6A ... $01000000 $00B9100C push dword 0 push dword ptr [00B9105Bh] $00B91007 push dword ptr [00B9105Bh] $00B91002 $00B91000 push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 00 6A 00 B9 10 1A 68 00 B9 10 5B 68 40 6A ... $01000000 $00B9100C push dword 0 push dword ptr [00B9105Bh] $00B91007 push dword ptr [00B9105Bh] $00B91002 $00B91000 push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) ... ... ... 685B10B90068 ... ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 68 $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code push dword 0 push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 685B10B90068 ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 01 $00B91007 00 FF F0 15 FF $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function push dword 0 push dword ptr [00B9105Bh] call [0100FFF0h] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) JMP to entrypoint EIP ... ... ... 685B10B90068 ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 01 $00B91007 00 FF F0 15 FF $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function push dword 0 push dword ptr [00B9105Bh] call [0100FFF0h] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) EIP JMP to entrypoint ... ... ... 685B10B90068 ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 01 $00B91007 00 FF F0 15 FF $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function push dword 0 push dword ptr [00B9105Bh] call [0100FFF0h] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 685B10B90068 ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 01 $00B91007 00 FF F0 15 FF $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 push dword ptr [00B9105Bh] call [0100FFF0h] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 685B10B90068 ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 01 $00B91007 00 FF F0 15 FF $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 push dword ptr [00B9105Bh] call [0100FFF0h] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 685B10B90068 ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 68 $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 6A $00B9100C 00 B9 10 1A 68 $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 ... ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h EIP code and data of DEBUGGER code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 RET ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function restore state of application & jump back Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h EIP code and data of DEBUGGER code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 RET ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function restore state of application & jump back Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER code and data of debugged application (= debugee) EIP JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 RET ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function restore state of application & jump back Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER code and data of debugged EIP application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 RET ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function restore state of application & jump back Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 RET ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function restore state of application & jump back Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h code and data of DEBUGGER EIP code and data of debugged application (= debugee) JMP to entrypoint ... ... ... 681A10B9006A ... $0100FFF0 RET ... ... ... ... ... ... ... $01000000 ... ... 00 01 $00B9100C 00 FF F0 15 FF $00B91007 00 B9 10 5B 68 $00B91002 40 6A $00B91000 ... variable holding copy of original app’s code variable address of debugger step function restore state of application & jump back Execute main debugger loop (Update/Draw cycle to display UI) save state of application (e.g. push all registers to stack) push dword 0 call [0100FFF0h] push dword ptr [00B9105Bh] push dword ptr [00B9105Bh] push dword 40h Stepping in Higher Level Programming Language (e.g. Pascal) A.pas C1 C2 C3 A.exe I1 I2 I3 I4 I5 I6 Stepping in Higher Level Programming Language (e.g. Pascal) A.pas C1 C2 C3 A.exe I1 I2 I3 I4 I5 I6 Stepping in Higher Level Programming Language (e.g. Pascal) A.pas C1 C2 C3 A.exe I1 I2 I3 I4 I5 I6 Typical ISA Arithmetic Instructions MIPS: a := b op c x86, 6502: a := a op b 6502 Registers (Accumulator Architecture) A 7 0 X 7 0 Y 7 0 7 0 7 0 S 0000 0001 P PC 15 0 Load Value Into Register (6502) LDA #$xx A := xx LDA $xxxx A := ($xxxx)^ Load Value Into Accumulator LDA #$xx A := xx LDA $xxxx A := ($xxxx)^ LDA $xxxx,X A := ($xxxx + X)^ LDA $xxxx,Y A := ($xxxx + Y)^ LDA ($xx,X) A := ( (^word($00xx + X))^ )^ LDA ($xx),Y A := ( (^word($00xx))^ + Y )^ Load Value Into Register LDA #$xx A := xx LDA $xxxx A := ($xxxx)^ LDA $xxxx,X A := ($xxxx + X)^ LDA $xxxx,Y A := ($xxxx + Y)^ LDX imm/addr X := imm/addr LDY imm/addr X := imm/addr & Store Value From Register LDA #$xx A := xx LDA $xxxx A := ($xxxx)^ LDA $xxxx,X A := ($xxxx + X)^ LDA $xxxx,Y A := ($xxxx + Y)^ LDX imm/addr X := imm/addr LDY imm/addr X := imm/addr STA $xxxx ($xxxx)^ := A STA $xxxx,X ($xxxx + X)^ := A STA $xxxx,Y ($xxxx + Y)^ := A STX addr addr := X STY addr addr := Y Move (Transfer) Value Between Registers LDA #$xx A := xx TAX X := A LDA $xxxx A := ($xxxx)^ TXA A := X LDA $xxxx,X A := ($xxxx + X)^ TAY Y := A LDA $xxxx,Y A := ($xxxx + Y)^ TYA A := Y LDX imm/addr X := imm/addr TSX X := S LDY imm/addr X := imm/addr TXS S := X STA $xxxx ($xxxx)^ := A STA $xxxx,X ($xxxx + X)^ := A STA $xxxx,Y ($xxxx + Y)^ := A STX addr addr := X STY addr addr := Y Push To Stack & Pop (Pull) From Stack LDA #$xx A := xx TAX X := A LDA $xxxx A := ($xxxx)^ TXA A := X LDA $xxxx,X A := ($xxxx + X)^ TAY Y := A LDA $xxxx,Y A := ($xxxx + Y)^ TYA A := Y LDX imm/addr X := imm/addr TSX X := S LDY imm/addr X := imm/addr TXS S := X STA $xxxx ($xxxx)^ := A STA $xxxx,X ($xxxx + X)^ := A STA $xxxx,Y ($xxxx + Y)^ := A STX addr addr := X STY addr addr := Y PHP push P (flags) PLP pop P (flags) PHA push A PLA pop A Setting Flags LDA #$xx A := xx LDA $xxxx A := ($xxxx)^ LDA $xxxx,X A := ($xxxx + X)^ LDA $xxxx,Y A := ($xxxx + Y)^ LDX imm/addr X := imm/addr LDY imm/addr X := imm/addr STA $xxxx ($xxxx)^ := A STA $xxxx,X ($xxxx + X)^ := A STA $xxxx,Y ($xxxx + Y)^ := A STX addr addr := X STY addr addr := Y TAX X := A TXA A := X TAY Y := A TYA A := Y P.Negative := target.7 TSX X := S if target = 0 then P.Zero := 1 else P.Zero := 0; TXS S := X PHP push P (flags) PLP pop P (flags) PHA push A PLA pop A 7654 3210 P N... ..Z. Setting Flags LDA #$xx A := xx LDA $xxxx A := ($xxxx)^ LDA $xxxx,X A := ($xxxx + X)^ LDA $xxxx,Y A := ($xxxx + Y)^ LDX imm/addr X := imm/addr LDY imm/addr X := imm/addr STA $xxxx ($xxxx)^ := A STA $xxxx,X ($xxxx + X)^ := A STA $xxxx,Y ($xxxx + Y)^ := A STX addr addr := X STY addr addr := Y TAX X := A TXA A := X TAY Y := A TYA A := Y P.Negative := target.7 TSX X := S if target = 0 then P.Zero := 1 else P.Zero := 0; TXS S := X PHP push P (flags) PLP pop P (flags) PHA push A PLA pop A 7654 3210 P CLC P.Carry := 0 SEC P.Carry := 1 N... ..Z. Bitwise Operations ORA imm/addr A := A BitwiseOr imm/addr P.Negative := A.7 AND imm/addr A := A BitwiseAnd imm/addr EOR imm/addr A := A BitwiseXor imm/addr if A = 0 then P.Zero := 1 else P.Zero := 0; ? NOT EOR #$FF ASL A A := A shl 1 LSR A A := A shr 1 Oring 16-bit Numbers (e.g. Little Endian) MSB of A stored at $A001 LSB of A stored at $A000 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 or MSB of B stored at $B001 LSB of B stored at $B000 B15 B14 B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0 = MSB of C stored at $C001 LSB of C stored at $C000 C15 C14 C13 C12 C11 C10 C9 C8 C7 C6 C5 C4 C3 C2 C1 C0 Oring 16-bit Numbers (e.g. Little Endian) MSB of A stored at $A001 LSB of A stored at $A000 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 or or MSB of B stored at $B001 LSB of B stored at $B000 B15 B14 B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0 = = MSB of C stored at $C001 LSB of C stored at $C000 C15 C14 C13 C12 C11 C10 C9 C8 C7 C6 C5 C4 C3 C2 C1 C0 LDA $A000 ORA $B000 STA $C000 LDA $A001 ORA $B001 STA $C001 Integer Operations ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; 7654 3210 P N... ..ZC Integer Operations (Adding 8-bit Numbers) ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 7654 3210 P N... ..ZC LSB of A stored at $A000 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; A7 A6 A5 A4 A3 A2 A1 A0 + LSB of B stored at $B000 B7 B6 B5 B4 B3 B2 B1 B0 = LSB of C stored at $C000 = C8 carry C7 C6 C5 C4 C3 C2 C1 C0 LDA $A000 CLC ADC $B000 STA $C000 0 carry + Adding 16-bit Numbers (e.g. Little Endian) MSB of A stored at $A001 LSB of A stored at $A000 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 + MSB of B stored at $B001 LSB of B stored at $B000 B15 B14 B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0 = MSB of C stored at $C001 LSB of C stored at $C000 C15 C14 C13 C12 C11 C10 C9 C8 C7 C6 C5 C4 C3 C2 C1 C0 ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; Adding 16-bit Numbers (e.g. Little Endian) LSB of A stored at $A000 A7 A6 A5 A4 A3 A2 A1 A0 + LSB of B stored at $B000 ADC imm/addr 0 carry + result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 B7 B6 B5 B4 B3 B2 B1 B0 = LSB of C stored at $C000 = C8 carry C7 C6 C5 C4 C3 C2 C1 C0 if A = 0 then P.Zero := 1 else P.Zero := 0; Adding 16-bit Numbers (e.g. Little Endian) LSB of A stored at $A000 A7 A6 A5 A4 A3 A2 A1 A0 + LSB of B stored at $B000 LDA $A000 CLC ADC $B000 STA $C000 ADC imm/addr 0 carry + result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 B7 B6 B5 B4 B3 B2 B1 B0 = LSB of C stored at $C000 = C8 carry C7 C6 C5 C4 C3 C2 C1 C0 if A = 0 then P.Zero := 1 else P.Zero := 0; Adding 16-bit Numbers (e.g. Little Endian) LSB of A stored at $A000 A7 A6 A5 A4 A3 A2 A1 A0 + LSB of B stored at $B000 LDA $A000 CLC ADC $B000 STA $C000 0 carry + result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 B7 B6 B5 B4 B3 B2 B1 B0 = LSB of C stored at $C000 = C8 MSB of A stored at $A001 ADC imm/addr carry + A15 A14 A13 A12 A11 A10 A9 A8 + MSB of B stored at $B001 B15 B14 B13 B12 B11 B10 B9 B8 = MSB of C stored at $C001 = C16 C15 C14 C13 C12 C11 C10 C9 C8 carry C7 C6 C5 C4 C3 C2 C1 C0 if A = 0 then P.Zero := 1 else P.Zero := 0; Adding 16-bit Numbers (e.g. Little Endian) LSB of A stored at $A000 A7 A6 A5 A4 A3 A2 A1 A0 + LSB of B stored at $B000 LDA $A000 CLC ADC $B000 STA $C000 0 carry + result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 B7 B6 B5 B4 B3 B2 B1 B0 = LSB of C stored at $C000 = C8 MSB of A stored at $A001 ADC imm/addr carry C7 C6 C5 C4 C3 C2 C1 C0 + A15 A14 A13 A12 A11 A10 A9 A8 + MSB of B stored at $B001 B15 B14 B13 B12 B11 B10 B9 B8 = MSB of C stored at $C001 = C16 C15 C14 C13 C12 C11 C10 C9 C8 carry LDA $A001 ADC $B001 STA $C001 if A = 0 then P.Zero := 1 else P.Zero := 0; Adding 16-bit Numbers (e.g. Little Endian) MSB of A stored at $A001 LSB of A stored at $A000 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 + MSB of B stored at $B001 LSB of B stored at $B000 B15 B14 B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0 = MSB of C stored at $C001 LSB of C stored at $C000 C15 C14 C13 C12 C11 C10 C9 C8 C7 C6 C5 C4 C3 C2 C1 C0 LDA CLC ADC STA LDA ADC STA $A000 $B000 $C000 $A001 $B001 $C001 ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; Integer Operations – Subtraction? Via Two’s Complement ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; A := value – A ↓ INC A NOT A ADD value A := value – A ↓ CLC ADC #1 EOR #$FF CLC ADC value Integer Operations – Subtraction? Subtract with Borrow ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; SBC imm/addr 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 := 1 else P.Zero := 0; Other Integer Operations ADC imm/addr result := A + imm/addr + P.Carry P.Carry := result.8 A := result.7 … result.0 P.Negative := A.7 if A = 0 then P.Zero := 1 else P.Zero := 0; SBC imm/addr 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 := 1 else P.Zero := 0; P.Negative := X/Y.7 INX INY DEX DEY X Y X Y := := := := X Y X Y + + – - 1 1 1 1 if X/Y = 0 then P.Zero := 1 else P.Zero := 0;