return value

the first word below, void in this case, specifes to the compiler wether there will be a return value or not. and if there is a return value, what TYPE (and how big) it is. The word void specifically means this function does not return a value


		void foo()
		{
		}
	  

register $RAX

In actuality a return value is a value that is stored in a cpu register. On intel x86 architecture the register where the return value is stored is called $EAX or $RAX depending on the size of the type returned.

Wait what are registers

Registers are the fastest form of memory known to mankind. They are located phyiscally on the CPU in each core. In modern cpu's the register are 8 bytes wide that is 64 bits. So far I have mentioned $pc the program counter, which on an x86 cpu is called $RIP, but in gdb you can reference as $pc (program counter). The $rip registers stores the address in memory where the next instruction to be executed is stored. Now I am discussing the $rax register where function store RETURN values right before they exit.

here are some of the registers and the values stored there in hex and base10

Lets change foo so that it returns an TYPE called int. If we view the disassembly in gdb notice what happens right before we return from the function

	  int foo()
	  {
	  int y = 4;
	  return 255;
	  }
	  

Now look what happens in main when we return from foo. The return value was stored in $eax so it is copied from $eax to the memory location specified by the symbol r. r happens to be located at the memory address specified by the $rbp register-4 bytes.


	  void main()
	  {
	  int r = foo();
	  }
	  

function anatomy: The Name

The next part is of the defintion is the name of the function. In this case foo, which is a symbol for the starting address in memory where a sequence of cpu instructions begin.


		// function defintion
		void foo(void)
		{
		}
	  

Arguments to the function

The part of the function definition in between the parentheses are things(values,bit patterns) that we want to send to the function in order for it to do it's work.. In this case because we are using the word void, Which means nothing we will send nothing to the function.


		void foo(void)
		{
		}
	  

How are arguments passed?

Prior to function being called the Arguemntes are copied to some registers by the calling function. The called function then copies the values from the registers to it's local stack frame. we will soon talk about the stack frame

In many computer architectures, particularly x86-64, there's a specific order and set of registers used for passing arguments to functions.

  • First argument: RDI
  • Second argument: RSI
  • Third argument: RDX
  • Fourth argument: RCX
  • Fifth argument: R8
  • Sixth argument: R9

lets see how the arguements are passed under the hood for this code.


	  int foo(int a, int b, int c, int d)
	  {
	      int y = a + b + c + d;
	      return y;
	  }

	  void main(void)
	  {
	      int p = foo(1 ,2, 3,4);

	  }
	  

Function signature

  • return type
  • name
  • the arguments

Combined are called the FUNCTION SIGNATURE or the FUNCTION PROTOTYPE

The signature or protoype defines the cirumstances of the function, how is it called, what does it take, and what does it return


		void foo(void) //Function prototype or signature
		{
		}
	  

function body

after the function signature/prototyp, we have the function body. The part in between the curly brackets is the function body. When the function is called the code that is in the body is what will be executed on the cpu


		void foo(void) //Function prototype or signature
		{
			//Function Body in between the curly braces
		}
	  

declarations and definitions

A function definition has a signature(aka prototype) and a body, as shown in the previous slide. If you just have the signature/prototype by itself and put a semi colon at the end. It is called a function declaration.


		void foo(void); //Function declaration.
	  

Forward Declarations and Defintions

C/C++ allow you to complete the compilation step of your code. As long as a function declaration is present prior to any function calls that you make to that function. This is called a FORWARD DECLARATION.

HOWEVER, if you never provide a full function definition the linker step will fail when it tries to resolve the symbols it is looking for in the function call.

When you include a standard header file like math.h You are including forward declarations for any function from that library that you want to use. The linker step will look for the complete function definition when it tried to resolve the function call. if it can't find it, you will get a linker error.


		// function declaration


		//function defintion
		void foo(void) //Function prototype or signature 
		{
			//Function Body in between the curly braces
		}
	  

statements and semi

