These are the courses that I regularly teach.
This undergraduate course focuses on understanding lower-level (closer to hardware) issues in computer design and programming. The course starts with the C programming language, down to assembly and machine-level code, to basic operating system concepts. Students learn to read assembly code and reverse-engineer programs in binary.
This undergraduate course introduces students to intermediate representations, inter-procedural and intra-procedural analyses, call graphs, pointer analysis, and analysis frameworks. Students acquire a solid knowledge about the theory of program analysis, as well as practical experience through the course assignments and project.
This graduate course provides a platform for students to discuss research papers that study what it takes to build secure software. It also enables students to conduct in-depth research in software security, with the ability to apply it to their own area of interest (e.g., computer architecture, machine learning).
This undergraduate course introduces students to the interface between software and hardware, as well as the major issues with the design and implementation of parallel programs that run in multiple processors. Students leave this course with an understanding of how machine code is generated by a compiler/assembler.