Operator On The Wire
← Back to Knowledge Base
OOTW / Chapter I - Foundation / 06. Programming & Debugging / 06. Functions

Functions

As programs grow larger, it becomes impractical to place all logic inside a single block of code. Functions solve this problem by allowing developers to organize code into reusable units.

A function is simply a named block of code that performs a specific task.

For example:

void PrintGreeting()
{
    printf("Hello World\n");
}

The function can then be executed elsewhere:

PrintGreeting();

This offers several benefits:

  • Reusability
  • Improved readability
  • Easier maintenance
  • Better organization

Instead of writing the same logic repeatedly, a function can be called whenever needed.

Functions can also accept input values known as parameters:

void PrintName(char name[])
{
    printf("%s\n", name);
}
PrintName("Peter");
PrintName("Alice");

Functions may also return values:

int Add(int a, int b)
{
    return a + b;
}
int result = Add(5, 10);

In practice, nearly every piece of software consists of thousands or millions of function calls. Operating system APIs, networking libraries, cryptographic routines and application logic are commonly exposed through functions.


Functions at the Machine Level

At a low level, a function is simply a block of instructions located somewhere in memory.

A simplified program might look like:

ADDRESS LABEL
0x1000  Main
0x1100  PrintGreeting
0x1200  Add

When the program wishes to execute a function, it performs a "call" instruction:

call PrintGreeting

It is essentially using that stored address.

Conceptually:

Main
 │
 ▼
Call Function
 │
 ▼
PrintGreeting
 │
 ▼
Return
 │
 ▼
Continue Execution

The CPU temporarily transfers execution to the target function. Once the function finishes, it executes a "ret" instruction which sends (returns) execution back to the original location.

A simplified assembly example might look like:

Main:
    call PrintGreeting
    ; Continue here after return

PrintGreeting:
    ; Function logic
    ret

This call-and-return mechanism is one of the most important concepts in computing. It allows programs to break complex problems into smaller reusable components.

As we progress through the course, functions will become increasingly important. Reverse engineers spend much of their time identifying functions, understanding their purpose and tracing how data flows between them. Many security vulnerabilities and exploits ultimately involve manipulating how functions are called or how they return control back to the program.