All statements in c end in a semicolon, white space is disregarded. The semi colon tells the compiler this is the end of the statement. It is completely ok to make a statement like this. It is not adviseable but will compile. White space only effects symbol names.


		int x,
			y
		,
		p =

                                             3;
	  

Line Feed and carriage return

C evaluates the following symbol '\n' as the number 10 (0xA). The '\' is an escape character. When the c compiler encounters the escape character in a string or delimted by single quotes, it does not evaluate it as a plain text backslash, it evaluates the \ and the next character as a control sequence. If you want to insert an actual backslash you would type two \\

End of line

On the ascii table if you look up 10 you will see that It stands for Line feed. On unix like systems that is the End of line character. Windows systems use 2 characters to demarkate the end of line. '\r' and '\n' combined, '\r' is number 13 on the ascii table.

Can we just press return in a "string" to demarkate end of line?

No you cannot. Typing the return key within a "string" will give you compilation error. You must type the control sequence of the ascii char you want to represent. If you want and end of line you type '\n'. On windows systems you do not need to type "some sentence \r\n" The c compiler will automatically make the adjustement for targeting windows systems. However if you inspect a plain text file on a windows systems the last two bytes of each line will be 00001101 00001010

CPU and Numeric values

A CPU is just an engine for manipulating numerical values. Memory is a gigantic store of these numeric values. The processor pulls numeric values from memory into registers, operates on them and puts the resulting numeric value back into memory. That is all a cpu does. Programming is just telling the CPU different ways to manipulate those values to produce some outcome.

variables

In c, when we are programming, we can ask for some SPACE in memory for one of these numeric values. When we declare a variable, we are asking for some space and giving that space a name. ie

	    
		int Integer;
	  
	  

Asks for space for a numeric value of type int that we name Integer. Each TYPE will have a certain amount of space associated with it.

assignment

The = sign in programming is different than = in math. The = sign in Programming means assignment. It tells the cpu to take that space that we requested and set the value there to what is specified on the RIGHT SIDE of the = in the statement.


		Integer = 5;
		Integer = 5 + 2;
		Integer = Integer + 1;

	  

Asking for space for whole number types

The following KEYWORDS in c usually resolve to requesting for these number of bytes of memory.
char 1 byte
short 2 byte
int 4 byte
long 8 byte

char Number = 100; uses movb for mov byte

short Number = 100; uses movw for mov word 2 bytes

int Number = 100; uses movl for move long 4 bytes

long Number = 100; use movq for quadword 8 bytes

unsigned and signed integers

An 8 bit value, 1 byte can represent 256 different values. That does not necessraily mean those values are 0 to 255. By default if I use the char keyword, I am saying I negative values as well as postivie ones using 8 bits. That means 8 bits can be interpreted as different numeric values.

We can add the additional keyword unsigned to let the compiler know we only want to treat the values as positive numbers. We can also explicity add the keyword signed, which is the default setting of whole number numeric types.

	    
	    char SmallS;           // -128 to 127
	    char unsigned SmallU;  // 0 - 255
	    
	  

            void main(void)
	    {
	    char unsigned SmallU = 255; // 11111111
	    
	    printf("%d\n", SmallU);
	    printf("%d\n", (char) SmallU);
	    
	    }
	  

	    $ ./a.out
	    255
	    -1
	  

Overflow


	    void main(void)
	    {
               char unsigned OverFlow = 254;
	       OverFlow = OverFlow + 1;
	       OverFlow = OverFlow + 1;
	       /* What will be the value of OverFlow  */
	    }
	  
live debug?

Intro to Strings

An ascii String in C is a series of Bytes, where the value of each byte is a value on the ascii table, From 0 to 127, where the value 0 is considedred The NULL character. In c, A string is enclosed in "quotes". The variable name that we use to refer to the string holds the address of the first bytes of the string. All strings in C are null terminated, meaning they end in a byte with the value of 0.

String bytes

next week

  • stack frame routine.(with streets)
  • keywords that represent types
  • argc, argv main is just a function
  • forward declaration/definition