Section 3: Assembly
This section contains a series of excercises to help get you more familiar with the Assembly Language and using GDB (GNU Debugger). By the end of it, we hope you'll be an Assembly superhero!
Warmup: Assembling the Right Tools
During this warmup, we'll be going over key parts of assembly like registers, then looking at some sample assembly programs.
WARMUP A. In x86-64 assembly, which register holds the return value of functions?
WARMUP B. Consider the register %rax
. How many subregisters does %rax
have? What are their names and sizes?
WARMUP C. What is the size (in bytes) of a long in x86-64 assembly?
Question 1: Fun!
Now it's time to have some fun! Unfortunately having fun is not quite that simple. Everyone has fun in their own special ways. In order for your computer to have some fun, you'll need to input a specific argument.
There are six different fun-having functions in this portion of the section. Each fun
function will return either 0 (if fun is had) or something else (if no fun is had). The goal is to find out the arguments so each fun-having function can have fun!
To compile the program, run make
inside the section3
directory in the section code.
To run a fun function, use the following command format:
$ ./fun [number of func] [argument to func]
For example:
$ ./fun 1 "CS300!"
Will run the first fun function (fun_one
) with input CS300!
.
In this part of the section, we will use the objdump
tool to look at the assembly code for executables we have already compiled, and we will use GDB to investigate the behavior of fun-inducing functions. GDB helps us analyze how each fun function responds to the inputted argument. (Check out this GDB cheatsheet for a brief overview of useful commands and their usage.)
NOTE: If you are on an Apple Silicon or other ARM64 device, please consult the README.apple
file in the section code for how to run GDB for this section.
Note that the call
instruction calls a function; in x86-64, register %rdi
(or its sub-registers) hold the first argument to a function at the time of the call
instruction.
QUESTION 1A. What argument will allow fun_one
to have fun? For reference, its assembly is below:
fun_one:
subq $24, %rsp
movq %rdi, 8(%rsp)
movq 8(%rsp), %rax
movl $33, %esi
movq %rax, %rdi
call strchr@PLT
testq %rax, %rax
je .L20
movl $0, %eax
jmp .L21
.L20:
movl $-1, %eax
.L21:
addq $24, %rsp
ret
QUESTION 1B. What argument will allow fun_two
to have fun? For reference, its assembly -- in objdump
output format -- is below. Note that %rdi
contains the first argument to a function called as before, %rsi
contains the second argument, and %rdx
contains the third argument.
0000000000001352 <fun_two>:
1352: sub $0x18,%rsp
1356: mov %rdi,0x8(%rsp)
135b: mov 0x8(%rsp),%rax
1360: mov $0x0,%edx
1365: mov $0x0,%esi
136a: mov %rax,%rdi
136d: callq 1060 <strtol@plt>
1372: add $0x1,%eax
1375: add $0x18,%rsp
1379: retq
QUESTION 1C. What argument will allow fun_three
to have fun? Let's investigate using GDB in layout asm
mode.
Note the following:
- The
si
command to GDB makes it step by a single assembly instruction at a time. - The
finish
command makes GDB run to the end of the current function (this is useful for getting out of standard library functions). - The
p
command followed by a register name written as$reg
prints the contents of the register; e.g.,p $edx
prints the contents of the lower 32 bits of the%rdx
register. - The
info registers
(or, for short,i reg
) command prints the contents of all the registers. You can print a specific register viai reg
followed by a register name. For example,i reg $rax
prints%rax
, ori reg $eflags
prints the contents of the%rflags
register.
QUESTION 1D. What argument will allow fun_four
to have fun? Use objdump
or GDB to investigate. The register table from the lecture notes may come in handy.
QUESTION 1E. What argument will allow fun_five
to have fun? For reference, its assembly is below:
fun_five:
movq %rdi, -8(%rsp)
movq -8(%rsp), %rax
movzbl (%rax), %eax
testb %al, %al
jne .L31
movl $-1, %eax
ret
.L31:
movq -8(%rsp), %rax
movzbl (%rax), %edx
movq -8(%rsp), %rax
addq $1, %rax
movzbl (%rax), %eax
cmpb %al, %dl
je .L33
movq -8(%rsp), %rax
addq $1, %rax
movzbl (%rax), %eax
movsbl %al, %eax
ret
.L33:
addq $1, -8(%rsp)
jmp .L31
QUESTION 1F. What argument will allow fun_six
to have fun? Investigate this question using GDB.
Question 2: Deciphering Assembly
For whatever reason, you happen to come across the following assembly code. Let's get a closer look at what this program is doing!
.file "q1.c"
.text
.section .rodata
.LC0:
.string "%d\n"
.text
.globl func
.type func, @function
func:
subq $24, %rsp
movl $42, 8(%rsp)
movl $0, 12(%rsp)
jmp .L2
.L3:
movl 12(%rsp), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl $0, %eax
call printf@PLT
addl $1, 12(%rsp)
.L2:
movl 12(%rsp), %eax
cmpl 8(%rsp), %eax
jl .L3
movl $1, %eax
addq $24, %rsp
ret
.size func, .-func
.globl main
.type main, @function
main:
subq $8, %rsp
movl $0, %eax
call func
addq $8, %rsp
ret
.size main, .-main
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
.section .note.GNU-stack,"",@progbits
QUESTION 2A. What does the function func
return?
QUESTION 2B. What does the function main
return?
QUESTION 2C. What C code could have generated func
?
Acknowledgements: Material in this section was originally developed for Harvard's CS 61 course. We are grateful to Eddie Kohler for allowing us to use the material for CS 300.