Final Prompt:
YOUR TURN
Enter the program in Listing 10-5 and use gdb to single-step through the code. Notice that when you execute the
mov
rsp
,rbp
instruction in the epilogue, TUI does not highlight the registers. Explain. Next, change the program so that it returns the integer 123. Run it withgdb
. What number base doesgdb
use to display the exit code?Enter the program in Listing 10-1 and compile it with debugging turned on (
-g
option). Set a breakpoint at main. Does gdb break at the entry to the function? Can you follow the actions of the prologue by using the s command? Can you continue through the program and step through the epilogue?Write the following C function in assembly language:
1 2 3 4 /* f.c */ int f(void) { return 0; }
Make sure that it assembles with no errors. Use the
-S
option to compilef.c
and compare gcc’s assembly language with yours. Write a main function in C that tests your assembly language function,f
, and prints out the function’s return value.Write three assembly language functions that do nothing but return an integer. They should each return a >different, nonzero integer. Write a main function in C that tests your assembly language functions and prints >out the functions’ return values by using printf.
Write three assembly language functions that do nothing but return a character. Each should return a >different character. Write a main function in C that tests your assembly language functions and prints out the >functions’ return values by using
printf
.Final based on Chapter 10 of Bob Plantz’s free ebook: Introduction to Computer Organization
Response:
- In order to highlight the registers you need to give gdb the command
layout regs
After setting the program to return 123, the program exits withcode 0173
instead of saying the program exited normally. Therax
register is also labeled as0x7b
instead of0x0
- gdb breaks at
return 0;
. using thes
command you can step into the epilogue but not the prologue since the program jumps straight to the breakpoint.
- When comparing my written assembler code(
f.s
) with the auto generated assembler code(ff
), some of the things that stand out in the generated code is the.LFEO:
section and also some code written in between thef:
function that are all prefixed with.cfi_
After writing the assembler function, I wrote a C function named fcall.c
to call the assembler function and print its return value:
1
2
3
4
5
6
7
8
9
//fcall.c
#include <stdio.h
int f(void);
int main(void)
{
printf("return code: %i\n", f());
return 0;
}
1
2
3
as -o f.o f.s #compile assembler program
gcc fcall.c f.s -o fcall # compiles c program
./fcall #returns "return code: 0"
- In order to call three assembly functions to return a non-zero integer I first assembled each
.s
file with their.o
object file. After they were assembled then I needed to include each header file where the functions were declared into my main c program and call each of them to print their return values.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//test_ints.c
#include <stdio.h
#include "twelve.h"
#include "four.h"
#include "twenty.h"
int main (void) {
int return1;
int return2;
int return3;
return1 = twelve();
return2 = four();
return3 = twenty();
printf("The returned ints are:\n%i\n", return1);
printf("%i\n", return2);
printf("%i\n", return3);
return 0;
}
After that all that was left was to compile the assembler files with the c program and to run it.
1
2
3
4
5
gcc test_ints.c twelve.s four.s twenty.s -o test_ints #compile c progam with assembly programs
./test_ints #returns: The returned ints are:
# 12
# 4
# 20
- Getting a C program to print the character returns of assembler functions was relatively similar to the previous example. There were still some important differences between the two however. First, in the main C program, the return values needed to be declared with
char
instead ofint
. Also when usingprintf
, the statement needed to include%c
instead of%i
in order to specify the character was being returned.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//test_char.c
#include <stdio.h
#include "a.h"
#include "b.h"
#include "c.h"
int main (void) {
char return1;
char return2;
char return3;
return1 = a();
return2 = b();
return3 = c();
printf("The returned characters are:\n%c \n", return1);
printf("%c \n", return2);
printf("%c \n", return3);
return 0;
}
Next, the .s
files needed the character return to be surrounded by quotes in order to specify that it is a string value.
1
2
3
4
5
6
7
8
9
10
11
12
#a.s
.text
.globl a
.type a, @function
a:
pushq %rbp
movq %rsp, %rbp
movq $'a', %rax
movq %rbp, %rsp
popq %rbp
ret
The final difference can be seen when compiling the C program with the .s
files. The gcc
command needed to include the no-pie
flags in order to compile without errors.
1
2
3
4
5
gcc -fno-pie -no-pie test_char.c a.s b.s c.s -o test_char #compiles c program with asm functions
./test_char #returns: The returned characters are:
# a
# b
# c