CS61: Systems Programing and Machine Organization



Similar documents
Assembly Language: Function Calls" Jennifer Rexford!

Off-by-One exploitation tutorial

CS:APP Chapter 4 Computer Architecture Instruction Set Architecture. CS:APP2e

Instruction Set Architecture

Lecture 7: Machine-Level Programming I: Basics Mohamed Zahran (aka Z)

CS412/CS413. Introduction to Compilers Tim Teitelbaum. Lecture 20: Stack Frames 7 March 08

Machine-Level Programming II: Arithmetic & Control

Hacking Techniques & Intrusion Detection. Ali Al-Shemery arabnix [at] gmail

Machine Programming II: Instruc8ons

Lecture 27 C and Assembly

64-Bit NASM Notes. Invoking 64-Bit NASM

Return-oriented programming without returns

Chapter 4 Processor Architecture

Faculty of Engineering Student Number:

A Tiny Guide to Programming in 32-bit x86 Assembly Language

Introduction. Application Security. Reasons For Reverse Engineering. This lecture. Java Byte Code

CHAPTER 6 TASK MANAGEMENT

Systems Design & Programming Data Movement Instructions. Intel Assembly

X86-64 Architecture Guide

Chapter 7D The Java Virtual Machine

Stack Overflows. Mitchell Adair

MACHINE ARCHITECTURE & LANGUAGE

x64 Cheat Sheet Fall 2015

Intel 8086 architecture

Unpacked BCD Arithmetic. BCD (ASCII) Arithmetic. Where and Why is BCD used? From the SQL Server Manual. Packed BCD, ASCII, Unpacked BCD

For a 64-bit system. I - Presentation Of The Shellcode

MICROPROCESSOR. Exclusive for IACE Students iacehyd.blogspot.in Ph: /422 Page 1

l C-Programming l A real computer language l Data Representation l Everything goes down to bits and bytes l Machine representation Language

Computer Organization and Architecture

CS:APP Chapter 4 Computer Architecture Instruction Set Architecture

PART B QUESTIONS AND ANSWERS UNIT I

Buffer Overflows. Security 2011

Abysssec Research. 1) Advisory information. 2) Vulnerable version

Advanced Computer Architecture-CS501. Computer Systems Design and Architecture 2.1, 2.2, 3.2

Computer Organization and Assembly Language

Instruction Set Architecture (ISA)

Chapter 5 Instructor's Manual

Caml Virtual Machine File & data formats Document version: 1.4

Overview of IA-32 assembly programming. Lars Ailo Bongo University of Tromsø

Intel Assembler. Project administration. Non-standard project. Project administration: Repository

Syscall 5. Erik Jonsson School of Engineering and Computer Science. The University of Texas at Dallas

Introduction. Figure 1 Schema of DarunGrim2

The programming language C. sws1 1

Memory Systems. Static Random Access Memory (SRAM) Cell

1 Classical Universal Computer 3

Using the RDTSC Instruction for Performance Monitoring

CSE 141L Computer Architecture Lab Fall Lecture 2

BCD (ASCII) Arithmetic. Where and Why is BCD used? Packed BCD, ASCII, Unpacked BCD. BCD Adjustment Instructions AAA. Example

PROBLEMS (Cap. 4 - Istruzioni macchina)

PC Assembly Language. Paul A. Carter

An Introduction to Assembly Programming with the ARM 32-bit Processor Family

MICROPROCESSOR AND MICROCOMPUTER BASICS

Embedded Systems. Review of ANSI C Topics. A Review of ANSI C and Considerations for Embedded C Programming. Basic features of C

(Refer Slide Time: 00:01:16 min)

How It All Works. Other M68000 Updates. Basic Control Signals. Basic Control Signals

Programming from the Ground Up

Programming Languages

Understanding a Simple Operating System

Computer Architectures

Lecture 21: Buffer Overflow Attack. Lecture Notes on Computer and Network Security. by Avi Kak

Automating Mimicry Attacks Using Static Binary Analysis

Instruction Set Architecture. or How to talk to computers if you aren t in Star Trek

CSC 2405: Computer Systems II

