17. What happens when I build code in C?#
17.1. What is buiding code?#
Building is transforming code from the input format to the final format.
This can mean different things in different contexts. For example:
the course website is built from markdown files in to html output
a C program is built from source code to executables
We sometimes say that compiling takes code from source to executable, but this process is actually multiple stages and compiling is one of those steps.
We will focus on what has to happen more than how it all happens.
CSC301, 402, 501, 502 go into greater detail on how languages work.
Our goal is to:
(where applicable) give you a preview
get enough understanding of what happens to know where to look when debugging
17.2. An overview#
This flowchart describes the build process for C. We are going to go through each step of the process and inspect the output of each step to build our understanding up.
17.3. Using SSH Keys#
We are going to work on seawulf so that we all have the same compiler.
To use it we use he -i
option and then the path to the private key file
ssh -i ~/seawulf brownsarahm@seawulf.uri.edu
Last login: Tue Mar 26 13:43:48 2024 from 172.20.126.231
17.4. Using an interactive session#
Last class we worked on the login node, but that is not best practice.
Today we will use an interactive session using the interactive
program.
First we’ll look at its help
Usage: interactive [-c] [-p] [-J] [-w]
Optional arguments:
-c: number of CPU cores to request (default: 1)
-p: partition to run job in (default: general)
-J: job name (default: interactive)
-w: node name
NB: interactive jobs have a time limit of 8 hours.
Written by: Alan Orth <a.orth@cgiar.org>
Then we will start one with all default settings
[brownsarahm@seawulf ~]$ interactive
salloc: Granted job allocation 27371
salloc: Waiting for resource configuration
salloc: Nodes n005 are ready for job
it tells us what it is doing while it gets ready.
We see that the prompt changes, now we are @n005
instead of @seawulf
, lets check out working directory:
[brownsarahm@n005 ~]$ ls
bash-lesson.tar.gz SRR307026_1.fastq
dmel-all-r6.19.gtf SRR307026_2.fastq
dmel_unique_protein_isoforms_fb_2016_01.tsv SRR307027_1.fastq
gene_association.fb SRR307027_2.fastq
SRR307023_1.fastq SRR307028_1.fastq
SRR307023_2.fastq SRR307028_2.fastq
SRR307024_1.fastq SRR307029_1.fastq
SRR307024_2.fastq SRR307029_2.fastq
SRR307025_1.fastq SRR307030_1.fastq
SRR307025_2.fastq SRR307030_2.fastq
our files are still there. The compute changed, but not our disk space location.
And our working directory is the same:
[brownsarahm@n005 ~]$ pwd
/home/brownsarahm
still our home directory
We will make an empty directory to work in for today.
[brownsarahm@n005 ~]$ mkdir compilec
and go into it to work
[brownsarahm@n005 ~]$ cd compilec/
17.5. A simple program#
[brownsarahm@n005 compilec]$ nano hello.c
and wew will put in a simple hello world program
#include <stdio.h>
void main () {
printf("Hello world\n");
}
we will confirm that it exists
[brownsarahm@n005 compilec]$ ls
hello.c
17.6. Preprocessing with gcc#
First we handle the preprocessing which pulls in headers that are included. We will use the compiler gcc
We will use gcc
for many steps, and use its options to have it do subsets of what it can possibly do:
-E
stops after preprocessing-o
makes it write the .i file and passes the file name for it
[brownsarahm@n005 compilec]$ gcc -E hello.c -o hello.i
If it succeeds, we see no output, but we can check the folder
[brownsarahm@n005 compilec]$ ls
now we have a new file
hello.c hello.i
We can inspect what it does using wc
[brownsarahm@n005 compilec]$ wc -l hello.c
6 hello.c
we started with just 6 lines of code
and we can compare that to the preprocessed file:
[brownsarahm@n005 compilec]$ wc -l hello.i
842 hello.i
and see we get a lot more
Since it is long, we will fist look at the top
[brownsarahm@n005 compilec]$ head hello.i
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 375 "/usr/include/features.h" 3 4
and the end
[brownsarahm@n005 compilec]$ tail hello.i
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 943 "/usr/include/stdio.h" 3 4
# 2 "hello.c" 2
void main () {
printf("Hello world\n");
}
we see that our original program, is at the end of the file, and the beginning is where the include line has been expanded.
17.7. Compiling#
Next we take our preprocessed file and compile it to get assembly code.
Again, we use gcc
:
-S
tells it to produce assemblywe will use the preprocessed file as input
[brownsarahm@n005 compilec]$ gcc -S hello.i
again, there is no output
but we can see what it output:
[brownsarahm@n005 compilec]$ ls
hello.c hello.i hello.s
we have a new file as well with the .s
extension.
Again, lets inspect
[brownsarahm@n005 compilec]$ wc -l hello.s
25 hello.s
this is longer than the source, but not as long as the header. The header contains lots of information that we might need, but the assembly is only what we do.
And it’s manageable, so we inspect it directly:
[brownsarahm@n005 compilec]$ cat hello.s
.file "hello.c"
.section .rodata
.LC0:
.string "Hello world"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
.section .note.GNU-stack,"",@progbits
There are many more steps and they are lower level operations, but it is text stored in the file.
Hint
Learning more about assembly languages is a good explore badge topic
17.8. Assembling#
Assembling is to take the assembly code and get object code. Assembly is relatively broad and there are families of assembly code, it is also still written for humans to understand it readily. It’s more complex than source code because it is closer to the hardware. The object code however, is specific instructions to your machine and not human readable.
Again, with gcc
:
-c
tells it to stop at the object file-o
again gives it the name of the file to write
[brownsarahm@n005 compilec]$ gcc -c hello.s -o hello.o
Again, check what it does by looking at files
[brownsarahm@n005 compilec]$ ls
hello.c hello.i hello.o hello.s
now we see a new file, the .o
and again check its length
[brownsarahm@n005 compilec]$ wc -l hello.o
5 hello.o
this is even shorter,
we can check how many characters and words
[brownsarahm@n005 compilec]$ wc hello.o
5 17 1496 hello.o
it is not even too many characters
let’s look at it
[brownsarahm@n005 compilec]$ cat hello.o
ELF>?@@
UH???]?Hello worldGCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)zRx
K A?C
?? hello.cmainputs
???????? .symtab.strtab.shstrtab.rela.text.data.bss.rodata.comment.note.GNU-stack.rela.eh_frame @?0
&PP1P
90\.B?W?R@
?
?0a
This is not machine readable, though:
17.9. Linking#
Now we can link it all together; in this program there are not a lot of other depdencies, but this fills in anything from libraries and outputs an executble
once again with gcc
:
-o
flag specifies the name for output-lm
tells it to link from the .o file.
[brownsarahm@n005 compilec]$ gcc -o hello hello.o -lm
again we can look at the directory
[brownsarahm@n005 compilec]$ ls
the file was a different color to indicate that it is executable
hello hello.c hello.i hello.o hello.s
We can look at this too:
[brownsarahm@n005 compilec]$ cat hello
ELF>P@@(@8 @@@@@@?88@8@@@ ``48 ``?TT@T@DDP?td??@?@44Q?tdR?td``/lib64/ld-linux-x86-64.so.2GNU GNU?hm|Y??!w\??د5P?S$)
libm.so.6__gmon_start__libc.so.6puts__libc_start_mainGLIBC_2.2.5ui ;?`` `(`H?H?
H??t?CH???5?
?%?
@?%?
h??????%?
h??????%?
h?????1?I??^H??H???PTI???@H??P@H??=@?????fD??`UH-8`H??H??w]øH??t?]?8`????8`UH-8`H??H??H??H???H?H??u]úH??t?]H?ƿ8`????==
uUH???~???]?*
??@H?= t?H??tU?`H????]?{????s???UH???@?????]?AWA??AVI??AUI??ATL?% UH?- SL)?1?H??H??e???H??t?L??L??D??A??H??H9?u?H?[]A\A]A^A_Ðf.???H?H??Hello world0$???|d???LQ????d????????
zRx
???*zRx
$????@FJ
K ??;*3$"D????A?C
Dd????eB?E?E ?E(?H0?H8?M@l8A0A(B BB?????@?@
???o?@@?@ ?@
G
`H?@?@ ???oh@???o???o`@`&@6@F@GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)8@T@t@?@?@@`h@ ?@
?@
?@
P@?@?@?@ @```?``0`4`??
=@?8`?k?4`'?@Fe0`r ??@??@?
?@crtstuff.c__JCR_LIST__deregister_tm_clones__do_global_dtors_auxcompleted.6355__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entryhello.c__FRAME_END____JCR_END____init_array_end_DYNAMIC__init_array_start__GNU_EH_FRAME_HDR_GLOBAL_OFFSET_TABLE___libc_csu_finiputs@@GLIBC_2.2.5_edata__libc_start_main@@GLIBC_2.2.5__data_start__gmon_start____dso_handle_IO_stdin_used__libc_csu_init__bss_startmain__TMC_END__.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fin@8#T@T 1t@t$D???o?@Ngot.got.plt.data.bss.comment
?@?V@G^???o`@k???oh@hz?@?B?@???@??@@?P@Pr??@? ??@??@?4?`???0`04`4?04-h?. P
but it is compltely unreadable
Finally we can run our program
[brownsarahm@n005 compilec]$ ./hello
Hello world
17.10. Putting it all together#
We can repeat with a different name and work directly from source to executable:
[brownsarahm@n005 compilec]$ gcc -o demohello hello.c -lm
and run again.
[brownsarahm@n005 compilec]$ ./demohello
it runs the same
Hello world
Next we can edit our program and add a !
[brownsarahm@n005 compilec]$ nano hello.c
so that it looks like this
#include <stdio.h>
void main () {
printf("Hello world!\n");
}
if we link the object file
[brownsarahm@n005 compilec]$ gcc -o hello hello.o -lm
and run
[brownsarahm@n005 compilec]$ ./hello
we see no change
Hello world
Now we can buld completely from source that we editied and run
[brownsarahm@n005 compilec]$ gcc -o hello hello.c -lm
[brownsarahm@n005 compilec]$ ./hello
Hello world!
now it has it
17.11. Working with multiple files#
This all looks a bit different if we have our code split across files.
we will make a new file main.c
[brownsarahm@n005 compilec]$ nano main.c
with content as follows
/* Used to illustrate separate compilation.
Created: Joe Zachary, October 22, 1992
Modified:
*/
#include <stdio.h>
void main () {
int n;
printf("Please enter a small positive integer: ");
scanf("%d", &n);
printf("The sum of the first n integers is %d\n", sum(n));
printf("The product of the first n integers is %d\n", product(n));
}
Then help.c
[brownsarahm@n005 compilec]$ nano help.c
/* Used to illustrate separate compilation
Created: Joe Zachary, October 22, 1992
Modified:
*/
/* Requires that "n" be positive. Returns the sum of the
first "n" integers. */
int sum (int n) {
int i;
int total = 0;
for (i = 1; i <= n; i++)
total += i;
return(total);
}
/* Requires that "n" be positive. Returns the product of the
first "n" integers. */
int product (int n) {
int i;
int total = 1;
for (i = 1; i <= n; i++)
total *= i;
return(total);
}
We can explore gcc
options
[brownsarahm@n005 compilec]$ gcc --help
Usage: gcc [options] file...
Options:
-pass-exit-codes Exit with highest error code from a phase
--help Display this information
--target-help Display target specific command line options
--help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]
Display specific types of command line options
(Use '-v --help' to display command line options of sub-processes)
--version Display compiler version information
-dumpspecs Display all of the built in spec strings
-dumpversion Display the version of the compiler
-dumpmachine Display the compiler's target processor
-print-search-dirs Display the directories in the compiler's search path
-print-libgcc-file-name Display the name of the compiler's companion library
-print-file-name=<lib> Display the full path to library <lib>
-print-prog-name=<prog> Display the full path to compiler component <prog>
-print-multiarch Display the target's normalized GNU triplet, used as
a component in the library path
-print-multi-directory Display the root directory for versions of libgcc
-print-multi-lib Display the mapping between command line options and
multiple library search directories
-print-multi-os-directory Display the relative path to OS libraries
-print-sysroot Display the target libraries directory
-print-sysroot-headers-suffix Display the sysroot suffix used to find headers
-Wa,<options> Pass comma-separated <options> on to the assembler
-Wp,<options> Pass comma-separated <options> on to the preprocessor
-Wl,<options> Pass comma-separated <options> on to the linker
-Xassembler <arg> Pass <arg> on to the assembler
-Xpreprocessor <arg> Pass <arg> on to the preprocessor
-Xlinker <arg> Pass <arg> on to the linker
-save-temps Do not delete intermediate files
-save-temps=<arg> Do not delete intermediate files
-no-canonical-prefixes Do not canonicalize paths when building relative
prefixes to other gcc components
-pipe Use pipes rather than intermediate files
-time Time the execution of each subprocess
-specs=<file> Override built-in specs with the contents of <file>
-std=<standard> Assume that the input sources are for <standard>
--sysroot=<directory> Use <directory> as the root directory for headers
and libraries
-B <directory> Add <directory> to the compiler's search paths
-v Display the programs invoked by the compiler
-### Like -v but options quoted and commands not executed
-E Preprocess only; do not compile, assemble or link
-S Compile only; do not assemble or link
-c Compile and assemble, but do not link
-o <file> Place the output into <file>
-pie Create a position independent executable
-shared Create a shared library
-x <language> Specify the language of the following input files
Permissible languages include: c c++ assembler none
'none' means revert to the default behavior of
guessing the language based on the file's extension
Options starting with -g, -f, -m, -O, -W, or --param are automatically
passed on to the various sub-processes invoked by gcc. In order to pass
other options on to these processes the -W<letter> options must be used.
For bug reporting instructions, please see:
<http://bugzilla.redhat.com/bugzilla>.
First we can make the two objects:
[brownsarahm@n005 compilec]$ gcc -Wall -g -c main.
main.c:8:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main () {
^
main.c: In function ‘main’:
main.c:12:2: warning: implicit declaration of function ‘sum’ [-Wimplicit-function-declaration]
printf("The sum of the first n integers is %d\n", sum(n));
^
main.c:13:2: warning: implicit declaration of function ‘product’ [-Wimplicit-function-declaration]
printf("The product of the first n integers is %d\n", product(n));
^
we need to declare soemthing about the sum
and product
functions here, so lets edit.
We can get around this, by telling main about the functions by adding
int sum(int n);
int product (int n);
to the main.c
[brownsarahm@n005 compilec]$ nano main.c
so we finally have:
/* Used to illustrate separate compilation.
Created: Joe Zachary, October 22, 1992
Modified:
*/
#include <stdio.h>
int sum(int n);
int product(int n);
void main () {
int n;
printf("Please enter a small positive integer: ");
scanf("%d", &n);
printf("The sum of the first n integers is %d\n", sum(n));
printf("The product of the first n integers is %d\n", product(n));
}
Now we try again
[brownsarahm@n005 compilec]$ gcc -Wall -g -c main.c
main.c:10:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main () {
^
we will leave only the one, which we will leave
Now we preprocess, compile and assemble the helper code:
[brownsarahm@n005 compilec]$ gcc -Wall -g -c help.c
and look at what was created
[brownsarahm@n005 compilec]$ ls
demohello hello.c hello.o help.c main.c
hello hello.i hello.s help.o main.o
Tip
One reason we split code is to make it readable, but another reason is what we just did. We can compile each file separately, when your code is large and compiling takes a long time, splitting it will mean you only have to recompile the file(s) you have recently changed and relink, instead of recompiling everything.
and finally we link them.
[brownsarahm@n005 compilec]$ gcc -o demo main.o help.o -lm
and then we can run
[brownsarahm@n005 compilec]$ ./demo
Please enter a small positive integer: 5
The sum of the first n integers is 15
The product of the first n integers is 120
17.12. Why is the object file not human readable?#
The object file displays as random weird characters because it is written to disk in a different format than our terminal reads it in. It is the specific instructions (from the assembly) and memory addresses written to a file in binary. Our terminal reads it one byte (8bits) at a time and interprets those as characters.
Today, we will see how characters are represented as integers, then binary, and read and write files in binary of strings we know to see how it what happens and mimic something like how that object file happened by writing as binary and then reading it as characters.
17.13. Prelude: REPL#
One way we can use many interpreted languages, including Python is to treat the interpreter like an application and then interact with it in the terminal.
This is called the Read, Execute, Print Loop or REPL.
We can execute simple expressions like mathemeatical expressions:
[brownsarahm@n005 compilec]$ python3
Python 3.6.8 (default, Nov 14 2023, 16:29:52)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
4+5
9
and it will print the result
We can create variables
name='sarah'
but assignment does not return anything, so nothing is printed.
We can see the value of a variable, by typing its name
name
'sarah'
and then it prints the value
17.13.1. Characters to Integers#
Python provides a builtin function ord
to find the Unicode key for that character.
ord('A')
65
ord('B')
66
ord('a')
97
This structure, the []
is called a list comprehension. It
executes a for
loop in order to build a list
. In the REPL,
it will then print out the list.
[ord(char) for char in name]
[115, 97, 114, 97, 104]
We get the integer representation for each one.
There was a question about anonymous functions:
nums_string = lambda s: [ord(char) for char in s]
nums_string('sarah brown')
[115, 97, 114, 97, 104, 32, 98, 114, 111, 119, 110]
Note that it’s important to try multiple things if you aren’t sure the format you are getting back or to check the official documents, as Denno found by testing this with his name in lowercase.
[ord(char) for char in 'denno']
[100, 101, 110, 110, 111]
Coincidentally, the letters in his name all fall into the hundreds and only require 0 and 1 in decimal, so it looks like they could be 3 bit binary numbers.
Python also allows us to change content into a byte array:
bytearray(34)
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
It does not display in the 0 and 1 like a string that we might expect, but it does change the type.
We can then write this to a file, by getting the actual byes of each item. First, we will save our list in a variable.
name_ints = [ord(char) for char in name]
We will use the Python with
keyword to open the file so that we do not to need to separately open and close the file.
in the open
function, the first parameter is the file name and the second is the mode. In this case, we want to write (‘w’) in binary (‘b’). f
is the filestream.
with open("name.txt",'wb') as f:
... f.write(bytes(bytearray(name_ints)))
...
it returns 5 in this case, because it wrote out 5 bytes, one per character.
If we exit python we can look at the file and see how it is interpreted.
exit()
we confimr the file exists
[brownsarahm@n005 compilec]$ ls
demo hello hello.i hello.s help.o main.o
demohello hello.c hello.o help.c main.c name.txt
Remember we wrote, as binary, the numbers, 115, 97, 114, 97, 104
to the file
[brownsarahm@n005 compilec]$ cat name.txt
sarah
but it is interpretted as the string by the terminal.
Back in Python, we can read the file as binary
[brownsarahm@n005 compilec]$ python
Python 2.7.5 (default, Nov 14 2023, 16:14:06)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> bytearray(2)
bytearray(b'\x00\x00')
>>> a = bytearray(2)
>>> type(a)
<type 'bytearray'>
>>> with open("name.txt",'rb') as f:
... print(f.read())
...
sarah
>>> with open("name.txt",'r') as f:
... print(f.read())
...
sarah
>>> with open("name.txt",'rb') as f:
... content = f.read()
...
>>> type(content)
<type 'str'>
>>> exit()
we noticed an odd behavior in python2 and switched to 3.
[brownsarahm@n005 compilec]$ python3
Python 3.6.8 (default, Nov 14 2023, 16:29:52)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> with open("name.txt",'rb') as f:
... content = f.read()
...
>>> type(content)
<class 'bytes'>
>>> content
b'sarah'
>>> exit()
This is binary, but the python interpreter also prints it as a string, the b
indicates the object is actually binary type.
when we log out:
[brownsarahm@n005 compilec]$ logout
salloc: Relinquishing job allocation 27371
we initilaly just leave the interactive session, going from n005
to the login node
[brownsarahm@seawulf ~]$ logout
Connection to seawulf.uri.edu closed.
17.14. Prepare for Next Class#
Install nand2tetris
17.15. Badges#
Create some variations of the
hello.c
we made in class. Make hello2.c print twice with 2 print commands. Make hello5.c print 5 times with a for loop and hello7.c print 7 times with a for loop. Build them all on the command line and make sure they run correctly.Write a bash script, assembly.sh to compile each program to assembly and print the number of lines in each file.
Put the output of your script in hello_assembly_compare.md. Add to the file some notes on how they are similar or different based on your own reading of them.
On Seawulf, modfiy main.c from class to accept the integer as a command line argument instead of via input while running the program. See this tutorial for an example.
Write a bash script demo_test.sh that runs your compiled program for each integer from 10 to 30 (syntax for a range is
{start..end}
so this would be{10..30}
)Write an sbatch script, batchrun.sh to run your script on a compute node and save the output to a file. The sbatch script should compile and link the program and then call the script. see the options
use scp to download your modified main, script files, and output to your local computer and include them in your kwl repo.
17.16. Experience Report Evidence#
export your terminal and append to the experience report.
17.17. Questions After Today’s Class#
17.17.1. Would these all work the same within the kwl or another directory?#
these are path independent, there only needs to be the right files.
17.17.2. is there any current day scenario where knowing how to write code in assembly would be advantageous?#
If you work at really low level things, yes! Also some number of people need to debug compilers, and there could be new innovations in hardware that mean we need new assembly language
17.17.3. How does one process know that the one before it is done?#
What you input, is how it knows what to do, the options tell it where to stop.
17.17.4. If my time runs out in my node, what happens to the files, are they deleted and lost?#
nothing happens to the file, but the code that was running is stopped
17.17.5. What way is the most efficient for compiling code?#
Comparing different compilers is a good explore badge.
17.17.6. Is the process for Python similar to the one in C?#
No, python is interpreted not compiled. However the Python interpretter is written in C. That is compiled to an executable, that we run. When we run that program it parses and executes our code, then exits either when we tell it to or at the end of a provided script.
17.17.7. What did the extensions mean?#
The extensions are to indicate which file is which, they are a part of the program.
17.17.8. What languages can we use through ssh?#
gcc
is only for C
, but we can use any langague through ssh. That does not limit what you can do.
seawulf has both Python
and gcc
available by default so we can use both of those, but it also has R
17.17.9. How does the compiler link two object files together if they are so unreadable?#
It knows how to parse the binary, they are just not in characters for us.
17.17.10. what is seawulf used for?#
Learning HPC systems. To see more generally about what servers are for, check the last class intro.
17.17.11. Is gcc
only used for C or can it also be used for C++?#
gcc is the Gnu Compiler Collection and, “ C, C++, Objective-C, Fortran, Ada, Go, and D, as well as libraries for these languages (libstdc++,…)”
17.17.12. If we write a program with multiple function, then how does the computer “know” to jump between different functions, since a program runs through the program line by line?#
jump
is on operation that can be in assembly
17.17.13. Is there a “standard” compiler that is recognized universally?#
gcc
is about the most universal, but the compiler has to know what