Intro to C Flashcards
Machine code
binary files (such as .obj, .exe, a.out)
Assembly code
text files (e.g. .asm)
C code
text files (.c, .h)
Compiler
converts a high-level language (like C) to low-level language (assembly), for example .c to .asm
Assembler
converts assembly language to machine language object files (.asm to .obj)
Linker
combines multiple object files (.obj) into a single executable object file; e.g. user_program.obj + os.obj → my_program.obj
Symbol table
created by a compiler to keep track of where data should be stored, the type of data stored, and scope of the data being stored by the program it compiled
Instead of recording exact addresses for variables, offset is used relative to the starting location (e.g. R5). WHY?
This was function could use any starting place in data memory and build its stack. Fct can be loaded at different places at different times.
Local variables
the “scope” of these variables exists only within the { }.
Variables must be declared at the top of block!
Stack
in the context of the C language, the region in data memory where data required to support functions in the C language will be stored (functions such as
arguments, local variables, and return values). It is organized like a physical stack: imagine piling one book on top of the next one in a stack of books. This is
why it grows “backwards” in memory.
Frame
a logical grouping of the data on the stack that belongs to a single function. Examples of data in the stack frame are arguments, local variables, and return values. As one function calls another, each function will have its own frame.
Frame pointer
a register that holds a starting address for the frame or , in the case of the LC4, a register holding the location of where the calling function’s frame pointer was stored in the active function’s stack frame. Sometimes called
the “base pointer.”
Return address
address in program memory to return after function completes
Prologue
assembly code created by the compiler to construct the frame for any given function. It is the first code executed when a function is called. It is also responsible for “pushing” the stack frame for the active function onto the stack.
Epilogue
assembly code created by the compiler to “pop” the stack from the active function off of the stack. It copies the return value into the proper location
on the stack so that the calling function has access to the returning data (if any) from the active function. It is executed every time a function exits
Prologue Code
Prologue: same for every function; remember this!
;; prologue
STR R7, R6, #-2 ; save caller’s return address
STR R5, R6, #-3 ; save caller’s frame pointer
ADD R6, R6, #-3 ; updates stack pointer
ADD R5, R6, #0 ; creates/updates frame pointer
○ Arguments are pushed onto stack from right to left.
○ This lets the first argument from the left be the one closest to the callee.
○ That is called “C convention” (while left-to-right is called “PASCAL”).
○ It is needed for functions with variable argument counts e.g. printf.
○ It can also lead to the order of evaluation being right-to-left.
■ Example: pow (a, ++a) may become pow (3, 3)
Epilogue Code
Before enter epilogue store return value in R7 ;;epilogue ADD R6, R5, #0 ; pop local variables ADD R6, R6, #3 ; decrease stack STR R7, R6, #-1 ;update return value LDR R5, R6, #-3 ; restore base ptr LDR R7, R6 #-2 ; restore R7 for RET
Big ideas of C
A high-level/low-level language: binds the gap between a machine level language and high-level languages.
- Imperative
- Procedural
- File-oriented
- Portability
Imperative
The imperative is similar to how you do something (step by step) - assignment statements that explicitly change memory values, while declarative is more similar to what you do, describe function
An imperative approach (HOW): “I see that table located under the Gone Fishin’ sign is empty. My husband and I are going to walk over there and sit down.”
A declarative approach (WHAT): “Table for two, please.”
Procedural
Emphasis on the program’s flow rather than the data operated on by functions
File-oriented
Files: a simple abstraction for permanent storage and I/O
Portability
The same C code can be compiled for different ISAs
How are arguments passed in C
● C is pass-by-value (not pass-by-reference)
○ Functions receive “copies” of local variables.
■ Recall that arguments to functions were copies of local vars.
○ Protects local variables from being modified accidentally.
Why must varialbe be declared at the start of function
○ Size of static/automatic variables are known at compile time:
ADD R6, R6, #-1 ; allocate space for local vars
Also, compiler may compile line-by-line, hence right upfront!
How are arrays stored on the stack
Like one giant variable. Address increases with array index
○ The order of arrays on the stack is consistent with the memory address
i.e. in increasing order.
○ Example:
arr[0] - x7FF5
arr[1] - x7FF6
arr[2] - x7FF7
What is a hashtable in C
An associative array where the incoming data is mapped to the proper storage location within the array. An array (bucket holder) of linked lists with a hashing function to determine where data should fit.
From c to obj
C -> compile -> .asm
.asm -> assemble -> .obj/machine code
Assembly code is not machine specific
WRONG
Main
- All C programs must start in main
- Recall C is procedural , I. e. everything is in a function
- Note that this gets converted to a label in assembly
Local Variables
Exist only in code block they are defined in
Are NOT initialized to 0 in C
Variables MUST be declared at the top of block. Because when assembling first thing done after prologue is create variables on stack
Where in memory do functions build their stack
Data memory, it will hold local variables, return values, return address, base pointer and arguments
Memory split in LC4 of Data memory
- Program Memory up to x1FFF
- Global Variables up to x3FFF
- Dynamic Storage - heap up to x6FFF
- Local Variables (STACK) up to x7FFF
Structure Frame
- temporaries, arguments to callees
- local variables
- Callers frame Pointer
- Return Address
- Return Value
- Arguments to function
1-4 addressed by R5 others by R6
Adding 2 Local Variables to stack after prologue complete
ADD R6 R6 #-2 CONST R7 #2 STR R7 R5 #-1 CONST R7 #3 STR R7 R5 #-2
->arguments added incremental
Where do R5 and R6 point to
R5 = "bottom"of the frame, entry, callers frame pointer R6 = top of stack
Adding Arguments to stack
One by one, right to left e.g Pow(2,3) LDR R7 R5 #-2 ADD R6, R6 #-1 STR R7, R6 #0 LDR R7 R5 #-1 ADD R6, R6 #-1 STR R7, R6 #0
Why is C pass-by-value
Protects local variables from being modified accidentally
How does calling main work in LC4
The LC4’s OS (Operating System) that we’ve written calls a function called USER_START, that puts the LC4 in user mode. USER_START then calls the function: main(), it must be called main() as it is hard coded in USER_START
.CODE .ADDR x8200 .FALIGN ;; first job of OS is to return PennSim to x0000 & downgrade privledge CONST R7, #0 ; R7 = 0 RTI ; PC = R7 ; PSR[15]=0
Explain Linking
It is useful if you write programs that have many separate files that depend on one another
It creates a pointer from one file to another.
“links” the files together as if they were one long .OBJ file.
Function Definition vs Function Declaration
A function definition provides the actual body of the function
A function declaration tells the compiler about a function’s name, return type, and parameters.
Where is #define PI stored
Nowhere, nno space allocated as it is a directive and not a available. When compiling, compiler will substitute PI in code with value
The name of the array IS a memory address. The pointer IS a memory address. The array itself does NOT contain memory addresses
CORRECT?
NO, pointer IS not a memory address but rather contains a memory address