Programming from the Ground Up. Jonathan Bartlett

Software Fingerprinting for Automated Malicious Code Analysis

ASSEMBLY PROGRAMMING ON A VIRTUAL COMPUTER

M A S S A C H U S E T T S I N S T I T U T E O F T E C H N O L O G Y DEPARTMENT OF ELECTRICAL ENGINEERING AND COMPUTER SCIENCE

Application Note. Introduction AN2471/D 3/2003. PC Master Software Communication Protocol Specification

An Overview of Stack Architecture and the PSC 1000 Microprocessor

Z80 Instruction Set. Z80 Assembly Language

Programming from the Ground Up

TitanMist: Your First Step to Reversing Nirvana TitanMist. mist.reversinglabs.com

Technical Support Bulletin Nr.18 Modbus Tips

8085 INSTRUCTION SET

Software Vulnerabilities

Compilers I - Chapter 4: Generating Better Code

Administration. Instruction scheduling. Modern processors. Examples. Simplified architecture model. CS 412 Introduction to Compilers

CPU Organisation and Operation

Under The Hood: The System Call

Exceptions in MIPS. know the exception mechanism in MIPS be able to write a simple exception handler for a MIPS machine

Stack machines The MIPS assembly language A simple source language Stack-machine implementation of the simple language Readings:

Informatica e Sistemi in Tempo Reale

High-speed image processing algorithms using MMX hardware

Interpreters and virtual machines. Interpreters. Interpreters. Why interpreters? Tree-based interpreters. Text-based interpreters

Encryption Wrapper. on OSX

1 The Java Virtual Machine

CS:APP Chapter 4 Computer Architecture. Wrap-Up. William J. Taffe Plymouth State University. using the slides of

Instruction Set Architecture

Complete 8086 instruction set

2) Write in detail the issues in the design of code generator.

B.Sc.(Computer Science) and. B.Sc.(IT) Effective From July 2011

Assembly Language Tutorial

About the Tutorial. Audience. Prerequisites. Copyright & Disclaimer

Hotpatching and the Rise of Third-Party Patches

Introduction. Compiler Design CSE 504. Overview. Programming problems are easier to solve in high-level languages

Motorola 8- and 16-bit Embedded Application Binary Interface (M8/16EABI)

Notes on Assembly Language

CPU performance monitoring using the Time-Stamp Counter register

esrever gnireenigne tfosorcim seiranib

Transcription:

CS61: Systems Programing and Machine Organization Fall 2009 Section Notes for Week 2 (September 14 th - 18 th ) Topics to be covered: I. Binary Basics II. Signed Numbers III. Architecture Overview IV. Control Flow V. Loops VI. Introduction to GDB VII. Procedure Calls

I. Binary Basics Some basics of conversion. 101 2 = (2 2 x 1) + (2 1 x 0) + (2 0 x 1) = 5 10 MSB: Most significant bit bit position with highest bit value LSB: Least significant bit bit position with lowest bit value Nibble: A group of four bits. Maximum value of a nibble is 15 10 = 1111 2 258 10 = 0x102 16 To convert from binary to hex, starting from the LSB, put the binary digits into groups of 4 bits (nibbles) and convert each group into corresponding hexadecimal value. E.g. 10011111011 2 0100 1111 1011 4FB 16 For the reverse direction, convert each hexadecimal into the corresponding nibble. Bit shifting: Simple way to multiple or divide by 2 n. << n multiply by 2 n E.g: compute 12 x 4 1100 2 << 2 = 110000 2 = 32 10 + 16 10 = 48 10 >> divide by 2 n E.g.: compute 12 / 4 1100 2 >> 2 = 11 2 = 2 10 + 1 10 = 3 10 II. Signed Numbers Let us assume we have a 1 byte variable x and we assigned -42 to it. How does the machine represent - 42 in binary? How does the computer store and interpret negative numbers? How do we perform 42 64? Is it addition or subtraction? After all, binary has no notion of +/-. The answer lies in how we interpret the MSB. Computers represent negative numbers using a system known as two's complement. Very simply, here is how it works. For -42, first, write down +42 in binary 00101010

now, invert the bits 11010101 and add +1 11010110 Note, the MSB is set to '1'. Hence, a signed interpretation of the above number will be as follows -2 7 + 2 6 + 2 4 + 2 2 + 2 1 = -128 + 64 + 16 + 4 + 2 = -42 Note: The value inferred from a binary representation really depends how the bits are interpreted. For example, for the same binary representation as above, an unsigned byte interpretation would result in 214 (not -42). For example, try the following in C, printf( %d (signed), (char)0xd6); But why is two's complement useful? It is commonly used in addition, subtraction, multiplcation, etc. on binary digits. Exercise #1: let us compute 42 10 64 10 Exercise #2: Fill in the blanks Binary Unsigned Byte Signed Byte 10000000 11111111 1 0 Exercise #3: Why does the compiler often generate code wherein memory locations are accessed using large offsets. E.g. mov 0xfffffffc (%ecx), %eax? What is this equal to?

III. Architecture Overview What does a CPU do, really? Not much, actually. It perfunctorily iterates trough the following: forever { fetch an instruction execute an instruction update instruction pointer } What does an instruction do? Again not all that much. Typically Change state of the CPU ALU operations Jumps Read data from memory Write data to memory x86 IA32 Registers Registers are places to keep data that are can be accessed very very quickly. Historically, they were very expensive to include on a chip, which is why IA32 only has only 8 of them. The IA32 architecture has 8 general purpose registers and 8 floating point registers. (Note: we're not going to discuss floating point in this course, but the textbook has lots of useful information on it.) Exercise #4: movl $0xFEEDFACE, %eax What are the contents of %ax? %ah? %al? EFLAGS is a 32 bit register that contains separate bits for each of the condition flags, which are set automatically by the CPU to represent the result of the previously executed instruction. Examples of condition flags include: CF (Carry Flag), PF(Parity Flag), OF(Overflow Flag), SF(Sign Flag). The x86 manual includes a complete description of all of the flags and which flags are modified by each instruction.

Typically these flags are set/unset as the result of an instruction (eg add, sub, cmp etc) and can then be used to perform conditional operations or jumps. e.g cmp %eax, %ecx subtracts the value of register %eax from the value of %ecx, but %ecx is not modified. However the corresponding flags are set as follows: SF: set if sign bit of result = = 1 ZF: set if result = = 0 CF: set if carry out from last arithmetic operation OF: set if overflow from last arithmetic operation (2's complement arithmetic) Similarly, test %eax, %ecx The instruction performs a logical AND on the values of the two registers. Again, %ecx is not modified, but the corresponding flags are updated. Register Size Special Uses EAX 32-bit Accumulator for operands and results EBX 32-bit Base pointer to data in the data segment ECX 32-bit Counter for loop operations EDX 32-bit I/O pointer EBP 32-bit Frame Pointer - useful for stack frames ESP 32-bit Stack Pointer - hardcoded into PUSH and POP operations ESI 32-bit Source Index - required for some array operations EDI 32-bit Destination Index - required for some array operations EIP 32-bit Instruction Pointer EFLAGS 32-bit Result Flags - hardcoded into conditional operations Some registers also have special uses and we will be learning about them later in the course. How are sign bits set? Let us look at how addl does this vis some simple examples. Exercise #5: For each one of the following, determine which flags are set by the add instruction? Why? [1] movl $0x40, %eax movl $0xffffffc0, %ebx addl %eax, %ebx

[2] movl $0x2a, %eax movl $0xffffffc0, %ebx addl %eax, %ebx [3] movl $0xffffffff, %eax movl $0x1, %ebx addl %eax, %ebx Endianess: When we write a hexadecimal value, like 0x1a2b3c4d, we write it with the most significant byte (0x1a) on the left, and the least significant byte (0x4d) on the right. That's just because humans have a convention of writing numbers in this way. But when such a value is stored in memory, the order in which the bytes are stored depends on the "endianness" of the CPU architecture. The x86 is a "littleendian" machine, which means it stores the low-order byte of a word in the LOWEST MEMORY ADDRESS. So, the value 0x1a2b3c4d would be stored in memory as memory address M M+1 M+2 M+3 content 0x4d 0x3c 0x2b 0x1a A "big-endian" architecture (like the Sun SPARC processor) stores the highest-order byte of a word in memory first. Why does this matter? Because when you look at a memory dump, say using GDB, you will see the contents of memory as they are stored. If you intend to interpret 4 bytes stored in memory as a word, you need to remember to 'swap the bytes' to make up the actual hex value of the word. So a memory dump of 0xab 0x40 0x1b 0x67 would be interpreted as the value 0x671b40ab. IV. Control Flow The 'jcc' (jump on condition) class of instructions cause a program to start executing from a different point. The condition refers to the status of the flags in the EFLAGS register. Examples of the jcc class includes jz, jnz, jge, jle etc. The conditional jump statements allow for the implementation of loops. There are two methods of performing jumps: direct and indirect. For direct jumps, the destination is specified as a label (e.g. jmp.l1). For indirect jumps, the jump target is read from a register or a memory location and is preceded by a '*'. E.g. jmp *%eax uses the value in register %eax as the jump target. Exercise #6: What do the following do? jmp *%eax jmp *(%eax)

Exercise #7: Lets say GCC generated the following code and we are told there is only ONE IF statement in the original C source. 1 movl 8(%ebp), %edx #variable 'x' 2 movl 12(%ebp), %eax #variable 'y' 3 movl $0x10, %ecx 4 testl %eax, %eax 5 je.l3 6 testl %edx, %edx 7 jle.l3 8 cmpl %ecx, %edx 9 jge.l3 10 addl %edx, (%eax) 11.L3: (1) Write a version in C that performs the same computation as above and mimics the control flow of the assembly code. V. Control Flow: Loops Let us now see how loops are implemented using conditional jumps. The following is a simple function to compute a Fibonacci sequence fibonacci.c int fibonacci(int n) { int i = 0; int val = 0; int nval = 1; do { int t = val + nval; val = nval; nval = t; i++; } while (i < n); return val; } Generate the assembly code in the cs61 machine: Linux> gcc34 -O2 -S -m32 fibonacci.c Let's look at the code inside the loop: Register usage Register Variable Initially

%ecx i 0 %ebx val 0 %edx nval 1 %esi n n %eax t -.L2: xorl %ecx, %ecx # i=0 movl $1, %edx # nval=1 pushl %esi # save previous value of %esi movl 8(%ebp), %esi # load n into %esi pushl %ebx # save previous value of %ebx xorl %ebx, %ebx # val=0 leal (%ebx,%edx), %eax # t=val + nval incl %ecx # i++ movl %edx, %ebx # val = nval cmpl %esi, %ecx # Compare i to n movl %eax, %edx # nval = t jl.l2 movl %ebx, %eax #Set val as return Note that assembly code instructions do not always appear in the same order as the corresponding code in the C program. For example, i in incremented in the beginning of the loop in the assembly program, but incremented at the end of the loop. The compiler is free to re-arrange the order of the instructions as long as it does not change the correctness of the code. VI. Introduction to GDB GDB contains a large repertoire of commands. The manual Debugging with GDB includes extensive documentation on the use of these commands, together with examples of their use. Furthermore, the command help invoked from within GDB activates a simple help facility which summarizes the available commands and their options. In this section we summarize a few of the most commonly used commands to give an idea of what GDB is about. You should create a simple program with debugging information and experiment with the use of these GDB commands on the program as you read through the following section. Now let work through an example. /*example1*/ #include <stdio.h> int main () { int i; i = 10; printf("the value of i is %d \n", i); i = incr(i);

} printf("the new value of i is %d\n",i); return 1; int incr( int j) { return j+1; } To compile this program > gcc34 -m32 -O example1.c -o example1 To add debugging information to the executable we use the -g flag. > gcc34 -m32 -g -O example1.c -o example1 To disassemble the program > objdump -d example1 08048354 <main>: 8048354: 55 push %ebp 8048355: 89 e5 mov %esp,%ebp 8048357: 83 ec 08 sub $0x8,%esp 804835a: 83 e4 f0 and $0xfffffff0,%esp 804835d: 83 ec 10 sub $0x10,%esp 8048360: c7 44 24 04 0a 00 00 movl $0xa,0x4(%esp) 8048367: 00 8048368: c7 04 24 6c 84 04 08 movl $0x804846c,(%esp) 804836f: e8 2c ff ff ff call 80482a0 <printf@plt> 8048374: c7 04 24 0a 00 00 00 movl $0xa,(%esp) 804837b: e8 17 00 00 00 call 8048397 <incr> 8048380: 89 44 24 04 mov %eax,0x4(%esp) 8048384: c7 04 24 83 84 04 08 movl $0x8048483,(%esp) 804838b: e8 10 ff ff ff call 80482a0 <printf@plt> 8048390: b8 01 00 00 00 mov $0x1,%eax 8048395: c9 leave 8048396: c3 ret 08048397 <incr>: 8048397: 55 push %ebp 8048398: 89 e5 mov %esp,%ebp 804839a: 8b 45 08 mov 0x8(%ebp),%eax 804839d: 40 inc %eax 804839e: c9 leave 804839f: c3 ret To run gdb >gdb./example1 (gdb)

Note that our program does not accept any user inputs and will run to completion if we execute it. So we need to set up breakpoints wherever we want to inspect the code. Lets say we want to break at some point within the main function and looking at the objdump output we pick 0x8048368. Gdb allows us to set a breakpoint at any memory address. We can also break at a function. New breakpoints can be set any time during a gdb session. The 'continue' command resumes execution. (gdb) break *0x8048368 Breakpoint 1 at 0x8048368: file example1.c, line 7. (gdb) break incr Breakpoint 2 at 0x804839a: file example1.c, line 15. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x08048368 in main at example1.c:7 2 breakpoint keep y 0x0804839a in incr at example1.c:15 (gdb) del breakpoints 1 (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y 0x0804839a in incr at example1.c:15 (gdb) break *0x8048368 Breakpoint 3 at 0x8048368: file example1.c, line 7. Now let us run the program until we hit this breakpoint. (gdb) run Starting program: /space/home/roy/example1 Breakpoint 3, 0x08048368 in main () at example1.c:7 7 printf("the value of i is %d \n", i); To see the disassembly around the current instruction being executed we can use the 'disassemble' command (gdb) disassemble Dump of assembler code for function main: 0x08048354 <main+0>: push %ebp 0x08048355 <main+1>: mov %esp,%ebp 0x08048357 <main+3>: sub $0x8,%esp 0x0804835a <main+6>: and $0xfffffff0,%esp 0x0804835d <main+9>: sub $0x10,%esp 0x08048360 <main+12>: movl $0xa,0x4(%esp) 0x08048368 <main+20>: movl $0x804846c,(%esp) 0x0804836f <main+27>: call 0x80482a0 <printf@plt> 0x08048374 <main+32>: movl $0xa,(%esp) 0x0804837b <main+39>: call 0x8048397 <incr> 0x08048380 <main+44>: mov %eax,0x4(%esp) 0x08048384 <main+48>: movl $0x8048483,(%esp) 0x0804838b <main+55>: call 0x80482a0 <printf@plt> 0x08048390 <main+60>: mov $0x1,%eax 0x08048395 <main+65>: leave 0x08048396 <main+66>: ret End of assembler dump.

If there is nothing to inspect, we can step through the instruction(s). The next command is like the step command except that it steps through function calls. Stepi steps through machine instruction rather than source lines. (gdb) stepi 0x0804836f 7 printf("the value of i is %d \n", i); Now suppose we want to see the value of the registers. (gdb) info registers eax 0xfff6aa84-611708 ecx 0x9792c626-1751988698 edx 0x1 1 ebx 0x971ff4 9904116 esp 0xfff6a9e0 0xfff6a9e0 ebp 0xfff6a9f8 0xfff6a9f8 esi 0x82fca0 8584352 edi 0x0 0 eip 0x804836f 0x804836f <main+27> eflags 0x282 [ SF IF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99 If we want to resume our execution: (gdb) continue Continuing. The value of i is 10 Breakpoint 2, incr (j=10) at example1.c:15 15 return j+1; If we want to inspect the value of j in function incr, we can simply print it out. The print command can print out in different formats formats using the switches /d, /x, /o etc. Moreover we can use the set command to alter the value of j. (gdb) print j $1 = 10 (gdb) print /x $eax $2 = 0x16 (gdb) set j=5 To display the backtrace of the call chain leading to the current point of execution, we use the 'backtrace' command and to inspect the function's stack frame we use the 'frame' command. The argument to the frame command is always with respect to the the function being executed. Thus incr is frame 0 and main is frame 1. The 'up/down' command allows us navigate between frames and look at

the state of their local variables. We would be talking more about stacks in our next section. (gdb) backtrace #0 incr (j=5) at example1.c:15 #1 0x08048380 in main () at example1.c:8 (gdb) frame 0 #0 incr (j=5) at example1.c:15 15 return j+1; (gdb) up #1 0x08048380 in main () at example1.c:8 8 i = incr(i); (gdb) quit *You may also want to try other frontends for debuggers. For example, ddd or insight offer a frontend GUI for gdb.

VII. Procedure Calls Register Usage Conventions: - %eax, %edx, and %ecx are saved by the caller. This means the callee may use and overwrite these registers without destroying any data required by the caller. - %ebx, %esi, and %edi are saved by the callee. These registers must be saved on the stack by the callee and restored before returning. - %ebp and %esp are also maintained as described above. Exercise #8: Lets say we are given the following assembly code for a function. 1 pushl %edi 2 pushl %esi 3 pushl %ebx 4 movl 24(%ebp), %eax 5 imull 16(%ebp), %eax 6 movl 24(%ebp), %ebx 7 leal 0(, %eax, 4), %ecx 8 addl 8(%ebp), %ecx 9 movl %ebx, %edx... 20 popl %ebx 21 popl %esi 22 popl %edi a. Why are %edi, %esi, and %ebx the only registers saved and restored by this piece of code? What about %eax, %edx, and %ecx? b. What do 24(%ebp) and 16(%ebp)refer to? Exercise #9: Lets say we are given the following assembly code for a function. int proc(void) { int x, y; scanf( %x %x, &y, &x); return x y; } and the corresponding assembly code generated is

1 proc: 2 pushl %ebp 3 movl %esp, %ebp 4 subl $24, $esp 5 addl $-4, %esp 6 leal -4(%ebp), %eax 7 pushl %eax 8 leal -8(%ebp), %eax 9 pushl %eax 10 pushl $.LC0 11 call scanf 12 movl -8(%ebp), %eax 13 movl -4(%ebp), %edx 14 subl %eax, %edx 15 movl %edx, %eax 16 movl %ebp, %esp 17 popl %ebp 18 ret Lets assume procedure proc starts executing with the following register values: %esp = 0x800040 %ebp = 0x800060 Suppose proc calls scanf (line 11) and scanf reads values 0x46 and 0x53 from the standard input. Assume the string %x %x is stored at memory location 0x300070. a. What value does %ebp get on line 3? b. At what addresses are local variables x and y stored? c. What is the value of %esp after line 10? d. What does the stack frame look like after line 11?

Appendix I: GDB Commands set args arguments The arguments list above is a list of arguments to be passed to the program on a subsequent run command, just as though the arguments had been entered on a normal invocation of the program. The set args command is not needed if the program does not require arguments. run The run command causes execution of the program to start from the beginning. If the program is already running, that is to say if you are currently positioned at a breakpoint, then a prompt will ask for confirmation that you want to abandon the current execution and restart. breakpoint location The breakpoint command sets a breakpoint, that is to say a point at which execution will halt and GDB will await further commands. location is either a line number within a file, given in the format file:linenumber, or it is the name of a subprogram. If you request that a breakpoint be set on a subprogram that is overloaded, a prompt will ask you to specify on which of those functions you want to breakpoint. You can also specify that all of them should be breakpointed. If the program is run and execution encounters the breakpoint, then the program stops and GDB signals that the breakpoint was encountered by printing the line of code before which the program is halted. breakpoint exception name A special form of the breakpoint command which breakpoints whenever exception name is raised. If name is omitted, then a breakpoint will occur when any exception is raised. print expression This will print the value of the given expression. Most simple expression formats are properly handled by GDB, so the expression can contain function calls, variables, operators, and attribute references. continue Continues execution following a breakpoint, until the next breakpoint or the termination of the program. step Executes a single line after a breakpoint. If the next statement is a subprogram call, execution continues into (the first statement of) the called subprogram. next Executes a single line. If this line is a subprogram call, executes and returns from the call. list Lists a few lines around the current source location. In practice, it is usually more convenient to have a separate edit window open with the relevant source file displayed. Successive applications of this command print subsequent lines. The command can be given an argument which is a line number, in which case it displays a few lines around the specified one. backtrace Displays a backtrace of the call chain. This command is typically used after a breakpoint has occurred, to examine the sequence of calls that leads to the current breakpoint. The display includes one line for each activation record (frame) corresponding to an active subprogram. up At a breakpoint, GDB can display the values of variables local to the current frame. The command up can be used to examine the contents of other active frames, by moving the focus up the stack, that is to say from callee to caller, one frame at a time. down Moves the focus of GDB down from the frame currently being examined to the frame of its callee

(the reverse of the previous command), frame n Inspect the frame with the given number. The value 0 denotes the frame of the current breakpoint, that is to say the top of the call stack.

Solutions to Exercises #1 42 + (-64) 42 10 = 00101010-64 10 = ~64 + 1 = (10111111 2 ) + 1 2 = 11000000 2 Hence, 00101010 + 11000000 - - - - - - - - 11101010 2 = -22 10 #2 Binary Unsigned Byte Signed Byte 10000000 128-128 11111111 255-1 1 1 1 0 0 0 #3 The offset, when treated as a signed number translates to an offset of -4 #4 Answer: %ax = 0xFACE, %ah = 0xFA, %al = 0xCE #5 a. We're performing 64 64. The result, stored in %ecx, is = 0. Hence, the ZF flag is set to 1. b. This is 42 64. Since the MSB of the result from the addl instruction is 1, the SF is set to 1. c. 0xffffffff + 1. The add instruction results in a carry and hence the CF flag is set. Note, the result is 0 so the ZF flag is also set. #6 The first one jumps to the address in memory pointed to by the contents in register %eax. The second one reads the jump target from memory, using the value in %eax as the read address.

#7 x is an int y is an int* (the hint lies in line 11 where we reference (%eax)) note, the order in which the conditionals are checked.e. we first check if y!= 0 and then if x > 0 and then if x < 10. if (y && x > 0 && x < 16) { *y += x; } OR if (y && x > 0) { if (x < 16) { *y += x; } } (this could also be the case for a very simple nested ifs) #8 a. Registers are %edi, %esi, and %ebx are callee saved registers. %eax, %ecx, and %edx are caller saved registers. b. 16(%ebp) refers to the 3 rd argument passed to this function. 24(%ebp) refers to the 4 th argument passed to this function. Lines 4 and 5 result in the multiplication of the 3 rd and 4 th arguments passed to this function. #9 a. We started with %esp = 0x800040. Line 2 decrements it by 4, thereby resulting in 0x80003C in the %esp register. Hence, this is the new value in %ebp. b. We can see how the two leal instructions compute the arguments to pass to scanf. Since arguments are pushed in reverse order, we can see that x is at offset -4 relative to %ebp and y is at offset -8. The addresses are therefore 0x800038 and 0x800034. c. Starting with the original value of 0x800040, line 2 decremented the stack pointed by 4. Line 4 decremented it by 24, and line 5 decremented it by 4. The three pushes decremented it by 12, resulting in an overall change of 44. Thus, after line 10 %esp = 0x800014.

d. Memory Addresses 0x80003C (%ebp) 0x800038 0x800034 0x800030 0x80002C 0x800028 0x800024 0x800020 0x80001C 0x800018 Stack Contents 0x800060 0x53 0x46 0x800038 0x800034 0x800014 (%esp) 0x300070 Note: byte addresses 0x800020 to 0x800033are unused by proc. These wasted spaces are allocated to improve cache performance. We'll see how and why later this semester.