Repository: tuhdo/os01 Branch: master Commit: a7587edc10c5 Files: 48 Total size: 2.0 MB Directory structure: gitextract_3fx0xerz/ ├── .gitignore ├── CHANGELOG.md ├── README.md ├── _config.yml ├── book_src/ │ ├── Operating Systems From 0 to 1.lyx │ ├── Operating Systems From 0 to 1.txt │ ├── images/ │ │ ├── .rid │ │ ├── 02/ │ │ │ └── layer_translation.graphml │ │ ├── 03/ │ │ │ └── .rid │ │ ├── 04/ │ │ │ ├── .rid │ │ │ └── modrm32.tex │ │ ├── 05/ │ │ │ └── .rid │ │ ├── 06/ │ │ │ └── .rid │ │ ├── 07/ │ │ │ └── .rid │ │ └── 08/ │ │ └── .rid │ └── references.bib └── code/ ├── chapter7/ │ └── os/ │ ├── .gdbinit │ ├── Makefile │ ├── bootloader/ │ │ ├── Makefile │ │ ├── bootloader.asm │ │ └── debug.elf │ ├── build/ │ │ ├── bootloader/ │ │ │ └── bootloader.o │ │ └── os/ │ │ └── sample.o │ ├── disk.img │ └── os/ │ ├── Makefile │ └── sample.asm └── chapter8/ └── os/ ├── .gdbinit ├── Makefile ├── bootloader/ │ ├── Makefile │ ├── bootloader.asm │ ├── bootloader.dbg │ └── bootloader.lds ├── build/ │ ├── bootloader/ │ │ ├── bootloader.elf │ │ ├── bootloader.o │ │ └── bootloader.o.elf │ ├── disk.img │ ├── main.o │ └── os/ │ ├── main.o │ ├── os │ ├── os.debug │ └── sample.o ├── disk.img └── os/ ├── Makefile ├── main ├── main.c ├── os ├── os.lds └── sample.asm ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.png *.lyx~ ================================================ FILE: CHANGELOG.md ================================================ ## 0.0.1 (2017-02-15) * [#6] Fix the figure `far_jmp_ex.svg` in chapter 4, where the segment and the offset in memory are reversed. * [#7] Fix example 5.3.1: change NULL section to .interp section. * [#8] Fix command output to reflect the source code. * [#9] abort(), not .abort(). A function call, not a section. * [#10] Use `__FUNCTION__` for consistency. * [#11] Fix incorrect filename. * [#12] Fix confusing sentence. * [#13] Fix a typo. ================================================ FILE: README.md ================================================ [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=tuhdo1710%40gmail%2ecom&lc=VN&item_number=tuhdo¤cy_code=USD&bn=PP%2dDonationsBF%3aDonate%2dPayPal%2dgreen%2esvg%3aNonHosted) [Operating Systems: From 0 to 1](https://tuhdo.github.io/os01/) ============================= This book helps you gain the foundational knowledge required to write an operating system from scratch. Hence the title, 0 to 1. After completing this book, at the very least you will learn: - How to write an operating system from scratch by reading hardware datasheets. In the real world, it works like that. You won't be able to consult Google for a quick answer. - A big picture of how each layer of a computer is related to the other, from hardware to software. - Write code independently. It's pointless to copy and paste code. Real learning happens when you solve problems on your own. Some examples are given to kick start, but most problems are yours to conquer. However, the solutions are available online for you to examine after giving it a good try. - Linux as a development environment and how to use common tools for low-level programming. - x86 assembly in-depth. - How a program is structured so that an operating system can run. - How to debug a program running directly on hardware with gdb and QEMU. - Linking and loading on bare metal x86_64, with pure C. No standard library. No runtime overhead. [Download the book](https://github.com/tuhdo/os01/blob/master/Operating_Systems_From_0_to_1.pdf) # The pedagogy of the book > You give a poor man a fish and you feed him for a day. You teach him to fish > and you give him an occupation that will feed him for a lifetime. This has been the guiding principle of the book when I was writing it. The book does not try to teach you everything, but enough to enable you to learn by yourself. The book itself, at this point, is quite "complete": once you master part 1 and part 2 (which consist of 8 chapters), you can drop the book and learn by yourself. At this point, smart readers should be able to continue on their own. For example, they can continue their journeys on [OSDev wiki](http://wiki.osdev.org/Main_Page); in fact, after you study everything in part 1 and part 2, you only meet the [minimum requirement](http://wiki.osdev.org/Required_Knowledge) by OSDev Wiki (well, not quite, the book actually goes deeper for the suggested topics). Or, if you consider developing an OS for fun is impractical, you can continue with a Linux-specific book, such as this free book [Linux Insides](https://0xax.gitbooks.io/linux-insides/content/), or other popular Linux kernel books. The book tries hard to provide you a strong foundation, and that's why part 1 and part 2 were released first. The book teaches you core concepts, such as x86 Assembly, ELF, linking and debugging on bare metal, etc., but more importantly, where such information come from. For example, instead of just teaching x86 Assembly, it also teaches how to use reference manuals from Intel. Learning to read the official manuals is important because only the hardware manufacturers themselves understand how their hardware work. If you only learn from the secondary resources because it is easier, you will never gain a complete understanding of the hardware you are programming for. Have you ever read a book on Assembly, and wondered where all the information came from? How does the author know everything he says is correct? And how one seems to magically know so much about hardware programming? This book gives pointers to such questions. As an example, you should skim through chapter 4, "x86 Assembly and C", to see how it makes use of the Intel manual, Volume 2. And in the process, it guides you how to use the official manuals. Part 3 is planned as a series of specifications that a reader will implement to complete each operating system component. It does not contain code aside from a few examples. Part 3 is just there to shorten the reader's time when reading the official manuals by giving hints where to read, explaining difficult concepts and how to use the manuals to debug. In short, the implementation is up to the reader to work on his or her own; the chapters are just like university assignments. # Prerequisites Know some circuit concepts: + Basic Concepts of Electricity: atoms, electrons, protons, neutrons, current flow. + Ohm's law However, if you know absolutely nothing about electricity, you can quickly learn it here: , by reading chapter 1 and chapter 2. C programming. In particular: + Variable and function declarations/definitions + While and for loops + Pointers and function pointers + Fundamental algorithms and data structures in C Linux basics: + Know how to navigate directory with the command line + Know how to invoke a command with options + Know how to pipe output to another program Touch typing. Since we are going to use Linux, touch typing helps. I know typing speed does not relate to problem-solving, but at least your typing speed should be fast enough not to let it get it the way and degrade the learning experience. In general, I assume that the reader has basic C programming knowledge, and can use an IDE to build and run a program. # Status: * Part 1 - Chapter 1: Complete - Chapter 2: Complete - Chapter 3: Almost. Currently, the book relies on the Intel Manual for fully explaining x86 execution environment. - Chapter 4: Complete - Chapter 5: Complete - Chapter 6: Complete * Part 2 - Chapter 7: Complete - Chapter 8: Complete * Part 3 - Chapter 9: Incomplete - Chapter 10: Incomplete - Chapter 11: Incomplete - Chapter 12: Incomplete - Chapter 13: Incomplete ... and future chapters not included yet ... In the future, I hope to expand part 3 to cover more than the first 2 parts. But for the time being, I will try to finish the above chapters first. # Sample OS [This repository](https://github.com/tuhdo/sample-os) is the sample OS of the book that is intended as a reference material for part 3. It covers 10 chapters of the "System Programming Guide" (Intel Manual Volume 3), along with a simple keyboard and video driver for input and output. However, at the moment, only the following features are implemented: - Protected mode. - Creating and managing processes with TSS (Task State Structure). - Interrupts - LAPIC. Paging and I/O are not yet implemented. I will try to implement it as the book progresses. # Contributing If you find any grammatical issues, please report it using Github Issues. Or, if some sentence or paragraph is difficult to understand, feel free to open an issue with the following title format: `[page number][type] Descriptive Title`. For example: `[pg.9][grammar] Incorrect verb usage`. `type` can be one of the following: - `Typo`: indicates typing mistake. - `Grammar`: indicates incorrect grammar usage. - `Style`: indicates a style improvement. - `Content`: indicates problems with the content. Even better, you can make a pull request with the provided book source. The main content of the book is in the file "Operating Systems: From 0 to 1.lyx". You can edit the .txt file, then I will integrate the changes manually. It is a workaround for now since Lyx can cause a huge diff which makes it impossible to review changes. The book is in development, so please bear with me if the English irritates you. I really appreciate it. Finally, if you like the project and if it is possible, please donate to help this project and keep it going. # Got questions? If you have any question related to the material or the development of the book, feel free to [open a Github issue](https://github.com/tuhdo/os01/issues/new). ================================================ FILE: _config.yml ================================================ theme: jekyll-theme-architect ================================================ FILE: book_src/Operating Systems From 0 to 1.lyx ================================================ #LyX 2.3 created this file. For more info see http://www.lyx.org/ \lyxformat 544 \begin_document \begin_header \save_transient_properties true \origin unavailable \textclass tufte-book \begin_preamble % DO NOT ALTER THIS PREAMBLE!!! % % This preamble is designed to ensure that the manual prints % out as advertised. If you mess with this preamble, % parts of the manual may not print out as expected. If you % have problems LaTeXing this file, please contact % the documentation team % email: lyx-docs@lists.lyx.org \usepackage[makeindex]{imakeidx} \makeindex[intoc] \usepackage{hyperref} % if pdflatex is used \usepackage{ifpdf} \ifpdf % set fonts for nicer pdf view \IfFileExists{lmodern.sty} {\usepackage{lmodern}}{} \fi % end if pdflatex is used % the pages of the TOC are numbered roman % and a PDF-bookmark for the TOC is added \pagenumbering{roman} \let\myTOC\tableofcontents \renewcommand{\tableofcontents}{% \pdfbookmark[1]{\contentsname}{} \myTOC \cleardoublepage \pagenumbering{arabic}} \usepackage{xcolor} % extra space for tables \newcommand{\extratablespace}[1]{\noalign{\vskip#1}} \usepackage{titlesec} \usepackage{graphicx} \definecolor{mygray}{gray}{0.3.} \definecolor{lightgray}{gray}{0.6} \definecolor{green}{rgb}{0.31, 0.78, 0.47} \definecolor{yellow}{rgb}{1.0, 0.87, 0.0} \definecolor{cyan}{rgb}{0.0, 0.72, 0.92} \hyphenation{MovCursor} \usepackage{multirow} % add numbers to chapters, sections, subsections \setcounter{secnumdepth}{4} % section format \titleformat{\section}% {\normalfont\LARGE\bfseries\color{mygray}}% format applied to label+text {\llap{\colorbox{mygray}{\parbox{3.5cm}{\hfill\color{white}\thesection}}}}% label {1em}% horizontal separation between label and title body {}% before the title body []% after the title body \titleformat{\subsection}% {\color{gray}\normalfont\large\itshape} {} {0em} {\large\thesubsection\hspace{0.6em}} [{\titlerule[0.8pt]}] \usepackage[activate={true, nocompatibility}, final, tracking=true, kerning=true, spacing=true, factor=1100, stretch=20, shrink=20]{microtype} \hyphenpenalty=10 \exhyphenpenalty=10 \doublehyphendemerits=10 \finalhyphendemerits=5000 \uchyph=0 \titleformat{\chapter}[display] {\normalfont\bfseries\color{mygray}} {\filleft\hspace*{-60pt}% \rotatebox[origin=c]{90}{% \normalfont\color{black}\Large% \textls[180]{\textsc{ }}% }\hspace{10pt}% {\setlength\fboxsep{0pt}% \colorbox{mygray}{\parbox[c][3cm][c]{3.5cm}{% \centering\color{white}\fontsize{80}{90}\fontfamily{lmtt}\selectfont\thechapter}% }}% } {10pt} {\raggedleft\Huge\itshape\bfseries\fontfamily{pzc}\selectfont} \usepackage{listings} \lstset{ basicstyle=\ttfamily, columns=fullflexible, breaklines=true, escapeinside={@|}{|@} } \usepackage{bookmark} % table of contents styling \usepackage{titletoc} \usepackage{etoolbox} \newcommand\frontformat{% \titlecontents{chapter}[0em] {\itshape}{\contentslabel{0em}} {}{\normalfont\titlerule*[1pc]{.}\contentspage}} \newcommand\mainformat{% \titlecontents{chapter}[1.4em] {\addvspace{10pt}\bfseries}{\contentslabel{1.5em}} {}{\normalfont\titlerule*[1pc]{.}\bfseries\contentspage} } \newcommand\backformat{% \titlecontents{chapter}[1.5em] {\addvspace{10pt}\itshape}{\contentslabel{1.5em}} {\hspace*{-1.5em}}{\normalfont\titlerule*[1pc]{.}\contentspage}} \titlecontents{section}[3.8em] {\itshape}{\contentslabel{2.3em}} {\hspace*{-2.3em}}{\titlerule*[1pc]{.}\contentspage} \apptocmd{\frontmatter}{\frontformat}{}{} \apptocmd{\mainmatter}{\mainformat}{}{} \apptocmd{\appendix}{\backformat}{}{} % caption customization \usepackage[font=small,labelfont=bf]{caption} \usepackage[many]{tcolorbox} \definecolor{greentitle}{RGB}{61,170,61} \definecolor{greentitleback}{RGB}{216,233,213} \newtcolorbox{shelloutput16.6}[1][]{% breakable, enhanced, title=Output, arc=0mm, auto outer arc, colback=white, boxrule=1pt, leftrule=5pt, before skip = 0mm, fonttitle=\bfseries\texttt\smaller, enlarge top initially by=5mm, width=16.6cm, attach boxed title to top left={xshift=-15.8mm,yshift=-5.72mm}, boxed title style={skin=enhancedfirst jigsaw,size=small,arc=0mm,bottom=0mm, interior style={fill=none, top color=mygray, bottom color=mygray}}, #1 } \definecolor{whitesmoke}{rgb}{0.96, 0.96, 0.96} \newtcolorbox{shelloutput}[1][]{% breakable, enhanced, colback=white, title=Output, arc=0mm, auto outer arc, boxrule=1pt, leftrule=5pt, fonttitle=\bfseries\texttt\smaller, enlarge top initially by=5mm, attach boxed title to top left={xshift=-15.8mm,yshift=-5.72mm}, boxed title style={skin=enhancedfirst jigsaw,size=small,arc=0mm,bottom=0mm, interior style={fill=none, top color=mygray, bottom color=mygray}}, #1 } \newtcolorbox{shellcommand}[1][]{% enlarge top initially by=5mm, } \RequirePackage{ragged2e} \setlength{\RaggedRightRightskip}{\z@ plus 0.01\hsize} \end_preamble \options bibliography=totoc,index=totoc,BCOR7.5mm,titlepage,captions=tableheading \use_default_options true \begin_modules eqs-within-sections figs-within-sections logicalmkup multicol shapepar algorithm2e tcolorbox theorems-ams-bytype enumitem tabs-within-sections theorems-ams-extended-bytype theorems-sec-bytype fix-cm fixltx2e \end_modules \maintain_unincluded_children false \begin_local_layout Format 7 InsetLayout CharStyle:MenuItem LyxType charstyle LabelString menu LatexType command LatexName menuitem Font Family Sans EndFont Preamble \newcommand*{\menuitem}[1]{{\sffamily #1}} EndPreamble End \end_local_layout \language english \language_package none \inputencoding auto \fontencoding global \font_roman "lmodern" "default" \font_sans "lmss" "default" \font_typewriter "lmtt" "default" \font_math "auto" "auto" \font_default_family default \use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 110 100 \font_tt_scale 100 100 \use_microtype false \use_dash_ligatures false \graphics default \default_output_format default \output_sync 1 \output_sync_macro "\synctex=1" \bibtex_command default \index_command default \paperfontsize 12 \spacing onehalf \use_hyperref true \pdf_title "LyX's Additional Features manual" \pdf_author "LyX Team" \pdf_subject "LyX's additional features documentation" \pdf_keywords "LyX, Documentation, Additional" \pdf_bookmarks true \pdf_bookmarksnumbered true \pdf_bookmarksopen false \pdf_bookmarksopenlevel 1 \pdf_breaklinks false \pdf_pdfborder false \pdf_colorlinks true \pdf_backref false \pdf_pdfusetitle false \pdf_quoted_options "linkcolor=black, citecolor=black, urlcolor=blue, filecolor=blue, pdfpagelayout=OneColumn, pdfnewwindow=true, pdfstartview=XYZ, plainpages=false" \papersize a4paper \use_geometry true \use_package amsmath 1 \use_package amssymb 1 \use_package cancel 0 \use_package esint 0 \use_package mathdots 1 \use_package mathtools 0 \use_package mhchem 1 \use_package stackrel 0 \use_package stmaryrd 0 \use_package undertilde 0 \cite_engine natbib \cite_engine_type authoryear \biblio_style plain \use_bibtopic true \use_indices false \paperorientation portrait \suppress_date false \justification true \use_refstyle 0 \use_minted 0 \notefontcolor #aa007f \index Index \shortcut idx \color #008000 \end_index \leftmargin 2cm \rightmargin 2cm \secnumdepth 2 \tocdepth 1 \paragraph_separation skip \defskip smallskip \is_math_indent 1 \math_indentation default \math_numbering_side default \quotes_style english \dynamic_quotes 0 \papercolumns 1 \papersides 2 \paperpagestyle fancy \listings_params "language=C,commentstyle={\color{lightgray}\itshape},emphstyle={\itshape},breaklines=true,basicstyle={\ttfamily},stringstyle={\color{gray}},frame=shadowbox,rulesepcolor={\color{black}}" \bullet 0 0 17 -1 \tracking_changes false \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict true \end_header \begin_body \begin_layout Title \noindent Operating Systems: \begin_inset Newline newline \end_inset From 0 to 1 \end_layout \begin_layout Author Tu, Do Hoang \end_layout \begin_layout Standard \begin_inset Newpage cleardoublepage \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash setcounter{page}{1}% Start page number with 1 \end_layout \begin_layout Plain Layout \backslash renewcommand{ \backslash thepage}{ \backslash Roman{page}}% Roman numerals for page counter \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset CommandInset toc LatexCommand tableofcontents \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash setcounter{page}{1}% Start page number with 1 \end_layout \begin_layout Plain Layout \backslash renewcommand{ \backslash thepage}{ \backslash roman{page}}% Roman numerals for page counter \end_layout \end_inset \end_layout \begin_layout Chapter* \emph on Preface \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash addcontentsline{toc}{chapter}{Preface} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left Greetings! \end_layout \begin_layout Standard \noindent You've probably asked yourself at least once how an operating system is written from the ground up. You might even have years of programming experience under your belt, yet your understanding of operating systems may still be a collection of abstract concepts not grounded in actual implementation. To those who've never built one, an operating system may seem like magic: a mysterious thing that can control hardware while handling a programmer's requests via the API of their favorite programming language. Learning how to build an operating system seems intimidating and difficult; no matter how much you learn, it never feels like you know enough. You're probably reading this book right now to gain a better understanding of operating systems to be a better software engineer. \end_layout \begin_layout Standard If that is the case, this book is for you. By going through this book, you will be able to find the missing pieces that are essential and enable you to implement your own operating system from scratch! Yes, from scratch, without going through any existing operating system layer to prove to yourself that you are an operating system developer. You may ask, \begin_inset Quotes eld \end_inset Isn't it more practical to learn the internals of Linux? \begin_inset Quotes erd \end_inset . \end_layout \begin_layout Standard Yes... \end_layout \begin_layout Standard and no. \end_layout \begin_layout Standard Learning Linux can help your workflow at your day job. However, if you follow that route, you still won't achieve the ultimate goal of writing an actual operating system. By writing your own operating system, you will gain knowledge that you will not be able to glean just from learning Linux. \end_layout \begin_layout Standard Here's a list of some benefits of writing your own OS: \end_layout \begin_layout Itemize You will learn how a computer works at the hardware level, and you will learn to write software to manage that hardware directly. \end_layout \begin_layout Itemize You will learn the fundamentals of operating systems, allowing you to adapt to any operating system, not just Linux \end_layout \begin_layout Itemize To hack on Linux internals suitably, you'll need to write at least one operating system on your own. This is just like applications programming: to write a large application, you'll need to start with simple ones. \end_layout \begin_layout Itemize You will open pathways to various low-level programming domains such as reverse engineering, exploits, building virtual machines, game console emulation and more. Assembly language will become one of your most indispensable tools for low-level analysis. (But that does not mean you have to write your operating system in Assembly!) \end_layout \begin_layout Itemize Writing an operating system is fun! \end_layout \begin_layout Section* \emph on Why another book on Operating Systems? \end_layout \begin_layout Standard There are many books and courses on this topic made by famous professors and experts out there already. Who am I to write a book on such an advanced topic? While it's true that many quality resources exist, I find them lacking. Do any of them show you how to compile your C code and the C runtime library independent of an existing operating system? Most books on operating system design and implementation only discuss the software side; how the operating system communicates with the hardware is skipped. Important hardware details are skipped, and it's difficult for a self-learner to find relevant resources on the Internet. The aim of this book is to bridge that gap: not only will you learn how to program hardware directly, but also how to read official documents from hardware vendors to program it. You no longer have to seek out resources to help yourself interpret hardware manuals and documentation: you can do it yourself. Lastly, I wrote this book from an autodidact's perspective. I made this book as self-contained as possible so you can spend more time learning and less time guessing or seeking out information on the Internet. \end_layout \begin_layout Standard One of the core focuses of this book is to guide you through the process of reading official documentation from vendors to implement your software. Official documents from hardware vendors like Intel are critical for implementi ng an operating system or any other software that directly controls the hardware. At a minimum, an operating system developer needs to be able to comprehend these documents and implement software based on a set of hardware requirements. Thus, the first chapter is dedicated to discussing relevant documents and their importance. \end_layout \begin_layout Standard Another distinct feature of this book is that it is \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset centric. Most examples revolve around variants of a \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset program, which will acquaint you with core concepts. These concepts must be learned before attempting to write an operating system. Anything beyond a simple \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset example gets in the way of teaching the concepts, thus lengthening the time spent on getting started writing an operating system. \end_layout \begin_layout Standard Let's dive in. With this book, I hope to provide enough foundational knowledge that will open doors for you to make sense of other resources. This book will be beneficial to students who've just finished their first C/C++ course greatly. Imagine how cool it would be to show prospective employers that you've already built an operating system. \end_layout \begin_layout Section* \emph on Prerequisites \end_layout \begin_layout Itemize Basic knowledge of circuits \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize Basic Concepts of Electricity: atoms, electrons, proton, neutron, current flow. \end_layout \begin_layout Itemize Ohm's law \end_layout \begin_layout Standard If you are unfamiliar with these concepts, you can quickly learn them here: \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://www.allaboutcircuits.com/textbook/ \end_layout \end_inset , by reading chapter 1 and chapter 2. \end_layout \end_deeper \begin_layout Itemize C programming. In particular: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize Variable and function declarations/definitions \end_layout \begin_layout Itemize While and for loops \end_layout \begin_layout Itemize Pointers and function pointers \end_layout \begin_layout Itemize Fundamental algorithms and data structures in C \end_layout \end_deeper \begin_layout Itemize Linux basics: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize Know how to navigate directory with the command line \end_layout \begin_layout Itemize Know how to invoke a command with options \end_layout \begin_layout Itemize Know how to pipe output to another program \end_layout \end_deeper \begin_layout Itemize Touch typing. Since we are going to use Linux, touch typing helps. I know typing speed does not relate to problem-solving, but at least your typing speed should be fast enough not to let it get in the way and degrade the learning experience. \end_layout \begin_layout Standard In general, I assume that the reader has basic C programming knowledge, and can use an IDE to build and run a program. \end_layout \begin_layout Section* \emph on What you will learn in this book \end_layout \begin_layout Itemize How to write an operating system from scratch by reading hardware datasheets. In the real world, you will not be able to consult Google for a quick answer. \end_layout \begin_layout Itemize Write code independently. It's pointless to copy and paste code. Real learning happens when you solve problems on your own. Some examples are provided to help kick start your work, but most problems are yours to conquer. However, the solutions are available online for you after giving a good try. \end_layout \begin_layout Itemize A big picture of how each layer of a computer related to each other, from hardware to software. \end_layout \begin_layout Itemize How to use Linux as a development environment and common tools for low-level programming. \end_layout \begin_layout Itemize How a program is structured so that an operating system can run. \end_layout \begin_layout Itemize How to debug a program running directly on hardware with \family typewriter gdb \family default and QEMU. \end_layout \begin_layout Itemize Linking and loading on bare metal x86_64, with pure C. No standard library. No runtime overhead. \end_layout \begin_layout Section* \emph on What this book is not about \end_layout \begin_layout Itemize \begin_inset Flex NewThought status open \begin_layout Plain Layout Electrical Engineering \end_layout \end_inset : The book discusses some concepts from electronics and electrical engineering only to the extent of how software operates on bare metal. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout How to use Linux or any OS types of books \end_layout \end_inset : Though Linux is used as a development environment and as a medium to demonstra te high-level operating system concepts, it is not the focus of this book. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout Linux Kernel development \end_layout \end_inset : There are already many high-quality books out there on this subject. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout Operating system books focused on algorithms \end_layout \end_inset : This book focuses more on actual hardware platform - Intel x86_64 - and how to write an OS that utilizes of OS support from the hardware platform. \end_layout \begin_layout Section* The organization of the book \end_layout \begin_layout Description Part \begin_inset space ~ \end_inset 1 provides a foundation for learning operating system. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize Chapter 1 briefly explains the importance of domain documents. Documents are crucial for the learning experience, so they deserve a chapter. \end_layout \begin_layout Itemize Chapter 2 explains the layers of abstractions from hardware to software. The idea is to provide insight into how code runs physically. \end_layout \begin_layout Itemize Chapter 3 provides the general architecture of a computer, then introduces a sample computer model that you will use to write an operating system. \end_layout \begin_layout Itemize Chapter 4 introduces the x86 assembly language through the use of the Intel manuals, along with commonly used instructions. This chapter gives detailed examples of how high-level syntax corresponds to low-level assembly, enabling you to read generated assembly code comfortably. It is necessary to read assembly code when debugging an operating system. \end_layout \begin_layout Itemize Chapter 5 dissects ELF in detail. Only by understanding how the structure of a program at the binary level, you can build one that runs on bare metal. \end_layout \begin_layout Itemize Chapter 6 introduces \family typewriter gdb \family default debugger with extensive examples for commonly used commands. After acquainting the reader with \family typewriter gdb \family default , it then provides insight on how a debugger works. This knowledge is essential for building a debuggable program on the bare metal. \end_layout \end_deeper \begin_layout Description Part \begin_inset space ~ \end_inset 2 presents how to write a bootloader to bootstrap a kernel. Hence the name \emph on \begin_inset Quotes eld \end_inset Groundwork \begin_inset Quotes erd \end_inset \emph default . After mastering this part, the reader can continue with the next part, which is a guide for writing an operating system. However, if the reader does not like the presentation, he or she can look elsewhere, such as OSDev Wiki: \begin_inset Flex URL status open \begin_layout Plain Layout http://wiki.osdev.org/ \end_layout \end_inset . \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize Chapter 7 introduces what the bootloader is, how to write one in assembly, and how to load it on QEMU, a hardware emulator. This process involves typing repetitive and long commands, so GNU Make is applied to improve productivity by automating the repetitive parts and simplifying the interaction with the project. This chapter also demonstrates the use of GNU Make in context. \end_layout \begin_layout Itemize Chapter 8 introduces linking by explaining the relocation process when combining object files. In addition to a bootloader and an operating system written in C, this is the last piece of the puzzle required for building debuggable programs on bare metal, including the bootloader written in Assembly and an operating system written in C. \end_layout \end_deeper \begin_layout Description Part \begin_inset space ~ \end_inset 3 provides guidance on how to write an operating system, as you should implement an operating system on your own and be proud of your creation. The guidance consists of simpler and coherent explanations of necessary concepts, from hardware to software, to implement the features of an operating system. Without such guidance, you will waste time gathering information spread through various documents and the Internet. It then provides a plan on how to map the concepts to code. \end_layout \begin_layout Section* \emph on Acknowledgments \end_layout \begin_layout Standard Thank you, my beloved family. Thank you, the contributors. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash mainmatter \end_layout \begin_layout Plain Layout \backslash renewcommand{ \backslash thepage}{ \backslash arabic{page}}% Arabic numerals for page counter \end_layout \begin_layout Plain Layout \backslash setcounter{page}{1}% Start page number with 2 \end_layout \end_inset \end_layout \begin_layout Part Preliminary \end_layout \begin_layout Chapter Domain documents \end_layout \begin_layout Section Problem domains \end_layout \begin_layout Standard In the real world, software engineering is not only focused on software, but also the problem domain it is trying to solve. \end_layout \begin_layout Quote A \emph on \begin_inset Index idx status open \begin_layout Plain Layout problem domain \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on problem domain \end_layout \end_inset problem domain \emph default is \emph on the part of the world \emph default where the computer is to produce effects, together with the means available to produce them, directly or indirectly. \begin_inset CommandInset citation LatexCommand citep key "Kovitz_psr" literal "true" \end_inset \end_layout \begin_layout Standard A \emph on problem domain \begin_inset Index idx status open \begin_layout Plain Layout problem domain \end_layout \end_inset \emph default is anything outside of programming that a software engineer needs to understand to produce correct code that can achieve the desired effects. \begin_inset Quotes eld \end_inset Directly \begin_inset Quotes erd \end_inset means include anything that the software can control to produce the desired effects, e.g. keyboards, printers, monitors, other software, etc. \begin_inset Quotes eld \end_inset Indirectly \begin_inset Quotes erd \end_inset means anything not part of the software but relevant to the problem domain e.g. appropriate people to be informed by the software when some event happens, students that move to correct classrooms according to the schedule generated by the software. To write a finance application, a software engineer needs to learn sufficient finance concepts to understand the \begin_inset Marginal status open \begin_layout Plain Layout \series bold requirements \end_layout \end_inset \emph on \begin_inset Index idx status open \begin_layout Plain Layout requirements \end_layout \end_inset requirements \emph default of a customer and implement such requirements, correctly. \end_layout \begin_layout Quote Requirements are the effects that the machine is to exert in the problem domain by virtue of its programming. \end_layout \begin_layout Standard Programming alone is not too complicated; programming to solve a problem domain, is \begin_inset Foot status collapsed \begin_layout Plain Layout We refer to the concept of \begin_inset Quotes eld \end_inset programming \begin_inset Quotes erd \end_inset here as someone able to write code in a language, but not necessary know any or all software engineering knowledge. \end_layout \end_inset . Not only a software engineer needs to understand how to implement the software, but also the problem domain that it tries to solve, which might require in-depth expert knowledge. The software engineer must also select the right programming techniques that apply to the problem domain he is trying to solve because many techniques that are effective in one domain might not be in another. For example, many types of applications do not require performant written code, but a short time to market. In this case, interpreted languages are widely popular because it can satisfy such need. However, for writing huge 3D games or operating system, compiled languages are dominant because it can generate the most efficient code required for such applications. \end_layout \begin_layout Standard Often, it is too much for a software engineer to learn non-trivial domains (that might require a bachelor degree or above to understand the domains). Also, it is easier for a \emph on \begin_inset Index idx status open \begin_layout Plain Layout domain expert \end_layout \end_inset domain expert \emph default to learn enough programming to break down the problem domain into parts small enough for the software engineers to implement. Sometimes, domain experts implement the software themselves. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Problem domains: Software and Non-software. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/01/domains_general.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard One example of such scenario is the domain that is presented in this book: \emph on operating system \emph default . A certain amount of electrical engineering (EE) knowledge is required to implement an operating system. If a computer science (CS) curriculum does not include minimum EE courses, students in the curriculum have little chance to implement a working operating system. Even if they can implement one, either they need to invest a significant amount of time to study on their own, or they fill code in a predefined framework just to understand high-level algorithms. For that reason, EE students have an easier time to implement an OS, as they only need to study a few core CS courses. In fact, only \emph on \begin_inset Quotes eld \end_inset C programming \begin_inset Quotes erd \end_inset \emph default and \emph on \begin_inset Quotes eld \end_inset Algorithms and Data Structures \begin_inset Quotes erd \end_inset \emph default classes are usually enough to get them started writing code for device drivers, and later generalize it into an \emph on operating system. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status collapsed \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Operating System domain. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/01/domains_os_example.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard One thing to note is that software is its own problem domain. A problem domain does not necessarily divide between software and itself. Compilers, 3D graphics, games, cryptography, artificial intelligence, etc., are parts of software engineering domains (actually it is more of a computer science domain than a software engineering domain). In general, a software-exclusive domain creates software to be used by other software. Operating System is also a domain, but is overlapped with other domains such as electrical engineering. To effectively implement an operating system, it is required to learn enough of the external domain. How much learning is enough for a software engineer? At the minimum, a software engineer should be knowledgeable enough to understand the documents prepared by hardware engineers for using (i.e. programming) their devices. \end_layout \begin_layout Standard Learning a programming language, even C or Assembly, does not mean a software engineer can automatically be good at hardware programming or any related low-level programming domains. One can spend 10 years, 20 years or his entire life writing C/C++ code, and he still cannot write an operating system, simply because of the ignorance of relevant domain knowledge. Just like learning English does not mean a person automatically becomes good at reading Math books written in English. Much more than that is needed. Knowing one or two programming languages is not enough. If a programmer writes software for a living, he had better be specialized in one or two problem domains outside of software if he does not want his job taken by domain experts who learn programming in their spare time. \end_layout \begin_layout Section Documents for implementing a problem domain \end_layout \begin_layout Standard Documents are essential for learning a problem domain (and actually, anything) since information can be passed down in a reliable way. It is evident that this written text has been used for thousands of years to pass knowledge from generation to generation. Documents are integral parts of non-trivial projects. Without the documents: \end_layout \begin_layout Itemize New people will find it much harder to join a project. \end_layout \begin_layout Itemize It is harder to maintain a project because people may forget important unresolve d bugs or quirks in their system. \end_layout \begin_layout Itemize It is challenging for customers to understand the product they are going to use. However, documents do not need to be written in book format. It can be anything from HTML format to database format to be displayed by a graphical user interface. Important information must be stored somewhere safe, readily accessible. \end_layout \begin_layout Standard There are many types of documents. However, to facilitate the understanding of a problem domain, these two documents need to be written: \emph on software requirement document \emph default and \emph on software specification \emph default . \end_layout \begin_layout Subsection Software Requirement Document \end_layout \begin_layout Standard \emph on \begin_inset Index idx status open \begin_layout Plain Layout Software requirement document \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Software requirement \end_layout \end_inset Software requirement document \emph default includes both a list of requirements and a description of the problem domain \begin_inset CommandInset citation LatexCommand citep key "Kovitz_psr" literal "true" \end_inset . \end_layout \begin_layout Standard A software solves a business problem. But, which problems to solve, are requested by a customer. Many of these requests make a list of requirements that our software needs to fulfill. However, an enumerated list of features is seldom useful in delivering software. As stated in the previous section, the tricky part is not programming alone but programming according to a problem domain. The bulk of software design and implementation depends upon the knowledge of the problem domain. The better understood the domain, the higher quality software can be. For example, building a house is practiced over thousands of years and is well understood, and it is easy to build a high-quality house; software is no different. Code that is difficult to understand is usually due to the author's ignorance of a problem domain. In the context of this book, we seek to understand the low-level working of various hardware devices. \end_layout \begin_layout Standard Because software quality depends upon the understanding of the problem domain, the amount of software requirement document should consist of problem domain description. \end_layout \begin_layout Standard Be aware that software requirements are not: \end_layout \begin_layout Description What \begin_inset space ~ \end_inset vs \begin_inset space ~ \end_inset How \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset Quotes eld \end_inset what \begin_inset Quotes erd \end_inset and \begin_inset Quotes eld \end_inset how \begin_inset Quotes erd \end_inset are vague terms. What is the \begin_inset Quotes eld \end_inset what \begin_inset Quotes erd \end_inset ? Is it nouns only? If so, what if a customer requires his software to perform specific steps of operations, such as purchasing procedure for a customer on a website. Does it include \begin_inset Quotes eld \end_inset verbs \begin_inset Quotes erd \end_inset now? However, isn't the \begin_inset Quotes eld \end_inset how \begin_inset Quotes erd \end_inset supposed to be step by step operations? Anything can be the \begin_inset Quotes eld \end_inset what \begin_inset Quotes erd \end_inset and anything can be the \begin_inset Quotes eld \end_inset how \begin_inset Quotes erd \end_inset . \end_layout \end_deeper \begin_layout Description Sketches \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Software requirement document is all about the problem domain. It should not be a high-level description of an implementation. Some problems might seem straightforward to map directly from its domain description to the structure of an implementation. For example: \end_layout \begin_layout Itemize Users are given a list of books in a \series bold \emph on drop-down menu \series default \emph default to choose. \end_layout \begin_layout Itemize Books are stored in a \series bold \emph on linked list \series default \emph default \begin_inset Quotes erd \end_inset . \end_layout \begin_layout Itemize etc \end_layout \begin_layout Standard In the future, instead of a drop-down menu, all books are listed directly on a page in thumbnails. Books might be reimplemented as a graph, and each node is a book for finding related books, as a recommender is going to be added in the next version. The requirement document needs updating again to remove all the outdated implementation details, thus required additional efforts to maintain the requirement document, and when the effort for syncing with the implementation is too much, the developers give up documentation, and everyone starts ranting how useless documentation is. \end_layout \begin_layout Standard More often than not there is no straightforward one-to-one mapping. For example, a regular computer user expects an OS to be something that runs some program with GUI, or their favorite computer games. But for such requirements, an operating system is implemented as multiple layers, each hiding the details from the upper layers. To implement an operating system, a large body of knowledge from multiple fields is required, especially if the operating system runs on non-PC devices. \end_layout \begin_layout Standard It's best to include information related to the problem domain in the requiremen t document. A good way to test the quality of a requirement document is to provide it to a domain expert for proofreading, to ensure he can understand the material thoroughly. A requirement document is also useful as a help document later, or for writing one much easier. \end_layout \end_deeper \begin_layout Subsection Software Specification \end_layout \begin_layout Standard \emph on \begin_inset Index idx status open \begin_layout Plain Layout Software specification \end_layout \end_inset \emph default \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Software specification \end_layout \end_inset \emph on Software specification \emph default document states rules relating desired behavior of the output devices to all possible behavior of the input devices, as well as any rules that other parts of the problem domain must obey. \begin_inset CommandInset citation LatexCommand cite key "Kovitz_psr" literal "true" \end_inset \end_layout \begin_layout Standard Simply put, software specification is interface design, with constraints for the problem domain to follow e.g. the software can accept certain types of input such as the software is designed to accept English but no other language. For a hardware device, a specification is always needed, as software depends on its hardwired behaviors. And in fact, it is mostly the case that hardware specifications are well-define d, with the tiniest details in it. It needs to be that way because once hardware is physically manufactured, there's no going back, and if defects exist, it's a devastating damage to the company on both finance and reputation. \end_layout \begin_layout Standard Note that, similar to a requirement document, a specification only concerns interface design. If implementation details leak in, it is a burden to sync between the actual implementation and the specification, and soon to be abandoned. \end_layout \begin_layout Standard Another important remark is that, though a specification document is important, it does not have to be produced \emph on before \emph default the implementation. It can be prepared in any order: before or after a complete implementation; or at the same time with the implementation, when some part is done, and the interface is ready to be recorded in the specification. Regardless of methods, what matter is a complete specification at the end. \end_layout \begin_layout Section Documents for writing an x86 Operating System \end_layout \begin_layout Standard When problem domain is different from software domain, requirement document and specification are usually separated. However, if the problem domain is inside software, specification most often includes both, and content of both can be mixed with each other. As demonstrated by previous sections the importance of documents, to implement an OS, we will need to collect relevant documents to gain sufficient domain knowledge. These documents are as follow: \end_layout \begin_layout Itemize Intel® 64 and IA-32 Architectures Software Developer’s Manual (Volume 1, 2, 3) \end_layout \begin_layout Itemize Intel® 3 Series Express Chipset Family Datasheet \end_layout \begin_layout Itemize System V Application Binary Interface \end_layout \begin_layout Standard Aside from the Intel's official website, the website of this book also hosts the documents for convenience \begin_inset Foot status collapsed \begin_layout Plain Layout Intel may change the links to the documents as they update their website, so this book doesn't contain any link to the documents to avoid confusion for readers. \end_layout \end_inset . \end_layout \begin_layout Standard Intel documents divide the requirement and specification sections clearly, but call the sections with different names. The corresponding to the requirement document is a section called \emph on \begin_inset Quotes eld \end_inset Functional Description \begin_inset Quotes erd \end_inset \emph default , which consists mostly of domain description; for specification, \emph on \begin_inset Quotes eld \end_inset Register Description \begin_inset Quotes erd \end_inset \emph default section describes all programming interfaces. Both documents carry no unnecessary implementation details \begin_inset Foot status collapsed \begin_layout Plain Layout As it should be, those details are trade secret. \end_layout \end_inset . Intel documents are also great examples of how to write well requirements/speci fications, as explained in this chapter. \end_layout \begin_layout Standard Other than the Intel documents, other documents will be introduced in the relevant chapters. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash chapter[From hardware to software: Layers of abstraction]{From hardware to software: \backslash \backslash Layers of abstraction} \end_layout \end_inset \end_layout \begin_layout Standard This chapter gives an intuition on how hardware and software connected together, and how software is represented physically. \end_layout \begin_layout Section The physical implementation of a bit \end_layout \begin_layout Standard All electronic devices, from simple to complex, manipulate this flow to achieve desired effects in the real world. Computers are no exception. When we write software, we indirectly manipulate electrical current at the physical level, in such a way that the underlying machine produces desired effects. To understand the process, we consider a simple light bulb. A light bulb can change two states between on and off with a switch, periodical ly: an off means number 0, and an on means 1. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout A lightbulb \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/02/bulb.svg scale 15 \end_inset \end_layout \end_inset \end_layout \begin_layout Standard However, one problem is that such a switch requires manual intervention from a human. What is required is an automatic switch based on the voltage level, as described above. To enable automatic switching of electrical signals, a device called \emph on transistor \emph default , invented by William Shockley, John Bardeen and Walter Brattain. This invention started the whole computer industry. \end_layout \begin_layout Standard At the core, a \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on transistor \end_layout \end_inset transistor \begin_inset Index idx status open \begin_layout Plain Layout transistor \end_layout \end_inset \emph default is just a resistor whose values can vary based on an input voltage value. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Modern transistor \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/02/transistor.svg scale 25 \end_inset \end_layout \end_inset With this property, a transistor can be used as a current amplifier (more voltage, less resistance) or switch electrical signals off and on (block and unblock an electron flow) based on a voltage level. At 0 \begin_inset space \thinspace{} \end_inset v, no current can pass through a transistor, thus it acts like a circuit with an open switch (light bulb off) because the resistor value is enough to block the electrical flow. Similarly, at +3.5 \begin_inset space \thinspace{} \end_inset v, current can flow through a transistor because the resistor value is lessened, effectively enables electron flow, thus acts like a circuit with a closed switch. \begin_inset Marginal status collapsed \begin_layout Plain Layout If you want a deeper explanation of transistors e.g. how electrons move, you should look at the video \begin_inset Quotes eld \end_inset How semiconductors work \begin_inset Quotes erd \end_inset on Youtube, by Ben Eater. \end_layout \end_inset \end_layout \begin_layout Standard A bit has two states: 0 and 1, which is the building block of all digital systems and software. Similar to a light bulb that can be turned on and off, bits are made out of this electrical stream from the power source: Bit 0 are represented with 0 \begin_inset space \thinspace{} \end_inset v (no electron flow), and bit 1 is +3.5 \begin_inset space \thinspace{} \end_inset v to +5 \begin_inset space \thinspace{} \end_inset v (electron flow). Transistor implements a bit correctly, as it can regulate the electron flow based on voltage level. \end_layout \begin_layout Subsection MOSFET transistors \end_layout \begin_layout Standard The classic transistors invented open a whole new world of micro digital devices. Prior to the invention, vacuum tubes - which are just fancier light bulbs - were used to present 0 and 1, and required human to turn it on and off. \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on MOSFET \end_layout \end_inset \emph on \begin_inset Index idx status open \begin_layout Plain Layout MOSFET \end_layout \end_inset MOSFET \emph default , or \series bold \emph on M \series default etal– \series bold O \series default xide– \series bold S \series default emiconductor \series bold F \series default ield- \series bold E \series default ffect \series bold T \series default ransistor \emph default , invented in 1959 by Dawon Kahng and Martin M. (John) Atalla at Bell Labs, is an improved version of classic transistors that is more suitable for digital devices, as it requires shorter switching time between two states 0 and 1, more stable, consumes less power and easier to produce. \end_layout \begin_layout Standard There are also two types of MOSFETs analogous to two types of transistors: n-MOSFET and p-MOSFET. n-MOSFET and p-MOSFET are also called NMOS and PMOS transistors for short. \end_layout \begin_layout Section Beyond transistors: digital logic gates \end_layout \begin_layout Standard All digital devices are designed with logic gates. A \emph on \begin_inset Index idx status open \begin_layout Plain Layout logic gate \end_layout \end_inset \emph default \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on logic gate \end_layout \end_inset \emph on logic gate \emph default is a device that implements a boolean function. Each logic gate includes a number of inputs and an output. All computer operations are built from the combinations of logic gates, which are just combinations of boolean functions. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Example: NAND gate \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/02/Nand-gate.svg scale 30 \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Subsection The theory behind logic gates \end_layout \begin_layout Standard Logic gates accept only binary inputs \begin_inset Foot status collapsed \begin_layout Plain Layout Input that is either a 0 or 1. \end_layout \end_inset and produce binary outputs. In other words, logic gates are functions that transform binary values. Fortunately, a branch of math that deals exclusively with binary values already existed, called \emph on Boolean Algebra \emph default , developed in the 19 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset century by George Boole. With a sound mathematical theory as a foundation logic gates were created \emph on . \emph default As logic gates implement Boolean functions, a set of Boolean functions is \begin_inset Index idx status collapsed \begin_layout Plain Layout functionally complete \end_layout \end_inset \begin_inset Marginal status collapsed \begin_layout Plain Layout \series bold \emph on functionally complete \end_layout \end_inset \emph on functionally complete \emph default , if this set can construct all other Boolean functions can be constructed from. Later, Charles Sanders Peirce (during 1880 – 1881) proved that either Boolean function of NOR or NAND alone is enough to create all other Boolean logic functions. Thus NOR and NAND gates are functionally complete \begin_inset CommandInset citation LatexCommand cite key "Peirce" literal "true" \end_inset . Gates are simply the implementations of Boolean logic functions, therefore NAND or NOR gate is enough to implement \series bold \emph on all \series default \emph default other logic gates. The simplest gates CMOS circuit can implement are inverters (NOT gates) and from the inverters, comes NAND gates. With NAND gates, we are confident to implement everything else. This is why the inventions of transistors, then CMOS circuit revolutionized computer industry. \begin_inset Marginal status collapsed \begin_layout Plain Layout If you want to understand why and how from NAND gate we can create all Boolean functions and a computer, I suggest the course \emph on Build a Modern Computer from First Principles: From Nand to Tetris \emph default available on Coursera: \begin_inset Flex URL status open \begin_layout Plain Layout https://www.coursera.org/learn/build-a-computer \end_layout \end_inset . Go even further, after the course, you should take the series \emph on Computational Structures \emph default on Edx. \end_layout \end_inset \end_layout \begin_layout Standard We should realize and appreciate how powerful boolean functions are available in all programming languages. \end_layout \begin_layout Subsection Logic Gate implementation: CMOS circuit \end_layout \begin_layout Standard Underlying every logic gate is a circuit called \series bold \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on CMOS \end_layout \end_inset CMOS \series default \emph default \begin_inset Index idx status open \begin_layout Plain Layout \emph on CMOS \end_layout \end_inset - \series bold \emph on C \series default omplementary \series bold MOS \series default FET \emph default . CMOS consists of two complementary transistors, \emph on NMOS \emph default and \emph on PMOS. \emph default The simplest CMOS circuit is an inverter or a \emph on NOT \emph default gate: \end_layout \begin_layout Standard \begin_inset VSpace vfill \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Electron flows of an inverter. Input is on the left side and output on the right side. The upper component is a PMOS and the lower component is a NMOS, both connect to the input and output. (Source: Created with \backslash url{http://www.falstad.com/circuit/})} \end_layout \begin_layout Plain Layout \backslash subfloat[When input is low]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.6]{images/02/inverter-0}} \backslash hfill{} \backslash subfloat[When input is high]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.6]{images/02/inverter-1}} \end_layout \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Standard From NOT gate, a NAND gate can be created: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \backslash caption{Electron flows of a NAND gate.} \end_layout \begin_layout Plain Layout \backslash subfloat[Input = 00, Ouput = 1]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.52]{images/02/nand-00}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[Input = 01, Ouput = 1]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.52]{images/02/nand-01}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[Input = 10, Output = 1]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.52]{images/02/nand-10}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[Input = 11, Output = 0]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.52]{images/02/nand-11}} \end_layout \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Standard From NAND gate, we have all other gates. As demonstrated, such a simple circuitry performs the logical operators in day-to-day program languages e.g. NOT operator \family typewriter ~ \family default is executed directly by an inverter circuit, and operator \family typewriter & \family default is executed by an AND circuit and so on. Code does not run on a magic black box. In contrast, code execution is precise and transparent, often as simple as running some hardwired circuit. When we write software, we simply manipulate electrical current at the physical level to run appropriate circuits to produce desired outcomes. However, this whole process somehow does not relate to any thought involving electrical current. That is the real magic and will be explained soon. \end_layout \begin_layout Standard One interesting property of CMOS is that \series bold \emph on a k-input gate uses k PMOS and k NMOS transistors \series default \emph default \begin_inset CommandInset citation LatexCommand citep key "John_digital" literal "true" \end_inset . All logic gates are built by pairs of NMOS and PMOS transistors, and gates are the building blocks of all digital devices from simple to complex, including any computer. Thanks to this pattern, it is possible to separate between the actual physical circuit implementation and logical implementation. Digital designs are done by designing with logic gates then later be \begin_inset Quotes eld \end_inset compiled \begin_inset Quotes erd \end_inset into physical circuits. In fact, later we will see that logic gates become a language that describes how circuits operate. Understanding how CMOS works is important to understand how a computer is designed, and as a consequence, how a computer works \begin_inset Foot status collapsed \begin_layout Plain Layout Again, if you want to understand how logic gates make a computer, consider the suggested courses on Coursera and Edx earlier. \end_layout \end_inset . \end_layout \begin_layout Standard Finally, an implemented circuit with its wires and transistors is stored physically in a package called a \emph on chip \emph default . A \emph on chip \begin_inset Index idx status open \begin_layout Plain Layout chip \end_layout \end_inset \emph default is a substrate that an integrated circuit is etched onto. However, a chip also refers to a completely packaged integrated circuit in consumer market. Depends on the context, it is understood differently. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout 74HC00 chip physical view \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/02/74hc00_nxp_physical.jpg scale 60 \end_inset \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example 74HC00 is a chip with four 2-input NAND gates. The chip comes with 8 input pins and 4 output pins, 1 pin for connecting to a voltage source and 1 pin for connecting to the ground. This device is the physical implementation of NAND gates that we can physically touch and use. But instead of just a single gate, the chip comes with 4 gates that can be combined. Each combination enables a different logic function, effective creating other logic gates. This feature is what make the chip popular. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout 74HC00 logic diagrams (Source: 74HC00 datasheet, \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://www.scrpdf.com/pdf/Semiconductors_new/Logic/74HCT/74HC_HCT00.pdf \end_layout \end_inset ) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Logic diagram of 74HC00 \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/02/7400_block_diagram.png \end_inset \end_layout \end_inset \begin_inset space \hfill{} \end_inset \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Logic diagram of one NAND gate \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/02/7400_logic_diagram.png \end_inset \end_layout \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Each of the gates above is just a simple NAND circuit with the electron flows, as demonstrated earlier. Yet, many these NAND-gates chips combined can build a simple computer. Software, at the physical level, is just electron flows. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Gates built from NAND gates, each accepts 2 input signals and generate 1 output signal.} \end_layout \begin_layout Plain Layout \backslash subfloat[NOT gate]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.5]{images/02/not-gate}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[AND gate]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.5]{images/02/and-gate}} \backslash hfill{} \backslash \backslash [0.5cm] \end_layout \begin_layout Plain Layout \backslash subfloat[OR gate]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.5]{images/02/or-gate}} \backslash qquad \end_layout \begin_layout Plain Layout \backslash subfloat[NOR gate]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.5]{images/02/nor-gate}} \end_layout \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Standard How can the above gates be created with 74HC00? It is simple: as every gate has 2 input pins and 1 output pin, we can write the output of 1 NAND gate to an input of another NAND gate, thus chaining NAND gates together to produce the diagrams as above. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Section Beyond Logic Gates: Machine Language \end_layout \begin_layout Subsection Machine language \end_layout \begin_layout Standard Being built upon gates, as gates only accept a series of 0 and 1, a hardware device only understands 0 and 1. However, a device only takes 0 and 1 in a systematic way. \emph on \begin_inset Marginal status collapsed \begin_layout Plain Layout \series bold \emph on Machine language \end_layout \end_inset Machine language \begin_inset Index idx status collapsed \begin_layout Plain Layout Machine language \end_layout \end_inset \emph default is a collection of unique bit patterns that a device can identify and perform a corresponding action. A \emph on machine instruction \emph default is a unique bit pattern that a device can identify. In a computer system, a device with its language is called \series bold \emph on CPU \series default - \series bold C \series default entral \series bold P \series default rocessing \series bold U \series default nit \emph default , which controls all activities going inside a computer. For example, in the x86 architecture, the pattern \family typewriter 10100000 \family default means telling a CPU to add two numbers, or \family typewriter 000000101 \family default to halt a computer. In the early days of computers, people had to write completely in binary. \end_layout \begin_layout Standard Why does such a bit pattern cause a device to do something? The reason is that underlying each instruction is a small circuit that implements the instruction. Similar to how a function/subroutine in a computer program is called by its name, a bit pattern is a name of a little function inside a CPU that got executed when the CPU finds one. \end_layout \begin_layout Standard Note that CPU is not the only device with its language. CPU is just a name to indicate a hardware device that controls a computer system. A hardware device may not be a CPU but still has its language. A device with its own machine language is a \emph on programmable device \emph default , since a user can use the language to command the device to perform different actions. For example, a printer has its set of commands for instructing it how to print a page. \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example \begin_inset CommandInset label LatexCommand label name "exa:74HC00-chip-can" \end_inset A user can use 74HC00 chip without knowing its internal, but only the interface for using the device. First, we need to know its layout: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout 74HC00 Pin Layout (Source: 74HC00 datasheet, \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://www.nxp.com/documents/data_sheet/74HC_HCT00.pdf \end_layout \end_inset ) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/02/7400_pin_configuration.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Then, the functionality of each pin: \end_layout \begin_layout Standard \begin_inset Float table wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Pin Description (Source: 74HC00 datasheet, \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://www.nxp.com/documents/data_sheet/74HC_HCT00.pdf \end_layout \end_inset ) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Symbol \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Pin \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1A to 4A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1, 4, 9, 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout data input \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1B to 4B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 2, 5, 10, 13 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout data input \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1Y to 4Y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 3, 6, 8, 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout data output \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout GND \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout ground (0 \begin_inset space \thinspace{} \end_inset V) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout V \begin_inset script subscript \begin_layout Plain Layout cc \end_layout \end_inset \begin_inset script subscript \begin_layout Plain Layout \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 14 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout supply voltage \end_layout \end_inset \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Finally, how to use the pins: \end_layout \begin_layout Standard \begin_inset Float table wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Functional Description \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Input \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Output \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold nA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold nB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold nY \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout L \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout L \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout H \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout L \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout X \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout H \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout X \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout L \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout H \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout H \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout H \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout L \end_layout \end_inset \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Marginal status collapsed \begin_layout Itemize n is a number, either 1, 2, 3, or 4 \end_layout \begin_layout Itemize H = HIGH voltage level; L = LOW voltage level; X = don’t care. \end_layout \end_inset The functional description provides a truth table with all possible pin inputs and outputs, which also describes the usage of all pins in the device. A user needs not to know the implementation, but on such a table to use the device. We can say that the truth table above is the machine language of the device. Since the device is digital, its language is a collection of binary strings: \end_layout \begin_layout Itemize The device has 8 input pins, and this means it accepts binary strings of 8 bits. \end_layout \begin_layout Itemize The device has 4 output pins, and this means it produces binary strings of 4 bits from the 8-bit inputs. \end_layout \begin_layout Standard The number of input strings is what the device understand, and the number of output strings is what the device can speak. Together, they make the language of the device. Even though this device is simple, yet the language it can accept contains quite many binary strings: \begin_inset Formula $2^{8}+2^{4}=272$ \end_inset . However, the number is a tiny fraction of a complex device like a CPU, with hundreds of pins. \end_layout \begin_layout Standard When leaving as is, 74HC00 is simply a NAND device with two 4-bit inputs \begin_inset Foot status open \begin_layout Plain Layout Or simply 4-bit NAND gate, as it can only accept 4 bits of input at the maximum. \end_layout \end_inset . \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Input \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Output \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Pin \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 1A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 1B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 2A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 2B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 3A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 3B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 4A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 4B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 1Y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 2Y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 3Y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 4Y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset VSpace medskip \end_inset \end_layout \begin_layout Standard The inputs and outputs as visually presented: \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Pins when receiving digital signals that correspond to a binary string. Green signals are inputs; blue signals are outputs. \end_layout \end_inset \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/02/7400_bin_string1.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard On the other hand, if OR gate is implemented, we can only build a 2-input OR gate from 74HC00, as it requires 3 NAND gates: 2 input NAND gates and 1 output NAND gate. Each input NAND gate represents only a 1-bit input of the OR gate. In the following figure, the pins of each input NAND gates are always set to the same values (either both inputs are A or both inputs are B) to represent a single bit input for the final OR gate: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{2-bit OR gate implementation} \end_layout \begin_layout Plain Layout \backslash subfloat[2-bit OR gate logic diagram, built from 3 NAND gates with 4 pins just \end_layout \begin_layout Plain Layout for 2 bits of input. \backslash newline]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.6]{images/02/or-gate-ex}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[Pin 3A and 3B take the values from 1Y and 2Y.]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/02/or-gate-layout-ex}} \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset VSpace bigskip \end_inset \begin_inset Float margintable wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Truth table of OR logic diagram. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Standard To implement a 4-bit OR gate, we need a total of four of 74HC00 chips configured as OR gates, packaged as a single chip as in figure \begin_inset CommandInset ref LatexCommand ref reference "or-chip-74hc00" \end_inset . \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout 4-bit OR chip made from four 74HC00 devices \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "or-chip-74hc00" \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/02/4-bit-or-gate-layout.pdf scale 41 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Subsection Assembly Language \end_layout \begin_layout Standard Assembly language is the symbolic representation of binary machine code, by giving bit patterns mnemonic names. It was a vast improvement when programmers had to write 0 and 1. For example, instead of writing \family typewriter 000000101 \family default , a programmer simply write \family typewriter hlt \family default to stop a computer. Such an abstraction makes instructions executed by a CPU easier to remember, and thus more instructions could be memorized, less time spent looking up CPU manual to find instructions in bit forms and as a result, code was written faster. \end_layout \begin_layout Standard Understand assembly language is crucial for low-level programming domains, even to this day. The more instructions a programmer want to understand, the deeper understanding of machine architecture is required. \end_layout \begin_layout Example We can build a device with 2 assembly instructions: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code or , \end_layout \begin_layout LyX-Code nand , \end_layout \begin_layout Itemize \family typewriter or \family default accepts two 4-bit operands. This corresponds to a 4-input OR gate device built from 4 74HC00 chips. \end_layout \begin_layout Itemize \family typewriter nand \family default accepts two 4-bit operands. This corresponds to a single 74HC00 chips, leave as is. \end_layout \begin_layout Standard Essentially, the gates in the example \begin_inset CommandInset ref LatexCommand ref reference "exa:74HC00-chip-can" \end_inset implements the instructions. Up to this point, we only specify input and output and manually feed it to a device. That is, to perform an operation: \end_layout \begin_layout Itemize Pick a device by hands. \end_layout \begin_layout Itemize Manually put electrical signals into pins. \end_layout \begin_layout Standard First, we want to automate the process of device selection. That is, we want to simply write assembly instruction and the device that implements the instruction is selected correctly. Solving this problem is easy: \end_layout \begin_layout Itemize Give each instruction an index in binary code, called \emph on operation code \emph default or \emph on opcode \emph default for short, and embed it as part of input. The value for each instruction is specified as in table \begin_inset CommandInset ref LatexCommand formatted reference "ex-ins-ops" \end_inset . \begin_inset Float margintable wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Instruction-Opcode mapping. \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "ex-ins-ops" \end_inset \end_layout \begin_layout Plain Layout \noindent \align center \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Instruction \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Binary Code \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter nand \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter or \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 01 \end_layout \end_inset \end_inset \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Each input now contains additional data at the beginning: an opcode. For example, the instruction: \end_layout \begin_layout LyX-Code \color red nand \color inherit 1100, 1100 \end_layout \begin_layout Standard corresponds to the binary string: \family typewriter \color red 00 \color inherit 11001100 \family default . The first two bits \family typewriter \color red 00 \family default \color inherit encodes a \family typewriter nand \family default instruction, as listed in the table above. \end_layout \end_deeper \begin_layout Itemize Add another device to select a device, based on a binary code peculiar to an instruction. \end_layout \begin_layout Standard Such a device is called a \emph on decoder \emph default , an important component in a CPU that decides which circuit to use. In the above example, when feeding \family typewriter \color red 00 \color inherit 11001100 \family default to the decoder, because the opcode is \family typewriter \color red 00 \family default \color inherit , data are sent to NAND device for computing. \end_layout \begin_layout Standard Finally, writing assembly code is just an easier way to write binary strings that a device can understand. When we write assembly code and save in a text file, a program called an \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on assembler \end_layout \end_inset assembler \begin_inset Index idx status open \begin_layout Plain Layout assembler \end_layout \end_inset \emph default translates the text file into binary strings that a device can understand. So, how can an assembler exist in the first place? Assume this is the first assembler in the world, then it is written in binary code. In the next version, life is easier: the programmers write the assembler in the assembly code, then use the first version to compile itself. These binary strings are then stored in another device that later can be retrieved and sent to a decoder. A \emph on \begin_inset Index idx status open \begin_layout Plain Layout storage device \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on storage device \end_layout \end_inset storage device \emph default is the device that stores machine instructions, which is an array of circuits for saving 0 and 1 states. \end_layout \begin_layout Standard A decoder is built out of logic gates similar to other digital devices. However, a storage device can be anything that can store 0 and 1 and is retrievable. A storage device can be a magnetized device that uses magnetism to store information, or it can be made out of electrical circuits that can change and rermember states when a voltage is applied. Regardless of the technology used, as long as the device can store data and is accessible to retrieve data, it suffices. Indeed, the modern devices are so complex that it is impossible and unnecessary to understand every implementation detail. Instead, we only need to learn the interfaces, e.g. the pins, that the devices expose. \end_layout \begin_layout Standard \begin_inset VSpace vfill \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{A decoder retrieves the current instruction pointed by the arrow and selects the NAND device to execute the \backslash texttt{nand} instruction.} \end_layout \begin_layout Plain Layout \backslash includegraphics{images/02/decoder-ex} \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard A computer essentially implements this process: \end_layout \begin_layout Itemize \emph on Fetch \emph default an instruction from a storage device. \end_layout \begin_layout Itemize \emph on Decode \emph default the instruction. \end_layout \begin_layout Itemize \emph on Execute \emph default the instruction. \end_layout \begin_layout Standard Or in short, a \begin_inset Index idx status open \begin_layout Plain Layout f@fetch – decode – execute \end_layout \end_inset fetch – decode – execute cycle. The above device is extremely rudimentary, but it already represents a computer with a \emph on fetch \emph default – \emph on decode \emph default – \emph on execute \emph default cycle. More instructions can be implemented by adding more devices and allocating more opcodes for the instructions, then update the decoder accordingly. The Apollo Guidance Computer, a digital computer produced for the Apollo space program from 1961 – 1972, was built entirely with NOR gates - the other choice to NAND gate for creating other logic gates. Similarly, if we keep improving our hypothetical device, it eventually becomes a full-fledge computer. \end_layout \end_deeper \begin_layout Subsection Programming Languages \end_layout \begin_layout Standard Assembly language is a step up from writing 0 and 1. As time goes by, people realized that many pieces of assembly code had repeating patterns of usages. It would be nice if instead of writing all the repeating blocks of code all over again in all places, we simply refer to such blocks of code with easier to use text forms. For example, a block of assembly code checks whether one variable is greater than another and if so, execute a block of code, else execute another block of code; in C, such block of assembly code is represented by an \begin_inset Flex Code status open \begin_layout Plain Layout if \end_layout \end_inset statement that is close to human language. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Repeated assembly patterns are generalized into a new language. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/02/asm_to_proglang.pdf scale 60 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard People created text forms to represent common blocks of assembly code, such as the \family typewriter if \family default syntax above, then write a program to translate the text forms into assembly code. The program that translates such text forms to machine code is called a \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on compiler \end_layout \end_inset \emph on compiler \emph default \begin_inset Index idx status open \begin_layout Plain Layout \emph on compiler \end_layout \end_inset : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{From high-level language back to low-level language.} \end_layout \begin_layout Plain Layout \backslash includegraphics{images/02/proglang_to_asm} \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard Any software logic a programming language can implement, hardware can also implement. The reverse is also true: any hardware logic that is implemented in a circuit can be reimplemented in a programming language. The simple reason is that programming languages, or assembly languages, or machine languages, or logic gates are just languages to express computations. It is impossible for software to implement something hardware is incapable of because programming language is just a simpler way to use the underlying hardware. At the end of the day, programming languages are translated to machine instructions that are valid to a CPU. Otherwise, code is not runnable, thus a useless software. In reverse, software can do everything hardware (that run the software) can, as programming languages are just an easier way to use the hardware. \end_layout \begin_layout Standard In reality, even though all languages are equivalent in power, not all of them are capable of express programs of each other. Programming languages vary between two ends of a spectrum: high level and low level. \end_layout \begin_layout Standard The higher level a programming language is, the more distant it becomes from the hardware. In some high-level programming languages, such as Python, a programmer cannot manipulate underlying hardware, despite being able to deliver the same computations as low-level programming languages. The reason is that high-level languages want to hide hardware details to free programmers from dealing with irrelevant details not related to current problem domains. Such convenience, however, is not free: it requires software to carry an extra code for managing hardware details (e.g. memory) thus making the code run slower, and it makes hardware programming difficult or impossible. The more abstractions a programming language imposes, the more difficult it is for writing low-level software, such as hardware drivers or an operating system. This is the reason why C is usually a language of choice for writing an operating system, since C is just a thin wrapper of the underlying hardware, making it easy to understand how exactly a hardware device runs when executing a certain piece of C code. \end_layout \begin_layout Standard Each programming language represents a way of thinking about programs. Higher-level programming languages help to focus on problem domains that are not related to hardware at all, and where programmer performance is more important than computer performance. Lower-level programming languages help to focus on the inner-working of a machine, thus are best suited for problem domains that are related to control hardware. That is why so many languages exist. Use the right tools for the right job to achieve the best results. \end_layout \begin_layout Standard \begin_inset Note Note status collapsed \begin_layout Plain Layout Explain the two ways to create new abstractions in programming languages \end_layout \end_inset \end_layout \begin_layout Section Abstraction \end_layout \begin_layout Standard \emph on Abstraction \begin_inset Index idx status open \begin_layout Plain Layout Abstraction \end_layout \end_inset \emph default is a technique for hiding complexity that is irrelevant to the problem in context. For example, writing programs without any other layer except the lowest layer: with circuits. Not only a person needs an in-depth understanding of how circuits work, making it much more obscure to design a circuit because the designer must look at the raw circuits but think in higher-level such as logic gates. It is a distracting process, as a designer must constantly translate the idea into circuits. It is possible for a designer simply thinks his high-level ideas straight, and later translate the ideas into circuits. Not only it is more efficient, but it is also more accurate as a designer can focus all his efforts into verifying the design with high-level thinking. When a new designer arrives, he can easily understand the high-level designs, thus can continue to develop or maintain existing systems. \end_layout \begin_layout Subsection Why abstraction works \end_layout \begin_layout Standard In all the layers, abstractions manifest itself: \end_layout \begin_layout Itemize Logic gates abstract away the details of CMOS. \end_layout \begin_layout Itemize Machine language abstracts away the details of logic gates. \end_layout \begin_layout Itemize Assembly language abstracts away the details of machine languages. \end_layout \begin_layout Itemize Programming language abstracts away the details of assembly languages. \end_layout \begin_layout Standard We see repeating patterns of how lower-layers build upper-layers: \end_layout \begin_layout Itemize A lower layer has a recurring pattern. Then, this recurring pattern is taken out and built a language on top of it. \end_layout \begin_layout Itemize A higher layer strips away layer-specific (non-recurring) details to focus on the recurring details. \end_layout \begin_layout Itemize The recurring details are given a new and simpler language than the languages of the lower layers. \end_layout \begin_layout Standard What to realize is that every layer is just \emph on a more convenient language to \series bold describe \series default the lower layer \emph default . Only after a description is fully created with the language of the higher layer, it is then be \emph on implemented \emph default with the language of the lower layer. \end_layout \begin_layout Itemize CMOS layer has a recurring pattern that makes sure logic gates are reliably translated to CMOS circuits: \series bold \emph on a k-input gate uses k PMOS and k NMOS transistors \series default \emph default \begin_inset CommandInset citation LatexCommand citep key "John_digital" literal "true" \end_inset . Since digital devices use CMOS exclusively, a language arose to describe higher level ideas while hiding CMOS circuits: Logic Gates. \end_layout \begin_layout Itemize Logic Gates hides the language of circuits and focuses on how to implement primitive Boolean functions and combine them to create new functions. All logic gates receive input and generate output as binary numbers. Thanks to this recurring patterns, logic gates are hidden away for the new language: Assembly, which is a set of predefined binary patterns that cause the underlying gates to perform an action. \end_layout \begin_layout Itemize Soon, people realized that many recurring patterns arisen from within Assembly language. Repeated blocks of Assembly code appear in Assembly source files that express the same or similar idea. There were many such ideas that can be reliably translated into Assembly code. Thus, the ideas were extracted for building into the high level programming languages that everyone programmer learns today. \end_layout \begin_layout Standard Recurring patterns are the key to abstraction. Recurring patterns are why abstraction works. Without them, no language can be built, and thus no abstraction. Fortunately, human already developed a systematic discipline for studying patterns: Mathematics. As quoted from the British mathematician G. H. Hardy \begin_inset CommandInset citation LatexCommand citeyearpar key "Hardy" literal "true" \end_inset : \end_layout \begin_layout Quote A mathematician, like a painter or a poet, is a maker of patterns. If his patterns are more permanent than theirs, it is because they are made with ideas. \end_layout \begin_layout Standard Isn't that a mathematical formula a representation of a pattern? A variable represents values with the same properties given by constraints? Mathematics provides a formal system to identify and describe existing patterns in nature. For that reason, this system can certainly be applied in the digital world, which is just a subset of the real world. Mathematics can be used as a common language to help translation between layers easier, and help with the understanding of layers. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Mathematics as a universal language for all layers. Since all layers \end_layout \begin_layout Plain Layout can express mathematics with their technologies, each layer can be \end_layout \begin_layout Plain Layout translated into another layer.} \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.5]{images/02/layer_translation} \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Subsection Why abstraction reduces complexity \end_layout \begin_layout Standard Abstraction by building language certainly leverages productivity by stripping irrelevant details to a problem. Imagine writing programs without any other layout except the lowest layer: with circuits. This is how complexity emerges: when high-level ideas are expressed with lower-level language, as the example above demonstrated. Unfortunately, this is the case with software as programming languages at the moment are more emphasized on software rather than the problem domains. That is, without prior knowledge, code written in a language is unable to express itself the knowledge of its target domain. In other words, \emph on a language is expressive if its syntax is designed to express the problem domain it is trying to solve \emph default . Consider this example: That is, the \emph on what \emph default it will do rather the \emph on how \emph default it will do. \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example Graphviz ( \begin_inset Flex URL status open \begin_layout Plain Layout http://www.graphviz.org/ \end_layout \end_inset ) is a visualization software that provides a language, called \family typewriter dot \family default , for describing graph: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{From graph description to graph.} \end_layout \begin_layout Plain Layout \backslash includegraphics{images/02/digraph} \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard As can be seen, the code perfectly expresses itself how the graph is connected. Even a non-programmer can understand and use such language easily. An implementation in C would be more troublesome, and that's assuming that the functions for drawing graphs are already available. To draw a line, in C we might write something like: \end_layout \begin_layout LyX-Code draw_line(a, b); \end_layout \begin_layout Standard However, it is still verbose compared with: \end_layout \begin_layout LyX-Code a -> b; \end_layout \begin_layout Standard Also, \family typewriter a \family default and \family typewriter b \family default must be defined in C, compared to the implicit nodes in the \family typewriter dot \family default language. However, if we do not factor in the verbosity, then C still has a limitation: it cannot change its syntax to suit the problem domain. A domain-specific language might even be more verbose, but it makes a domain more understandable. If a problem domain must be expressed in C, then it is constraint by the syntax of C. Since C is not a specialized language for a problem domain that, but is a \emph on general-purpose \emph default programming language, the domain knowledge is buried within the implementation details. As a result, a C programmer is needed to decipher and extract the domain knowledge out. If the domain knowledge cannot be extracted, then the software cannot be further developed. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example Linux is full of applications controlled by many domain-specific languages and are placed in \family typewriter /etc \family default directory, such as a web server. Instead of reprogramming the software, a domain-agnostic language is made for it. \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Standard In general, code that can express a problem domain must be understandable by a domain expert. Even within the software domain, building a language out of repeated programmin g patterns is useful. It helps people aware the existence of such patterns in code and thus making software easier to maintain, as software structure is visible as a language. Only a programming language that is capable of morphing itself to suit a problem domain can achieve that goal. Such language is called a \emph on programmable programming language \emph default . Unfortunately, this approach of turning software structure visible is not favored among programmers, as a new language must be made out of it along with new toolchain to support it. Thus, software structure and domain knowledge are buried within code written in the syntax of a general-purpose language, and if a programmer is not familiar or even aware of the existence of a code pattern, then it is hopeless to understand the code. A prime example is reading C code that controls hardware, e.g. an operating system: if a programmer knows absolutely nothing about hardware, then it is impossible to read and write operating system code in C, even if he could have 20 years of writing application C code. \end_layout \begin_layout Standard With abstraction, a software engineer can also understand the inner-working of a device without specialized knowledge of physical circuit design, enables the software engineer to write code that controls a device. The separation between logical and physical implementation also entails that gate designs can be reused even when the underlying technologies changed. For example, in some distant future biological computer could be a reality, and gates might not be implemented as CMOS but some kind of biological cells e.g. as living cells; in either technology: electrical or biological, as long as logic gates are physically realized, the same computer design could be implemented. \end_layout \begin_layout Chapter Computer Architecture \end_layout \begin_layout Standard To write lower level code, a programmer must understand the architecture of a computer. It is similar to when one writes programs in a software framework, he must know what kinds of problems the framework solves, and how to use the framework by its provided software interfaces. But before getting to the definition of what computer architecture is, we must understand what exactly is a computer, as many people still think that a computer is a regular computer we put on a desk, or at best, a server. Computers come in various shapes and sizes and are devices that people never imagine they are computers, and that code can run on such devices. \end_layout \begin_layout Section What is a computer? \end_layout \begin_layout Standard A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on computer \end_layout \end_inset computer \begin_inset Index idx status open \begin_layout Plain Layout computer \end_layout \end_inset \emph default is a hardware device that consists of at least a processor (CPU), a memory device and input/output interfaces. All the computers can be grouped into two types: \end_layout \begin_layout Description Single-purpose \begin_inset space ~ \end_inset computer is a computer built at the \emph on hardware level \emph default for specific tasks. For example, dedicated application encoders/decoders , timer, image/video/sound processors. \end_layout \begin_layout Description General-purpose \begin_inset space ~ \end_inset computer is a computer that can be programmed (without modifying its hardware) to emulate various features of single-purpose computers. \end_layout \begin_layout Subsection Server \end_layout \begin_layout Standard A \emph on \begin_inset Index idx status open \begin_layout Plain Layout server \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on server \end_layout \end_inset server \emph default is a general-purpose high-performance computer with huge resources to provide large-scale services for a broad audience. The audience are people with their personal computer connected to a server. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Blade servers. Each blade server is a computer with a modular design optimize for the use of physical space and energy. The enclosure of blade servers is called a \emph on chassis \emph default .(Source: \begin_inset CommandInset href LatexCommand href name "Wikimedia" target "https://commons.wikimedia.org/wiki/File:Wikimedia_Foundation_Servers-8055_35.jpg" literal "false" \end_inset , author: Victorgrigas) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/03/Wikimedia_Foundation_Servers-8055_35.jpg scale 80 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Subsection Desktop Computer \end_layout \begin_layout Standard A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on desktop computer \end_layout \end_inset desktop computer \begin_inset Index idx status collapsed \begin_layout Plain Layout desktop computer \end_layout \end_inset \emph default is a general-purpose computer with an input and output system designed for a human user, with moderate resources enough for regular use. The input system usually includes a mouse and a keyboard, while the output system usually consists of a monitor that can display a large mount of pixels. The computer is enclosed in a chassis large enough for putting various computer components such as a processor, a motherboard, a power supply, a hard drive, etc. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout A typical desktop computer. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/03/computer-158675.svg scale 50 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Subsection Mobile Computer \end_layout \begin_layout Standard A \emph on \begin_inset Index idx status open \begin_layout Plain Layout mobile computer \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on mobile computer \end_layout \end_inset mobile computer \emph default is similar to a desktop computer with fewer resources but can be carried around. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Mobile computers} \end_layout \begin_layout Plain Layout \backslash subfloat[A laptop]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/macbook}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[A tablet]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/tablet}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[A mobile phone]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/mobile_phone}} \end_layout \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Subsection Game Consoles \end_layout \begin_layout Standard Game consoles are similar to desktop computers but are optimized for gaming. Instead of a keyboard and a mouse, the input system of a game console are game controllers, which is a device with a few buttons for controlling on-screen objects; the output system is a television. The chassis is similar to a desktop computer but is smaller. Game consoles use custom processors and graphic processors but are similar to ones in desktop computers. For example, the first Xbox uses a custom Intel Pentium III processor. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Current-gen Game Consoles} \end_layout \begin_layout Plain Layout \backslash subfloat[A Play Station 4]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/PS4-Console-wDS4}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[A Xbox One]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/Xbox_One_Console_Set}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[A Wii U]{ \end_layout \begin_layout Plain Layout \backslash hfill{} \backslash includegraphics[scale=0.7]{images/03/Wii_U_Console_and_Gamepad}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash hfill \backslash break \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard Handheld game consoles are similar to game consoles, but incorporate both the input and output systems along with the computer in a single package. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Some Handheld Consoles} \end_layout \begin_layout Plain Layout \backslash subfloat[A Nintendo DS]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/256px-Nintendo-DS-Lite-w-stylus}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[A PS Vita]{ \end_layout \begin_layout Plain Layout \backslash includegraphics{images/03/PlayStation-Vita}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Subsection Embedded Computer \end_layout \begin_layout Standard An \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on embedded computer \end_layout \end_inset embedded computer \begin_inset Index idx status open \begin_layout Plain Layout embedded computer \end_layout \end_inset \emph default is a single-board or single-chip computer with limited resources designed for integrating into larger hardware devices. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout An Intel 82815 Graphics and Memory Controller Hub embedded on a PC motherboard. (Source: \begin_inset CommandInset href LatexCommand href name "Wikimedia" target "https://commons.wikimedia.org/wiki/File:Intel_82815_GMCH.jpg" literal "false" \end_inset , author: Qurren) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/03/Intel_82815_GMCH.jpg scale 50 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout A PIC microcontroller. (Soure: \begin_inset CommandInset href LatexCommand href name "Microchip" target "http://www.microchip.com/wwwproducts/en/PIC18F4620" literal "false" \end_inset ) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/03/medium-PIC18F4620-PDIP-40.png scale 50 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on microcontroller \end_layout \end_inset microcontroller \begin_inset Index idx status open \begin_layout Plain Layout Microcontroller \end_layout \end_inset \emph default is an embedded computer designed for controlling other hardware devices. A microcontroller is mounted on a chip. Microcontrollers are general-purpose computers, but with limited resources so that it is only able to perform one or a few specialized tasks. These computers are used for a single purpose, but they are still general-purpo se since it is possible to program them to perform different tasks, depends on the requirements, without changing the underlying hardware. \end_layout \begin_layout Standard Another type of embedded computer is \emph on system-on-chip \emph default . A \emph on system-on-chip \begin_inset Index idx status open \begin_layout Plain Layout system-on-chip \end_layout \end_inset \emph default is a full computer on a single chip. Though a microcontroller is housed on a chip, its purpose is different: to control some hardware. A microcontroller is usually simpler and more limited in hardware resources as it specializes only in one purpose when running, whereas a system-on-chip is a general-purpose computer that can serve multiple purposes. A system-on-chip can run like a regular desktop computer that is capable of loading an operating system and run various applications. A system-on-chip typically presents in a smartphone, such as Apple A5 SoC used in Ipad2 and iPhone 4S, or Qualcomm Snapdragon used in many Android phones. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Apple A5 SoC \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/03/128px-Apple_A5_Chip.jpg \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Be it a microcontroller or a system-on-chip, there must be an environment where these devices can connect to other devices. This environment is a circuit board called a \emph on \begin_inset Index idx status collapsed \begin_layout Plain Layout PCB \end_layout \end_inset PCB \emph default – \emph on \begin_inset Index idx status collapsed \begin_layout Plain Layout Printed Circuit Board \end_layout \end_inset \series bold P \series default rinted \series bold C \series default ircuit \series bold B \series default oard. \emph default A \emph on printed circuit board \begin_inset Index idx status collapsed \begin_layout Plain Layout Printed Circuit Board \end_layout \end_inset \emph default is a physical board that contains lines and pads to enable electron flows between electrical and electronics components. Without a PCB, devices cannot be combined to create a larger device. As long as these devices are hidden inside a larger device and contribute to a larger device that operates at a higher level layer for a higher level purpose, they are embedded devices. Writing a program for an embedded device is therefore called \emph on \begin_inset Index idx status open \begin_layout Plain Layout embedded programming \end_layout \end_inset embedded programming \emph default . Embedded computers are used in automatically controlled devices including power tools, toys, implantable medical devices, office machines, engine control systems, appliances, remote controls and other types of embedded systems. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Raspberry Pi B+ Rev 1.2, a single-board computer that includes both a system-on-chip and a microcontroller.} \end_layout \begin_layout Plain Layout \backslash subfloat[Functional View. \end_layout \begin_layout Plain Layout \backslash newline The SoC is a Broadcom BCM2835. \end_layout \begin_layout Plain Layout \backslash newline The microcontroller is the Ethernet Controller LAN9514. \end_layout \begin_layout Plain Layout \backslash newline (Source: \backslash protect \backslash href{https://commons.wikimedia.org/wiki/File:Raspberry_Pi_B \backslash %2B_rev_1.2.svg}{Wikimedia}, author: Efa2)]{ \end_layout \begin_layout Plain Layout \backslash hfill{} \backslash includegraphics[scale=1.1]{images/03/Raspberry_Pi_B} \backslash hfill{}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[Physical View]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.075]{images/03/Raspberry_Pi_2_Model_B}} \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard The line between a microcontroller and a system-on-chip is blurry. If hardware keeps evolving more powerful, then a microcontroller can get enough resources to run a minimal operating system on it for multiple specializ ed purposes. In contrast, a system-on-chip is powerful enough to handle the job of a microcontroller. However, using a system-on-chip as a microcontroller would not be a wise choice as price will rise significantly, but we also waste hardware resources since the software written for a microcontroller requires little computing resources. \end_layout \begin_layout Subsection Field Gate Programmable Array \end_layout \begin_layout Standard \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Field Programmable Gate Array \end_layout \end_inset Field Programmable Gate Array \begin_inset Index idx status collapsed \begin_layout Plain Layout Field Gate Programmable Array \end_layout \end_inset \emph default ( \emph on \begin_inset Index idx status collapsed \begin_layout Plain Layout FPGA \end_layout \end_inset FPGA \emph default ) is a hardware an array of reconfigurable gates that makes circuit structure programmable after it is shipped away from the factory \begin_inset Foot status collapsed \begin_layout Plain Layout This is why it is called \series bold \emph on Field \series default \emph default Gate Programmable Array. It is changeable \begin_inset Quotes eld \end_inset in the field \begin_inset Quotes erd \end_inset where it is applied. \end_layout \end_inset . Recall that in the previous chapter, each 74HC00 chip can be configured as a gate, and a more sophisticated device can be built by combining multiple 74HC00 chips. In a similar manner, each FPGA device contains thousands of chips called \emph on logic blocks \emph default , which is a more complicated chip than a 74HC00 chip that can be configured to implement a Boolean logic function. These logic blocks can be chained together to create a high-level hardware feature. This high-level feature is usually a dedicated algorithm that needs high-speed processing. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout FPGA Architecture (Source: \begin_inset CommandInset href LatexCommand href name "National Instruments" target "http://www.ni.com/tutorial/6097/en/" literal "false" \end_inset ) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/03/fpga_400x212.jpg scale 80 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Digital devices can be designed by combining logic gates, without regarding actual circuit components, since the physical circuits are just multiples of CMOS circuits. Digital hardware, including various components in a computer, is designed by writing code, like a regular programmer, by using a language to describe how gates are wired together. This language is called a \emph on Hardware Description Language \begin_inset Index idx status open \begin_layout Plain Layout Hardware Description Language \end_layout \end_inset \emph default . Later the hardware description is compiled to a description of connected electronic components called a \emph on \begin_inset Index idx status open \begin_layout Plain Layout netlist \end_layout \end_inset netlist \emph default , which is a more detailed description of how gates are connected. \end_layout \begin_layout Standard The difference between FPGA and other embedded computers is that programs in FPGA are implemented at the digital logic level, while programs in embedded computers like microcontrollers or system-on-chip devices are implemented at assembly code level. An algorithm written for a FPGA device is a description of the algorithm in logic gates, which the FPGA device then follows the description to configure itself to run the algorithm. An algorithm written for a microcontroller is in assembly instructions that a processor can understand and act accordingly. \end_layout \begin_layout Standard FPGA is applied in the cases where the specialized operations are unsuitable and costly to run on a regular computer such as real-time medical image processing, cruise control system, circuit prototyping, video encoding/decoding , etc. These applications require high-speed processing that is not achievable with a regular processor because a processor wastes a significant amount of time in executing many non-specialized instructions - which might add up to thousands of instructions or more - to implement a specialized operation, thus more circuits at physical level to carry the same operation. A FPGA device carries no such overhead; instead, it runs a single specialized operation implemented in hardware directly. \end_layout \begin_layout Subsection Application-Specific Integrated Circuit \end_layout \begin_layout Standard An \emph on \begin_inset Index idx status collapsed \begin_layout Plain Layout Application-Specific Integrated Circuit \end_layout \end_inset \series bold A \series default pplication- \series bold S \series default pecific \series bold I \series default ntegrated \series bold C \series default ircuit \emph default (or \emph on ASIC \series bold \begin_inset Index idx status collapsed \begin_layout Plain Layout ASIC \end_layout \end_inset \series default \emph default ) is a chip designed for a particular purpose rather than for general-purpose use. ASIC does not contain a generic array of logic blocks that can be reconfigured to adapt to any operation like an FPGA; instead, every logic block in an ASIC is made and optimized for the circuit itself. FPGA can be considered as the prototyping stage of an ASIC, and ASIC as the final stage of circuit production. ASIC is even more specialized than FPGA, so it can achieve even higher performance. However, ASICs are very costly to manufacture and once the circuits are made, if design errors happen, everything is thrown away, unlike the FPGA devices which can simply be reprogrammed because of the generic gate array. \end_layout \begin_layout Section Computer Architecture \end_layout \begin_layout Standard The previous section examined various classes of computers. Regardless of shapes and sizes, every computer is designed for an architect from high level to low level. \end_layout \begin_layout Standard \begin_inset Formula \[ Computer\,Architecture=Instruction\,Set\,Architecture+Computer\,Organization+Hardware \] \end_inset \end_layout \begin_layout Standard At the highest-level is the Instruction Set Architecture. \end_layout \begin_layout Standard At the middle-level is the Computer Organization. \end_layout \begin_layout Standard At the lowest-level is the Hardware. \end_layout \begin_layout Subsection Instruction Set Architecture \end_layout \begin_layout Standard An \emph on instruction set \begin_inset Index idx status open \begin_layout Plain Layout instruction set \end_layout \end_inset \emph default is the basic set of commands and instructions that a microprocessor understands and can carry out. \end_layout \begin_layout Standard An \series bold \emph on I \series default nstruction \series bold S \series default et \series bold A \series default rchitecture \emph default \begin_inset Index idx status open \begin_layout Plain Layout Instruction Set Architecture \end_layout \end_inset , or \emph on \begin_inset Index idx status open \begin_layout Plain Layout ISA \end_layout \end_inset \series bold ISA \series default \emph default , is the design of an environment that implements an instruction set. Essentially, a runtime environment similar to those interpreters of high-level languages. The design includes all the instructions, registers, interrupts, memory models (how memory are arranged to be used by programs), addressing modes, I/O, etc., of a CPU. The more features (e.g. more instructions) a CPU has, the more circuits are required to implement it. \end_layout \begin_layout Subsection Computer organization \end_layout \begin_layout Standard \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Computer organization \end_layout \end_inset Computer organization \begin_inset Index idx status open \begin_layout Plain Layout Computer organization \end_layout \end_inset \emph default is the functional view of the design of a computer. In this view, hardware components of a computer are presented as boxes with input and output that connects to each other and form the design of a computer. Two computers may have the same ISA, but different organizations. For example, both AMD and Intel processors implement x86 ISA, but the hardware components of each processor that make up the environments for the ISA are not the same. \end_layout \begin_layout Standard Computer organizations may vary depend on a manufacturer's design, but they are all originated from the Von Neumann architecture \begin_inset Foot status collapsed \begin_layout Plain Layout \emph on John von Neumann \emph default was a mathematician and physicist who invented a computer architecture. \end_layout \end_inset : \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Von-Neumann Architecture \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \space{} \end_inset \begin_inset Graphics filename images/03/von_neumann_architecture.pdf scale 50 \end_inset \begin_inset space \space{} \end_inset \end_layout \end_inset \end_layout \begin_layout Description CPU \emph on \begin_inset Index idx status open \begin_layout Plain Layout CPU \end_layout \end_inset \emph default fetches instructions continuously from main memory and execute. \end_layout \begin_layout Description Memory \begin_inset Index idx status open \begin_layout Plain Layout Memory \end_layout \end_inset stores program code and data. \end_layout \begin_layout Description Bus \begin_inset Index idx status open \begin_layout Plain Layout Bus \end_layout \end_inset are electrical wires for sending raw bits between the above components. \end_layout \begin_layout Description I/O \begin_inset space ~ \end_inset Devices \begin_inset Index idx status open \begin_layout Plain Layout I/O Devices \end_layout \end_inset are devices that give input to a computer i.e. keyboard, mouse, sensor, etc, and takes the output from a computer i.e. monitor takes information sent from CPU to display it, LED turns on/off according to a pattern computed by CPU, etc. \end_layout \begin_layout Standard The Von-Neumann computer operates by storing its instructions in main memory, and CPU repeatedly fetches those instructions into its internal storage for executing, one after another. Data are transferred through a data bus between CPU, memory and I/O devices, and where to store in the devices is transferred through the address bus by the CPU. This architecture completely implements the \emph on \begin_inset Index idx status open \begin_layout Plain Layout f@fetch – decode – execute \end_layout \end_inset fetch – decode – execute \emph default cycle. \end_layout \begin_layout Standard The earlier computers were just the exact implementations of the Von Neumann architecture, with CPU and memory and I/O devices communicate through the same bus. Today, a computer has more buses, each is specialized in a type of traffic. However, at the core, they are still Von Neumann architecture. To write an OS for a Von Neumann computer, a programmer needs to be able to understand and write code that controls the cores components: CPU, memory, I/O devices, and bus. \end_layout \begin_layout Standard \emph on \begin_inset Index idx status open \begin_layout Plain Layout CPU \end_layout \end_inset \series bold CPU \series default \emph default , or \series bold \emph on C \series default entral \series bold P \series default rocessing \series bold U \series default nit \emph default \begin_inset Index idx status open \begin_layout Plain Layout Central Processing Unit \end_layout \end_inset , is the heart and brain of any computer system. Understand a CPU is essential to writing an OS from scratch: \end_layout \begin_layout Itemize To use these devices, a programmer needs to controls the CPU to use the programming interfaces of other devices. CPU is the only way, as CPU is the only direct device a programmer can use and the only device that understand code written by a programmer. \end_layout \begin_layout Itemize In a CPU, many OS concepts are already implemented directly in hardware, e.g. task switching, paging. A kernel programmer needs to know how to use the hardware features, to avoid duplicating such concept in software, thus wasting computer resources. \end_layout \begin_layout Itemize CPU built-in OS features boost both OS performance and developer productivity because those features are actual hardware, the lowest possible level, and developers are free to implement such features. \end_layout \begin_layout Itemize To effectively use the CPU, a programmer needs to understand the documentation provided by the CPU manufacturer. For example, \begin_inset CommandInset href LatexCommand href name "Intel® 64 and IA-32 Architectures Software Developer Manuals" target "[http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html" literal "false" \end_inset . \end_layout \begin_layout Itemize After understanding one CPU architecture well, it is easier to learn other CPU architectures. \end_layout \begin_layout Standard A CPU is an implementation of an ISA, effectively the implementation of an assembly language (and depending on the CPU architecture, the language may vary). Assembly language is one of the interfaces that are provided for software engineers to control a CPU, thus control a computer. But how can every computer device be controlled with only access to the CPU? The simple answer is that a CPU can communicate with other devices through these two interfaces, thus commanding them: \end_layout \begin_layout Description \emph on Registers \emph default \emph on \begin_inset Index idx status open \begin_layout Plain Layout Registers \end_layout \end_inset \begin_inset Marginal status collapsed \begin_layout Plain Layout \series bold \emph on Registers \end_layout \end_inset \emph default are a hardware component for high-speed data access and communication with other hardware devices. Registers allow software to control hardware directly by writing to registers of a device, or receive information from a hardware device when reading from registers of a device. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Not all registers are used for communication with other devices. In a CPU, most registers are used as high-speed storage for temporary data. Other devices that a CPU can communicate with always have a set of registers for interfacing with the CPU. \end_layout \end_deeper \begin_layout Description \emph on Port \emph default \emph on \begin_inset Index idx status open \begin_layout Plain Layout Port \end_layout \end_inset \begin_inset Marginal status collapsed \begin_layout Plain Layout \series bold \emph on Port \end_layout \end_inset \emph default is a specialized register in a hardware device used for communication with other devices. When data is written to a port, it causes a hardware device to perform some operation according to values written to the port. The difference between a port and a register is that a port does not store data, but delegates data to some other circuit. \end_layout \begin_layout Standard These two interfaces are extremely important, as they are the only interfaces for controlling hardware with software. Writing device drivers is essentially learning the functionality of each register and how to use them properly to control the device. \end_layout \begin_layout Standard \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Memory \end_layout \end_inset Memory \begin_inset Index idx status open \begin_layout Plain Layout Memory \end_layout \end_inset \emph default is a storage device that stores information. Memory consists of many cells. Each cell is a byte with its address number, so a CPU can use such address number to access an exact location in memory. Memory is where software instructions (in the form of machine language) is stored and retrieved to be executed by CPU; memory also stores data needed by some software. Memory in a Von Neumann machine does not distinguish between which bytes are data and which bytes are software instructions. It's up to the software to decide, and if somehow data bytes are fetched and executed as instructions, CPU still does it if such bytes represents valid instructions, but will produce undesirable results. To a CPU, there's no code and data; both are merely different types of data for it to act on: one tells it how to do something in a specific manner, and one is necessary materials for it to carry such action. \end_layout \begin_layout Standard The RAM is controlled by a device called a \emph on memory controller \begin_inset Index idx status open \begin_layout Plain Layout memory controller \end_layout \end_inset \emph default . Currently, most processors have this device embedded, so the CPU has a dedicated memory bus connecting the processor to the RAM. On older CPU \begin_inset Foot status open \begin_layout Plain Layout Prior to the CPU's produced in 2009 \end_layout \end_inset , however, this device was located in a chip also known as \series bold MCH \series default or \series bold \emph on M \series default emory \series bold C \series default ontroller \series bold H \series default ub \begin_inset Index idx status open \begin_layout Plain Layout Memory Controller Hub \end_layout \end_inset \emph default . In this case, the CPU does not communicate directly to the RAM, but to the MCH chip, and this chip then accesses the memory to read or write data. The first option provides better performance since there is no middleman in the communications between the CPU and the memory. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{CPU - Memory Communication} \end_layout \begin_layout Plain Layout \backslash subfloat[Old CPU]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.4]{images/03/cpu_chipset_memory}} \backslash hfill{} \end_layout \begin_layout Plain Layout \backslash subfloat[Modern CPU]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.4]{images/03/cpu_memory_chipset}} \end_layout \begin_layout Plain Layout \backslash hfill \backslash break \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard At the physical level, RAM is implemented as a grid of cells that each contain a transistor and an electrical device called a \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on capacitor \end_layout \end_inset capacitor \emph default \begin_inset Index idx status open \begin_layout Plain Layout capacitor \end_layout \end_inset , which stores charge for short periods of time. The transistor controls access to the capacitor; when switched on, it allows a small charge to be read from or written to the capacitor. The charge on the capacitor slowly dissipates, requiring the inclusion of a refresh circuit to periodically read values from the cells and write them back after amplification from an external power source. \end_layout \begin_layout Standard \emph on \begin_inset Index idx status open \begin_layout Plain Layout Bus \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Bus \end_layout \end_inset Bus \emph default is a subsystem that transfers data between computer components or between computers. Physically, buses are just electrical wires that connect all components together and each wire transfer a single big chunk of data. The total number of wires is called \emph on \begin_inset Index idx status open \begin_layout Plain Layout bus width \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on bus width \end_layout \end_inset bus width \emph default , and is dependent on how many wires a CPU can support. If a CPU can only accept 16 bits at a time, then the bus has 16 wires connectin g from a component to the CPU, which means the CPU can only retrieve 16 bits of data a time. \end_layout \begin_layout Subsection Hardware \end_layout \begin_layout Standard Hardware is a specific implementation of a computer. A line of processors implement the same instruction set architecture and use nearly identical organizations but differ in hardware implementation. For example, the Core i7 family provides a model for desktop computers that is more powerful but consumes more energy, while another model for laptops is less performant but more energy efficient. To write software for a hardware device, seldom we need to understand a hardware implementation if documents are available. Computer organization and especially the instruction set architecture are more relevant to an operating system programmer. For that reason, the next chapter is devoted to study the x86 instruction set architecture in depth. \end_layout \begin_layout Section x86 architecture \end_layout \begin_layout Standard A \emph on \begin_inset Index idx status open \begin_layout Plain Layout chipset \end_layout \end_inset chipset \emph default is a chip with multiple functions. Historically, a chipset is actually a set of individual chips, and each is responsible for a function, e.g. memory controller, graphic controllers, network controller, power controller, etc. As hardware progressed, the set of chips were incorporated into a single chip, thus more space, energy, and cost efficient. In a desktop computer, various hardware devices are connected to each other through a PCB called a \emph on \begin_inset Index idx status open \begin_layout Plain Layout motherboard \end_layout \end_inset motherboard \emph default . Each CPU needs a compatible motherboard that can host it. Each motherboard is defined by its chipset model that determine the environment that a CPU can control. This environment typically consists of \end_layout \begin_layout Itemize a slot or more for CPU \end_layout \begin_layout Itemize a chipset of two chips which are the Northbridge and Southbridge chips \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize Northbridge chip is responsible for the high-performance communication between CPU, main memory and the graphic card. \end_layout \begin_layout Itemize Southbridge chip is responsible for the communication with I/O devices and other devices that are not performance sensitive. \end_layout \end_deeper \begin_layout Itemize slots for memory sticks \end_layout \begin_layout Itemize a slot or more for graphic cards. \end_layout \begin_layout Itemize generic slots for other devices, e.g. network card, sound card. \end_layout \begin_layout Itemize ports for I/O devices, e.g. keyboard, mouse, USB. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Motherboard organization. \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "mobo-organization" \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/03/Motherboard_diagram.svg \end_inset \end_layout \end_inset \end_layout \begin_layout Standard To write a complete operating system, a programmer needs to understand how to program these devices. After all, an operating system manages hardware automatically to free applicati on programs doing so. However, of all the components, learning to program the CPU is the most important, as it is the component present in any computer, regardless of what type a computer is. For this reason, the primary focus of this book will be on how to program an x86 CPU. Even solely focused on this device, a reasonably good minimal operating system can be written. The reason is that not all computers include all the devices as in a normal desktop computer. For example, an embedded computer might only have a CPU and limited internal memory, with pins for getting input and producing an output; yet, operating systems were written for such devices. \end_layout \begin_layout Standard However, learning how to program an x86 CPU is a daunting task, with 3 primary manuals written for it: almost 500 pages for volume 1, over 2000 pages for volume 2 and over 1000 pages for volume 3. It is an impressive feat for a programmer to master every aspect of x86 CPU programming. \end_layout \begin_layout Section Intel Q35 Chipset \end_layout \begin_layout Standard Q35 is an Intel chipset released September 2007. Q35 is used as an example of a high-level computer organization because later we will use QEMU to emulate a Q35 system, which is latest Intel system that QEMU can emulate. Though released in 2007, Q35 is relatively modern to the current hardware, and the knowledge can still be reused for current chipset model. With a Q35 chipset, the emulated CPU is also relatively up-to-date with features presented in current day CPUs so we can use the latest software manuals from Intel. \end_layout \begin_layout Standard Figure \begin_inset CommandInset ref LatexCommand vref reference "mobo-organization" \end_inset is a typical current-day motherboard organization, in which Q35 shares similar organization. \end_layout \begin_layout Section x86 Execution Environment \end_layout \begin_layout Standard An \emph on execution environment \begin_inset Index idx status open \begin_layout Plain Layout execution environment \end_layout \end_inset \emph default is an environment that provides the facility to make code executable. The execution environment needs to address the following question: \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout Supported \begin_inset space ~ \end_inset operations? \end_layout \end_inset data transfer, arithmetic, control, floating-point, etc. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout Where are operands stored? \end_layout \end_inset registers, memory, stack, accumulator \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout How many explicit operands are there for each instruction? \end_layout \end_inset 0, 1, 2, or 3 \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout How is the operand location specified? \end_layout \end_inset register, immediate, indirect, etc. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout What type and size of operands are supported? \end_layout \end_inset byte, int, float, double, string, vector, etc. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout etc. \end_layout \end_inset \end_layout \begin_layout Standard For the remain of this chapter, please carry on the reading to chapter 3 in Intel Manual Volume 1, \emph on \begin_inset Quotes eld \end_inset Basic Execution Environment \begin_inset Quotes erd \end_inset \emph default . \end_layout \begin_layout Chapter x86 Assembly and C \end_layout \begin_layout Standard In this chapter, we will explore assembly language, and how it connects to C. But why should we do so? Isn't it better to trust the compiler, plus no one writes assembly anymore? \end_layout \begin_layout Standard Not quite. Surely, the compiler at its current state of the art is trustworthy, and we do not need to write code in assembly, \emph on most of the time \emph default . A compiler can generate code, but as mentioned previously, a high-level language is a collection of patterns of a lower-level language. It does not cover everything that a hardware platform provides. As a consequence, not every assembly instruction can be generated by a compiler, so we still need to write assembly code for these circumstances to access hardware-specific features. Since hardware-specific features require writing assembly code, debugging requires reading it. We might spend even more time reading than writing. Working with low-level code that interacts directly with hardware, assembly code is unavoidable. Also, understand how a compiler generates assembly code could improve a programmer's productivity. For example, if a job or school assignment requires us to write assembly code, we can simply write it in C, then let \family typewriter gcc \family default does the hard working of writing the assembly code for us. We merely collect the generated assembly code, modify as needed and be done with the assignment. \end_layout \begin_layout Standard We will learn \family typewriter objdump \family default extensively, along with how to use Intel documents to aid in understanding x86 assembly code. \end_layout \begin_layout Section objdump \end_layout \begin_layout Standard \begin_inset Flex Code status open \begin_layout Plain Layout objdump \emph on \begin_inset Index idx status open \begin_layout Plain Layout objdump \end_layout \end_inset \end_layout \end_inset is a program that displays information about object files. It will be handy later to debug incorrect layout from manual linking. Now, we use \begin_inset Flex Code status open \begin_layout Plain Layout objdump \end_layout \end_inset to examine how high level source code maps to assembly code. For now, we ignore the output and learn how to use the command first. Supposed that we have a executable binary named \begin_inset Flex Code status open \begin_layout Plain Layout hello \end_layout \end_inset compiled from a \begin_inset Flex Code status open \begin_layout Plain Layout hello.c \end_layout \end_inset thath prints \begin_inset Quotes eld \end_inset Hello World', it is simple to use \begin_inset Flex Code status open \begin_layout Plain Layout objdump \end_layout \end_inset : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -d hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset Flex Code status open \begin_layout Plain Layout -d \end_layout \end_inset option only displays assembled contents of executable sections. A \emph on \begin_inset Index idx status open \begin_layout Plain Layout section \end_layout \end_inset section \emph default is a block of memory that contains either program code or data. A code section is executable by the CPU, while a data section is not executable. Non-executable sections, such as \begin_inset Flex Code status open \begin_layout Plain Layout .data \end_layout \end_inset and \begin_inset Flex Code status open \begin_layout Plain Layout .bss \end_layout \end_inset (for storing program data), debug sections, etc, are not displayed. We will learn more about section when studying ELF binary file format in chapter \begin_inset CommandInset ref LatexCommand vref reference "chap:The-Anatomy-of-a-program" \end_inset . On the other hand: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -D hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left where \begin_inset Flex Code status open \begin_layout Plain Layout -D \end_layout \end_inset option displays assembly contents of all sections. If \begin_inset Flex Code status open \begin_layout Plain Layout -D \end_layout \end_inset , \begin_inset Flex Code status open \begin_layout Plain Layout -d \end_layout \end_inset is implicitly assumed. \begin_inset Flex Code status open \begin_layout Plain Layout objdump \end_layout \end_inset is mostly used for inspecting assembly code, so \begin_inset Flex Code status open \begin_layout Plain Layout -d \end_layout \end_inset is the most useful and thus is set by default. \end_layout \begin_layout Standard The output overruns the terminal screen. To make it easy for reading, send all the output to \begin_inset Flex Code status open \begin_layout Plain Layout less \end_layout \end_inset : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -d hello | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard To intermix source code and assembly, the binary must be compiled with \begin_inset Flex Code status open \begin_layout Plain Layout -g \end_layout \end_inset option to include source code in it, then add \begin_inset Flex Code status open \begin_layout Plain Layout -S \end_layout \end_inset option: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -S hello | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard The default syntax used by \begin_inset Flex Code status open \begin_layout Plain Layout objdump \end_layout \end_inset is AT&T syntax. To change it to the familiar Intel syntax: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -M intel -D hello | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left When using \family typewriter -M \family default option, option \family typewriter -D \family default or \family typewriter -d \family default must be explicitly supplied. Next, we will use \begin_inset Flex Code status open \begin_layout Plain Layout objdump \end_layout \end_inset to examine how compiled C data and code are represented in machine code. \end_layout \begin_layout Standard Finally, we will write a 32-bit kernel, therefore we will need to compile a 32-bit binary and examine it in 32-bit mode: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -M i386,intel -D hello | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset Flex Code status open \begin_layout Plain Layout -M i386 \end_layout \end_inset tells objdump to display assembly content using 32-bit layout. Knowing the difference between 32-bit and 64-bit is crucial for writing kernel code. We will examine this matter later on when writing our kernel. \end_layout \begin_layout Section Reading the output \end_layout \begin_layout Standard At the start of the output displays the file format of the object file: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout LyX-Code \noindent \align left hello: file format elf64-x86-64 \end_layout \begin_layout Standard After the line is a series of disassembled sections: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout LyX-Code \noindent \align left Disassembly of section .interp: \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code Disassembly of section .note.ABI-tag: \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code Disassembly of section .note.gnu.build-id: \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code etc \end_layout \begin_layout Standard Finally, each disassembled section displays its actual content - which is a sequence of assembly instructions - with the following format: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout LyX-Code \noindent \align left \color red 4004d6 \color inherit : \color blue 55 \color inherit \color green push rbp \end_layout \begin_layout Itemize The \color red first column \color inherit is the address of an assembly instruction. In the above example, the address is \family typewriter 0x4004d6 \family default . \end_layout \begin_layout Itemize The \color blue second column \color inherit is assembly instruction in raw hex values. In the above example, the value is \family typewriter 0x55 \family default . \end_layout \begin_layout Itemize The \color green third column \color inherit is the assembly instruction. Depends on the section, the assembly instruction might be meaningful or meaningless. For example, if the assembly instructions are in a \family typewriter .text \family default section, then the assembly instructions are actual program code. On the other hand, if the assembly instructions are displayed in a \family typewriter .data \family default section, then we can safely ignore the displayed instructions. The reason is that \begin_inset Flex Code status open \begin_layout Plain Layout objdump \end_layout \end_inset doesn't know which hex values are code and which are data, so it blindly translates every hex values into assembly instructions. In the above example, the assembly instruction is \family typewriter push %rbp \family default . \end_layout \begin_layout Itemize The optional fourth column is a comment - appears when there is a reference to an address - to inform where the address originates. For example, the comment in \color blue blue \color inherit : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Full Width \family typewriter \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset lea r12, \color red [rip+0x2008ee] \color inherit \color blue # 600e10 <__frame_dummy_init_array_entry> \end_layout \begin_layout Standard is to inform that the referenced address from \family typewriter \color red [rip+0x2008ee] \family default \color inherit is \family typewriter \color blue 0x600e10 \family default \color inherit , where the variable \family typewriter __frame_dummy_init_array_entry \family default resides. \end_layout \end_deeper \begin_layout Standard In a disassembled section, it may also contain \emph on labels \emph default . A label is a name given to an assembly instruction. The label denotes the purpose of an assembly block to a human reader, to make it easier to understand. For example, \family typewriter .text \family default section carries many of such labels to denote where code in a program start; \family typewriter .text \family default section below carries two functions: \family typewriter \color red _start \family default \color inherit and \family typewriter \color red deregister_tm_clones \family default \color inherit . The \family typewriter \color red _start \family default \color inherit function starts at address \family typewriter \color blue 4003e0 \family default \color inherit , is annotated to the left of the function name. Right below \family typewriter \color red _start \color inherit \family default label is also the instruction at address \family typewriter \color blue 4003e0 \family default \color inherit . This whole thing means that a label is simply a name of a memory address. The function \family typewriter deregister_tm_clones \family default also shares the same format as every function in the section. \end_layout \begin_layout LyX-Code 0000000000 \color blue 4003e0 \color inherit \color red <_start> \color inherit : \end_layout \begin_layout LyX-Code \color blue 4003e0 \color inherit : 31 ed xor ebp,ebp \end_layout \begin_layout LyX-Code 4003e2: 49 89 d1 mov r9,rdx \end_layout \begin_layout LyX-Code 4003e5: 5e pop rsi \end_layout \begin_layout LyX-Code ...more assembly code.... \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0000000000 \color blue 400410 \color inherit \color red \color inherit : \end_layout \begin_layout LyX-Code \color blue 400410 \color inherit : b8 3f 10 60 00 mov eax,0x60103f \end_layout \begin_layout LyX-Code 400415: 55 push rbp \end_layout \begin_layout LyX-Code 400416: 48 2d 38 10 60 00 sub rax,0x601038 \end_layout \begin_layout LyX-Code ...more assembly code.... \end_layout \begin_layout Section Intel manuals \end_layout \begin_layout Standard The best way to understand and use assembly language properly is to understand precisely the underlying computer architecture and what each machine instructio n does. To do so, the most reliable source is to refer to documents provided by vendors. After all, hardware vendors are the one who made their machines. To understand Intel's instruction set, we need the document \begin_inset Quotes eld \end_inset \emph on Intel 64 and IA-32 architectures software developer's manual combined volumes 2A, 2B, 2C, and 2D: Instruction set reference, A-Z \emph default \begin_inset Quotes erd \end_inset . The document can be retrieved here: \begin_inset Flex URL status open \begin_layout Plain Layout https://software.intel.com/en-us/articles/intel-sdm \end_layout \end_inset . \end_layout \begin_layout Itemize Chapter 1 provides brief information about the manual, and the comment notations used in the book. \end_layout \begin_layout Itemize Chapter 2 provides an in-depth explanation of the anatomy of an assembly instruction, which we will investigate in the next section. \end_layout \begin_layout Itemize Chapter 3 - 5 provide the details of every instruction of the x86_64 architectur e. \end_layout \begin_layout Itemize Chapter 6 provides information about safer mode extensions. We won't need to use this chapter. \end_layout \begin_layout Standard The first volume \begin_inset Quotes eld \end_inset \emph on Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture \emph default \begin_inset Quotes erd \end_inset describes the basic architecture and programming environment of Intel processor s. In the book, Chapter 5 gives the summary of all Intel instructions, by listing instructions into different categories. We only need to learn general-purpose instructions listed \emph on chapter 5.1 \emph default for our OS. \emph on Chapter 7 \emph default describes the purpose of each category. Gradually, we will learn all of these instructions. \end_layout \begin_layout Exercise Read section 1.3 in volume 2, exclude sections 1.3.5 and 1.3.7. \end_layout \begin_layout Section Experiment with assembly code \end_layout \begin_layout Standard The subsequent sections examine the anatomy of an assembly instruction. To fully understand, it is necessary to write code and see the code in its actual form displayed as hex numbers. For this purpose, we use \family typewriter nasm \family default assembler to write a few line of assembly code and see the generated code. \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Full Width \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example Suppose we want to see the machine code generated for this instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code jmp eax \end_layout \begin_layout Standard Then, we use an editor e.g. Emacs, then create a new file, write the code and save it in a file, e.g. \family typewriter test.asm \family default . Then, in the terminal, run the command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ nasm -f bin test.asm -o test \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \family typewriter -f \family default option specifies the file format, e.g. ELF, of the final output file. But in this case, the format is \family typewriter bin \family default , which means this file is just a flat binary output without any extra informati on. That is, the written assembly code is translated to machine code as is, without the overhead of the metadata from file format like ELF. Indeed, after compiling, we can examine the output using this command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ hd test \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter hd \family default (short for hexdump) is a program that displays the content of a file in hex format \begin_inset Marginal status open \begin_layout Plain Layout Though its name is short for hexdump, \family typewriter hd \family default can display in different base, e.g. binary, other than hex. \end_layout \end_inset . \family typewriter \family default And get the following output: \end_layout \begin_layout LyX-Code 00000000 66 ff e0 |f..| \end_layout \begin_layout LyX-Code 00000003 \end_layout \begin_layout Standard The file only consists of 3 bytes: \family typewriter \color red 66 ff e0 \family default \color inherit , which is equivalent to the instruction \family typewriter jmp eax \family default . \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example If we were to use \family typewriter elf \family default as file format: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ nasm -f elf test.asm -o test \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left It would be more challenging to learn and understand assembly instructions with all the added noise \begin_inset Foot status collapsed \begin_layout Plain Layout The output from \family typewriter hd. \end_layout \end_inset : \end_layout \begin_layout LyX-Code 00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| \end_layout \begin_layout LyX-Code 00000010 01 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000020 40 00 00 00 00 00 00 00 34 00 00 00 00 00 28 00 |@.......4.....(.| \end_layout \begin_layout LyX-Code 00000030 05 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code * \end_layout \begin_layout LyX-Code 00000060 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000070 06 00 00 00 00 00 00 00 10 01 00 00 02 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000080 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000090 07 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 000000a0 20 01 00 00 21 00 00 00 00 00 00 00 00 00 00 00 | ...!...........| \end_layout \begin_layout LyX-Code 000000b0 01 00 00 00 00 00 00 00 11 00 00 00 02 00 00 00 |................| \end_layout \begin_layout LyX-Code 000000c0 00 00 00 00 00 00 00 00 50 01 00 00 30 00 00 00 |........P...0...| \end_layout \begin_layout LyX-Code 000000d0 04 00 00 00 03 00 00 00 04 00 00 00 10 00 00 00 |................| \end_layout \begin_layout LyX-Code 000000e0 19 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 000000f0 80 01 00 00 0d 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000100 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000110 ff e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code 00000120 00 2e 74 65 78 74 00 2e 73 68 73 74 72 74 61 62 |..text..shstrtab| \end_layout \begin_layout LyX-Code 00000130 00 2e 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62 |..symtab..strtab| \end_layout \begin_layout LyX-Code 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| \end_layout \begin_layout LyX-Code * \end_layout \begin_layout LyX-Code 00000160 01 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff |................| \end_layout \begin_layout LyX-Code 00000170 00 00 00 00 00 00 00 00 00 00 00 00 03 00 01 00 |................| \end_layout \begin_layout LyX-Code 00000180 00 74 65 73 74 2e 61 73 6d 00 00 00 00 00 00 00 |.disp8-5.asm....| \end_layout \begin_layout LyX-Code 00000190 \end_layout \begin_layout Standard Thus, it is better just to use flat binary format in this case, to experiment instruction by instruction. \end_layout \end_deeper \begin_layout Standard With such a simple workflow, we are ready to investigate the structure of every assembly instruction. \end_layout \begin_layout Standard \series bold Note: \series default Using the bin format puts \family typewriter nasm \family default by default into 16-bit mode. To enable 32-bit code to be generated, we must add this line at the beginning of an \family typewriter nasm \family default source file: \end_layout \begin_layout LyX-Code bits 32 \end_layout \begin_layout Section Anatomy of an Assembly Instruction \end_layout \begin_layout Standard Chapter 2 of the instruction reference manual provides an in-depth of view of instruction format. But, the information is too much that it can overwhelm beginners. This section provides an easier instruction before reading the actual chapter in the manual. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash caption{Intel 64 and IA-32 Architectures Instruction Format} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Graphics filename images/04/x86_instruction_format.pdf \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard Recall that an assembly instruction is simply a fixed-size series of bits. The length of an instruction varies and depends on how complicated an instructi on is. What every instruction shares is a common format described in the figure above that divides the bits of an instruction into smaller parts that encode different types of information. These parts are: \end_layout \begin_layout Description \family typewriter Instruction \begin_inset space ~ \end_inset Prefixes \family default appears at the beginning of an instruction. Prefixes are optional. A programmer can choose to use a prefix or not because in practice, a so-called prefix is just another assembly instruction to be inserted before another assembly instruction that such prefix is applicable. Instructions with 2 or 3-bytes opcodes include the prefixes by default. \end_layout \begin_layout Description \family typewriter Opcode \family default is a unique number that identifies an instruction. Each opcode is given an mnemonic name that is human readable, e.g. one of the opcodes for instruction \family typewriter add \family default is \family typewriter 04 \family default . When a CPU sees the number \family typewriter 04 \family default in its instruction cache, it sees instruction \family typewriter add \family default and execute accordingly. Opcode can be 1,2 or 3 bytes long and includes an additional 3-bit field in the \family typewriter ModR/M \family default byte when needed. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example This instruction: \end_layout \begin_layout LyX-Code jmp [0x1234] \end_layout \begin_layout Standard \noindent \align left generates the machine code: \end_layout \begin_layout LyX-Code \color red ff \color inherit 26 34 12 \end_layout \begin_layout Standard \noindent \align left The very first byte, \family typewriter \color red 0xff \family default \color inherit is the opcode, which is unique to \family typewriter jmp \family default instruction. \end_layout \end_deeper \begin_layout Description \family typewriter ModR/M \family default specifies operands of an instruction. Operand can either be a register, a memory location or an immediate value. This component of an instruction consists of 3 smaller parts: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize \family typewriter \emph on mod \family default \emph default field, or \emph on modifier \emph default field, is combined with \family typewriter r/m \family default field for a total of 5 bits of information to encode 32 possible values: 8 registers and 24 addressing modes. \end_layout \begin_layout Itemize \family typewriter \emph on reg/opcode \family default \emph default field encodes either a register operand, or extends the \family typewriter Opcode \family default field with 3 more bits. \end_layout \begin_layout Itemize \family typewriter \emph on r/m \family default \emph default field encodes either a register operand or can be combined with \family typewriter mod \family default field to encode an addressing mode. \end_layout \begin_layout Standard The tables \begin_inset CommandInset ref LatexCommand formatted reference "mod-rm-16" \end_inset and \begin_inset CommandInset ref LatexCommand formatted reference "mod-rm-32" \end_inset list all possible 256 values of \family typewriter ModR/M \family default byte and how each value maps to an addressing mode and a register, in 16-bit and 32-bit modes. \end_layout \end_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begingroup \backslash tabcolsep=2pt \backslash def \backslash arraystretch{0.7} \end_layout \begin_layout Plain Layout \backslash begin{table*} \end_layout \begin_layout Plain Layout \backslash setlength{ \backslash arrayrulewidth}{.2mm} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash caption{16-Bit Addressing Forms with the ModR/M Byte} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r8(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize AL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize CL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize AH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize CH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r16(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize AX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize CX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize SP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BP \begin_inset script superscript \begin_layout Plain Layout 1 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize SI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r32(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EAX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ECX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EDX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EBX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ESP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EBP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ESI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EDI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize mm(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize xmm(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize (In decimal) /digit (Opcode) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize (In binary) REG = \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Effective Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Mod \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset R/M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Values of ModR/M Byte (In Hexadecimal) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX + SI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 18 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 20 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 28 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 30 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 38 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX + DI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 19 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 21 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 29 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 31 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 39 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP + SI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 22 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP + DI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 13 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 23 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 33 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [SI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 14 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 24 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 34 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [DI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 15 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 25 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 35 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize disp16 \begin_inset script superscript \begin_layout Plain Layout 2 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 26 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 36 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 17 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 27 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 37 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX + SI] + disp8 \begin_inset script superscript \begin_layout Plain Layout 3 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 40 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 48 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 50 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 58 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 60 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 68 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 70 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 78 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX + DI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 41 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 49 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 51 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 59 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 61 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 69 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 71 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 79 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP + SI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 42 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 52 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 62 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 72 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP + DI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 43 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 53 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 63 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 73 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [SI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 44 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 54 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 64 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 74 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [DI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 45 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 55 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 65 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 75 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 46 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 56 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 66 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 76 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 47 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 57 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 67 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 77 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX + SI] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 80 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 88 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 90 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 98 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX + DI] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 81 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 89 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 91 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 99 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP + SI] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 82 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 92 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP + DI] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 83 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 93 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [SI] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 84 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 94 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [DI] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 85 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 95 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BP] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 86 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 96 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [BX] + disp16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 87 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 97 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EAX/AX/AL/MM0/XMM0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ECX/CX/CL/MM1/XMM1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EDX/DX/DL/MM2/XMM2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EBX/BX/BL/MM3/XMM3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ESP/SP/AHMM4/XMM4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EBP/BP/CH/MM5/XMM5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ED \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ESI/SI/DH/MM6/XMM6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EDI/DI/BH/MM7/XMM7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FF \end_layout \end_inset \begin_inset Text \begin_layout Enumerate \family sans \size footnotesize The default segment register is SS for the effective addresses containing a BP index, DS for other effective addresses. \end_layout \begin_layout Enumerate \family sans \size footnotesize The disp16 nomenclature denotes a 16-bit displacement that follows the ModR/M byte and that is added to the index. \end_layout \begin_layout Enumerate \family sans \size footnotesize The disp8 nomenclature denotes an 8-bit displacement that follows the ModR/M byte and that is sign-extended and added to the index. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \begin_inset CommandInset label LatexCommand label name "mod-rm-16" \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{table*} \end_layout \begin_layout Plain Layout \backslash endgroup \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begingroup \backslash tabcolsep=2pt \backslash def \backslash arraystretch{0.7} \end_layout \begin_layout Plain Layout \backslash begin{table*} \end_layout \begin_layout Plain Layout \backslash setlength{ \backslash arrayrulewidth}{.2mm} \end_layout \begin_layout Plain Layout \backslash caption{32-Bit Addressing Forms with the ModR/M Byte} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r8(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize AL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize CL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize AH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize CH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r16(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize AX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize CX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize SP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize BP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize SI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize DI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r32(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EAX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ECX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EDX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EBX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ESP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EBP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ESI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EDI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize mm(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize MM7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize xmm(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize XMM7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize (In decimal) /digit (Opcode) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize (In binary) REG = \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Effective Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Mod \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset R/M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Values of ModR/M Byte (In Hexadecimal) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 18 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 20 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 28 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 30 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 38 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 19 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 21 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 29 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 31 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 39 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 22 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 13 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 23 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 33 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ][- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ] \begin_inset script superscript \begin_layout Plain Layout 1 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 14 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 24 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 34 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize disp32 \begin_inset script superscript \begin_layout Plain Layout 2 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 15 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 25 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 35 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 26 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 36 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 0F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 17 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 1F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 27 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 2F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 37 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 3F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX] + disp8 \begin_inset script superscript \begin_layout Plain Layout \family sans \size footnotesize 3 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 40 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 48 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 50 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 58 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 60 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 68 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 70 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 78 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 41 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 49 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 51 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 59 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 61 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 69 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 71 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 79 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 42 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 52 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 62 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 72 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 43 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 53 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 63 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 73 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ][- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 44 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 54 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 64 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 74 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBP] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 45 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 55 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 65 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 75 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 46 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 56 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 66 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 76 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI] + disp8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 47 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 4F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 57 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 5F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 67 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 6F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 77 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 7F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 80 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 88 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 90 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 98 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 81 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 89 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 91 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 99 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 82 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 92 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 83 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 93 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ][- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 84 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 94 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBP] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 85 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 95 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 86 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 96 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 87 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 8F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 97 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 9F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize A7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize AF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize B7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize BF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EAX/AX/AL/MM0/XMM0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ECX/CX/CL/MM/XMM1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EDX/DX/DL/MM2/XMM2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EBX/BX/BL/MM3/XMM3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ESP/SP/AH/MM4/XMM4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EBP/BP/CH/MM5/XMM5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ED \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize ESI/SI/DH/MM6/XMM6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EDI/DI/BH/MM7/XMM7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize C7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize CF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize D7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize DF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize E7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize EF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize F7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize FF \end_layout \end_inset \begin_inset Text \begin_layout Enumerate \family sans \size footnotesize The [- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ][- \begin_inset ERT status open \begin_layout Plain Layout \backslash -- \end_layout \end_inset ] nomenclature means a SIB follows the ModR/M byte. \end_layout \begin_layout Enumerate \family sans \size footnotesize The disp32 nomenclature denotes a 32-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is added to the index. \end_layout \begin_layout Enumerate \family sans \size footnotesize The disp8 nomenclature denotes an 8-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is sign-extended and added to the index. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \begin_inset CommandInset label LatexCommand label name "mod-rm-32" \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{table*} \end_layout \begin_layout Plain Layout \backslash endgroup \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset VSpace vfill \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset \end_layout \begin_layout Standard \begin_inset Flex Noun status open \begin_layout Plain Layout How to read the table: \end_layout \end_inset \end_layout \begin_layout Standard In an instruction, next to the opcode is a \family typewriter ModR/M \family default byte. Then, look up the byte value in this table to get the corresponding operands in the row and column. \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example An instruction uses this addressing mode: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code jmp [0x1234] \end_layout \begin_layout Standard \noindent \align left Then, the machine code is: \end_layout \begin_layout LyX-Code ff \color red 26 \color inherit 34 12 \end_layout \begin_layout Standard \noindent \align left \family typewriter 0xff \family default is the opcode. Next to it, \family typewriter \color red 0x26 \family default \color inherit is the \family typewriter ModR/M \family default byte. Look up in the 16-bit table \begin_inset Marginal status open \begin_layout Plain Layout Remember, using \family typewriter bin \family default format generates 16-bit code by default \end_layout \end_inset , the first operand is in the row, equivalent to a \family typewriter disp16 \family default , which means a 16-bit offset. Since the instruction does not have a second operand, the column can be ignored. \end_layout \begin_layout Example An instruction uses this addressing mode: \end_layout \begin_layout LyX-Code add eax, ecx \end_layout \begin_layout Standard \noindent \align left Then the machine code is: \end_layout \begin_layout LyX-Code 66 01 \color red c8 \end_layout \begin_layout Standard \noindent \align left The interesting feature of this instruction is that \family typewriter 0x66 \family default is the not the opcode. \family typewriter 0x01 \family default is the opcode. So then, what is \family typewriter 0x66 \family default ? Recall that for every assembly instruction, there will be an optional instruction prefix, and that is what \family typewriter 0x66 \family default is. According to the Intel manual, vol 1: \end_layout \begin_layout Quote The operand-size override prefix allows a program to switch between 16- and 32-bit operand sizes. Either size can be the default; use of the prefix selects the non-default size. \end_layout \begin_layout Standard If the CPU is switched to 32-bit mode, when it runs an instruction with \family typewriter 0x66 \family default prefix, the instruction operands are limited to only 16-bit width. On the other hand, if the CPU is in 16-bit environment, as a result, 32-bit is considered non-standard and as such, instruction operands are temporary upgraded to 32-bit width while the instructions without the prefix use 16-bit operands. \end_layout \begin_layout Standard \noindent \align left Next to it, \family typewriter \color red c8 \color inherit \family default is the \family typewriter ModR/M \family default byte. Look up in the 16-bit table at \family typewriter \color red c8 \family default \color inherit value, the row tells the first operand is \family typewriter ax \family default \begin_inset Marginal status open \begin_layout Plain Layout Remember, using bin format generates 16-bit code by default \end_layout \end_inset , the column tells the second operand is \family typewriter cx \family default ; the column can't be ignored as the second operand is in the instruction. \end_layout \begin_layout Standard Why is the first operand in the row and the second in a column? Let's break down the \family typewriter ModR/M \family default byte, with an example value \family typewriter c8 \family default , into bits: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align center \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold mod \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold reg/opcode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold r/m \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \end_inset \end_layout \begin_layout Standard The \family typewriter mod \family default field divides addressing modes into 4 different categories. Further combines with the \family typewriter r/m \family default field, exactly one addressing mode can be selected from one of the 24 rows. If an instruction only requires one operand, then the column can be ignored. Then the \family typewriter reg/opcode \family default field finally provides an extra register or different variants, if an instructi on requires one. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Description \family typewriter SIB \family default \series bold \series default is \series bold \emph on S \series default cale- \series bold I \series default ndex- \series bold B \series default ase \emph default byte. This byte encodes ways to calculate the memory position into an element of an array. SIB is the name that is based on this formula for calculating an effective address: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align center \begin_inset Formula $\mathtt{Effective\,address=scale*index+base}$ \end_inset \end_layout \begin_layout Itemize \family typewriter Index \family default is an offset into an array. \end_layout \begin_layout Itemize \family typewriter Scale \family default is a factor of \family typewriter Index \family default . \family typewriter Scale \family default is one of the values 1, 2, 4 or 8; any other value is invalid. To scale with values other than 2, 4 or 8, the scale factor must be set to 1, and the offset must be calculated manually. For example, if we want to get the address of the \family typewriter n \begin_inset script superscript \begin_layout Plain Layout \family typewriter th \end_layout \end_inset \family default element in an array and each element is \family typewriter 12 \family default -bytes long. Because each element is 12-bytes long instead of 1, 2, 4 or 8, \family typewriter Scale \family default is set to 1 and a compiler needs to calculate the offset: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align center \begin_inset Formula $\mathtt{Effective\,address=1*(12*n)+base}$ \end_inset \end_layout \begin_layout Standard Why do we bother with SIB when we can manually calculate the offset? The answer is that in the above scenario, an additional \family typewriter mul \family default instruction must be executed to get the offset, and the \family typewriter mul \family default instruction consumes more than 1 byte, while the SIB only consumes 1 byte. More importantly, if the element is repeatedly accessed many times in a loop, e.g. millions of times, then an extra \family typewriter mul \family default instruction can detriment the performance as the CPU must spend time executing millions of these additional \family typewriter mul \family default instructions. \end_layout \begin_layout Standard The values 2, 4 and 8 are not random chosen. They map to 16-bit (or 2 bytes), 32-bit (or 4 bytes) and 64-bit (or 8 bytes) numbers that are often used for intensive numeric calculations. \end_layout \end_deeper \begin_layout Itemize \family typewriter Base \family default is the starting address. \end_layout \begin_layout Standard Below is the table listing all 256 values of \family typewriter SIB \family default byte, with the lookup rule similar to \family typewriter ModR/M \family default tables: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begingroup \backslash tabcolsep=2pt \backslash def \backslash arraystretch{0.7} \end_layout \begin_layout Plain Layout \backslash begin{table*} \end_layout \begin_layout Plain Layout \backslash setlength{ \backslash arrayrulewidth}{.2mm} \end_layout \begin_layout Plain Layout \backslash caption{32-Bit Addressing Forms with the SIB Byte} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize r32(/r) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EAX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ECX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EDX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EBX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ESP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EBP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize ESI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EDI \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize (In decimal) /digit (Opcode) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize (In binary) REG = \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Effective Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset SS \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset R/M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Values of SIB Byte (In Hexadecimal) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 13 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 14 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 15 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 17 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 18 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 19 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize none \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 20 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 21 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 22 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 23 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 24 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 25 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 26 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 27 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBP] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 28 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 29 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 30 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 31 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 33 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 34 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 35 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 36 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 37 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 38 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 39 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 3A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 3B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 3C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 3D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 3E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 3F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 40 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 41 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 42 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 43 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 44 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 45 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 46 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 47 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 48 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 49 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 50 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 51 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 52 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 53 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 54 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 55 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 56 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 57 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 58 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 59 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 5A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 5B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 5C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 5D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 5E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 5F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize none \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 60 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 61 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 62 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 63 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 64 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 65 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 66 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 67 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBP*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 68 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 69 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 6A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 6B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 6C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 6D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 6E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 6F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 70 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 71 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 72 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 73 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 74 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 75 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 76 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 77 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI*2] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 78 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 79 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 7A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 7B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 7C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 7D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 7E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 7F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 80 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 81 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 82 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 83 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 84 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 85 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 86 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 87 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 88 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 89 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 8A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 8B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 8C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 8D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 8E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 8F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 90 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 91 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 92 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 93 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 94 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 95 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 96 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 97 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 98 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 99 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 9A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 9B \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 9C \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 9D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 9E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 9F \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize none \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBP*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter AA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter AB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter AC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter AD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter AE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter AF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI*4] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter B9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter BA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter BB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter BC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter BD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter BE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter BF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EAX*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 11 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ECX*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter C9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter CA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter CB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter CC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter CD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter CE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter CF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDX*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBX*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 011 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter D9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize none \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 100 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EBP*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 101 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter EA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter EB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter EC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ED \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter EE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter EF \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [ESI*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 110 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F7 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize [EDI*8] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \size footnotesize 111 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter F9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter FA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter FB \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter FC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter FD \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter FE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter FF \end_layout \end_inset \begin_inset Text \begin_layout Enumerate \family sans \size footnotesize The [*] nomenclature means a disp32 with no base if the MOD is 00B. Otherwise, [*] means disp8 or disp32 + [EBP]. This provides the following address modes: \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize MOD bits \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Effective Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize [scaled index] + disp32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize [scaled index] + disp8 + [EBP] \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize 10 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize [scaled index] + disp32 + [EBP] \end_layout \end_inset \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \begin_inset CommandInset label LatexCommand label name "sib" \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{table*} \end_layout \begin_layout Plain Layout \backslash endgroup \end_layout \end_inset \end_layout \begin_layout Example This instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code jmp [eax*2 + ebx] \end_layout \begin_layout Standard generates the following code: \end_layout \begin_layout LyX-Code \family typewriter 00000000 67 ff 24 \color red 43 \end_layout \begin_layout Standard First of all, the first byte, \family typewriter 0x67 \family default is \emph on not \emph default an opcode but a \emph on prefix \emph default . The number is a predefined prefix for address-size override prefix. After the prefix, comes the opcode \family typewriter 0xff \family default and the \family typewriter ModR/M \family default byte \family typewriter 0x24 \family default . The value from \family typewriter ModR/M \family default suggests that there exists a \family typewriter SIB \family default byte that follows. The \family typewriter SIB \family default byte is \family typewriter \color red 0x43 \family default \color inherit . \end_layout \begin_layout Standard Look up in the \family typewriter SIB \family default table, the row tells that \family typewriter eax \family default is scaled by 2, and the column tells that the base to be added is in \family typewriter ebx \family default . \end_layout \end_deeper \end_deeper \begin_layout Description \family typewriter Displacement \family default is the offset from the start of the base index. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example This instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code jmp [ \color red 0x1234 \color inherit ] \end_layout \begin_layout Standard generates machine code is: \end_layout \begin_layout LyX-Code ff 26 \color red 34 12 \color inherit \end_layout \begin_layout Standard \family typewriter \color red 0x1234 \family default \color inherit , which is generated as \family typewriter 34 12 \family default in raw machine code, is the displacement and stands right next to \family typewriter 0x26 \family default , which is the \family typewriter ModR/M \family default byte. \end_layout \begin_layout Example This instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code jmp [eax * 4 + \color red 0x1234 \color inherit ] \end_layout \end_deeper \begin_layout Standard generates the machine code: \end_layout \begin_layout LyX-Code 67 ff 24 85 \color red 34 12 00 00 \end_layout \begin_layout Itemize \family typewriter 0x67 \family default is an address-size override prefix. Its meaning is that if an instruction runs a default address size e.g. 16-bit, the use of prefix enables the instruction to use non-default address size, e.g. 32-bit or 64-bit. Since the binary is supposed to be 16-bit, \family typewriter 0x67 \family default changes the instruction to 32-bit mode. \end_layout \begin_layout Itemize \family typewriter 0xff \family default is the opcode. \end_layout \begin_layout Itemize \family typewriter 0x24 \family default is the \family typewriter ModR/M \family default byte. According to table \begin_inset CommandInset ref LatexCommand formatted reference "mod-rm-32" \end_inset , the value suggests that a SIB byte follows, . \end_layout \begin_layout Itemize \family typewriter 0x85 \family default is the \family typewriter SIB \family default byte. According to table \begin_inset CommandInset ref LatexCommand formatted reference "sib" plural "false" caps "false" noprefix "false" \end_inset , the byte \family typewriter 0x85 \family default can be destructured into bits as follow: \end_layout \begin_deeper \begin_layout Standard \noindent \align center \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold SS \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold R/M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold REG \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \end_inset \end_layout \begin_layout Standard The above values are obtained through the columns \series bold SS \series default , \series bold R/M \series default and finally the 8 column of \series bold REG \series default respectively. The total bits combined into the value \family typewriter 10000101 \family default , which is \family typewriter 0x85 \family default in hex value. By default, if a register after the displacement is not specified, it is set to \family typewriter EBP \family default register, and thus the 6 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset column (bit pattern \family typewriter 101 \family default ) is always chosen. If the example uses another register: \end_layout \begin_layout Example For example: \end_layout \begin_layout LyX-Code jmp [eax * 4 + eax + \color red esi \color inherit ] \end_layout \begin_layout Standard the \family typewriter SIB \family default byte becomes \family typewriter 0x86 \family default instead of , which is in the 7 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset column. Try to verify with the table \begin_inset CommandInset ref LatexCommand formatted reference "sib" plural "false" caps "false" noprefix "false" \end_inset again. \end_layout \end_deeper \begin_layout Itemize \family typewriter \color red 34 12 00 00 \color inherit \family default is the displacement. As can be seen, the displacement is 4 bytes in size, which is equivalent to 32-bit, due to address-size override prefix. \end_layout \end_deeper \end_deeper \begin_layout Description \family typewriter Immediate \family default When an instruction accepts a fixed value, e.g. \family typewriter 0x1234 \family default , as an operand, this optional field holds the value. Note that this field is different from displacement: the value is not necessary used an offset, but an arbitrary value of anything. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example This instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code mov eax, \color red 0x1234 \end_layout \begin_layout Standard generates the code: \end_layout \begin_layout LyX-Code 66 b8 34 12 00 00 \end_layout \begin_layout Itemize \family typewriter 0x66 \family default is operand-sized override prefix. Similar to address-size override prefix, this prefix enables operand-size to be non-default. \end_layout \begin_layout Itemize \family typewriter 0xb8 \family default is one of the opcodes for \family typewriter mov \family default instruction. \end_layout \begin_layout Itemize \family typewriter 0x1234 \family default is the value to be stored in register \family typewriter eax \family default . It is just a value for storing directly into a register, and nothing more. On the other hand, displacement value is an offset for some address calculation. \end_layout \end_deeper \end_deeper \begin_layout Exercise Read section 2.1 in Volume 2 for even more details. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Exercise Skim through section 5.1 in volume 1. Read chapter 7 in volume 1. If there are terminologies that you don't understand e.g. segmentation, don't worry as the terms will be explained in later chapters or ignored. \end_layout \end_deeper \begin_layout Section Understand an instruction in detail \end_layout \begin_layout Standard In the instruction reference manual (Volume 2), from chapter 3 onward, every x86 instruction is documented in detail. Whenever the precise behavior of an instruction is needed, we always consult this document first. However, before using the document, we must know the writing conventions first. Every instruction has the following common structure for organizing information : \end_layout \begin_layout Description \family typewriter Opcode \begin_inset space ~ \end_inset table \family default lists all possible opcodes of an assembly instruction. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Each table contains the following fields, and can have one or more rows: \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Opcode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Instruction \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Op/En \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize 64/32-bit Mode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize CPUID \begin_inset Newline newline \end_inset Feature flag \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Description \end_layout \end_inset \end_inset \end_layout \begin_layout Description \family typewriter Opcode \family default shows \family typewriter \family default a unique hexadecimal number assigned to an instruction. There can be more than one opcode for an instruction, each encodes a variant of the instruction. For example, one variant requires one operand, but another requires two. In this column, there can be other notations aside from hexadecimal numbers. For example, \family typewriter /r \family default indicates that the \family typewriter ModR/M \family default byte of the instruction contains a \family typewriter reg \family default operand and an \family typewriter r/m \family default operand. The detail listing is in section \emph on 3.1.1.1 \emph default and \emph on 3.1.1.2 \emph default in the Intel's manual, volume 2. \end_layout \begin_layout Description \family typewriter Instruction \family default gives the syntax of the assembly instruction that a programmer can use for writing code. Aside from the mnemonic representation of the opcode, e.g. \family typewriter jmp \family default , other symbols represent operands with specific properties in the instruction. For example, \family typewriter rel8 \family default represents a relative address from 128 bytes before the end of the instruction to 127 bytes after the end of instruction; similarly \family typewriter rel16/rel32 \family default also represents relative addresses, but with the operand size of 16/32-bit instead of 8-bit like \family typewriter rel8 \family default . For a detailed listing, please refer to section \family typewriter 3.1.1.3 \family default of volume 2. \end_layout \begin_layout Description \family typewriter Op/En \family default is short for \series bold \emph on Op \series default erand/ \series bold En \series default coding \emph default . An operand encoding specifies how a \family typewriter ModR/M \family default byte encodes the operands that an instruction requires. If a variant of an instruction requires operands, then an additional table named \emph on \begin_inset Quotes eld \end_inset Instruction Operand Encoding \begin_inset Quotes erd \end_inset \emph default is added for explaining the operand encoding, with the following structure: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Op/En \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Operand 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Operand 2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Operand 3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \size footnotesize Operand 4 \end_layout \end_inset \end_inset \end_layout \begin_layout Standard Most instructions require one to two operands. We make use of these instructions for our OS and skip the instructions that require three or four operands. The operands can be readable or writable or both. The symbol \family typewriter (r) \family default denotes a readable operand, and \family typewriter (w) \family default denotes a writable operand. For example, when \family typewriter Operand 1 \family default field contains \family typewriter ModRM:r/m (r) \family default , it means the first operand is encoded in \family typewriter r/m \family default field of \family typewriter ModR/M \family default byte, and is only \family typewriter readable \family default . \family typewriter \end_layout \end_deeper \begin_layout Description \family typewriter 64/32-bit \begin_inset space ~ \end_inset mode \family default indicates whether the opcode sequence is supported in a 64-bit mode and possibly 32-bit mode. \end_layout \begin_deeper \begin_layout Description \family typewriter CPUID \begin_inset space ~ \end_inset Feature \begin_inset space ~ \end_inset Flag \family default indicates a particular CPU feature must be available to enable the instruction. An instruction is invalid if a CPU does not support the required feature. \begin_inset Marginal status collapsed \begin_layout Plain Layout In Linux, the command: \end_layout \begin_layout LyX-Code cat /proc/cpuinfo \end_layout \begin_layout Plain Layout lists the information of available CPUs and its features in \family typewriter flags \family default field. \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Description \family typewriter Compat/Leg \begin_inset space ~ \end_inset Mode \family default Many instructions do not have this field, but instead is replaced with \family typewriter Compat/Leg Mode \family default , which stands for \emph on Compatibility or Legacy Mode \emph default . This mode enables 64-bit variants of instructions to run normally in 16 or 32-bit mode. \begin_inset Float margintable wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Notations in \family typewriter Compat/Leg Mode \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Notation \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Supported \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter I \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Not supported \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter N.E. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The 64-bit opcode cannot be encoded as it overlaps with existing 32-bit opcode. \end_layout \end_inset \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter Description \family default briefly explains the variant of an instruction in the current row. \end_layout \end_deeper \begin_layout Description \family typewriter Description \family default specifies the purpose of the instructions and how an instruction works in detail. \end_layout \begin_layout Description \family typewriter Operation \family default is pseudo-code that implements an instruction. If a description is vague, this section is the next best source to understand an assembly instruction. The syntax is described in section \emph on 3.1.1.9 \emph default in volume 2. \end_layout \begin_layout Description \family typewriter Flags \begin_inset space ~ \end_inset affected \family default lists the possible changes to system flags in \family typewriter EFLAGS \family default register. \end_layout \begin_layout Description \family typewriter Exceptions \family default list the possible errors that can occur when an instruction cannot run correctly. This section is valuable for OS debugging. Exceptions fall into one of the following categories: \end_layout \begin_layout Itemize Protected Mode Exceptions \end_layout \begin_layout Itemize Real-Address Mode Exception \end_layout \begin_layout Itemize Virtual-8086 Mode Exception \end_layout \begin_layout Itemize Floating-Point Exception \end_layout \begin_layout Itemize SIMD Floating-Point Exception \end_layout \begin_layout Itemize Compatibility Mode Exception \end_layout \begin_layout Itemize 64-bit Mode Exception \end_layout \begin_layout Standard For our OS, we only use \emph on Protected Mode Exceptions \emph default and \emph on Real-Address Mode Exceptions \emph default . The details are in section \emph on 3.1.1.13 \emph default and \emph on 3.1.1.14 \emph default , volume 2. \end_layout \begin_layout Section Example: \family typewriter jmp \family default instruction \end_layout \begin_layout Standard Let's look at our good old \family typewriter jmp \family default instruction. First, the opcode table: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begingroup \backslash tabcolsep=2pt \backslash def \backslash arraystretch{1} \end_layout \begin_layout Plain Layout \backslash begin{table*} \end_layout \begin_layout Plain Layout \backslash setlength{ \backslash arrayrulewidth}{.2mm} \end_layout \begin_layout Plain Layout \backslash caption{ \backslash texttt{jmp} opcode table} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Opcode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Instruction \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Op/ \end_layout \begin_layout Plain Layout \family sans \series bold \size footnotesize En \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize 64-bit Mode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Compat/Leg Mode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \series bold \size footnotesize Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EB cb \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP rel8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump short, RIP = RIP + 8-bit displacement sign extended to 64-bits \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize E9 cw \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP rel16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize N.S. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump near, relative, displacement relative to next instruction. Not supported in 64-bit mode. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize E9 cd \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP rel32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump near, relative, RIP = RIP + 32-bit displacement sign extended to 64-bits \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize FF /4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP r/m16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize N.S. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump near, absolute indirect, address = zero- extended r/m16. Not supported in 64-bit mode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize FF /4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP r/m32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize N.S. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump near, absolute indirect, address given in r/m32. Not supported in 64-bit mode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize FF /4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP r/m64 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize N.E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump near, absolute indirect, RIP = 64-Bit offset from register or memory \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EA cd \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP ptr16:16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Inv. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump far, absolute, address given in operand \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize EA cp \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP ptr16:32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Inv. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump far, absolute, address given in operand \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize FF /5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP m16:16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump far, absolute indirect, address given in m16:16 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize FF /5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP m16:32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump far, absolute indirect, address given in m16:32 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize REX.W + FF /5 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize JMP m16:64 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize D \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Valid \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize N.E. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family sans \size footnotesize Jump far, absolute indirect, address given in m16:64 \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset CommandInset label LatexCommand label name "jmp-instruction" \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash hfill \backslash break \end_layout \begin_layout Plain Layout \backslash end{table*} \end_layout \begin_layout Plain Layout \backslash endgroup \end_layout \end_inset \end_layout \begin_layout Standard Each row lists a variant of \family typewriter jmp \family default instruction. The first column has the opcode \family typewriter EB cb \family default , with an equivalent symbolic form \family typewriter jmp rel8 \family default . Here, \family typewriter rel8 \family default means 128 bytes offset, counting from the end of the instruction. The end of an instruction is the next byte after the last byte of an instructio n. To make it more concrete, consider this assembly code: \end_layout \begin_layout LyX-Code main: \end_layout \begin_layout LyX-Code \color red jmp main \end_layout \begin_layout LyX-Code \color blue jmp main2 \end_layout \begin_layout LyX-Code jmp main \end_layout \begin_layout LyX-Code main2: \end_layout \begin_layout LyX-Code \color green jmp 0x1234 \end_layout \begin_layout Standard \noindent \align left generates the machine code: \end_layout \begin_layout Standard \noindent \align center \begin_inset Float table wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Memory address of each opcode \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter main \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter main2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color magenta 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color magenta 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color magenta 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Opcode \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color red eb \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color red fe \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue eb \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter eb \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter fa \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color green e9 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color green 2b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color green 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \noindent \align left The first \family typewriter \color red jmp main \family default \color inherit instruction is generated into \family typewriter \color red eb fe \family default \color inherit and occupies the addresses \family typewriter 00 \family default and \family typewriter 01 \family default ; the end of the first \family typewriter \color red jmp main \family default \color inherit is at address \family typewriter \color magenta 02 \family default \color inherit , past the last byte of the first \family typewriter \color red jmp main \family default \color inherit which is located at the address \family typewriter 01 \family default . The value \family typewriter \color red fe \color inherit \family default is equivalent to \family typewriter -2 \family default , since \family typewriter \color red eb \family default \color inherit opcode uses only a byte (8 bits) for relative addressing. The offset is \family typewriter -2 \family default , and the end address of the first \family typewriter \color red jmp main \family default \color inherit is \family typewriter 02 \family default , adding them together we get \family typewriter 00 \family default which is the destination address for jumping to. \end_layout \begin_layout Standard \noindent \align left Similarly, the \family typewriter \color blue jmp main2 \family default \color inherit instruction is generated into \family typewriter \color blue eb 02 \family default \color inherit , which means the offset is \family typewriter +2 \family default ; the end address of \family typewriter \color blue jmp main2 \family default \color inherit is at \family typewriter \color magenta 04 \family default \color inherit , and adding together with the offset we get the destination address is \family typewriter 06 \family default , which is the start instruction marked by the label \family typewriter main2 \family default . \end_layout \begin_layout Standard The same rule can be applied to \family typewriter rel16 \family default and \family typewriter rel32 \family default encoding. In the example code, \family typewriter \color green jmp 0x1234 \color inherit \family default uses \family typewriter rel16 \family default (which means 2-byte offset) and is generated into \family typewriter \color green e9 2b 12 \family default \color inherit . As the table \begin_inset CommandInset ref LatexCommand formatted reference "jmp-instruction" \end_inset shows, \family typewriter e9 \family default opcode takes a \family typewriter cw \family default operand, which is a 2-byte offset (section \emph on 3.1.1.1 \emph default , volume 2). Notice one strange issue here: the offset value is \family typewriter \color green 2b 12 \family default \color inherit , while it is supposed to be \family typewriter 34 12 \family default . There is nothing wrong. Remember, \family typewriter rel8/rel16/rel32 \family default is an \emph on offset \emph default , not an \emph on address \emph default . A offset is a distance from a point. Since no label is given but a number, the offset is calculated from the start of a program. In this case, the start of the program is the address \family typewriter 00 \family default , the end of \family typewriter \color green jmp 0x1234 \family default \color inherit is the address \family typewriter \color magenta 09 \family default \color inherit \begin_inset Foot status open \begin_layout Plain Layout which means 9 bytes was consumed, starting from address 0. \end_layout \end_inset , so the offset is calculated as \family typewriter 0x1234 - 0x9 = 0x122b \family default . That solved the mystery! \end_layout \begin_layout Standard The \family typewriter jmp \family default instructions with opcode \family typewriter FF /4 \family default enable jumping to a \emph on near, absolute \emph default address stored in a general-purpose register or a memory location; or in short, as written in the description, \emph on absolute indirect \emph default . The symbol \family typewriter /4 \family default is the column with digit 4 in table \begin_inset CommandInset ref LatexCommand formatted reference "mod-rm-16" \end_inset \begin_inset Foot status collapsed \begin_layout Plain Layout The column with the following fields: \end_layout \begin_layout Plain Layout \family typewriter AH \end_layout \begin_layout Plain Layout \family typewriter SP \end_layout \begin_layout Plain Layout \family typewriter ESP \end_layout \begin_layout Plain Layout \family typewriter M45 \end_layout \begin_layout Plain Layout \family typewriter XMM4 \end_layout \begin_layout Plain Layout \family typewriter 4 \end_layout \begin_layout Plain Layout \family typewriter 100 \end_layout \end_inset . For example: \end_layout \begin_layout LyX-Code jmp \color blue [0x1234] \end_layout \begin_layout Standard \noindent \align left is generated into: \end_layout \begin_layout LyX-Code ff \color blue 26 \color inherit \color blue 34 12 \end_layout \begin_layout Standard \noindent \align left Since this is 16-bit code, we use table \begin_inset CommandInset ref LatexCommand formatted reference "mod-rm-16" \end_inset . Looking up the table, \family typewriter ModR/M \family default value \family typewriter 26 \family default means \family typewriter disp16 \family default , which means a 16-bit offset from the start of current index \begin_inset Foot status open \begin_layout Plain Layout Look at the note under the table. \end_layout \end_inset , which is the base address stored in \family typewriter DS \family default register. In this case, \family typewriter jmp [0x1234] \family default is implicitly understood as \family typewriter jmp [ds: \color blue 0x1234 \color inherit ] \family default , which means the destination address is \family typewriter 0x1234 \family default bytes away from the start of a data segment. \end_layout \begin_layout Standard The \family typewriter jmp \family default instruction with opcode \family typewriter FF /5 \family default enables jumping to a \emph on far, absolute \emph default address stored in a \emph on memory location \emph default (as opposed to \family typewriter /4 \family default , which means stored in a register); in short, \emph on a far pointer \emph default . To generate such instruction, the keyword \family typewriter far \family default is needed to tell \family typewriter nasm \family default we are using a far pointer: \end_layout \begin_layout LyX-Code jmp \color red far \color inherit [eax] \end_layout \begin_layout Standard \noindent \align left is generated into: \end_layout \begin_layout LyX-Code 67 ff \color red 28 \end_layout \begin_layout Standard \noindent \align left Since \family typewriter \color red 28 \family default \color inherit is the value in the 5th column of the table \begin_inset CommandInset ref LatexCommand formatted reference "mod-rm-32" \end_inset \begin_inset Foot status collapsed \begin_layout Plain Layout Remember the prefix \family typewriter 67 \family default indicates the instruction is used as 32-bit. The prefix only added if the default environment is assumed as 16-bit when generating code by an assembler. \end_layout \end_inset that refers to \family typewriter [eax] \family default , we successfully generate an instruction for a far jump. After CPU runs the instruction, the program counter \family typewriter eip \family default and code segment register \family typewriter cs \family default is set to the memory address, stored in the memory location that \family typewriter eax \family default points to, and CPU starts fetching code from the new address in \family typewriter cs \family default and \family typewriter eip \family default . To make it more concrete, here is an example: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{far \backslash texttt{jmp} example, with the destination memory stored at address \backslash texttt{0x1000}, which is stored in \backslash texttt{eax} to be dereferenced. After CPU executes the instruction, code segment register \backslash texttt{cs} and instruction pointer \backslash texttt{eip} } \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/04/far_jmp_ex.pdf scale 90 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left The far address consumes total of 6 bytes in size for a 16-bit segment and 32-bit address, which is encoded as \family typewriter m16:32 \family default from the table \begin_inset CommandInset ref LatexCommand formatted reference "jmp-instruction" \end_inset . As can be seen from the figure above, the \color blue blue \color inherit part is a segment address, loaded into \family typewriter cs \family default register with the value \family typewriter \color blue 0x5678 \family default \color inherit ; the \color red red \color inherit part is the memory address within that segment, loaded into \family typewriter eip \family default register with the value \family typewriter \color red 0x1234 \family default \color inherit and start executing from there. \end_layout \begin_layout Standard Finally, the \family typewriter jmp \family default instructions with \family typewriter EA \family default opcode jump to a direct absolute address. For example, the instruction: \end_layout \begin_layout LyX-Code jmp \color blue 0x5678 \color inherit : \color red 0x1234 \end_layout \begin_layout Standard \noindent \align left is generated into: \end_layout \begin_layout LyX-Code ea \color red 34 12 \color inherit \color blue 78 56 \end_layout \begin_layout Standard \noindent \align left The address \family typewriter \color blue 0x5678 \color inherit : \color red 0x1234 \family default \color inherit is right next to the opcode, unlike \family typewriter FF /5 \family default instruction that needs an indirect address in \family typewriter eax \family default register. \end_layout \begin_layout Standard We skip the jump instruction with \family typewriter REX \family default prefix, as it is a 64-bit instruction. \end_layout \begin_layout Standard \begin_inset Note Note status open \begin_layout Plain Layout Explain the remaining sections \end_layout \end_inset \end_layout \begin_layout Section Examine compiled data \end_layout \begin_layout Standard In this section, we will examine how data definition in C maps to its assembly form. The generated code is extracted from \family typewriter .bss \family default section. That means, the assembly code displayed has no \begin_inset Foot status collapsed \begin_layout Plain Layout Actually, code is just a type of data, and is often used for hijacking into a running program to execute such code. However, we have no use for it in this book. \end_layout \end_inset , aside from showing that such a value has an equivalent assembly opcode that represents an instruction. \end_layout \begin_layout Standard The code-assembly listing is not random, but is based on \emph on Chapter 4 \emph default of Volume 1, \emph on \begin_inset Quotes eld \end_inset Data Type \begin_inset Quotes erd \end_inset \emph default . The chapter lists fundamental data types that x86 hardware operates on, and through learning the generated assembly code, it can be understood how close C maps its syntax to hardware, and then a programmer can see why C is appropriate for OS programming. The specific \family typewriter objdump \family default command used in this section will be: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -z -M intel -S -D -j .data -j .bss | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard \series bold Note: \series default zero bytes are hidden with three dot symbols: \family typewriter ... \family default To show all the zero bytes, we add \family typewriter -z \family default option. \end_layout \begin_layout Subsection Fundamental data types \end_layout \begin_layout Standard The most basic types that x86 architecture works with are based on sizes, each is twice as large as the previous one: 1 byte (8 bits), 2 bytes (16 bits), 4 bytes (32 bits), 8 bytes (64 bits) and 16 bytes (128 bits). \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Fundamental Data Types} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Graphics filename images/04/fundamental_data_types.pdf scale 50 \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Standard These types are simplest: they are just chunks of memory at different sizes that enables CPU to access memory efficiently. From the manual, \emph on section 4.1.1 \emph default , volume 1: \end_layout \begin_layout Quote Words, doublewords, and quadwords do not need to be aligned in memory on natural boundaries. The natural boundaries for words, double words, and quadwords are even-numbered addresses, addresses evenly divisible by four, and addresses evenly divisible by eight, respectively. However, to improve the performance of programs, data structures (especially stacks) should be aligned on natural boundaries whenever possible. The reason for this is that the processor requires two memory accesses to make an unaligned memory access; aligned accesses require only one memory access. A word or doubleword operand that crosses a 4-byte boundary or a quadword operand that crosses an 8-byte boundary is considered unaligned and requires two separate memory bus cycles for access. \end_layout \begin_layout Quote Some instructions that operate on double quadwords require memory operands to be aligned on a natural boundary. These instructions generate a general-protection exception ( \family typewriter #GP \family default ) if an unaligned operand is specified. A natural boundary for a double quadword is any address evenly divisible by 16. Other instructions that operate on double quadwords permit unaligned access (without generating a general-protection exception). However, additional memory bus cycles are required to access unaligned data from memory. \end_layout \begin_layout Standard In C, the following primitive types (must include \family typewriter stdint.h \family default ) maps to the fundamental types: \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Full Width \begin_inset listings inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout uint8_t @| \backslash color{red} \backslash bfseries byte|@ = 0x12; \end_layout \begin_layout Plain Layout uint16_t @| \backslash color{blue} \backslash bfseries word|@ = 0x1234; \end_layout \begin_layout Plain Layout uint32_t @| \backslash color{green} \backslash bfseries dword|@ = 0x12345678; \end_layout \begin_layout Plain Layout uint64_t @| \backslash color{magenta} \backslash bfseries qword|@ = 0x123456789abcdef; \end_layout \begin_layout Plain Layout unsigned __int128 @| \backslash color{cyan} \backslash bfseries dqword1|@ = (__int128) 0x123456789abcdef; \end_layout \begin_layout Plain Layout unsigned __int128 @| \backslash color{cyan} \backslash bfseries dqword2|@ = (__int128) 0x123456789abcdef << 64; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code \noindent \align left 0804a018 < \color red byte \color inherit >: \end_layout \begin_layout LyX-Code 804a018: \color red 12 00 \color inherit adc al,BYTE PTR [eax] \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0804a01a < \color blue word \color inherit >: \end_layout \begin_layout LyX-Code 804a01a: \color blue 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0804a01c < \color green dword \color inherit >: \end_layout \begin_layout LyX-Code 804a01c: \color green 78 56 \color inherit js 804a074 <_end+0x48> \end_layout \begin_layout LyX-Code 804a01e: \color green 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0804a020 < \color magenta qword \color inherit >: \end_layout \begin_layout LyX-Code 804a020: \color magenta ef \color inherit out dx,eax \end_layout \begin_layout LyX-Code 804a021: \color magenta cd ab \color inherit int 0xab \end_layout \begin_layout LyX-Code 804a023: \color magenta 89 67 45 \color inherit mov DWORD PTR [edi+0x45],esp \end_layout \begin_layout LyX-Code 804a026: \color magenta 23 01 \color inherit and eax,DWORD PTR [ecx] \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0000000000601040 < \color cyan dqword1 \color inherit >: \end_layout \begin_layout LyX-Code 601040: \color cyan ef \color inherit out dx,eax \end_layout \begin_layout LyX-Code 601041: \color cyan cd ab \color inherit int 0xab \end_layout \begin_layout LyX-Code 601043: \color cyan 89 67 45 \color inherit mov DWORD PTR [rdi+0x45],esp \end_layout \begin_layout LyX-Code 601046: \color cyan 23 01 \color inherit and eax,DWORD PTR [rcx] \end_layout \begin_layout LyX-Code 601048: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 60104a: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 60104c: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 60104e: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0000000000601050 < \color cyan dqword2 \color inherit >: \end_layout \begin_layout LyX-Code 601050: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601052: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601054: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601056: \color cyan 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601058: \color cyan ef \color inherit out dx,eax \end_layout \begin_layout LyX-Code 601059: \color cyan cd ab \color inherit int 0xab \end_layout \begin_layout LyX-Code 60105b: \color cyan 89 67 45 \color inherit mov DWORD PTR [rdi+0x45],esp \end_layout \begin_layout LyX-Code 60105e: \color cyan 23 01 \color inherit and eax,DWORD PTR [rcx] \end_layout \begin_layout LyX-Code \end_layout \end_deeper \begin_layout Standard \noindent \align left \family typewriter gcc \family default generates the variables \family typewriter \color red byte \family default \color inherit , \family typewriter \color blue word \family default \color inherit , \family typewriter \color green dword \family default \color inherit , \family typewriter \color magenta qword \family default \color inherit , \family typewriter \color cyan dqword1 \family default \color inherit , \family typewriter \color cyan dword2 \family default \color inherit , written earlier, with their respective values highlighted in the same colors; variables of the same type are also highlighted in the same color. Since this is data section, \family typewriter \family default the assembly listing carries no meaning. When \family typewriter byte \family default is declared with \family typewriter uint8_t \family default , \family typewriter gcc \family default guarantees that the size of \family typewriter byte \family default is always 1 byte. But, an alert reader might notice the \family typewriter \color red 00 \family default \color inherit value next to the \family typewriter \color red 12 \family default \color inherit value in the \family typewriter \color red byte \family default \color inherit variable. This is normal, as \family typewriter gcc \family default avoid memory misalignment by adding extra \emph on \begin_inset Index idx status open \begin_layout Plain Layout padding bytes \end_layout \end_inset padding bytes \emph default . To make it easier to see, we look at \family typewriter readelf \family default output of \family typewriter .data \family default section: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -x .data hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left the output is (the colors mark which values belong to which variables): \end_layout \begin_layout LyX-Code Hex dump of section '.data': \end_layout \begin_layout LyX-Code 0x00601020 00000000 00000000 00000000 00000000 ................ \end_layout \begin_layout LyX-Code 0x00601030 \color red 1200 \color blue 3412 \color inherit \color green 78563412 \color inherit \color magenta efcdab89 67452301 \color inherit ..4.xV4.....gE#. \end_layout \begin_layout LyX-Code 0x00601040 \color cyan efcdab89 67452301 00000000 00000000 \color inherit ....gE#......... \end_layout \begin_layout LyX-Code 0x00601050 \color cyan 00000000 00000000 efcdab89 67452301 \color inherit ............gE#. \end_layout \begin_layout Standard As can be seen in the \family typewriter readelf \family default output, variables are allocated storage space according to their types and in the declared order by the programmer (the colors correspond the the variables). Intel is a little-endian machine, which means smaller addresses hold bytes with smaller values, larger addresses hold byte with larger values. For example, \family typewriter 0x1234 \family default is displayed as \family typewriter 34 12 \family default ; that is, \family typewriter 34 \family default appears first at address \family typewriter 0x601032 \family default , then \family typewriter 12 \family default at \family typewriter 0x601033 \family default . The decimal values within a byte is unchanged, so we see \family typewriter 34 \family default \family typewriter 12 \family default instead of \family typewriter 43 21 \family default . This is quite confusing at first, but you will get used to it soon. \end_layout \begin_layout Standard \noindent Also, isn't it redundant when \family typewriter char \family default type is always 1 byte already and why do we bother adding \family typewriter int8_t \family default ? The truth is, \family typewriter char \family default type is not guaranteed to be 1 byte in size, but only the minimum of 1 byte in size. In C, a byte is defined to be the size of a char, and a char is defined to be smallest addressable unit of the underlying hardware platform. There are hardware devices that the smallest addressable unit is 16 bit or even bigger, which means char is 2 bytes in size and a \begin_inset Quotes eld \end_inset byte \begin_inset Quotes erd \end_inset in such platforms is actually 2 units of 8-bit bytes. \end_layout \begin_layout Standard Not all architectures support the double quadword type. Still, \family typewriter gcc \family default does provide support for 128-bit number and generate code when a CPU supports it (that is, a CPU must be 64-bit). By specifying a variable of type \family typewriter __int128 \family default or \family typewriter unsigned __int128 \family default , we get a 128-bit variable. If a CPU does not support 64-bit mode, \family typewriter gcc \family default throws an error. \end_layout \begin_layout Standard The data types in C, which represents the fundamental data types, are also called \emph on unsigned numbers \emph default . Other than numerical calculations, unsigned numbers are used as a tool for structuring data in memory; we will see this application later on the book, when various data structures are organized into bit groups. \end_layout \begin_layout Standard In all the examples above, when the value of a variable with smaller size is assigned to a variable with larger size, the value easily fits in the larger variable. On the contrary, the value of a variable with larger size is assigned to a variable with smaller size, two scenarios occur: \end_layout \begin_layout Itemize The value is greater than the maximum value of the variable with smaller layout, so it needs truncating to the size of the variable and causing incorrect value. \end_layout \begin_layout Itemize The value is smaller than the maximum value of the variable with a smaller layout, so it fits the variable. \end_layout \begin_layout Standard However, the value might be unknown until runtime and can be value, it is best not to let such implicit conversion handled by the compiler, but explicitl y controlled by a programmer. Otherwise it will cause subtle bugs that are hard to catch as the erroneous values might rarely be used to reproduce the bugs. \end_layout \begin_layout Subsection Pointer Data Types \end_layout \begin_layout Standard Pointers are variables that hold memory addresses. x86 works with 2 types of pointers: \end_layout \begin_layout Description Near \begin_inset space ~ \end_inset pointer is a 16-bit/32-bit offset within a segment, also called \emph on effective address \emph default . \end_layout \begin_layout Description Far \begin_inset space ~ \end_inset pointer is also an offset like a near pointer, but with an explicit segment selector. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Numeric Data Types} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/04/pointer_data_type.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Standard C only provides support for near pointers, since far pointers are platform dependent, such as x86. In application code, you can assume that the address of current segment starts at 0, so the offset is actually any memory address from 0 to the maximum address. \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Full Width \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int8_t i = 0; \end_layout \begin_layout Plain Layout int8_t @| \backslash color{red} \backslash bfseries *p1|@ = (int8_t *) 0x1234; \end_layout \begin_layout Plain Layout int8_t @| \backslash color{blue} \backslash bfseries *p2|@ = &i; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 0000000000601030 < \color red p1 \color inherit >: \end_layout \begin_layout LyX-Code 601030: \color red 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code 601032: \color red 00 00 \color inherit add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601034: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601036: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 0000000000601038 < \color blue p2 \color inherit >: \end_layout \begin_layout LyX-Code 601038: \color blue 41 10 60 \color inherit \color blue 00 \color inherit adc BYTE PTR [r8+0x0],spl \end_layout \begin_layout LyX-Code 60103c: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 60103e: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code Disassembly of section .bss: \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 0000000000601040 <__bss_start>: \end_layout \begin_layout LyX-Code 601040: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 0000000000601041 : \end_layout \begin_layout LyX-Code \color blue 601041 \color inherit : 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601043: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601045: 00 00 add BYTE PTR [rax],al \end_layout \begin_layout LyX-Code 601047: 00 .byte 0x0 \end_layout \end_deeper \begin_layout Standard The pointer \family typewriter \color red p1 \family default \color inherit holds a direct address with the value \family typewriter 0x1234 \family default . The pointer \family typewriter \color blue p2 \family default \color inherit holds the address of the variable \family typewriter i \family default . Note that both the pointers are 8 bytes in size (or 4-byte, if 32-bit). \end_layout \begin_layout Subsection Bit Field Data Type \end_layout \begin_layout Standard A \emph on bit field \begin_inset Index idx status open \begin_layout Plain Layout bit field \end_layout \end_inset \emph default is a contiguous sequence of bits. Bit fields allow data structuring at bit level. For example, a 32-bit data can hold multiple bit fields that represent multiples different pieces of information, such as bits 0-4 specifies the size of a data structure, bit 5-6 specifies permissions and so on. Data structures at the bit level are common for low-level programming. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure} \end_layout \begin_layout Plain Layout \backslash caption{Numeric Data Types (Source: Figure 4-6, Volume 1}. \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/04/bit_field_data_type.pdf scale 78 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure} \end_layout \end_inset \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout struct bit_field { \end_layout \begin_layout Plain Layout int data1:8; \end_layout \begin_layout Plain Layout int data2:8; \end_layout \begin_layout Plain Layout int data3:8; \end_layout \begin_layout Plain Layout int data4:8; \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout struct bit_field2 { \end_layout \begin_layout Plain Layout int data1:8; \end_layout \begin_layout Plain Layout int data2:8; \end_layout \begin_layout Plain Layout int data3:8; \end_layout \begin_layout Plain Layout int data4:8; \end_layout \begin_layout Plain Layout char data5:4; \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout struct normal_struct { \end_layout \begin_layout Plain Layout int data1; \end_layout \begin_layout Plain Layout int data2; \end_layout \begin_layout Plain Layout int data3; \end_layout \begin_layout Plain Layout int data4; \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout struct normal_struct @| \backslash color{red} \backslash bfseries ns|@ = { \end_layout \begin_layout Plain Layout .data1 = @| \backslash color{red} \backslash bfseries 0x12345678|@, \end_layout \begin_layout Plain Layout .data2 = @| \backslash color{red} \backslash bfseries 0x9abcdef0|@, \end_layout \begin_layout Plain Layout .data3 = @| \backslash color{red} \backslash bfseries 0x12345678|@, \end_layout \begin_layout Plain Layout .data4 = @| \backslash color{red} \backslash bfseries 0x9abcdef0|@, \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int @| \backslash color{blue} \backslash bfseries i|@ = 0x12345678; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout struct bit_field @| \backslash color{magenta} \backslash bfseries bf|@ = { \end_layout \begin_layout Plain Layout .data1 = @| \backslash color{magenta} \backslash bfseries 0x12|@, \end_layout \begin_layout Plain Layout .data2 = @| \backslash color{magenta} \backslash bfseries 0x34|@, \end_layout \begin_layout Plain Layout .data3 = @| \backslash color{magenta} \backslash bfseries 0x56|@, \end_layout \begin_layout Plain Layout .data4 = @| \backslash color{magenta} \backslash bfseries 0x78|@ \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout struct bit_field2 @| \backslash color{green} \backslash bfseries bf2|@ = { \end_layout \begin_layout Plain Layout .data1 = @| \backslash color{green} \backslash bfseries 0x12|@, \end_layout \begin_layout Plain Layout .data2 = @| \backslash color{green} \backslash bfseries 0x34|@, \end_layout \begin_layout Plain Layout .data3 = @| \backslash color{green} \backslash bfseries 0x56|@, \end_layout \begin_layout Plain Layout .data4 = @| \backslash color{green} \backslash bfseries 0x78|@, \end_layout \begin_layout Plain Layout .data5 = @| \backslash color{green} \backslash bfseries 0xf|@ \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Each variable and its value are given a unique color in the assembly listing below: \end_layout \begin_layout LyX-Code 0804a018 < \color red ns \color inherit >: \end_layout \begin_layout LyX-Code 804a018: \color red 78 56 \color inherit js 804a070 <_end+0x34> \end_layout \begin_layout LyX-Code 804a01a: \color red 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code 804a01c: \color red f0 de bc 9a 78 56 34 \color inherit lock fidivr WORD PTR [edx+ebx*4+0x12345678] \end_layout \begin_layout LyX-Code 804a023: \color red 12 \end_layout \begin_layout LyX-Code 804a024: \color red f0 de bc 9a 78 56 34 \color inherit lock fidivr WORD PTR [edx+ebx*4+0x12345678] \end_layout \begin_layout LyX-Code 804a02b: \color red 12 \end_layout \begin_layout LyX-Code 0804a028 < \color blue i \color inherit >: \end_layout \begin_layout LyX-Code 804a028: \color blue 78 56 \color inherit js 804a080 <_end+0x44> \end_layout \begin_layout LyX-Code 804a02a: \color blue 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code 0804a02c < \color magenta bf \color inherit >: \end_layout \begin_layout LyX-Code 804a02c: \color magenta 12 34 56 \color inherit adc dh,BYTE PTR [esi+edx*2] \end_layout \begin_layout LyX-Code \color magenta 804a02f \color inherit : \color blue \color magenta 78 \color inherit 12 \color magenta \color blue \color inherit js 804a043 <_end+0x7> \end_layout \begin_layout LyX-Code 0804a030 < \color green bf2 \color inherit >: \end_layout \begin_layout LyX-Code 804a030: \color green 12 34 56 \color inherit adc dh,BYTE PTR [esi+edx*2] \end_layout \begin_layout LyX-Code 804a033: \color green 78 0f \color inherit js 804a044 <_end+0x8> \end_layout \begin_layout LyX-Code 804a035: \color green 00 00 \color inherit add BYTE PTR [eax],al \end_layout \begin_layout LyX-Code 804a037: \color green 00 \color blue \color inherit .byte 0x0 \end_layout \end_deeper \begin_layout Standard The sample code creates 4 variables: \family typewriter \color red ns \family default \color inherit , \family typewriter \color blue i \family default \color inherit , \family typewriter \color magenta bf \family default \color inherit , \family typewriter \color green bf2 \family default \color inherit . The definition of \family typewriter normal_struct \family default and \family typewriter bit_field \family default structs both specify 4 integers. \family typewriter bit_field \family default specifies additional information next to its member name, separated by a colon, e.g. \family typewriter .data1 : 8 \family default . This extra information is the bit width of each bit group. It means, even though defined as an \family typewriter int \family default , \family typewriter .data1 \family default only consumes 8 bit of information. If additional data members are specified after \family typewriter .data1 \family default , two scenarios happen: \end_layout \begin_layout Itemize If the new data members fit within the remaining bits after \family typewriter .data \family default , which are 24 bits \begin_inset Foot status collapsed \begin_layout Plain Layout Since .data1 is declared as an int, 32 bits are still allocated, but \family typewriter .data1 \family default can only access 8 bits of information. \end_layout \end_inset , then the total size of \family typewriter bit_field \family default struct is still 4 bytes, or 32 bits. \end_layout \begin_layout Itemize If the new data members don't fit, then the remaining 24 bits (3 bytes) are still allocated. However, the new data members are allocated brand new storages, without using the previous 24 bits. \end_layout \begin_layout Standard In the example, the 4 data members: \family typewriter .data1 \family default , \family typewriter .data2 \family default , \family typewriter .data3 \family default and \family typewriter .data4 \family default , each can access 8 bits of information, and together can access all of 4 bytes of the integer first declared by \family typewriter .data1 \family default . As can be seen by the generated assembly code, the values of \family typewriter bf \family default are follow natural order as written in the C code: \family typewriter \color red 12 34 56 78 \family default \color inherit , since each value is a separate members. In contrast, the value of \family typewriter i \family default is a number as a whole, so it is subject to the rule of little endianess and thus contains the value \family typewriter \color blue 78 \family default \family typewriter 56 34 12 \family default \color inherit . Note that at \family typewriter \color magenta 804a02f \family default \color inherit , is the address of the final byte in \color magenta \family typewriter bf \family default \color inherit , but next to it is a number \family typewriter 12 \family default , despite \family typewriter 78 \family default is the last number in it. This extra number \family typewriter 12 \family default does not belong to the value of \family typewriter \color magenta bf \family default \color inherit . \family typewriter objdump \family default is just being confused that \family typewriter 78 \family default is an opcode; \family typewriter 78 \family default corresponds to \family typewriter js \family default instruction, and it requires an operand. For that reason, \family typewriter objdump \family default grabs whatever the next byte after 78 and put it there. \family typewriter objdump \family default is a tool to display assembly code after all. A better tool to use is \family typewriter gdb \family default that we will learn in the next chapter. But for this chapter, \family typewriter objdump \family default suffices. \end_layout \begin_layout Standard Unlike \family typewriter bf \family default , each data member in \family typewriter ns \family default is allocated fully as an integer, 4 bytes each, 16 bytes in total. As we can see, bit field and normal struct are different: bit field structure data at the bit level, while normal struct works at byte level. \end_layout \begin_layout Standard Finally, the struct of \family typewriter \color green bf2 \color inherit \begin_inset Foot status open \begin_layout Plain Layout bit_field2 \end_layout \end_inset \family default is the same of \family typewriter \color magenta bf \family default \color inherit \begin_inset Foot status open \begin_layout Plain Layout bit_field \end_layout \end_inset , except it contains one more data member: \family typewriter .data5 \family default , and is defined as a \begin_inset Flex Code status open \begin_layout Plain Layout char \end_layout \end_inset . For this reason, another 4 bytes are allocated just for \family typewriter .data5 \family default , even though it can only access 4 bits of information, and the final value of \family typewriter \color green bf2 \family default \color inherit is: \family typewriter \color green 12 34 56 78 0f 00 00 00 \family default \color inherit . The remaining 3 bytes must be accessed by the mean of a pointer, or casting to another data type that can fully access all 4 bytes.. \end_layout \begin_layout Exercise What happens when the definition of \family typewriter bit_field \family default struct and \family typewriter bf \family default variable are changed to: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code struct bit_field { \end_layout \begin_layout LyX-Code int data1:8; \end_layout \begin_layout LyX-Code }; \end_layout \begin_layout LyX-Code struct bit_field bf = { \end_layout \begin_layout LyX-Code .data1 = 0x1234, \end_layout \begin_layout LyX-Code }; \end_layout \begin_layout Standard What will be the value of \family typewriter .data1 \family default ? \end_layout \begin_layout Exercise What happens when the definition of \family typewriter bit_field2 \family default struct is changed to: \end_layout \begin_layout LyX-Code struct bit_field2 { \end_layout \begin_layout LyX-Code int data1:8; \end_layout \begin_layout LyX-Code int data5:32; \end_layout \begin_layout LyX-Code }; \end_layout \begin_layout Standard What is layout of a variable of type \family typewriter bit_field2? \end_layout \end_deeper \begin_layout Subsection String Data Types \end_layout \begin_layout Standard Although share the same name, string as defined by x86 is different than a string in C. x86 defines string as \emph on \begin_inset Quotes eld \end_inset continuous sequences of bits, bytes, words, or doublewords \begin_inset Quotes erd \end_inset \emph default . On the other hand, C defines a string as an array of 1-byte characters with a zero as the last element of the array to make a \emph on null-terminated string \emph default . This implies that strings in x86 are arrays, not C strings. A programmer can define an array of bytes, words or doublewords with \family typewriter char \family default or \family typewriter uint8_t \family default , \family typewriter short \family default or \family typewriter uint16_t \family default and \family typewriter int \family default or \family typewriter uint32_t \family default , except an array of bits. However, such a feature can be easily implemented, as an array of bits is essentially any array of bytes, or words or doublewords, but operates at the bit level. \end_layout \begin_layout Standard The following code demonstrates how to define array (string) data types: \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout uint8_t @| \backslash color{red} \backslash bfseries a8[2]|@ = {0x12, 0x34}; \end_layout \begin_layout Plain Layout uint16_t @| \backslash color{blue} \backslash bfseries a16[2]|@ = {0x1234, 0x5678}; \end_layout \begin_layout Plain Layout uint32_t @| \backslash color{magenta} \backslash bfseries a32[2]|@ = {0x12345678, 0x9abcdef0}; \end_layout \begin_layout Plain Layout uint64_t @| \backslash color{green} \backslash bfseries a64[2]|@ = {0x123456789abcdef0, 0x123456789abcdef0}; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 0804a018 < \color red a8 \color inherit >: \end_layout \begin_layout LyX-Code 804a018: \color red 12 34 00 \color inherit adc dh,BYTE PTR [eax+eax*1] \end_layout \begin_layout LyX-Code 804a01b: \color red 00 \color inherit 34 12 add BYTE PTR [edx+edx*1],dh \end_layout \begin_layout LyX-Code 0804a01c < \color blue a16 \color inherit >: \end_layout \begin_layout LyX-Code 804a01c: \color blue 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code 804a01e: \color blue 78 56 \color inherit js 804a076 <_end+0x3a> \end_layout \begin_layout LyX-Code 0804a020 < \color magenta a32 \color inherit >: \end_layout \begin_layout LyX-Code 804a020: \color magenta 78 56 \color inherit js 804a078 <_end+0x3c> \end_layout \begin_layout LyX-Code 804a022: \color magenta 34 12 \color inherit xor al,0x12 \end_layout \begin_layout LyX-Code 804a024: \color magenta f0 de bc 9a \color inherit f0 de bc lock fidivr WORD PTR [edx+ebx*4-0x65432110] \end_layout \begin_layout LyX-Code 804a02b: 9a \color magenta \end_layout \begin_layout LyX-Code 0804a028 < \color green a64 \color inherit >: \end_layout \begin_layout LyX-Code 804a028: \color green f0 de bc 9a 78 56 34 \color inherit lock fidivr WORD PTR [edx+ebx*4+0x12345678] \end_layout \begin_layout LyX-Code 804a02f: \color green 12 \color inherit \end_layout \begin_layout LyX-Code 804a030: \color green f0 de bc 9a 78 56 34 \color inherit lock fidivr WORD PTR [edx+ebx*4+0x12345678] \end_layout \begin_layout LyX-Code 804a037: \color green 12 \end_layout \end_deeper \begin_layout Standard Despite \family typewriter \color red a8 \family default \color inherit is an array with 2 elements, each is 1-byte long, but it is still allocated with 4 bytes. Again, to ensure natural alignment for best performance, \family typewriter gcc \family default pads extra zero bytes. As shown in the assembly listing, the actual value of \family typewriter \color red a8 \family default \color inherit is \family typewriter 12 34 00 00 \family default , with \family typewriter \color red a8 \color inherit [0] \family default equals to \family typewriter 12 \family default and \family typewriter \color red a8 \color inherit [1] \family default equals to \family typewriter 34 \family default . \end_layout \begin_layout Standard Then it comes \family typewriter \color blue a16 \family default \color inherit with 2 elements, each is 2-byte long. Since 2 elements are 4 bytes in total, which is in the natural alignment, \family typewriter gcc \family default pads no byte. The value of \family typewriter \color blue a16 \family default \color inherit is \family typewriter 34 12 78 56 \family default , with \family typewriter \color blue a16 \color inherit [0] \family default equals to \family typewriter 34 12 \family default and \family typewriter \color blue a16 \color inherit [1] \family default equals to \family typewriter 78 56 \family default . Note that, objdump is confused again, as \family typewriter de \family default is the opcode for the instruction \family typewriter fidivr \family default (short of reverse divide) that requires another operand, so \family typewriter objdump \family default grabs whatever the next bytes that makes sense to it for creating \begin_inset Quotes eld \end_inset an operand \begin_inset Quotes erd \end_inset . Only the highlighted values belong to \family typewriter \color magenta a32 \family default \color inherit . \end_layout \begin_layout Standard Next is \family typewriter \color magenta a32 \family default \color inherit , with 2 elements, 4 bytes each. Similar to above arrays, the value of \family typewriter \color magenta a32 \color inherit [0] \family default is \family typewriter 78 56 34 12 \family default , the value of \family typewriter \color magenta a32 \color inherit [1] \family default is \family typewriter f0 de bc 9a \family default , exactly what is assigned in the C code. \end_layout \begin_layout Standard Finally is \family typewriter \color green a64 \family default \color inherit , also with 2 elements, but 8 bytes each. The total size of \family typewriter \color green a64 \family default \color inherit is 16 bytes, which is in the natural alignment, therefore no padding bytes added. The values of both \family typewriter \color green a64 \color inherit [0] \family default and \family typewriter \color green a64 \color inherit [1] \family default are the same: \family typewriter f0 de bc 9a 78 56 34 12 \family default , that got misinterpreted to \family typewriter fidivr \family default instruction. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \family typewriter a8 \family default , \family typewriter a16 \family default , \family typewriter a32 \family default and \family typewriter a64 \family default memory layouts \end_layout \end_inset \end_layout \begin_layout Plain Layout \family typewriter \color red a8 \color inherit : \begin_inset space ~ \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 12 | \begin_inset space ~ \end_inset 34 \end_layout \end_inset \end_inset \end_layout \begin_layout Plain Layout \family typewriter \color blue a16 \color inherit : \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 34 12 \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset 78 56 \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \end_layout \end_inset \end_inset \end_layout \begin_layout Plain Layout \family typewriter \color magenta a32 \color inherit : \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 78 56 34 12 \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset f0 de bc 9a \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \end_layout \end_inset \end_inset \end_layout \begin_layout Plain Layout \family typewriter \color green a64 \color inherit : \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter f0 de bc 9a 78 56 34 12 \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset | \begin_inset space ~ \end_inset f0 de bc 9a 78 56 34 12 \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \end_layout \end_inset \end_inset \end_layout \end_inset \end_layout \begin_layout Standard However, beyond one-dimensional arrays that map directly to hardware string type, C provides its own syntax for multi-dimensional arrays: \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout uint8_t @| \backslash color{red} \backslash bfseries a2[2][2]|@ = { \end_layout \begin_layout Plain Layout {0x12, 0x34}, \end_layout \begin_layout Plain Layout {0x56, 0x78} \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout uint8_t @| \backslash color{blue} \backslash bfseries a3[2][2][2]|@ = { \end_layout \begin_layout Plain Layout {{0x12, 0x34}, \end_layout \begin_layout Plain Layout {0x56, 0x78}}, \end_layout \begin_layout Plain Layout {{0x9a, 0xbc}, \end_layout \begin_layout Plain Layout {0xde, 0xff}}, \end_layout \begin_layout Plain Layout }; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 0804a018 < \color red a2 \color inherit >: \end_layout \begin_layout LyX-Code 804a018: \color red 12 34 56 \color inherit adc dh,BYTE PTR [esi+edx*2] \end_layout \begin_layout LyX-Code 804a01b: \color red 78 \color inherit 12 js 804a02f <_end+0x7> \end_layout \begin_layout LyX-Code 0804a01c < \color blue a3 \color inherit >: \end_layout \begin_layout LyX-Code 804a01c: \color blue 12 34 56 \color inherit adc dh,BYTE PTR [esi+edx*2] \end_layout \begin_layout LyX-Code 804a01f: \color blue 78 9a \color inherit js 8049fbb <_DYNAMIC+0xa7> \end_layout \begin_layout LyX-Code 804a021: \color blue bc \color inherit .byte 0xbc \end_layout \begin_layout LyX-Code 804a022: \color blue de ff \color inherit fdivrp st(7),st \end_layout \begin_layout LyX-Code \end_layout \end_deeper \begin_layout Standard Technically, multi-dimensional arrays are like normal arrays: in the end, the total size is translated into flat allocated bytes. A 2 x 2 array is allocated with 4 bytes; a \begin_inset Formula $2\times2\times2$ \end_inset array is allocated with 8 bytes, as can be seen in the assembly listing of \family typewriter \color red a2 \color inherit \begin_inset Foot status collapsed \begin_layout Plain Layout Again, \family typewriter objdump \family default is confused and put the number \family typewriter 12 \family default next to 78 in \family typewriter a3 \family default listing. \end_layout \end_inset \family default and \family typewriter \color blue a3 \family default \color inherit . In low-level assembly code, the representation is the same between \family typewriter a[4] \family default and \family typewriter a[2][2] \family default . However, in high-level C code, the difference is tremendous. The syntax of multi-dimensional array enables a programmer to think with higher level concepts, instead of translating manually from high-level concepts to low-level code and work with high-level concepts in his head at the same time. \end_layout \begin_layout Example The following two-dimensional array can hold a list of 2 names with the length of 10: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout char names[2][10] = { \end_layout \begin_layout Plain Layout "John Doe", \end_layout \begin_layout Plain Layout "Jane Doe" \end_layout \begin_layout Plain Layout }; \end_layout \end_inset \end_layout \begin_layout Standard To access a name, we simply adjust the column index \begin_inset Foot status collapsed \begin_layout Plain Layout The left index is called column index since it changes the index based on a column. \end_layout \end_inset e.g. \family typewriter names[0] \family default , \family typewriter names[1] \family default . To access individual character within a name, we use the row index \begin_inset Foot status collapsed \begin_layout Plain Layout Same with column index, the right index is called row index since it changes the index based on a row. \end_layout \end_inset e.g. \family typewriter names[0][0] \family default gives the character \begin_inset Quotes eld \end_inset J \begin_inset Quotes erd \end_inset , \family typewriter names[0][1] \family default gives the character \begin_inset Quotes eld \end_inset o \begin_inset Quotes erd \end_inset and so on. \end_layout \begin_layout Standard Without such syntax, we need to create a 20-byte array e.g. \family typewriter names[20] \family default , and whenever we want to access a character e.g. to check if the names contains with a number in it, we need to calculate the index manually. It would be distracting, since we constantly need to switch thinkings between the actual problem and the translate problem. \end_layout \begin_layout Standard Since this is a repeating pattern, C abstracts away this problem with the syntax for define and manipulating multi-dimensional array. Through this example, we can clearly see the power of abstraction through language can give us. It would be ideal if a programmer is equipped with such power to define whatever syntax suitable for a problem at hands. Not many languages provide such capacity. Fortunately, through C macro, we can partially achieve that goal . \end_layout \end_deeper \begin_layout Standard In all cases, an array is guaranteed to generate contiguous bytes of memory, regardless of the dimensions it has. \end_layout \begin_layout Exercise What is the difference between a multi-dimensional array and an array of pointers, or even pointers of pointers? \end_layout \begin_layout Section Examine compiled code \end_layout \begin_layout Standard This section will explore how compiler transform high level code into assembly code that CPU can execute, and see how common assembly patterns help to create higher level syntax. \family typewriter -S \family default option is added to \family typewriter objdump \family default to better demonstrate the connection between high and low level code. \end_layout \begin_layout Standard In this section, the option \family typewriter --no-show-raw-insn \family default is added to objdump command to omit the opcodes for clarity: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump --no-show-raw-insn -M intel -S -D | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Subsection Data Transfer \end_layout \begin_layout Standard Previous section explores how various types of data are created, and how they are laid out in memory. Once memory storages are allocated for variables, they must be accessible and writable. Data transfer instructions move data (bytes, words, doublewords or quadwords) between memory and registers, and between registers, effectively read from a storage source and write to another storage source. \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int32_t i = 0x12345678; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout int j = i; \end_layout \begin_layout Plain Layout int k = 0xabcdef; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 080483db
: \end_layout \begin_layout LyX-Code #include \end_layout \begin_layout LyX-Code int32_t i = 0x12345678; \end_layout \begin_layout LyX-Code int main(int argc, char *argv[]) { \end_layout \begin_layout LyX-Code 80483db: push ebp \end_layout \begin_layout LyX-Code \color red 80483dc: mov ebp,esp \end_layout \begin_layout LyX-Code 80483de: sub esp,0x10 \end_layout \begin_layout LyX-Code int j = i; \end_layout \begin_layout LyX-Code \color blue 80483e1: \color inherit \color blue mov eax,ds:0x804a018 \end_layout \begin_layout LyX-Code \color blue 80483e6: \color inherit \color blue mov DWORD PTR [ebp-0x8],eax \end_layout \begin_layout LyX-Code int k = 0xabcdef; \end_layout \begin_layout LyX-Code \color magenta 80483e9: mov DWORD PTR [ebp-0x4],0xabcdef \end_layout \begin_layout LyX-Code return 0; \end_layout \begin_layout LyX-Code \color green 80483f0: mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 80483f5: leave \end_layout \begin_layout LyX-Code 80483f6: ret \end_layout \begin_layout LyX-Code 80483f7: xchg ax,ax \end_layout \begin_layout LyX-Code 80483f9: xchg ax,ax \end_layout \begin_layout LyX-Code 80483fb: xchg ax,ax \end_layout \begin_layout LyX-Code 80483fd: xchg ax,ax \end_layout \begin_layout LyX-Code 80483ff: nop \end_layout \end_deeper \begin_layout Standard The general data movement is performed with the \family typewriter mov \family default instruction. Note that despite the instruction being called \family typewriter mov \family default , it actually copies data from one destination to another. \end_layout \begin_layout Standard \color red The red \color inherit instruction copies data from the register \family typewriter \color red esp \family default \color inherit to the register \family typewriter \color red ebp \family default \color inherit . This \family typewriter mov \family default instruction moves data between registers and is assigned the opcode \family typewriter 89 \family default . \end_layout \begin_layout Standard \color blue The blue \color inherit instructions copies data from one memory location (the \family typewriter i \family default variable) to another (the \family typewriter j \family default variable). There exists no data movement from memory to memory; it requires two \family typewriter mov \family default instructions, one for copying the data from a memory location to a register, and one for copying the data from the register to the destination memory location. \end_layout \begin_layout Standard The \color magenta pink \color inherit instruction copies an immediate value into memory. Finally, the \color green green \color inherit instruction copies immediate data into a register. \end_layout \begin_layout Subsection Expressions \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout int expr(int i, int j) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout int add = i + j; \end_layout \begin_layout Plain Layout int sub = i - j; \end_layout \begin_layout Plain Layout int mul = i * j; \end_layout \begin_layout Plain Layout int div = i / j; \end_layout \begin_layout Plain Layout int mod = i % j; \end_layout \begin_layout Plain Layout int neg = -i; \end_layout \begin_layout Plain Layout int and = i & j; \end_layout \begin_layout Plain Layout int or = i | j; \end_layout \begin_layout Plain Layout int xor = i ^ j; \end_layout \begin_layout Plain Layout int not = ~i; \end_layout \begin_layout Plain Layout int shl = i << 8; \end_layout \begin_layout Plain Layout int shr = i >> 8; \end_layout \begin_layout Plain Layout char equal1 = (i == j); \end_layout \begin_layout Plain Layout int equal2 = (i == j); \end_layout \begin_layout Plain Layout char greater = (i > j); \end_layout \begin_layout Plain Layout char less = (i < j); \end_layout \begin_layout Plain Layout char greater_equal = (i >= j); \end_layout \begin_layout Plain Layout char less_equal = (i <= j); \end_layout \begin_layout Plain Layout int logical_and = i && j; \end_layout \begin_layout Plain Layout int logical_or = i || j; \end_layout \begin_layout Plain Layout ++i; \end_layout \begin_layout Plain Layout --i; \end_layout \begin_layout Plain Layout int i1 = i++; \end_layout \begin_layout Plain Layout int i2 = ++i; \end_layout \begin_layout Plain Layout int i3 = i--; \end_layout \begin_layout Plain Layout int i4 = --i; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard The full assembly listing is really long. For that reason, we examine expression by expression. \end_layout \begin_layout Description Expression: \family typewriter int \color blue add \color inherit = i + j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80483e1: mov edx,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 80483e4: mov eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 80483e7: add eax,edx \end_layout \begin_layout LyX-Code 80483e9: mov DWORD PTR \color blue [ebp-0x34] \color inherit ,eax \end_layout \begin_layout Standard The assembly code is straight forward: variable \family typewriter i \family default and \family typewriter j \family default are stored in \family typewriter eax \family default and \family typewriter edx \family default respectively, then added together with the \family typewriter \color red add \family default \color inherit instruction, and the final result is stored into \family typewriter eax \family default . Then, the result is saved into the local variable \family typewriter \color blue add \family default \color inherit , which is at the location \family typewriter \color blue [ebp-0x34] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue sub \color inherit = i - j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80483ec: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 80483ef: sub eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 80483f2: mov DWORD PTR \color blue [ebp-0x30] \color inherit ,eax \end_layout \begin_layout Standard Similar to \family typewriter add \family default instruction, x86 provides a \family typewriter \color red sub \family default \color inherit instruction for subtraction. Hence, \family typewriter gcc \family default translates a subtraction into \family typewriter \color red sub \family default \color inherit instruction, with \family typewriter eax \family default is reloaded with \family typewriter i \family default , as \family typewriter eax \family default still carries the result from previous expression. Then, \family typewriter j \family default is subtracted from \family typewriter i \family default . After the subtraction, the value is saved into the variable \family typewriter \color blue sub \family default \color inherit , at location \family typewriter \color blue [ebp-0x30] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue mul \color inherit = i * j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80483f5: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 80483f8: imul eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 80483fc: mov DWORD PTR \color blue [ebp-0x34] \color inherit ,eax \end_layout \begin_layout Standard Similar to \family typewriter sub \family default instruction, only \family typewriter eax \family default is reloaded, since it carries the result of previous calculation. \family typewriter \color red imul \family default \color inherit performs signed multiply \begin_inset Foot status collapsed \begin_layout Plain Layout Unsigned multiply is perform by \family typewriter mul \family default instruction. \end_layout \end_inset . \family typewriter eax \family default is first loaded with \family typewriter i \family default , then is multiplied with \family typewriter j \family default and stored the result back into \family typewriter eax \family default , then stored into the variable \family typewriter \color blue mul \family default \color inherit at location \family typewriter \color blue [ebp-0x34] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue div \color inherit = i / j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80483ff: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 8048402: cdq \end_layout \begin_layout LyX-Code \color red 8048403: idiv DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 8048406: mov DWORD PTR \color blue [ebp-0x30] \color inherit , \color red eax \end_layout \begin_layout Standard Similar to \family typewriter imul \family default , \family typewriter \color red idiv \family default \color inherit performs sign divide. But, different from \family typewriter imul \family default above \family typewriter \color red idiv \family default \color inherit only takes one operand: \end_layout \begin_layout Enumerate First, \family typewriter i \family default is reloaded into \family typewriter eax \family default . \end_layout \begin_layout Enumerate Then, \family typewriter cdq \family default converts the double word value in \family typewriter eax \family default into a quadword value stored in the pair of registers \family typewriter edx:eax \family default , by copying the signed (bit 31 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset ) of the value in \family typewriter eax \family default into every bit position in \family typewriter edx \family default . The pair \family typewriter edx:eax \family default is the dividend, which is the variable i, and the operand to \family typewriter idiv \family default is the divisor, which is the variable \family typewriter j \family default . \end_layout \begin_layout Enumerate After the calculation, the result is stored into the pair \family typewriter edx:eax \family default registers, with the quotient in \family typewriter eax \family default and remainder in \family typewriter edx \family default . The quotient is stored in the variable \family typewriter \color blue div \family default \color inherit , at location \family typewriter \color blue [ebp-0x30] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue mod \color inherit = i % j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048409: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 804840c: cdq \end_layout \begin_layout LyX-Code \color red 804840d: idiv DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 8048410: mov DWORD PTR \color blue [ebp-0x2c] \color inherit , \color red edx \end_layout \begin_layout Standard The same \family typewriter idiv \family default instruction also performs the modulo operation, since it also calculates a remainder and stores in the variable \family typewriter \color blue mod \family default \color inherit , at location \family typewriter \color blue [ebp-0x2c] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue neg \color inherit = -i; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048413: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048416: \color inherit \color red neg eax \color inherit \end_layout \begin_layout LyX-Code 8048418: mov DWORD PTR \color blue [ebp-0x28] \color inherit ,eax \end_layout \begin_layout Standard \family typewriter \color red neg \family default \color inherit replaces the value of operand (the destination operand) with its two's complement (this operation is equivalent to subtracting the operand from 0). In this example, the value \family typewriter i \family default in \family typewriter eax \family default is replaced replaced with \family typewriter -i \family default using \family typewriter \color red neg \family default \color inherit instruction. Then, the new value is stored in the variable neg at \family typewriter \color blue [ebp-0x28] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue and \color inherit = i & j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 804841b: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 804841e: \color inherit \color red and eax,DWORD PTR [ebp+0xc] \color inherit \end_layout \begin_layout LyX-Code 8048421: mov DWORD PTR [ebp-0x24],eax \end_layout \begin_layout Standard \family typewriter \color red and \family default \color inherit performs a bitwise \family typewriter AND \family default operation on two operands, and stores the result in the destination operand, which is the variable \family typewriter \color blue and \family default \color inherit at \family typewriter \color blue [ebp-0x24] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue or \color inherit = i | j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048424: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048427: or eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 804842a: mov DWORD PTR \color blue [ebp-0x20] \color inherit ,eax \end_layout \begin_layout Standard Similar to \family typewriter and \family default instruction, \family typewriter \color red or \family default \color inherit performs a bitwise \family typewriter OR \family default operation on two operands, and stores the result in the destination operand, which is the variable \family typewriter \color blue or \family default \color inherit at \family typewriter \color blue [ebp-0x20] \family default \color inherit in this case. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue xor \color inherit = i ^ j; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 804842d: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048430: xor eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 8048433: mov DWORD PTR \color blue [ebp-0x1c] \color inherit ,eax \end_layout \begin_layout Standard Similar to \family typewriter and/or \family default instruction, \family typewriter \color red xor \family default \color inherit performs a bitwise \family typewriter XOR \family default operation on two operands, and stores the result in the destination operand, which is the variable \family typewriter \color blue xor \family default \color inherit at \family typewriter \color blue [ebp-0x1c] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue not \color inherit = ~i; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048436: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048439: \color inherit \color red not eax \color inherit \end_layout \begin_layout LyX-Code 804843b: mov DWORD PTR \color blue [ebp-0x18] \color inherit ,eax \end_layout \begin_layout Standard \family typewriter \color red not \family default \color inherit performs a bitwise \family typewriter NOT \family default operation (each 1 is set to 0, and each 0 is set to 1) on the destination operand and stores the result in the destination operand location, which is the variable \family typewriter \color blue not \family default \color inherit at \family typewriter \color blue [ebp-0x18] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue shl \color inherit = i << 8; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 804843e: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048441: shl eax,0x8 \end_layout \begin_layout LyX-Code 8048444: mov DWORD PTR \color blue [ebp-0x14] \color inherit ,eax \end_layout \begin_layout Standard \family typewriter \color red shl \family default \color inherit (shift logical left) shifts the bits in the destination operand to the left by the number of bits specified in the source operand. In this case, \family typewriter eax \family default stores i and \family typewriter \color red shl \family default \color inherit shifts \family typewriter eax \family default by 8 bits to the left. A different name for \family typewriter \color red shl \family default \color inherit is \family typewriter sal \family default \emph on ( \emph default shift arithmetic left). Both can be used synonymous. Finally, the result is stored in the variable \family typewriter \color blue shl \family default \color inherit at \family typewriter \color blue [ebp-0x14] \family default \color inherit . \end_layout \begin_layout Standard Here is a visual demonstration of \family typewriter shl \family default / \family typewriter sal \family default and \family typewriter shr \family default instructions: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Shift Instructions ( \backslash textcolor{red}{red} is the start bit, \backslash textcolor{blue}{blue} is the end bit.)} \end_layout \begin_layout Plain Layout \backslash subfloat[SHL/SAL (Source: Figure 7-6, Volume 1)]{ \backslash label{shr} \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.55]{images/04/shl_sal}} \end_layout \begin_layout Plain Layout \backslash hfill{} \backslash subfloat[SHR (Source: Figure 7-7, Volume 1)]{ \end_layout \begin_layout Plain Layout \backslash includegraphics[scale=0.55]{images/04/shr}} \end_layout \begin_layout Plain Layout \backslash hfill \backslash break \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard After shifting to the left, the right most bit is set for Carry Flag in \family typewriter EFLAGS \family default register. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue shr \color inherit = i >> 8; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048447: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 804844a: sar eax,0x8 \end_layout \begin_layout LyX-Code 804844d: mov DWORD PTR \color blue [ebp-0x10] \color inherit ,eax \end_layout \begin_layout Standard \family typewriter \color red sar \family default \color inherit is similar to \family typewriter shl/sal \family default , but shift bits to the right and extends the sign bit. For right shift, \family typewriter shr \family default and \family typewriter \color red sar \family default \color inherit are two different instructions. \family typewriter shr \family default differs to \family typewriter \color red sar \color inherit \family default is that it does not extend the sign bit. Finally, the result is stored in the variable \family typewriter \color blue shr \family default \color inherit at \family typewriter \color blue [ebp-0x10] \family default \color inherit . \end_layout \begin_layout Standard In the figure \begin_inset ERT status open \begin_layout Plain Layout \backslash ref{shr} \end_layout \end_inset (b), notice that initially, the sign bit is 1, but after 1-bit and 10-bit shiftings, the shifted-out bits are filled with zeros. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout SAR Instruction Operation (Source: Figure 7-8, Volume 1) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/04/sar.pdf scale 55 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard With \family typewriter \color red sar \family default \color inherit , the sign bit (the most significant bit) is preserved. That is, if the sign bit is 0, the new bits always get the value 0; if the sign bit is 1, the new bits always get the value 1. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter char \color blue equal1 \color inherit = (i == j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048450: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048453: \color inherit \color red cmp eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 8048456: sete al \color inherit \end_layout \begin_layout LyX-Code 8048459: mov BYTE PTR \color blue [ebp-0x41] \color inherit ,al \end_layout \begin_layout Standard \family typewriter \color red cmp \family default \color inherit and variants of the variants of \family typewriter \color red set \family default \color inherit instructions make up all the logical comparisons. In this expression, \family typewriter \color red cmp \family default \color inherit compares variable \family typewriter i \family default and \family typewriter j \family default ; then \family typewriter \color red sete \family default \color inherit stores the value 1 to \family typewriter al \family default register if the comparison from \family typewriter \color red cmp \family default \color inherit earlier is equal, or stores 0 otherwise. The general name for variants of \family typewriter \color red set \family default \color inherit instruction is called \family typewriter SETcc \family default . The suffix \family typewriter cc \family default denotes the condition being tested for in \family typewriter EFLAGS \family default register. Appendix B in volume 1, \emph on “EFLAGS Condition Codes” \emph default , lists the conditions it is possible to test for with this instruction. Finally, the result is stored in the variable \family typewriter \color blue equal1 \family default \color inherit at \family typewriter \color blue [ebp-0x41] \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int equal2 = (i == j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 804845c: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 804845f: cmp eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 8048462: sete al \end_layout \begin_layout LyX-Code \color red 8048465: movzx eax,al \end_layout \begin_layout LyX-Code 8048468: mov DWORD PTR [ebp-0xc],eax \end_layout \begin_layout Standard Similar to equality comparison, this expression also compares for equality, with an exception that the result is stored in an int type. For that reason, one more instruction is a added: \family typewriter \color red movzx \family default \color inherit instruction, a variant of \family typewriter mov \family default that copies the result into a destination operand and fills the remaining bytes with 0. In this case, since \family typewriter eax \family default is 4-byte wide, after copying the first byte in \family typewriter al \family default , the remaining bytes of \family typewriter eax \family default are filled with 0 to ensure the \family typewriter eax \family default carries the same value as \family typewriter al \family default . \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \family typewriter movzx \family default instruction \end_layout \end_inset \begin_inset space \hfill{} \end_inset \begin_inset Float figure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \family typewriter eax \family default before \family typewriter movzx \end_layout \end_inset \end_layout \begin_layout Plain Layout \family typewriter \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 34 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 56 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 78 \end_layout \end_inset \end_inset \end_layout \end_inset \begin_inset space \hfill{} \end_inset \begin_inset Float figure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout after \family typewriter movzx eax, al \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 78 \end_layout \end_inset \end_inset \end_layout \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Expression: \family typewriter char greater = (i > j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 804846b: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 804846e: cmp eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 8048471: setg al \color inherit \end_layout \begin_layout LyX-Code 8048474: mov BYTE PTR [ebp-0x40],al \end_layout \begin_layout Standard Similar to equality comparison, but used \family typewriter \color red setg \family default \color inherit for \series bold g \series default reater comparison instead. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter char less = (i < j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048477: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 804847a: \color inherit \color red cmp eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 804847d: setl al \color inherit \end_layout \begin_layout LyX-Code 8048480: mov BYTE PTR [ebp-0x3f],al \end_layout \begin_layout Standard Applied \family typewriter \color red setl \family default \color inherit for \series bold l \series default ess comparison. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter char greater_equal = (i >= j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 8048483: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048486: \color inherit \color red cmp eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 8048489: \color inherit \color red setge al \color inherit \end_layout \begin_layout LyX-Code 804848c: mov BYTE PTR [ebp-0x3e],al \end_layout \begin_layout Standard Applied \family typewriter \color red setge \family default \color inherit for \series bold g \series default reater or \series bold e \series default qual comparison. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter char less_equal = (i <= j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 804848f: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 8048492: cmp eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code \color red 8048495: \color inherit \color red setle al \end_layout \begin_layout LyX-Code 8048498: mov BYTE PTR [ebp-0x3d],al \end_layout \begin_layout Standard Applied \family typewriter \color red setle \family default \color inherit for \series bold l \series default ess than or \series bold e \series default qual comparison. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color blue logical_and \color inherit = (i && j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code \color red 804849b: cmp DWORD PTR [ebp+0x8],0x0 \end_layout \begin_layout LyX-Code 804849f: je \color blue \color magenta 80484ae \color blue \color magenta \color blue \color inherit \end_layout \begin_layout LyX-Code \color red 80484a1: cmp DWORD PTR [ebp+0xc],0x0 \end_layout \begin_layout LyX-Code 80484a5: je \color blue \color magenta 80484ae \color blue \end_layout \begin_layout LyX-Code \color red 80484a7: mov eax,0x1 \color inherit \end_layout \begin_layout LyX-Code 80484ac: jmp \color green 80484b3 \color inherit \end_layout \begin_layout LyX-Code \color magenta 80484ae: \color inherit \color magenta mov eax,0x0 \color inherit \end_layout \begin_layout LyX-Code \color green 80484b3: \color inherit mov DWORD PTR \color blue [ebp-0x8] \color inherit ,eax \end_layout \begin_layout Standard Logical \family typewriter AND \family default operator \family typewriter && \family default is one of the syntaxes that is made entirely in software \begin_inset Foot status open \begin_layout Plain Layout That is, there is no equivalent assembly instruction implemented in hardware. \end_layout \end_inset with simpler instructions. The algorithm from the assembly code is simple: \end_layout \begin_layout Enumerate First, check if \family typewriter i \family default is \family typewriter 0 \family default with the instruction at \family typewriter \color red 0x804849b \family default \color inherit . \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Enumerate If true, jump to \family typewriter \color magenta 0x80484ae \color inherit \family default and set eax to 0. \end_layout \begin_layout Enumerate Set the variable \family typewriter logical \family default _and to 0, as it is the next instruction after \family typewriter \color magenta 0x80484ae \family default \color inherit . \end_layout \end_deeper \begin_layout Enumerate If \family typewriter i \family default is not \family typewriter 0 \family default , check if \family typewriter j \family default is \family typewriter 0 \family default with the instruction at \family typewriter \color red 0x80484a1 \family default \color inherit . \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Enumerate If true, jump to \family typewriter \color magenta 0x80484ae \color inherit \family default and set eax to 0. \end_layout \begin_layout Enumerate Set the variable \family typewriter logical \family default _and to 0, as it is the next instruction after \family typewriter \color magenta 0x80484ae \family default \color inherit . \end_layout \end_deeper \begin_layout Enumerate If both \family typewriter i \family default and \family typewriter j \family default are not \family typewriter 0 \family default , the result is certainly \family typewriter 1 \family default , or \family typewriter true \family default . \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Enumerate Set it accordingly with the instruction at \family typewriter \color red 0x80484a7 \family default \color inherit . \end_layout \begin_layout Enumerate Then jump to the instruction at \family typewriter \color green 0x80484b3 \family default \color inherit to set the variable \family typewriter \color blue logical_and \family default \color inherit at \color blue \family typewriter [ebp-0x8] \family default \color inherit to 1. \end_layout \end_deeper \end_deeper \begin_layout Description Expression: \family typewriter int logical_or = (i || j); \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80484b6: cmp DWORD PTR [ebp+0x8],0x0 \end_layout \begin_layout LyX-Code 80484ba: jne 80484c2 \end_layout \begin_layout LyX-Code 80484bc: cmp DWORD PTR [ebp+0xc],0x0 \end_layout \begin_layout LyX-Code 80484c0: je 80484c9 \end_layout \begin_layout LyX-Code 80484c2: mov eax,0x1 \end_layout \begin_layout LyX-Code 80484c7: jmp 80484ce \end_layout \begin_layout LyX-Code 80484c9: mov eax,0x0 \end_layout \begin_layout LyX-Code 80484ce: mov DWORD PTR [ebp-0x4],eax \end_layout \begin_layout Standard Logical \family typewriter OR \family default operator \family typewriter || \family default is similar to logical and above. Understand the algorithm is left as an exercise for readers. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter ++i; \family default and \family typewriter --i; \family default (or \family typewriter i++ \family default and \family typewriter i-- \family default ) \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80484d1: \color red add DWORD PTR [ebp+0x8],0x1 \end_layout \begin_layout LyX-Code 80484d5: \color red sub DWORD PTR [ebp+0x8],0x1 \end_layout \begin_layout Standard The syntax of increment and decrement is similar to logical \family typewriter AND \family default and logical \family typewriter OR \family default in that it is made from existing instruction, that is \family typewriter add \family default . The difference is that the CPU actually does has a built-in instruction, but \family typewriter gcc \family default decided not to use the instruction because \family typewriter inc \family default and \family typewriter dec \family default cause a \emph on partial flag register stall \emph default , occurs when an instruction modifies a part of the flag register and the following instruction is dependent on the outcome of the flags ( \emph on section 3.5.2.6 \emph default , \begin_inset CommandInset citation LatexCommand citealt before "Optimization Manual," key "intel_opt_manual" literal "true" \end_inset ). The manual even suggests that \family typewriter inc \family default and \family typewriter dec \family default should be replaced with \family typewriter add \family default and \family typewriter sub \family default instructions (section \emph on 3.5.1.1 \emph default , \begin_inset CommandInset citation LatexCommand citealt before "Optimization Manual," key "intel_opt_manual" literal "true" \end_inset ). \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int \color green i1 \color inherit = i++; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code \color blue 80484d9 \color inherit : mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code \color red 80484dc: lea edx,[eax+0x1] \end_layout \begin_layout LyX-Code \color blue 80484df \color inherit : mov DWORD PTR [ebp+0x8],edx \end_layout \begin_layout LyX-Code \color blue 80484e2 \color inherit : mov DWORD PTR \color green [ebp-0x10] \color inherit ,eax \end_layout \begin_layout Standard First, \family typewriter i \family default is copied into \family typewriter eax \family default at \family typewriter \color blue 80484d9 \family default \color inherit . Then, the value of \family typewriter eax + 0x1 \family default is copied into \family typewriter edx \family default as an \emph on effective address \emph default at \family typewriter \color red 80484dc \family default \color inherit . The \family typewriter lea \family default ( \emph on load effective address \emph default ) instruction copies a memory address into a register. According to Volume 2, the source operand is a memory address specified with one of the processors addressing modes. This means, the source operand must be specified by the addressing modes defined in 16-bit/32-bit ModR/M Byte tables, \begin_inset CommandInset ref LatexCommand ref reference "mod-rm-16" \end_inset and \begin_inset CommandInset ref LatexCommand ref reference "mod-rm-32" \end_inset . \end_layout \begin_layout Standard After loading the incremented value into \family typewriter edx \family default , the value of \family typewriter i \family default is increased by 1 at \family typewriter \color blue 80484df \family default \color inherit . Finally, the \emph on previous \emph default \family typewriter i \family default value is stored back to \family typewriter \color green i1 \family default \color inherit at \family typewriter \color green [ebp-0x8] \family default \color inherit by the instruction at \family typewriter \color blue 80484e2 \family default \color inherit . \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int i2 = ++i; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code \color red 80484e5: add DWORD PTR [ebp+0x8],0x1 \end_layout \begin_layout LyX-Code 80484e9: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 80484ec: mov DWORD PTR [ebp-0xc],eax \end_layout \begin_layout Standard The primary differences between this increment syntax and the previous one are: \end_layout \begin_layout Itemize \family typewriter \color red add \family default \color inherit is used instead of \family typewriter lea \family default to increase \family typewriter i \family default directly. \end_layout \begin_layout Itemize the newly incremented \family typewriter i \family default is stored into \family typewriter i2 \family default instead of the old value. \end_layout \begin_layout Itemize the expression only costs 3 instructions instead of 4. \end_layout \begin_layout Standard This prefix-increment syntax is faster than the post-fix one used previously. It might not matter much which version to use if the increment is only used once or a few hundred times in a small loop, but it matters when a loop runs millions or more times. Also, depends on different circumstances, it is more convenient to use one over the other e.g. if \family typewriter i \family default is an index for accessing an array, we want to use the old value for accessing previous array element and newly incremented \family typewriter i \family default for current element. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int i3 = i--; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80484ef: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 80484f2: lea edx,[eax-0x1] \end_layout \begin_layout LyX-Code 80484f5: mov DWORD PTR [ebp+0x8],edx \end_layout \begin_layout LyX-Code 80484f8: mov DWORD PTR [ebp-0x8],eax \end_layout \begin_layout Standard Similar to \family typewriter i++ \family default syntax, and is left as an exercise to readers. \end_layout \end_deeper \begin_layout Description Expression: \family typewriter int i4 = --i; \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 80484fb: sub DWORD PTR [ebp+0x8],0x1 \end_layout \begin_layout LyX-Code 80484ff: mov eax,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 8048502: mov DWORD PTR [ebp-0x4],eax \end_layout \begin_layout Standard Similar to \family typewriter ++i \family default syntax, and is left as an exercise to readers. \end_layout \end_deeper \end_deeper \begin_layout Exercise Read section \emph on 3.5.2.4 \emph default , \emph on \begin_inset Quotes eld \end_inset Partial Register Stalls \begin_inset Quotes erd \end_inset \emph default to understand register stalls in general. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Exercise Read the sections from \emph on 7.3.1 \emph default to \emph on 7.3.7 \emph default in volume 1. \end_layout \end_deeper \begin_layout Subsection Stack \end_layout \begin_layout Standard A stack is a contiguous array of memory locations that holds a collection of discrete data. When a new element is added, a stack \emph on grows down \emph default in memory toward lesser addresses, and \emph on shrinks up \emph default toward greater addresses when an element is removed. x86 uses the \family typewriter esp \family default register to point to the top of the stack, at the newest element. A stack can be originated anywhere in main memory, as \family typewriter esp \family default can be set to any memory address. x86 provides two operations for manipulating stacks: \family typewriter \end_layout \begin_layout Itemize \family typewriter push \family default instruction and its variants add a new element on top of the stack \end_layout \begin_layout Itemize \family typewriter pop \family default instructions and its variants remove the top-most element from the stack. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Stack operations} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash subfloat[Initial state at address \backslash texttt{0x10004}] { \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10002 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10003 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10004 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color red 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\leftarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter esp \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout } \end_layout \end_inset \begin_inset space \hspace*{\fill} \end_inset \begin_inset ERT status open \begin_layout Plain Layout \backslash subfloat[After executing \backslash texttt{push word 0x5678}] { \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10002 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue 78 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\leftarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter esp \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10003 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue 56 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10004 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color red 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout } \end_layout \end_inset \begin_inset space \hspace*{\fill} \end_inset \begin_inset ERT status open \begin_layout Plain Layout \backslash subfloat[After executing \backslash texttt{pop word}] { \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10001 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10002 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10003 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10004 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color red 12 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\leftarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter esp \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Subsection Automatic variables \end_layout \begin_layout Standard Local variables are variables that exist within a scope. A scope is delimited by a pair of braces: \family typewriter {..} \family default . The most common scope to define local variables is at function scope. However, scope can be unnamed, and variables created inside an unnamed scope do not exist outside of its scope and its inner scope. \end_layout \begin_layout Example Function scope: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout void foo() { \end_layout \begin_layout Plain Layout int a; \end_layout \begin_layout Plain Layout int b; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter a \family default and \family typewriter b \family default are variables local to the function \family typewriter foo \family default . \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example Unnamed scope: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout int foo() { \end_layout \begin_layout Plain Layout int i; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout int a = 1; \end_layout \begin_layout Plain Layout int b = 2; \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout return i = a + b; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter a \family default and \family typewriter b \family default are local to where it is defined and local into its inner child scope that return \family typewriter i = a + b \family default . However, they do not exist at the function scope that creates \family typewriter i \family default . \end_layout \end_deeper \begin_layout Standard When a local variable is created, it is pushed on the stack; when a local variable goes out of scope, it is pop out of the stack, thus destroyed. When an argument is passed from a caller to a callee, it is pushed on the stack; when a callee returns to the caller, the arguments are popped out the stack. The local variables and arguments are automatically allocated upon enter a function and destroyed after exiting a function, that's why it's called \emph on automatic variables \emph default . \end_layout \begin_layout Standard A base frame pointer points to the start of the current function frame, and is kept in \family typewriter ebp \family default register. Whenever a function is called, it is allocated with its own dedicated storage on stack, called \emph on stack frame \emph default . A stack frame is where all local variables and arguments of a function are placed on a stack \begin_inset Foot status collapsed \begin_layout Plain Layout Data and only data are exclusively allocated on stack for every stack frame. No code resides here. \end_layout \end_inset . \end_layout \begin_layout Standard When a function needs a local variable or an argument, it uses \family typewriter ebp \family default to access a variable: \end_layout \begin_layout Itemize All local variables are allocated after the \family typewriter ebp \family default pointer. Thus, to access a local variable, a number is subtracted from \family typewriter ebp \family default to reach the location of the variable. \end_layout \begin_layout Itemize All arguments are allocated before \family typewriter ebp \family default pointer. To access an argument, a number is added to \family typewriter ebp \family default to reach the location of the argument. \end_layout \begin_layout Itemize The \family typewriter ebp \family default itself pointer points to the return address of its caller. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Function arguments and local variables} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter Previous Frame \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Current Frame \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Function Arguments \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Local variables \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on A1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on A2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on A3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on ........ \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on An \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on Return Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Old ebp \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on L1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on L2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on L3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on ........ \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \emph on Ln \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter A \family default = Argument \end_layout \begin_layout Standard \family typewriter L \family default = Local Variable \end_layout \begin_layout Standard Here is an example to make it more concrete: \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4" inline false status open \begin_layout Plain Layout int add(int @| \backslash color{red} \backslash bfseries a|@, int @| \backslash color{green} \backslash bfseries b|@) { \end_layout \begin_layout Plain Layout int @| \backslash color{blue} \backslash bfseries i|@ = @| \backslash color{red} \backslash bfseries a|@ + @| \backslash color{green} \backslash bfseries b|@; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return i; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 080483db : \end_layout \begin_layout LyX-Code #include \end_layout \begin_layout LyX-Code int add(int \color red a \color inherit , int \color green b \color inherit ) { \end_layout \begin_layout LyX-Code 80483db: push ebp \end_layout \begin_layout LyX-Code 80483dc: mov ebp,esp \end_layout \begin_layout LyX-Code 80483de: \color magenta sub esp,0x10 \end_layout \begin_layout LyX-Code int \color blue i \color inherit = \color red a \color inherit + \color green b \color inherit ; \end_layout \begin_layout LyX-Code 80483e1: mov edx,DWORD PTR \color red [ebp+0x8] \end_layout \begin_layout LyX-Code 80483e4: mov eax,DWORD PTR \color green [ebp+0xc] \end_layout \begin_layout LyX-Code 80483e7: add eax,edx \end_layout \begin_layout LyX-Code 80483e9: mov DWORD PTR \color blue [ebp-0x4] \color inherit ,eax \end_layout \begin_layout LyX-Code return \color blue i \color inherit ; \end_layout \begin_layout LyX-Code 80483ec: mov eax,DWORD PTR \color blue [ebp-0x4] \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 80483ef: leave \end_layout \begin_layout LyX-Code 80483f0: ret \end_layout \end_deeper \begin_layout Standard In the assembly listing, \family typewriter \color blue [ebp-0x4] \family default \color inherit is the local variable \family typewriter \color blue i \family default \color inherit , since it is allocated \emph on after \family typewriter \emph default ebp \family default , with the length of 4 bytes (an \family typewriter int \family default ). On the other hand, \family typewriter \color red a \family default \color inherit and \family typewriter \color green b \family default \color inherit are arguments and can be accessed with \family typewriter ebp \family default : \end_layout \begin_layout Itemize \family typewriter \color red [ebp+0x8] \color inherit \family default accesses \family typewriter \color red a \family default \color inherit . \end_layout \begin_layout Itemize \family typewriter \color green [ebp+0xc] \family default \color inherit access \family typewriter \color green b \family default \color inherit . \end_layout \begin_layout Standard For accessing arguments, the rule is that the closer a variable on stack to \family typewriter ebp \family default , the closer it is to a function name. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Function arguments and local variables in memory} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp+0xc \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp+0x8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp+0x4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0d \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0e \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0f \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0x10000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \color green b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \color red a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Return Address \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter Old ebp \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp+0x8 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ebp+0x4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\downarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0d \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0e \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0f \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \begin_inset space ~ \end_inset 0xffe0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter N \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue i \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter N \family default = Next local variable starts here \end_layout \begin_layout Standard From the figure, we can see that \family typewriter a \family default and \family typewriter b \family default are laid out in memory with the exact order as written in C, relative to the return address. \end_layout \begin_layout Subsection Function Call and Return \begin_inset CommandInset label LatexCommand label name "subsec:Function-Call-and" \end_inset \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int add(int a, int b) { \end_layout \begin_layout Plain Layout int local = 0x12345; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return a + b; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout add(1,1); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard For every function call, \family typewriter gcc \family default pushes arguments on the stack in reversed order with the \family typewriter \color red push \family default \color inherit instructions. That is, the arguments pushed on stack are in reserved order as it is written in high level C code, to ensure the relative order between arguments, as seen in previous section how function arguments and local variables are laid out. Then, \family typewriter gcc \family default generates a \family typewriter \color blue call \family default \color inherit instruction, which then implicitly pushes a return address before transferring the control to \family typewriter add \family default function: \end_layout \begin_layout LyX-Code 080483f2
: \end_layout \begin_layout LyX-Code int main(int argc, char *argv[]) { \end_layout \begin_layout LyX-Code 80483f2: push ebp \end_layout \begin_layout LyX-Code 80483f3: mov ebp,esp \end_layout \begin_layout LyX-Code add(1,2); \end_layout \begin_layout LyX-Code \color red 80483f5: push 0x2 \end_layout \begin_layout LyX-Code \color red 80483f7: push 0x1 \end_layout \begin_layout LyX-Code \color blue 80483f9: call 80483db \end_layout \begin_layout LyX-Code \color green 80483fe: add esp,0x8 \end_layout \begin_layout LyX-Code return 0; \end_layout \begin_layout LyX-Code 8048401: mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code \color magenta 8048406: leave \color red \end_layout \begin_layout LyX-Code \color cyan 8048407: ret \color inherit \end_layout \end_deeper \begin_layout Standard Upon finishing the call to \family typewriter add \family default function, the stack is restored by adding \family typewriter 0x8 \family default to stack pointer \family typewriter esp \family default (which is equivalent to 2 \family typewriter pop \family default instructions). Finally, a \family typewriter leave \family default instruction is executed and main returns with a \family typewriter ret \family default instruction. A \family typewriter ret \family default instruction transfers the program execution back to the caller to the instructi on right after the \family typewriter call \family default instruction, the \family typewriter add \family default instruction. The reason \family typewriter ret \family default can return to such location is that the return address implicitly pushed by the \family typewriter call \family default instruction, which is the address right after the \family typewriter call \family default instruction; whenever the CPU executes \family typewriter ret \family default instruction, it retrieves the return address that sits right after all the arguments on the stack: \end_layout \begin_layout Standard At the end of a function, \family typewriter gcc \family default places a \family typewriter leave \family default instruction to clean up all spaces allocated for local variables and restore the frame pointer to frame pointer of the caller. \end_layout \begin_layout LyX-Code 080483db : \end_layout \begin_layout LyX-Code #include \end_layout \begin_layout LyX-Code int add(int a, int b) { \end_layout \begin_layout LyX-Code \color red 80483db \color inherit : \color red push ebp \end_layout \begin_layout LyX-Code \color red 80483dc \color inherit : \color red mov ebp,esp \end_layout \begin_layout LyX-Code 80483de: sub esp,0x10 \end_layout \begin_layout LyX-Code int \color blue local \color inherit = \color magenta 0x12345 \color inherit ; \end_layout \begin_layout LyX-Code 80483e1: \color blue DWORD PTR [ebp-0x4] \color magenta ,0x12345 \end_layout \begin_layout LyX-Code return a + b; \end_layout \begin_layout LyX-Code 80483e8: mov edx,DWORD PTR [ebp+0x8] \end_layout \begin_layout LyX-Code 80483eb: mov eax,DWORD PTR [ebp+0xc] \end_layout \begin_layout LyX-Code 80483ee: \color red add eax,edx \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code \color red 80483f0 \color inherit : \color red leave \color inherit \end_layout \begin_layout LyX-Code \color red 80483f1 \color inherit : \color red ret \color inherit \end_layout \begin_layout Exercise The above code that \family typewriter gcc \family default generated for function calling is actually the standard method x86 defined. Read chapter 6, \emph on \begin_inset Quotes eld \end_inset Produce Calls, Interrupts, and Exceptions \begin_inset Quotes erd \end_inset , \emph default Intel manual volume 1. \end_layout \begin_layout Subsection Loop \end_layout \begin_layout Standard Loop is simply resetting the instruction pointer to an already executed instruction and starting from there all over again. A loop is just one application of \family typewriter jmp \family default instruction. However, because looping is a pervasive pattern, it earned its own syntax in C. \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout for (int i = 0; i < 10; i++) { \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code 080483db
: \end_layout \begin_layout LyX-Code #include \end_layout \begin_layout LyX-Code int main(int argc, char *argv[]) { \end_layout \begin_layout LyX-Code 80483db: push ebp \end_layout \begin_layout LyX-Code 80483dc: mov ebp,esp \end_layout \begin_layout LyX-Code 80483de: sub esp,0x10 \end_layout \begin_layout LyX-Code for ( \color red int i = 0 \color inherit ; \color green i < 10 \color inherit ; i++) { \end_layout \begin_layout LyX-Code \color red 80483e1: \color inherit mov \color red DWORD PTR [ebp-0x4],0x0 \end_layout \begin_layout LyX-Code \color green 80483e8: \color inherit \color green jmp 80483ee \end_layout \begin_layout LyX-Code \color blue 80483ea: \color inherit \color blue add DWORD PTR [ebp-0x4],0x1 \end_layout \begin_layout LyX-Code \color green 80483ee: cmp DWORD PTR [ebp-0x4],0x9 \end_layout \begin_layout LyX-Code \color green 80483f2: jle \color blue 80483ea \color green \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code return 0; \end_layout \begin_layout LyX-Code 80483f4: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 80483f9: c9 leave \end_layout \begin_layout LyX-Code 80483fa: c3 ret \end_layout \begin_layout LyX-Code 80483fb: 66 90 xchg ax,ax \end_layout \begin_layout LyX-Code 80483fd: 66 90 xchg ax,ax \end_layout \begin_layout LyX-Code 80483ff: 90 nop \end_layout \begin_layout Standard The colors mark corresponding high level code to assembly code: \end_layout \begin_layout Enumerate The \color red red \color inherit instruction initialize \family typewriter i \family default to \family typewriter 0 \family default . \end_layout \begin_layout Enumerate The \color green green \color inherit instructions compare i to 10 by using \family typewriter jle \family default and compare it to \family typewriter 9 \family default . If true, jump to \family typewriter \color blue 80483ea \family default \color inherit for another iteration. \end_layout \begin_layout Enumerate The \color blue blue \color inherit instruction increase i by 1, making the loop able to terminate once the terminate condition is satisfied. \end_layout \begin_layout Exercise Why does the increment instruction (the \color blue blue \color inherit instruction) appears before the compare instructions (the \color green green \color inherit instructions)? \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Exercise What assembly code can be generated for \family typewriter while \family default and \family typewriter do...while \family default ? \end_layout \end_deeper \end_deeper \begin_layout Subsection Conditional \end_layout \begin_layout Standard Again, conditional in C with \family typewriter if...else... \family default construct is just another application of \family typewriter jmp \family default instruction under the hood. It is also a pervasive pattern that earned its own syntax in C. \end_layout \begin_layout Description Source \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) { \end_layout \begin_layout Plain Layout int i = 0; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout if (argc) { \end_layout \begin_layout Plain Layout i = 1; \end_layout \begin_layout Plain Layout } else { \end_layout \begin_layout Plain Layout i = 0; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Description Assembly \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code int main(int argc, char *argv[]) { \end_layout \begin_layout LyX-Code 80483db: push ebp \end_layout \begin_layout LyX-Code 80483dc: mov ebp,esp \end_layout \begin_layout LyX-Code 80483de: sub esp,0x10 \end_layout \begin_layout LyX-Code int i = 0; \end_layout \begin_layout LyX-Code 80483e1: mov DWORD PTR [ebp-0x4],0x0 \end_layout \begin_layout LyX-Code \color red if (argc) { \end_layout \begin_layout LyX-Code \color red 80483e8 \color inherit : \color red cmp DWORD PTR [ebp+0x8],0x0 \end_layout \begin_layout LyX-Code \color red 80483ec \color inherit : \color red je \color inherit \color blue 80483f7 \color inherit \end_layout \begin_layout LyX-Code \color red i = 1; \end_layout \begin_layout LyX-Code \color red 80483ee \color inherit : \color red mov DWORD PTR [ebp-0x4],0x1 \end_layout \begin_layout LyX-Code 80483f5: \color red jmp \color inherit \color green 80483fe \color inherit \end_layout \begin_layout LyX-Code \color blue } else { \end_layout \begin_layout LyX-Code \color blue i = 0; \end_layout \begin_layout LyX-Code \color blue 80483f7 \color inherit : \color blue mov DWORD PTR [ebp-0x4],0x0 \end_layout \begin_layout LyX-Code \color blue } \end_layout \begin_layout LyX-Code \color green return 0; \end_layout \begin_layout LyX-Code \color green 80483fe \color inherit : \color green mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 8048403: leave \end_layout \begin_layout LyX-Code 8048404: ret \end_layout \begin_layout Standard The generated assembly code follows the same order as the corresponding high level syntax: \end_layout \begin_layout Itemize \color red red \color inherit instructions represents \family typewriter if \family default branch. \end_layout \begin_layout Itemize \color blue blue \color inherit instructions represents \family typewriter else \family default branch. \end_layout \begin_layout Itemize \color green green \color inherit instruction is the exit point for both \family typewriter if \family default and \family typewriter else \family default branch. \end_layout \begin_layout Standard \family typewriter if \family default branch first compares whether \family typewriter argc \family default is \emph on false \emph default (equal to 0) with \family typewriter cmp \family default instruction. If true, it proceeds to \family typewriter else \family default branch at \family typewriter \color blue 80483f7 \family default \color inherit . Otherwise, \family typewriter if \family default branch continues with the code of its branch, which is the next instruction at \family typewriter \color red 80483ee \color inherit \family default for copying \family typewriter 1 \family default to \family typewriter i \family default . \family typewriter \family default Finally, it skips over \family typewriter else \family default branch and proceeds to \family typewriter \color green 80483fe \family default \color inherit , which is the next instruction pasts the \family typewriter if..else... \family default construct. \end_layout \begin_layout Standard \family typewriter else \family default branch is entered when \family typewriter cmp \family default instruction from \family typewriter if \family default branch is true. \family typewriter else \family default branch starts at \family typewriter \color blue 80483f7 \family default \color inherit , which is the first instruction of \family typewriter else \family default branch. The instruction copies \family typewriter 0 \family default to \family typewriter i \family default , and proceeds naturally to the next instruction pasts the \family typewriter if...else... \family default construct without any jump. \end_layout \end_deeper \begin_layout Chapter The Anatomy of a Program \begin_inset CommandInset label LatexCommand label name "chap:The-Anatomy-of-a-program" \end_inset \end_layout \begin_layout Standard Every program consists of code and data, and only those two components made up a program. However, if a program consists purely code and data of its own, from the perspective of an operating system (as well as human), it does not know in a program, which block of binary is a program and which is just raw data, where in the program to start execution, which region of memory should be protected and which is free to modify. For that reason, each program carries extra metadata to communicate with the operating system how to handle the program. \end_layout \begin_layout Standard When a source file is compiled, the generated machine code is stored into an \emph on \begin_inset Index idx status open \begin_layout Plain Layout object file \end_layout \end_inset \emph default \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on object file \end_layout \end_inset \emph on object file \emph default , which is just a block of binary. One or more object files can be combined to produce an \emph on \begin_inset Index idx status open \begin_layout Plain Layout executable binary \end_layout \end_inset \emph default \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on executable binary \end_layout \end_inset \emph on executable binary \emph default , which is a complete program runnable in an operating system. \end_layout \begin_layout Standard \begin_inset Flex Code status open \begin_layout Plain Layout readelf \end_layout \end_inset is a program that recognizes and displays the ELF metadata of a binary file, be it an object file or an executable binary. \series bold \emph on ELF \series default \emph default , or \series bold \emph on E \series default xecutable and \series bold L \series default inkable \series bold F \series default ormat \emph default , is the content at the very beginning of an executable to provide an operating system necessary information to load into main memory and run the executable. ELF can be thought of similar to the table of contents of a book. In a book, a table of contents list the page numbers of the main sections, subsections, sometimes even figures and tables for easy lookup. Similarly, ELF lists various sections used for code and data, and the memory addresses of each symbol along with other information. \end_layout \begin_layout Standard An ELF binary is composed of: \end_layout \begin_layout Itemize An \begin_inset Index idx status open \begin_layout Plain Layout ELF header \end_layout \end_inset \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on ELF header \end_layout \end_inset ELF header \emph default : the very first section of an executable that describes the file's organization. \end_layout \begin_layout Itemize A \begin_inset Index idx status open \begin_layout Plain Layout Program header table \end_layout \end_inset \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on program header table \end_layout \end_inset program header table \emph default : is an array of fixed-size structures that describes segments of an executable. \end_layout \begin_layout Itemize A \begin_inset Index idx status open \begin_layout Plain Layout Section header table \end_layout \end_inset \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on section header table \end_layout \end_inset section header table \emph default : is an array of fixed-size structures that describes sections of an executable. \end_layout \begin_layout Itemize \emph on \begin_inset Index idx status open \begin_layout Plain Layout Segments and section \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Segments and section \emph default s \end_layout \end_inset Segments and section \emph default s are the main content of an ELF binary, which are the code and data, divided into chunks of different purposes. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard A \emph on segment \begin_inset Index idx status open \begin_layout Plain Layout segment \end_layout \end_inset \emph default is a composition of zero or more sections and is directly loaded by an operating system at runtime. \end_layout \begin_layout Standard A \emph on section \begin_inset Index idx status open \begin_layout Plain Layout section \end_layout \end_inset \emph default is a block of binary that is either: \end_layout \begin_layout Itemize actual program code and data that is available in memory when a program runs. \end_layout \begin_layout Itemize metadata about other sections used only in the linking process, and disappear from the final executable. \end_layout \begin_layout Standard Linker uses sections to build segments. \end_layout \end_deeper \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout ELF - Linking View vs Executable View (Source: Wikipedia) \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/05/Elf-layout--en.pdf scale 30 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Later we will compile our kernel as an ELF executable with GCC, and explicitly specify how segments are created and where they are loaded in memory through the use a \emph on linker script \emph default , a text file to instruct how a linker should generate a binary. For now, we will examine the anatomy of an ELF executable in detail. \end_layout \begin_layout Section Reference documents: \end_layout \begin_layout Standard The \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on ELF specification \end_layout \end_inset ELF specification is bundled as a \family typewriter man \family default page in Linux: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ man elf \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard It is a useful resource to understand and implement ELF. However, it will be much easier to use after you finish this chapter, as the specification mixes implementation details in it. \end_layout \begin_layout Standard The default specification is a generic one, in which every ELF implementation follows. However, each platform provides extra features unique to it. The ELF specification for x86 is currently maintained on Github by H.J. Lu: \begin_inset Flex URL status collapsed \begin_layout Plain Layout https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI \end_layout \end_inset . \end_layout \begin_layout Standard Platform-dependent details are referred to as \begin_inset Quotes eld \end_inset processor specific \begin_inset Quotes erd \end_inset in the generic ELF specification. We will not explore these details, but study the generic details, which are enough for crafting an ELF binary image for our operating system. \end_layout \begin_layout Section ELF header \end_layout \begin_layout Standard To see the information of an ELF header: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -h hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left The output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ELF Header: \end_layout \begin_layout LyX-Code Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 \end_layout \begin_layout LyX-Code Class: ELF64 \end_layout \begin_layout LyX-Code Data: 2's complement, little endian \end_layout \begin_layout LyX-Code Version: 1 (current) \end_layout \begin_layout LyX-Code OS/ABI: UNIX - System V \end_layout \begin_layout LyX-Code ABI Version: 0 \end_layout \begin_layout LyX-Code Type: EXEC (Executable file) \end_layout \begin_layout LyX-Code Machine: Advanced Micro Devices X86-64 \end_layout \begin_layout LyX-Code Version: 0x1 \end_layout \begin_layout LyX-Code Entry point address: 0x400430 \end_layout \begin_layout LyX-Code Start of program headers: 64 (bytes into file) \end_layout \begin_layout LyX-Code Start of section headers: 6648 (bytes into file) \end_layout \begin_layout LyX-Code Flags: 0x0 \end_layout \begin_layout LyX-Code Size of this header: 64 (bytes) \end_layout \begin_layout LyX-Code Size of program headers: 56 (bytes) \end_layout \begin_layout LyX-Code Number of program headers: 9 \end_layout \begin_layout LyX-Code Size of section headers: 64 (bytes) \end_layout \begin_layout LyX-Code Number of section headers: 31 \end_layout \begin_layout LyX-Code Section header string table index: 28 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Let's go through each field: \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Magic \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Displays the raw bytes that uniquely addresses a file is an ELF executable binary. Each byte gives a brief information. \end_layout \begin_layout Standard In the example, we have the following magic bytes: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout LyX-Code \noindent \align left Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Examine byte by byte: \end_layout \begin_layout Standard \begin_inset space \quad{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Byte \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 7f 45 4c 46 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Predefined values. The first byte is always \begin_inset Flex Code status open \begin_layout Plain Layout 7F \end_layout \end_inset , the remaining 3 bytes represent the string \begin_inset Flex Code status open \begin_layout Plain Layout \begin_inset Quotes eld \end_inset ELF \end_layout \end_inset \begin_inset Quotes erd \end_inset . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 02 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout See \begin_inset Flex Code status open \begin_layout Plain Layout Class \end_layout \end_inset field below. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 01 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout See \begin_inset Flex Code status open \begin_layout Plain Layout Data \end_layout \end_inset field below. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 01 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout See \begin_inset Flex Code status open \begin_layout Plain Layout Version \end_layout \end_inset field below. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 00 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout See \begin_inset Flex Code status open \begin_layout Plain Layout OS/ABI \end_layout \end_inset field below. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 00 00 00 00 00 00 00 00 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Padding bytes. These bytes are unused and are always set to 0. Padding bytes are added for proper alignment, and is reserved for future use when more information is needed. \end_layout \end_inset \end_inset \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Class \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard A byte in \begin_inset Flex Code status open \begin_layout Plain Layout Magic \end_layout \end_inset field. It specifies the class or capacity of a file. \end_layout \begin_layout Standard Possible values: \end_layout \begin_layout Standard \begin_inset space \quad{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 0 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Invalid class \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 1 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 32-bit objects \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 2 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 64-bit objects \end_layout \end_inset \end_inset \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Data \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard A byte in \begin_inset Flex Code status open \begin_layout Plain Layout Magic \end_layout \end_inset field. It specifies the data encoding of the processor-specific data in the object file. \end_layout \begin_layout Standard Possible values: \end_layout \begin_layout Standard \begin_inset space \quad{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 0 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Invalid data encoding \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 1 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Little endian, 2's complement \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 2 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Big endian, 2's complement \end_layout \end_inset \end_inset \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Version \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard A byte in \begin_inset Flex Code status open \begin_layout Plain Layout Magic \end_layout \end_inset . It specifies the ELF header version number. \end_layout \begin_layout Standard Possible values: \end_layout \begin_layout Standard \begin_inset space \quad{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Invalid version \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Current version \end_layout \end_inset \end_inset \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout OS/ABI \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard A byte in \begin_inset Flex Code status open \begin_layout Plain Layout Magic \end_layout \end_inset field. It specifies the target operating system \begin_inset Flex Code status open \begin_layout Plain Layout ABI \end_layout \end_inset . Originally, it was a padding byte. \end_layout \begin_layout Standard Possible values: Refer to the latest ABI document, as it is a long list of different operating systems. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Type \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Identifies the object file type. \end_layout \begin_layout Standard \begin_inset space \quad{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 0 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout No file type \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 1 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Relocatable file \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 2 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Executable file \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 3 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Shared object file \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 4 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Core file \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 0xff00 \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Processor specific, lower bound \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout 0xffff \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Processor specific, upper bound \end_layout \end_inset \end_inset \end_layout \begin_layout Standard The values from \begin_inset Flex Code status open \begin_layout Plain Layout 0xff00 \end_layout \end_inset to \begin_inset Flex Code status open \begin_layout Plain Layout 0xffff \end_layout \end_inset are reserved for a processor to define additional file types meaningful to it. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Machine \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the required architecture value for an ELF file e.g. x86_64, MIPS, SPARC, etc. In the example, the machine is of \begin_inset Flex Code status open \begin_layout Plain Layout x86_64 \end_layout \end_inset architecture. \end_layout \begin_layout Standard Possible values: Please refer to the latest ABI document, as it is a long list of different architectures. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Version \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the version number of the current \emph on object file \emph default (not the version of the ELF header, as the above \begin_inset Flex Code status open \begin_layout Plain Layout Version \end_layout \end_inset field specified). \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Entry \begin_inset space ~ \end_inset point \begin_inset space ~ \end_inset address \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the memory address where the very first code to be executed. The address of \begin_inset Flex Code status open \begin_layout Plain Layout main \end_layout \end_inset function is the default in a normal application program, but it can be any function by explicitly specifying the function name to \family typewriter gcc \family default . For the operating system we are going to write, this is the single most important field that we need to retrieve to bootstrap our kernel, and everythin g else can be ignored. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Start \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset program \begin_inset space ~ \end_inset headers \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard The offset of the program header table, in bytes. In the example, this number is \begin_inset Flex Code status open \begin_layout Plain Layout 64 \end_layout \end_inset bytes, which means the \begin_inset Flex Code status open \begin_layout Plain Layout 65th \end_layout \end_inset byte, or \begin_inset Flex Code status open \begin_layout Plain Layout + 64 \end_layout \end_inset , is the start address of the program header table. That is, if a program is loaded at address \begin_inset Flex Code status open \begin_layout Plain Layout 0x10000 \end_layout \end_inset in memory, then the start address is \begin_inset Flex Code status open \begin_layout Plain Layout 0x10000 \end_layout \end_inset (the very first byte of \begin_inset Flex Code status open \begin_layout Plain Layout Magic \end_layout \end_inset field, where the value \begin_inset Flex Code status open \begin_layout Plain Layout 0x7f \end_layout \end_inset resides) and the start address of program header table is \begin_inset Flex Code status open \begin_layout Plain Layout 0x10000 + 0x40 = 0x10040 \end_layout \end_inset . \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Start \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset section \begin_inset space ~ \end_inset headers \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard The offset of the section header table in bytes, similar to the start of program headers. In the example, it is \begin_inset Flex Code status open \begin_layout Plain Layout 6648 \end_layout \end_inset bytes into file. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Flags \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Hold processor-specific flags associated with the file. When the program is loaded, in a x86 machine, \begin_inset Flex Code status open \begin_layout Plain Layout EFLAGS \end_layout \end_inset register is set according to this value. In the example, the value is \begin_inset Flex Code status open \begin_layout Plain Layout 0x0 \end_layout \end_inset , which means \begin_inset Flex Code status open \begin_layout Plain Layout EFLAGS \end_layout \end_inset register is in a clear state. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Size \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset this \begin_inset space ~ \end_inset header \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the total size of ELF header's size in bytes. In the example, it is \family typewriter 64 \family default bytes, which is equivalent to Start of program headers. Note that these two numbers are not necessarily equivalent, as program header table might be placed far away from the ELF header. The only fixed component in the ELF executable binary is the ELF header, which appears at the very beginning of the file. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Size \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset program \begin_inset space ~ \end_inset headers \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the size of \emph on each \emph default program header in bytes. In the example, it is \family typewriter 64 \family default bytes. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Number \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset program \begin_inset space ~ \end_inset headers \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the total number of program headers. In the example, the file has a total of \family typewriter 9 \family default program headers. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Size \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset section \begin_inset space ~ \end_inset headers \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the size of \emph on each \emph default section header in bytes. In the example, it is 64 bytes. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Number \begin_inset space ~ \end_inset of \begin_inset space ~ \end_inset section \begin_inset space ~ \end_inset headers \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the total number of section headers. In the example, the file has a total of \begin_inset Flex Code status open \begin_layout Plain Layout 31 \end_layout \end_inset section headers. In a section header table, the first entry in the table is always an empty section. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Section \begin_inset space ~ \end_inset header \begin_inset space ~ \end_inset string \begin_inset space ~ \end_inset table \begin_inset space ~ \end_inset index \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Specifies the index of the header in the section header table that points to the section that holds all null-terminated strings. In the example, the index is \family typewriter 28 \family default , which means it's the 28 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset entry of the table. \end_layout \end_deeper \begin_layout Section Section header table \end_layout \begin_layout Standard As we know already, code and data compose a program. However, not all types of code and data have the same purpose. For that reason, instead of a big chunk of code and data, they are divided into smaller chunks, and each chunk must satisfy these conditions (according to gABI): \end_layout \begin_layout Itemize Every section in an object file has exactly one section header describing it. But, section headers may exist that do not have a section. \end_layout \begin_layout Itemize Each section occupies one contiguous (possibly empty) sequence of bytes within a file. That means, there's no two regions of bytes that are the same section. \end_layout \begin_layout Itemize Sections in a file may not overlap. No byte in a file resides in more than one section. \end_layout \begin_layout Itemize An object file may have inactive space. The various headers and the sections might not \begin_inset Quotes eld \end_inset cover \begin_inset Quotes erd \end_inset every byte in an object file. The contents of the inactive data are unspecified. \end_layout \begin_layout Standard To get all the headers from an executable binary e.g. \begin_inset Flex Code status open \begin_layout Plain Layout hello \end_layout \end_inset , use the following command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -S hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left Here is a sample output (do not worry if you don't understand the output. Just skim to get your eyes familiar with it. We will dissect it soon enough): \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code There are 31 section headers, starting at offset 0x19c8: \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code Section Headers: \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [ 0] NULL 0000000000000000 00000000 \end_layout \begin_layout LyX-Code 0000000000000000 0000000000000000 0 0 0 \end_layout \begin_layout LyX-Code [ 1] .interp PROGBITS 0000000000400238 00000238 \end_layout \begin_layout LyX-Code 000000000000001c 0000000000000000 A 0 0 1 \end_layout \begin_layout LyX-Code [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000000 A 0 0 4 \end_layout \begin_layout LyX-Code [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 \end_layout \begin_layout LyX-Code 0000000000000024 0000000000000000 A 0 0 4 \end_layout \begin_layout LyX-Code [ 4] .gnu.hash GNU_HASH 0000000000400298 00000298 \end_layout \begin_layout LyX-Code 000000000000001c 0000000000000000 A 5 0 8 \end_layout \begin_layout LyX-Code [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 \end_layout \begin_layout LyX-Code 0000000000000048 0000000000000018 A 6 1 8 \end_layout \begin_layout LyX-Code [ 6] .dynstr STRTAB 0000000000400300 00000300 \end_layout \begin_layout LyX-Code 0000000000000038 0000000000000000 A 0 0 1 \end_layout \begin_layout LyX-Code [ 7] .gnu.version VERSYM 0000000000400338 00000338 \end_layout \begin_layout LyX-Code 0000000000000006 0000000000000002 A 5 0 2 \end_layout \begin_layout LyX-Code [ 8] .gnu.version_r VERNEED 0000000000400340 00000340 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000000 A 6 1 8 \end_layout \begin_layout LyX-Code [ 9] .rela.dyn RELA 0000000000400360 00000360 \end_layout \begin_layout LyX-Code 0000000000000018 0000000000000018 A 5 0 8 \end_layout \begin_layout LyX-Code [10] .rela.plt RELA 0000000000400378 00000378 \end_layout \begin_layout LyX-Code 0000000000000018 0000000000000018 AI 5 24 8 \end_layout \begin_layout LyX-Code [11] .init PROGBITS 0000000000400390 00000390 \end_layout \begin_layout LyX-Code 000000000000001a 0000000000000000 AX 0 0 4 \end_layout \begin_layout LyX-Code [12] .plt PROGBITS 00000000004003b0 000003b0 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000010 AX 0 0 16 \end_layout \begin_layout LyX-Code [13] .plt.got PROGBITS 00000000004003d0 000003d0 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000000 AX 0 0 8 \end_layout \begin_layout LyX-Code [14] .text PROGBITS 00000000004003e0 000003e0 \end_layout \begin_layout LyX-Code 0000000000000192 0000000000000000 AX 0 0 16 \end_layout \begin_layout LyX-Code [15] .fini PROGBITS 0000000000400574 00000574 \end_layout \begin_layout LyX-Code 0000000000000009 0000000000000000 AX 0 0 4 \end_layout \begin_layout LyX-Code [16] .rodata PROGBITS 0000000000400580 00000580 \end_layout \begin_layout LyX-Code 0000000000000004 0000000000000004 AM 0 0 4 \end_layout \begin_layout LyX-Code [17] .eh_frame_hdr PROGBITS 0000000000400584 00000584 \end_layout \begin_layout LyX-Code 000000000000003c 0000000000000000 A 0 0 4 \end_layout \begin_layout LyX-Code [18] .eh_frame PROGBITS 00000000004005c0 000005c0 \end_layout \begin_layout LyX-Code 0000000000000114 0000000000000000 A 0 0 8 \end_layout \begin_layout LyX-Code [19] .init_array INIT_ARRAY 0000000000600e10 00000e10 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000000 WA 0 0 8 \end_layout \begin_layout LyX-Code [20] .fini_array FINI_ARRAY 0000000000600e18 00000e18 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000000 WA 0 0 8 \end_layout \begin_layout LyX-Code [21] .jcr PROGBITS 0000000000600e20 00000e20 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000000 WA 0 0 8 \end_layout \begin_layout LyX-Code [22] .dynamic DYNAMIC 0000000000600e28 00000e28 \end_layout \begin_layout LyX-Code 00000000000001d0 0000000000000010 WA 6 0 8 \end_layout \begin_layout LyX-Code [23] .got PROGBITS 0000000000600ff8 00000ff8 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000008 WA 0 0 8 \end_layout \begin_layout LyX-Code [24] .got.plt PROGBITS 0000000000601000 00001000 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000008 WA 0 0 8 \end_layout \begin_layout LyX-Code [25] .data PROGBITS 0000000000601020 00001020 \end_layout \begin_layout LyX-Code 0000000000000010 0000000000000000 WA 0 0 8 \end_layout \begin_layout LyX-Code [26] .bss NOBITS 0000000000601030 00001030 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000000 WA 0 0 1 \end_layout \begin_layout LyX-Code [27] .comment PROGBITS 0000000000000000 00001030 \end_layout \begin_layout LyX-Code 0000000000000034 0000000000000001 MS 0 0 1 \end_layout \begin_layout LyX-Code [28] .shstrtab STRTAB 0000000000000000 000018b6 \end_layout \begin_layout LyX-Code 000000000000010c 0000000000000000 0 0 1 \end_layout \begin_layout LyX-Code [29] .symtab SYMTAB 0000000000000000 00001068 \end_layout \begin_layout LyX-Code 0000000000000648 0000000000000018 30 47 8 \end_layout \begin_layout LyX-Code [30] .strtab STRTAB 0000000000000000 000016b0 \end_layout \begin_layout LyX-Code 0000000000000206 0000000000000000 0 0 1 \end_layout \begin_layout LyX-Code Key to Flags: \end_layout \begin_layout LyX-Code W (write), A (alloc), X (execute), M (merge), S (strings), l (large) \end_layout \begin_layout LyX-Code I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) \end_layout \begin_layout LyX-Code O (extra OS processing required) o (OS specific), p (processor specific) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The first line: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm,width=12.3cm] \end_layout \end_inset \end_layout \begin_layout LyX-Code There are 31 section headers, starting at offset 0x19c8 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left summarizes the total number of sections in the file, and where the address where it starts. Then, comes the listing section by section with the following header, is also the format of each section output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Each section has two lines with different fields: \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Nr \end_layout \end_inset The index of each section. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Name \end_layout \end_inset The name of each section. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Type \end_layout \end_inset This field (in a section header) identifies the type of each section. Types are used to classify sections. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Address \end_layout \end_inset The starting \emph on virtual \emph default address of each section. Note that the addresses are virtual only when a program runs in an OS with support for virtual memory enabled. In our OS, we run on the bare metal, the addresses will all be physical. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Offset \end_layout \end_inset \emph on \begin_inset Index idx status open \begin_layout Plain Layout offset \end_layout \end_inset \emph default is a distance in bytes, from the first byte of a file to the start of an object, such as a section or a segment in the context of an ELF binary file. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Size \end_layout \end_inset The size in bytes of each section. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on EntSize \end_layout \end_inset Some sections hold a table of fixed-size entries, such as a symbol table. For such a section, this member gives the size in bytes of each entry. The member contains 0 if the section does not hold a table of fixed-size entries. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Flags \end_layout \end_inset \emph on \emph default describes attributes of a section. Flags together with a type defines the purpose of a section. Two sections can be of the same type, but serve different purposes. For example, even though \family typewriter .data \family default and \family typewriter .text \family default share the same type, \family typewriter .data \family default holds the initialized data of a program while \family typewriter .text \family default holds executable instructions of a program. For that reason, \family typewriter .data \family default is given read and write permission, but not executable. Any attempt to execute code in \family typewriter .data \family default is denied by the running OS: in Linux, such invalid section usage gives a \emph on segmentation fault \emph default . \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard ELF gives information to enable an OS with such protection mechanism. However, running on bare metal, nothing can prevent from doing anything. Our OS can execute code in data section, and vice versa, writing to code section. \end_layout \end_deeper \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Section Flags \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Flag \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Descriptions \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter W \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Bytes in this section are writable during execution. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter A \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Memory is allocated for this section during process execution. Some control sections do not reside in the memory image of an object file; this attribute is off for those sections. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter X \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section contains executable instructions. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter M \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The data \family default \series default \shape default \size default \emph on \bar default \strikeout default \uuline default \uwave default \noun default \color inherit in the section \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none may be merged to eliminate duplication. \family default \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit Each element in the section is compared against other elements in sections with the same name, type and flags. Elements that would have identical values at program run-time may be merged. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter S \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The data elements in the section consist of null-terminated character strings. The size of each character is specified in the section header's \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on EntSize \end_layout \end_inset field. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter l \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Specific large section for x86_64 architecture. This flag is not specified in the Generic ABI but in x86_64 ABI. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter I \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The \emph on \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter Info \end_layout \end_inset \emph default field of this section header holds an index of a section header. Otherwise, the number is the index of something else. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter L \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Preserve section ordering when linking. If this section is combined with other sections in the output file, it must appear in the same relative order with respect to those sections, as the linked-to section appears with respect to sections the linked-to section is combined with. Apply when the \family typewriter \series bold \emph on Link \family default \series default \emph default field of this section's header references another section (the linked-to section) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter G \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout This section is a member (perhaps the only one) of a section group. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter T \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout This section holds \series bold T \series default hread- \series bold L \series default ocal \series bold S \series default torage, meaning that each thread has its own distinct instance of this data. A thread is a distinct execution flow of code. A program can have multiple threads that pack different pieces of code and execute separately, at the same time. We will learn more about threads when writing our kernel. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Link editor is to exclude this section from executable and shared library that it builds when those objects are not to be further relocated. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter x \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Unknown flag to \family typewriter readelf \family default . It happens because the linking process can be done manually with a linker like \family typewriter GNU ld \family default (we will later later). That is, section flags can be specified manually, and some flags are for a customized ELF that the open-source \family typewriter readelf \family default doesn't know of. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter O \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout This section requires special OS-specific processing (beyond the standard linking rules) to avoid incorrect behavior. A link editor encounters sections whose headers contain OS-specific values it does not recognize by Type or Flags values defined by ELF standard, the link editor should combine those sections. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter o \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout All bits included in this flag are reserved for operating system-specific semantics. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter p \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout All bits included in this flag are reserved for processor-specific semantics. If meanings are specified, the processor supplement explains them. \end_layout \end_inset \end_inset \end_layout \begin_layout Description \family typewriter \emph on \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Link \begin_inset space ~ \end_inset and \begin_inset space ~ \end_inset Info \end_layout \end_inset \family default \emph default are numbers that references the indexes of sections, symbol table entries, hash table entries. \family typewriter Link \family default field only holds the index of a section, while \family typewriter Info \family default field holds an index of a section, a symbol table entry or a hash table entry, depends on the type of a section. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard Later when writing our OS, we will handcraft the kernel image by explicitly linking the object files (produced by \family typewriter gcc \family default ) through a linker script. We will specify the memory layout of sections by specifying at what addresses they will appear in the final image. But we will not assign any section flag and let the linker take care of it. Nevertheless, knowing which flag does what is useful. \end_layout \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter \emph on Align \end_layout \end_inset is a value that enforces the offset of a section should be divisible by the value. Only 0 and positive integral powers of two are allowed. Values 0 and 1 mean the section has no alignment constraint. \end_layout \begin_layout Example Output of \family typewriter .interp \family default section: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [ 1] .interp PROGBITS 0000000000400238 00000238 \end_layout \begin_layout LyX-Code 000000000000001c 0000000000000000 A 0 0 1 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \emph on Nr \family default \emph default is \family typewriter 1 \family default . \end_layout \begin_layout Standard \family typewriter \emph on Type \family default \emph default is \family typewriter PROGBITS \family default , which means this section is part of the program. \end_layout \begin_layout Standard \family typewriter \emph on Address \family default \emph default is \family typewriter 0x0000000000400238 \family default , which means the program is loaded at this virtual memory address at runtime. \end_layout \begin_layout Standard \family typewriter \emph on Offset \family default \emph default is \family typewriter 0x00000238 \family default \emph on bytes \emph default into file. \end_layout \begin_layout Standard \family typewriter \emph on Size \family default \emph default is \family typewriter 0x000000000000001c \family default in bytes. \end_layout \begin_layout Standard \family typewriter \emph on EntSize \family default \emph default is \family typewriter 0 \family default , which means this section does not have any fixed-size entry. \end_layout \begin_layout Standard \family typewriter \emph on Flags \family default \emph default are \family typewriter A \family default (Allocatable), which means this section consumes memory at runtime. \end_layout \begin_layout Standard \family typewriter \emph on Info \emph default and Link \family default are \family typewriter 0 \family default and \family typewriter 0 \family default , which means this section links to no section or entry in any table. \end_layout \begin_layout Standard \family typewriter \emph on Align \family default \emph default is \family typewriter 1 \family default , which means no alignment. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example Output of the \family typewriter .text \family default section: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [14] .text PROGBITS 00000000004003e0 000003e0 \end_layout \begin_layout LyX-Code 0000000000000192 0000000000000000 AX 0 0 16 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \emph on Nr \family default \emph default is \family typewriter 14 \family default . \end_layout \begin_layout Standard \family typewriter \emph on Type \family default \emph default is \family typewriter PROGBITS \family default , which means this section is part of the program. \end_layout \begin_layout Standard \family typewriter \emph on Address \family default \emph default is \family typewriter 0x00000000004003e0 \family default , which means the program is loaded at this virtual memory address at runtime. \end_layout \begin_layout Standard \family typewriter \emph on Offset \family default \emph default is \family typewriter 0x000003e0 \family default \emph on bytes \emph default into file. \end_layout \begin_layout Standard \family typewriter \emph on Size \family default \emph default is \family typewriter 0x0000000000000192 \family default in bytes. \end_layout \begin_layout Standard \family typewriter \emph on EntSize \family default \emph default is \family typewriter 0 \family default , which means this section does not have any fixed-size entry. \end_layout \begin_layout Standard \family typewriter \emph on Flags \family default \emph default are \family typewriter A \family default (Allocatable) and \family typewriter X \family default (Executable), which means this section consumes memory and can be executed as code at runtime. \end_layout \begin_layout Standard \family typewriter \emph on Info \emph default and Link \family default are \family typewriter 0 \family default and \family typewriter 0 \family default , which means this section links to no section or entry in any table. \end_layout \begin_layout Standard \family typewriter \emph on Align \family default \emph default is \family typewriter 16 \family default , which means the starting address of the section should be divisible by \family typewriter 16 \family default , or \family typewriter 0x10 \family default . Indeed, it is: \begin_inset Formula $\mathtt{0x3e0/0x10=0x3e}$ \end_inset . \end_layout \end_deeper \begin_layout Section Understand Section in-depth \end_layout \begin_layout Standard In this section, we will learn different details of section types and the purposes of special sections e.g. \family typewriter .bss, .text, .data \family default , etc, by looking at each section one by one. We will also examine the content of each section as a hexdump with the commands: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -x
\end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard For example, if you want to examine the content of section with index 25 (the \family typewriter .bss \family default section in the sample output) in the file \family typewriter hello \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -x 25 hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard Equivalently, using name instead of index works: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{tcolorbox}[enlarge top initially by=5mm] \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -x .data hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{tcolorbox} \end_layout \end_inset \end_layout \begin_layout Standard If a section contains strings e.g. string symbol table, the flag \family typewriter -x \family default can be replaced with \family typewriter -p \family default . \end_layout \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter NULL \end_layout \end_inset \family default marks a section header as inactive and does not have an associated section. \family typewriter NULL \family default section is always the first entry of section header table. It means, any useful section starts from 1. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example The sample output of \family typewriter NULL \family default section: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [ 0] NULL 0000000000000000 00000000 \end_layout \begin_layout LyX-Code 0000000000000000 0000000000000000 0 0 0 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard Examining the content, the section is empty: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput} \end_layout \end_inset \end_layout \begin_layout LyX-Code Section '' has no data to dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput} \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter NOTE \end_layout \end_inset \family default marks a section with special information that other programs will check for conformance, compatibility, etc, by a vendor or a system builder. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example In the sample output, we have 2 \family typewriter NOTE \family default sections: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000000 A 0 0 4 \end_layout \begin_layout LyX-Code [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 \end_layout \begin_layout LyX-Code 0000000000000024 0000000000000000 A 0 0 4 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard Examine 2nd section with the command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -x 2 hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard we have: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Hex dump of section '.note.ABI-tag': \end_layout \begin_layout LyX-Code 0x00400254 04000000 10000000 01000000 474e5500 ............GNU. \end_layout \begin_layout LyX-Code 0x00400264 00000000 02000000 06000000 20000000 ............ ... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter PROGBITS \end_layout \end_inset \family default indicates a section holding the main content of a program, either code or data. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example There are many PROGBITS sections: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [ 1] .interp PROGBITS 0000000000400238 00000238 \end_layout \begin_layout LyX-Code 000000000000001c 0000000000000000 A 0 0 1 \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code [11] .init PROGBITS 0000000000400390 00000390 \end_layout \begin_layout LyX-Code 000000000000001a 0000000000000000 AX 0 0 4 \end_layout \begin_layout LyX-Code [12] .plt PROGBITS 00000000004003b0 000003b0 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000010 AX 0 0 16 \end_layout \begin_layout LyX-Code [13] .plt.got PROGBITS 00000000004003d0 000003d0 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000000 AX 0 0 8 \end_layout \begin_layout LyX-Code [14] .text PROGBITS 00000000004003e0 000003e0 \end_layout \begin_layout LyX-Code 0000000000000192 0000000000000000 AX 0 0 16 \end_layout \begin_layout LyX-Code [15] .fini PROGBITS 0000000000400574 00000574 \end_layout \begin_layout LyX-Code 0000000000000009 0000000000000000 AX 0 0 4 \end_layout \begin_layout LyX-Code [16] .rodata PROGBITS 0000000000400580 00000580 \end_layout \begin_layout LyX-Code 0000000000000004 0000000000000004 AM 0 0 4 \end_layout \begin_layout LyX-Code [17] .eh_frame_hdr PROGBITS 0000000000400584 00000584 \end_layout \begin_layout LyX-Code 000000000000003c 0000000000000000 A 0 0 4 \end_layout \begin_layout LyX-Code [18] .eh_frame PROGBITS 00000000004005c0 000005c0 \end_layout \begin_layout LyX-Code 0000000000000114 0000000000000000 A 0 0 8 \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code [23] .got PROGBITS 0000000000600ff8 00000ff8 \end_layout \begin_layout LyX-Code 0000000000000008 0000000000000008 WA 0 0 8 \end_layout \begin_layout LyX-Code [24] .got.plt PROGBITS 0000000000601000 00001000 \end_layout \begin_layout LyX-Code 0000000000000020 0000000000000008 WA 0 0 8 \end_layout \begin_layout LyX-Code [25] .data PROGBITS 0000000000601020 00001020 \end_layout \begin_layout LyX-Code 0000000000000010 0000000000000000 WA 0 0 8 \end_layout \begin_layout LyX-Code [27] .comment PROGBITS 0000000000000000 00001030 \end_layout \begin_layout LyX-Code 0000000000000034 0000000000000001 MS 0 0 1 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left For our operating system, we only need the following section: \end_layout \begin_layout Description \family typewriter .text \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard This section holds all the compiled code of a program. \end_layout \end_deeper \begin_layout Description \family typewriter .data \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard This section holds the initialized data of a program. Since the data are initialized with actual values, \family typewriter gcc \family default allocates the section with actual byte in the executable binary. \end_layout \end_deeper \begin_layout Description \family typewriter .rodata \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard This section holds read-only data, such as fixed-size strings in a program, e.g. \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset , and others. \end_layout \end_deeper \begin_layout Description \family typewriter .bss \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard This section, shorts for \series bold \emph on B \series default lock \series bold S \series default tarted by \series bold S \series default ymbol \emph default , holds uninitialized data of a program. Unlike other sections, no space is allocated for this section in the image of the executable binary on disk. The section is allocated only when the program is loaded into main memory. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left Other sections are mainly needed for dynamic linking, that is code linking at runtime for sharing between many programs. To enable such feature, an OS as a runtime environment must be presented. Since we run our OS on bare metal, we are effectively creating such environment. For simplicity, we won't add dynamic linking to our OS. \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter SYMTAB \begin_inset space ~ \end_inset and \begin_inset space ~ \end_inset DYNSYM \end_layout \end_inset \family default These sections hold symbol table. A \emph on symbol table \emph default is an array of entries that describe symbols in a program. A \emph on symbol \emph default is a name assigned to an entity in a program. The types of these entities are also the types of symbols, and these are the possible types of an entity: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example In the sample output, section 5 and 29 are symbol tables: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 \end_layout \begin_layout LyX-Code 0000000000000048 0000000000000018 A 6 1 8 \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code [29] .symtab SYMTAB 0000000000000000 00001068 \end_layout \begin_layout LyX-Code 0000000000000648 0000000000000018 30 47 8 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard To show the symbol table: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -s hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Output consists of 2 symbol tables, corresponding to the two sections above, \family typewriter .dynsym \family default and \family typewriter .symtab \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \size small Symbol table '.dynsym' contains 4 entries: \end_layout \begin_layout LyX-Code \size small Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code \size small 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND \end_layout \begin_layout LyX-Code \size small 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2) \end_layout \begin_layout LyX-Code \size small 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLI BC_2.2.5 (2) \end_layout \begin_layout LyX-Code \size small 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ \end_layout \begin_layout LyX-Code \size small Symbol table '.symtab' contains 67 entries: \end_layout \begin_layout LyX-Code \size small Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code \size small .......................................... \end_layout \begin_layout LyX-Code \size small 59: 0000000000601040 0 NOTYPE GLOBAL DEFAULT 26 _end \end_layout \begin_layout LyX-Code \size small 60: 0000000000400430 42 FUNC GLOBAL DEFAULT 14 _start \end_layout \begin_layout LyX-Code \size small 61: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 26 __bss_start \end_layout \begin_layout LyX-Code \size small 62: 0000000000400526 32 FUNC GLOBAL DEFAULT 14 main \end_layout \begin_layout LyX-Code \size small 63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses \end_layout \begin_layout LyX-Code \size small 64: 0000000000601038 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ \end_layout \begin_layout LyX-Code \size small 65: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneT able \end_layout \begin_layout LyX-Code \size small 66: 00000000004003c8 0 FUNC GLOBAL DEFAULT 11 _init \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter TLS \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The symbol is associated with a Thread-Local Storage entity. \end_layout \begin_layout Description \family typewriter Num \family default is the index of an entry in a table. \end_layout \begin_layout Description \family typewriter Value \family default is the virtual memory address where the symbol is located. \end_layout \begin_layout Description \family typewriter Size \family default is the size of the entity associated with a symbol. \end_layout \begin_layout Description \family typewriter Type \family default is a symbol type according to table. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Description \family typewriter NOTYPE \family default The type of a symbol is not specified. \end_layout \begin_layout Description \family typewriter OBJECT \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The symbol is associated with a data object. In C, any variable definition is of \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit OBJECT \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none type. \end_layout \begin_layout Description \family typewriter FUNC \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The symbol is associated with a function or other executable code. \end_layout \begin_layout Description \family typewriter SECTION \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The symbol is associated with a section, and exists primarily for relocation. \end_layout \begin_layout Description \family typewriter FILE \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The symbol is the name of a source file associated with an executable binary. \end_layout \begin_layout Description \family typewriter COMMON \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none The symbol labels an uninitialized variable. That is, when a variable in C is defined as global variable without an initial value, or as an external variable using the extern keyword. In other words, these variables stay in \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit .bss \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none section. \end_layout \end_deeper \begin_layout Description \family typewriter Bind \family default is the scope of a symbol. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout LOCAL \end_layout \end_inset are symbols that are only visible in the object files that defined them. In C, the \family typewriter static \family default modifier marks a symbol (e.g. a variable/function) as local to only the file that defines it. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example If we define variables and functions with \family typewriter static \family default modifer: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "title={hello.c}" inline false status open \begin_layout Plain Layout static int global_static_var = 0; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout static void local_func() { \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout static int local_static_var = 0; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \end_deeper \begin_layout Example Then we get the \family typewriter static \family default variables listed as local symbols after compiling: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 hello.c -o hello \end_layout \begin_layout Standard \family typewriter $ readelf -s hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Symbol table '.dynsym' contains 5 entries: \end_layout \begin_layout LyX-Code Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \end_layout \begin_layout LyX-Code 1: 00000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.0 (2) \end_layout \begin_layout LyX-Code 2: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ \end_layout \begin_layout LyX-Code 3: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) \end_layout \begin_layout LyX-Code 4: 080484bc 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used \end_layout \begin_layout LyX-Code Symbol table '.symtab' contains 72 entries: \end_layout \begin_layout LyX-Code Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code ......... output omitted ......... \end_layout \end_deeper \begin_layout LyX-Code 38: 0804a020 4 \color magenta OBJECT \color inherit \color blue LOCAL \color inherit DEFAULT 26 \color red global_static_var \end_layout \begin_layout LyX-Code 39: 0804840b 6 \color magenta FUNC \color inherit \color blue LOCAL \color inherit DEFAULT 14 \color red local_func \end_layout \begin_layout LyX-Code 40: 0804a024 4 \color magenta OBJECT \color inherit \color blue LOCAL \color inherit DEFAULT 26 \color red local_static_var.1938 \end_layout \begin_layout LyX-Code ......... output omitted ......... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \end_deeper \begin_layout Description \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none \begin_inset Flex Strong status open \begin_layout Plain Layout GLOBAL \end_layout \end_inset are symbols that are accessible by other object files when linking together. These symbols are primarily non- \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit static \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none functions and non- \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit static \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none global data. The \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit extern \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none modifier marks a symbol as externally defined elsewhere but is accessible in the final executable binary, so an \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit extern \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none variable is also considered \family typewriter \series default \shape default \size default \emph default \bar default \strikeout default \uuline default \uwave default \noun default \color inherit GLOBAL \family roman \series medium \shape up \size normal \emph off \bar no \strikeout off \uuline off \uwave off \noun off \color none . \family default \series default \shape default \size default \bar default \color inherit \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example Similar to the \family typewriter LOCAL \family default example above, the output lists many \family typewriter GLOBAL \family default symbols such as \family typewriter main \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code ......... output omitted ......... \end_layout \begin_layout LyX-Code 66: 080483e1 10 \color magenta FUNC \color inherit \color blue GLOBAL \color inherit DEFAULT 14 \color red main \end_layout \begin_layout LyX-Code ......... output omitted ......... \end_layout \end_deeper \end_deeper \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout WEAK \end_layout \end_inset are symbols whose definitions can be redefined. Normally, a symbol with multiple definitions are reported as an error by a compiler. However, this constraint is lax when a definition is explicitly marked as weak, which means the default implementation can be replaced by a different definition at link time. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example Suppose we have a default implementation of the function \family typewriter add \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((weak)) int add(int a, int b) { \end_layout \begin_layout Plain Layout printf("warning: function is not implemented. \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("add(1,2) is %d \backslash n", add(1,2)); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter __attribute__((weak)) \family default is a \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on function attribute \end_layout \end_inset function attribute. A \emph on \begin_inset Index idx status open \begin_layout Plain Layout function attribute \end_layout \end_inset function attribute \emph default is extra information for a compiler to handle a function differently from a normal function. In this example, \family typewriter weak \family default attribute makes the function \family typewriter add \family default a weak function,which means the default implementation can be replaced by a different definition at link time. Function attribute is a feature of a compiler, not standard C. \end_layout \begin_layout Standard If we do not supply a different function definition in a different file (must be in a different file, otherwise \family typewriter gcc \family default reports as an error), then the default implementation is applied. When the function \family typewriter add \family default is called, it only prints the message: \family typewriter "warning: function not implemented" \family default and returns 0: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ./hello \end_layout \begin_layout Standard \family typewriter warning: function is not implemented. \end_layout \begin_layout Standard \family typewriter add(1,2) is 0 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard However, if we supply a different definition in another file e.g. \family typewriter math.c \family default : \end_layout \begin_layout Standard \begin_inset listings lstparams "language=C,tabsize=4,title={\texttt{math.c}}" inline false status open \begin_layout Plain Layout int add(int a, int b) { \end_layout \begin_layout Plain Layout return a + b; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left and compile the two files together: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc math.c hello.c -o hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, when running \family typewriter hello \family default , no warning message is printed and the correct value is returned. \end_layout \begin_layout Standard Weak symbol is a mechanism to provide a default implementation, but replaceable when a better implementation is available (e.g. more specialized and optimized) at link-time. \end_layout \end_deeper \end_deeper \end_deeper \begin_layout Description \family typewriter Vis \family default is the visibility of a symbol. The following values are available: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Symbol Visibility \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DEFAULT \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The visibility is specified by the binding type of asymbol. \end_layout \begin_layout Itemize Global and weak symbols are visible outside of their defining component (executable file or shared object). \end_layout \begin_layout Itemize Local symbols are hidden. See \family typewriter HIDDEN \family default below. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter HIDDEN \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout A symbol is hidden when the name is not visible to any other program outside of its running program. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter PROTECTED \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout A symbol is protected when it is shared outside of its running program or shared libary and cannot be overridden. That is, there can only be one definition for this symbol across running programs that use it. No program can define its own definition of the same symbol. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter INTERNAL \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Visibility is processor-specific and is defined by processor-specific ABI. \end_layout \end_inset \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter Ndx \family default is the index of a section that the symbol is in. Aside from fixed index numbers that represent section indexes, index has these special values: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Symbol Index \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ABS \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The index will not be changed by any symbol relocation. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter COM \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The index refers to an unallocated common block. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter UND \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The symbol is undefined in the current object file, which means the symbol depends on the actual definition in another file. Undefined symbols appears when the object file refers to symbols that are available at runtime, from shared library. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter LORESERVE \end_layout \begin_layout Plain Layout \family typewriter HIRESERVE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter LORESERVE \family default is the lower boundary of the reserve indexes. Its value is \family typewriter 0xff00 \family default . \end_layout \begin_layout Plain Layout \family typewriter HIREVERSE \family default is the upper boundary of the reserve indexes. Its value is \family typewriter 0xffff \family default . \end_layout \begin_layout Plain Layout The operating system reserves exclusive indexes between \family typewriter LORESERVE \family default and \family typewriter HIRESERVE \family default , which do not map to any actual section header. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter XINDEX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The index is larger than \family typewriter LORESERVE \family default . The actual value will be contained in the section \family typewriter SYMTAB_SHNDX \family default , where each entry is a mapping between a symbol, whose \family typewriter Ndx \family default field is a \family typewriter XINDEX \family default value, and the actual index value. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Others \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Sometimes, values such as \family typewriter ANSI_COM \family default , \family typewriter LARGE_COM \family default , \family typewriter SCOM \family default , \family typewriter SUND \family default appear. This means that the index is processor-specific. \end_layout \end_inset \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter Name \family default is the symbol name. \end_layout \begin_layout Example A C application program always starts from symbol \family typewriter main \family default . The entry for \family typewriter main \family default in the symbol table in \family typewriter .symtab \family default section is: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code 62: 0000000000400526 32 FUNC GLOBAL DEFAULT 14 main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard The entry shows that: \end_layout \begin_layout Itemize \family typewriter main \family default is the 62 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset entry in the table. \end_layout \begin_layout Itemize \family typewriter main \family default starts at address \family typewriter 0x0000000000400526 \family default . \end_layout \begin_layout Itemize \family typewriter main \family default consumes 32 bytes. \end_layout \begin_layout Itemize \family typewriter main \family default is a function. \end_layout \begin_layout Itemize \family typewriter main \family default is in global scope. \end_layout \begin_layout Itemize \family typewriter main \family default is visible to other object files that use it. \end_layout \begin_layout Itemize \family typewriter main \family default is inside the 14 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset section, which is \family typewriter .text \family default . This is logical, since \family typewriter .text \family default holds all program code. \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter STRTAB \end_layout \end_inset \family default hold a table of null-terminated strings, called \emph on string table \emph default . The first and last byte of this section is always a NULL character. A string table section exists because a string can be reused by more than one section to represent symbol and section names, so a program like \family typewriter readelf \family default or \family typewriter objdump \family default can display various objects in a program, e.g. variable, functions, section names, in a human-readable text instead of its raw hex address. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example In the sample output, section \family typewriter 28 \family default and \family typewriter 30 \family default are of \family typewriter STRTAB \family default type: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [28] .shstrtab STRTAB 0000000000000000 000018b6 \end_layout \begin_layout LyX-Code 000000000000010c 0000000000000000 0 0 1 \end_layout \begin_layout LyX-Code [30] .strtab STRTAB 0000000000000000 000016b0 \end_layout \begin_layout LyX-Code 0000000000000206 0000000000000000 0 0 1 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter .shstrtab \family default holds all the section names. \end_layout \begin_layout Description \family typewriter .strtab \family default holds the symbols e.g. variable names, function names, struct names, etc., in a C program, but not fixed-size null-terminated C strings; the C strings are kept in \family typewriter .rodata \family default section. \end_layout \begin_layout Example Strings in those \family typewriter \family default section can be inspected with the command: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -p 29 hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The output shows all the section names, with the offset (also the string index) into \family typewriter .shstrtab \family default the table to the left: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code String dump of section '.shstrtab': \end_layout \begin_layout LyX-Code [ 1] .symtab \end_layout \begin_layout LyX-Code [ 9] .strtab \end_layout \begin_layout LyX-Code [ 11] .shstrtab \end_layout \begin_layout LyX-Code [ 1b] .interp \end_layout \begin_layout LyX-Code [ 23] .note.ABI-tag \end_layout \begin_layout LyX-Code [ 31] .note.gnu.build-id \end_layout \begin_layout LyX-Code [ 44] .gnu.hash \end_layout \begin_layout LyX-Code [ 4e] .dynsym \end_layout \begin_layout LyX-Code [ 56] .dynstr \end_layout \begin_layout LyX-Code [ 5e] .gnu.version \end_layout \begin_layout LyX-Code [ 6b] .gnu.version_r \end_layout \begin_layout LyX-Code [ 7a] .rela.dyn \end_layout \begin_layout LyX-Code [ 84] .rela.plt \end_layout \begin_layout LyX-Code [ 8e] .init \end_layout \begin_layout LyX-Code [ 94] .plt.got \end_layout \begin_layout LyX-Code [ 9d] .text \end_layout \begin_layout LyX-Code [ a3] .fini \end_layout \begin_layout LyX-Code [ a9] .rodata \end_layout \begin_layout LyX-Code [ b1] .eh_frame_hdr \end_layout \begin_layout LyX-Code [ bf] .eh_frame \end_layout \begin_layout LyX-Code [ c9] .init_array \end_layout \begin_layout LyX-Code [ d5] .fini_array \end_layout \begin_layout LyX-Code [ e1] .jcr \end_layout \begin_layout LyX-Code [ e6] .dynamic \end_layout \begin_layout LyX-Code [ ef] .got.plt \end_layout \begin_layout LyX-Code [ f8] .data \end_layout \begin_layout LyX-Code [ fe] .bss \end_layout \begin_layout LyX-Code [ 103] .comment \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The actual implementation of a string table is a contiguous array of null-termin ated strings. The index of a string is the position of its first character in the array. For example, in the above string table, \family typewriter .symtab \family default is at index 1 in the array (NULL character is at index 0). The length of \family typewriter .symtab \family default is 7, plus the NULL character, which occurs 8 bytes in total. So, \family typewriter .strtab \family default starts at index 9, and so on. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{String table in memory of \backslash texttt{.shstrtab.} A \backslash textcolor{red}{red} number is the starting index of a string.} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \color red 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \color red 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0d \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0e \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0f \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 00000000 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \backslash 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter s \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter y \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter m \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \backslash 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter s \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter r \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 00 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \color red 01 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 02 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 03 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 04 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 05 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 06 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 07 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 08 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 09 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold \color red 0b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0d \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0e \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 0f \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold 00000010 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \backslash 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter s \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter h \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter s \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter r \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter b \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \backslash 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter i \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter n \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter e \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter .... and so on .... \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset VSpace bigskip \end_inset \end_layout \begin_layout Standard Similarly, the output of \family typewriter .strtab \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code String dump of section '.strtab': \end_layout \begin_layout LyX-Code [ 1] crtstuff.c \end_layout \begin_layout LyX-Code [ c] __JCR_LIST__ \end_layout \begin_layout LyX-Code [ 19] deregister_tm_clones \end_layout \begin_layout LyX-Code [ 2e] __do_global_dtors_aux \end_layout \begin_layout LyX-Code [ 44] completed.7585 \end_layout \begin_layout LyX-Code [ 53] __do_global_dtors_aux_fini_array_entry \end_layout \begin_layout LyX-Code [ 7a] frame_dummy \end_layout \begin_layout LyX-Code [ 86] __frame_dummy_init_array_entry \end_layout \begin_layout LyX-Code [ a5] \series bold \size larger hello.c \end_layout \begin_layout LyX-Code [ ad] __FRAME_END__ \end_layout \begin_layout LyX-Code [ bb] __JCR_END__ \end_layout \begin_layout LyX-Code [ c7] __init_array_end \end_layout \begin_layout LyX-Code [ d8] _DYNAMIC \end_layout \begin_layout LyX-Code [ e1] __init_array_start \end_layout \begin_layout LyX-Code [ f4] __GNU_EH_FRAME_HDR \end_layout \begin_layout LyX-Code [ 107] _GLOBAL_OFFSET_TABLE_ \end_layout \begin_layout LyX-Code [ 11d] __libc_csu_fini \end_layout \begin_layout LyX-Code [ 12d] _ITM_deregisterTMCloneTable \end_layout \begin_layout LyX-Code [ 149] j \end_layout \begin_layout LyX-Code [ 14b] _edata \end_layout \begin_layout LyX-Code [ 152] __libc_start_main@@GLIBC_2.2.5 \end_layout \begin_layout LyX-Code [ 171] __data_start \end_layout \begin_layout LyX-Code [ 17e] __gmon_start__ \end_layout \begin_layout LyX-Code [ 18d] __dso_handle \end_layout \begin_layout LyX-Code [ 19a] _IO_stdin_used \end_layout \begin_layout LyX-Code [ 1a9] __libc_csu_init \end_layout \begin_layout LyX-Code [ 1b9] __bss_start \end_layout \begin_layout LyX-Code [ 1c5] \series bold \size larger main \end_layout \begin_layout LyX-Code [ 1ca] _Jv_RegisterClasses \end_layout \begin_layout LyX-Code [ 1de] __TMC_END__ \end_layout \begin_layout LyX-Code [ 1ea] _ITM_registerTMCloneTable \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter HASH \end_layout \end_inset \family default holds a symbol hash table, which supports symbol table access. \end_layout \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter DYNAMIC \end_layout \end_inset \family default holds information for dynamic linking. \end_layout \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter NOBITS \end_layout \end_inset \family default is similar to \family typewriter PROGBITS \family default but occupies no space. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example \family typewriter .bss \family default section holds uninitialized data, which means the bytes in the section can have any value. Until a operating system actually loads the section into main memory, there is no need to allocate space for the binary image on disk to reduce the size of a binary file. Here is the details of \family typewriter .bss \family default from the example output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code [Nr] Name Type Address Offset \end_layout \begin_layout LyX-Code Size EntSize Flags Link Info Align \end_layout \begin_layout LyX-Code [26] .bss NOBITS 0000000000601038 \color magenta 00001038 \end_layout \begin_layout LyX-Code \color red 0000000000000008 \color inherit 0000000000000000 WA 0 0 1 \end_layout \begin_layout LyX-Code [27] .comment PROGBITS 0000000000000000 \color magenta 00001038 \end_layout \begin_layout LyX-Code 0000000000000034 0000000000000001 MS 0 0 1 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard In the above output, the \color red size \color inherit of the section is only 8 bytes, while the \color magenta offsets \color inherit of both sections are the same, which means \family typewriter .bss \family default consumes no byte of the executable binary on disk. \end_layout \begin_layout Standard Notice that the \family typewriter .comment \family default section has no starting address. This means that this section is discarded when the executable binary is loaded into memory. \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter REL \end_layout \end_inset \family default holds relocation entries without explicit addends. This type will be explained in details in \begin_inset CommandInset ref LatexCommand ref reference "sec:Understand-relocations-with-readelf" \end_inset \end_layout \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter RELA \end_layout \end_inset \family default holds relocation entries with explicit addends. This type will be explained in details in \begin_inset CommandInset ref LatexCommand ref reference "sec:Understand-relocations-with-readelf" \end_inset \end_layout \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter INIT_ARRAY \end_layout \end_inset \family default is an array of function pointers for program initialization. When an application program runs, before getting to \family typewriter main() \family default , initialization code in \family typewriter .init \family default and this section are executed first. The first element in this array is an ignored function pointer. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard It might not make sense when we can include initialization code in the \family typewriter main() \family default function. However, for shared object files where there are no \family typewriter main() \family default , this section ensures that the initialization code from an object file executes before any other code to ensure a proper environment for main code to run properly. It also makes an object file more modularity, as the main application code needs not to be responsible for initializing a proper environment for using a particular object file, but the object file itself. Such a clear division makes code cleaner. \end_layout \begin_layout Standard However, we will not use any \family typewriter .init \family default and \family typewriter INIT_ARRAY \family default sections in our operating system, for simplicity, as initializing an environment is part of the operating-system domain. \end_layout \begin_layout Example To use the \family typewriter INIT_ARRAY \family default , we simply mark a function with the attribute \family typewriter constructor \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((constructor)) static void init1(){ \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((constructor)) static void init2(){ \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("hello world \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard The program automatically calls the constructor without explicitly invoking it: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 hello.c -o hello \end_layout \begin_layout Standard \family typewriter $ ./hello \end_layout \begin_layout Standard \family typewriter init1 \end_layout \begin_layout Standard \family typewriter init2 \end_layout \begin_layout Standard \family typewriter hello world \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example Optionally, a constructor can be assigned with a priority from 101 onward. The priorities from 0 to 100 are reserved for \family typewriter gcc \family default . If we want \family typewriter init2 \family default to run before \family typewriter init1 \family default , we give it a higher priority: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((constructor(102))) static void init1(){ \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((constructor(101))) static void init2(){ \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("hello world \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard The call order should be exactly as specified: \end_layout \end_deeper \begin_layout Example \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Example \family typewriter $ gcc -m32 hello.c -o hello \end_layout \begin_layout Example \family typewriter $ ./hello \end_layout \begin_layout Example \family typewriter init2 \end_layout \begin_layout Example \family typewriter init1 \end_layout \begin_layout Example \family typewriter hello world \end_layout \begin_layout Example \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example We can add initialization functions using another method: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void init1() { \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void init2() { \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout /* Without typedef, init is a definition of a function pointer. \end_layout \begin_layout Plain Layout With typedef, init is a declaration of a type.*/ \end_layout \begin_layout Plain Layout typedef void (*init)(); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((section(".init_array"))) init init_arr[2] = {init1, init2}; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("hello world! \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard The attribute \family typewriter section( \begin_inset Quotes eld \end_inset ... \begin_inset Quotes erd \end_inset ) \family default put a function into a particular section rather than the default \family typewriter .text \family default . In this example, it is \family typewriter .init_array \family default . The section name is not necessary the same as the standard header in an ELF file (such as \family typewriter .text \family default or \family typewriter .init_array \family default , but can be anything. Non-standard section names are often used for controlling the final binary layout of a compiled program. We will explore this techinque in more details when learning the \family typewriter GNU ld \family default linker and the linking process. Again, the program automatically calls the constructors without explicitly invoking it: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 hello.c -o hello \end_layout \begin_layout Standard \family typewriter $ ./hello \end_layout \begin_layout Standard \family typewriter init1 \end_layout \end_deeper \begin_layout Example \family typewriter init2 \end_layout \begin_layout Example \family typewriter hello world! \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter FINI_ARRAY \end_layout \end_inset \family default is an array of function pointers for program termination, called after exiting \family typewriter main() \family default . If the application terminate abnormally, such as through \family typewriter abort() \family default call or a crash, the \family typewriter .finit_array \family default is ignored. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example A destructor is automatically called after exiting main(), if one or more available: \end_layout \begin_layout Standard \begin_inset listings lstparams "title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((destructor)) static void destructor(){ \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("hello world \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 hello.c -o hello \end_layout \begin_layout Standard \family typewriter $ ./hello \end_layout \begin_layout Standard \family typewriter hello world \end_layout \begin_layout Standard \family typewriter destructor \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter PREINIT_ARRAY \end_layout \end_inset \family default is an array of function pointers that are invoked before all other initializatio n functions in \family typewriter INIT_ARRAY \family default . \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example To use the \family typewriter .preinit_array \family default , the only way to put functions into this section is to use the attribute \family typewriter section() \family default : \end_layout \begin_layout Standard \begin_inset listings lstparams "title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void preinit1() { \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void preinit2() { \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void init1() { \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void init2() { \end_layout \begin_layout Plain Layout printf("%s \backslash n", __FUNCTION__); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout typedef void (*preinit)(); \end_layout \begin_layout Plain Layout typedef void (*init)(); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout __attribute__((section(".preinit_array"))) preinit preinit_arr[2] = {preinit1, preinit2}; \end_layout \begin_layout Plain Layout __attribute__((section(".preinit_array"))) init init_arr[2] = {init1, init2}; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("hello world! \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 hello2.c -o hello2 \end_layout \begin_layout Standard \family typewriter $ ./hello2 \end_layout \begin_layout Standard \family typewriter preinit1 \end_layout \begin_layout Standard \family typewriter preinit2 \end_layout \begin_layout Standard \family typewriter init1 \end_layout \begin_layout Standard \family typewriter init2 \end_layout \begin_layout Standard \family typewriter hello world! \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter GROUP \end_layout \end_inset \family default defines a section group, which is the same section that appears in different object files but when merged into the final executable binary file, only one copy is kept and the rest in other object files are discarded. This section is only relevant in C++ object files, so we will not examine further. \end_layout \begin_layout Description \family typewriter \begin_inset Flex Strong status open \begin_layout Plain Layout \family typewriter SYMTAB_SHNDX \end_layout \end_inset \family default is a section containing extended section indexes, that are associated with a symbol table. This section only appears when the \family typewriter Ndx \family default value of an entry in the symbol table exceeds the \family typewriter LORESERVE \family default value. This section then maps between a symbol and an actual index value of a section header. \end_layout \begin_layout Standard Upon understanding section types, we can understand the number in \family typewriter Link \emph on \family default \emph default and \family typewriter Info \emph on \family default \emph default fields: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{table*} \end_layout \begin_layout Plain Layout \backslash caption{The meannings of \backslash texttt{ \backslash textbf{ \backslash emph{Link}}} and \backslash texttt{ \backslash textbf{ \backslash emph{Info}} depend on section types.} interpretation} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Type \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Link \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Info \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter DYNAMIC \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Entries in this section uses the section index of the dynamic string table. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter HASH \end_layout \begin_layout Plain Layout \family typewriter GNU_HASH \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section index of the symbol table to which the hash table applies. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout 0 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter REL \end_layout \begin_layout Plain Layout \family typewriter RELA \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section index of the associated symbol table. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section index to which the relocation applies. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter SYMTAB \end_layout \begin_layout Plain Layout \family typewriter DYNSYM \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section index of the associated string table. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout One greater than the symbol table index of the last local symbol. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter GROUP \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section index of the associated symbol table. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The symbol index of an entry in the associated symbol table. The name of the specified symbol table entry provides a signature for the section group. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter SYMTAB_SHNDX \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout The section header index of the associated symbol table. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash hfill \backslash break \end_layout \begin_layout Plain Layout \backslash end{table*} \end_layout \end_inset \end_layout \begin_layout Exercise Verify that the value of the \family typewriter Link \family default field of a \family typewriter SYMTAB \family default section is the index of a \family typewriter STRTAB \family default section. \end_layout \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Exercise Verify that the value of the \family typewriter Info \family default field of a \family typewriter SYMTAB \family default section is the index of last local symbol + 1. It means, in the symbol table, from the index listed by \family typewriter Info \family default field onward, no local symbol appears. \end_layout \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Exercise Verify that the value of the \family typewriter Info \family default field of a \family typewriter REL \family default section is the index of the \family typewriter SYMTAB \family default section. \end_layout \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Exercise Verify that the value of the \family typewriter Link \family default field of a \family typewriter REL \family default section is the index of the section where relocation is applied. For example. if the section is \family typewriter .rel.text \family default , then the relocating section should be \family typewriter .text \family default . \end_layout \begin_layout Section Program header table \begin_inset CommandInset label LatexCommand label name "sec:Program-header-table" \end_inset \end_layout \begin_layout Standard A \emph on program header table \begin_inset Index idx status open \begin_layout Plain Layout program header table \end_layout \end_inset \emph default is an array of program headers that defines the memory layout of a program at runtime. \end_layout \begin_layout Standard A \emph on program header \begin_inset Index idx status open \begin_layout Plain Layout program header \end_layout \end_inset \emph default is a description of a program segment. \end_layout \begin_layout Standard A \emph on program segment \begin_inset Index idx status open \begin_layout Plain Layout program segment \end_layout \end_inset \emph default is a collection of related sections. A segment contains zero or more sections. An operating system when loading a program, \emph on only use segments \emph default , not sections. To see the information of a program header table, we use the \family typewriter -l \family default option with \family typewriter readelf: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \noindent \family typewriter $ readelf -l \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Similar to a section, a program header also has types: \end_layout \begin_layout Description \family typewriter PHDR \family default specifies the location and size of the program header table itself, both in the file and in the memory image of the program \end_layout \begin_layout Description \family typewriter INTERP \family default \series bold \series default specifies the location and size of a null-terminated path name to invoke as an interpreter for linking runtime libraries. \end_layout \begin_layout Description \family typewriter LOAD \family default specifies a loadable segment. That is, this segment is loaded into main memory. \end_layout \begin_layout Description \family typewriter \series bold DYNAMIC \family default \series default specifies dynamic linking information. \end_layout \begin_layout Description \family typewriter NOTE \family default specifies the location and size of auxiliary information. \end_layout \begin_layout Description \family typewriter TLS \family default specifies the \emph on Thread-Local Storage template \emph default , which is formed from the combination of all sections with the flag \family typewriter TLS \family default . \end_layout \begin_layout Description \family typewriter GNU_STACK \family default indicates whether the program's stack should be made executable or not. Linux kernel uses this type. \end_layout \begin_layout Standard A segment also has permission, which is a combination of these 3 values: \begin_inset Float margintable wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Segment Permission \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Permission \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout R \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Readable \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout W \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Writable \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Executable \end_layout \end_inset \end_inset \end_layout \end_inset \end_layout \begin_layout Itemize Read ( \family typewriter R \family default ) \end_layout \begin_layout Itemize Write ( \family typewriter W \family default ) \end_layout \begin_layout Itemize Execute ( \family typewriter E \family default ) \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example The command to get the program header table: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \noindent \family typewriter $ readelf -l hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Output: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x400430 \end_layout \begin_layout LyX-Code There are 9 program headers, starting at offset 64 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr \end_layout \begin_layout LyX-Code FileSiz MemSiz Flags Align \end_layout \begin_layout LyX-Code PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 \end_layout \begin_layout LyX-Code 0x00000000000001f8 0x00000000000001f8 R E 8 \end_layout \begin_layout LyX-Code INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 \end_layout \begin_layout LyX-Code 0x000000000000001c 0x000000000000001c R 1 \end_layout \begin_layout LyX-Code [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] \end_layout \begin_layout LyX-Code \color red LOAD \color inherit 0x0000000000000000 0x0000000000400000 0x0000000000400000 \end_layout \begin_layout LyX-Code 0x000000000000070c 0x000000000000070c R E 200000 \end_layout \begin_layout LyX-Code \color red LOAD \color inherit 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 \end_layout \begin_layout LyX-Code 0x0000000000000228 0x0000000000000230 RW 200000 \end_layout \begin_layout LyX-Code DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 \end_layout \begin_layout LyX-Code 0x00000000000001d0 0x00000000000001d0 RW 8 \end_layout \begin_layout LyX-Code NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 \end_layout \begin_layout LyX-Code 0x0000000000000044 0x0000000000000044 R 4 \end_layout \begin_layout LyX-Code GNU_EH_FRAME 0x00000000000005e4 0x00000000004005e4 0x00000000004005e4 \end_layout \begin_layout LyX-Code 0x0000000000000034 0x0000000000000034 R 4 \end_layout \begin_layout LyX-Code GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 \end_layout \begin_layout LyX-Code 0x0000000000000000 0x0000000000000000 RW 10 \end_layout \begin_layout LyX-Code GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 \end_layout \begin_layout LyX-Code 0x00000000000001f0 0x00000000000001f0 R 1 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .interp \end_layout \begin_layout LyX-Code 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr \end_layout \begin_layout LyX-Code .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini \end_layout \begin_layout LyX-Code .rodata .eh_frame_hdr .eh_frame \end_layout \begin_layout LyX-Code 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss \end_layout \begin_layout LyX-Code 04 .dynamic \end_layout \begin_layout LyX-Code 05 .note.ABI-tag .note.gnu.build-id \end_layout \begin_layout LyX-Code 06 .eh_frame_hdr \end_layout \begin_layout LyX-Code 07 \end_layout \begin_layout LyX-Code 08 .init_array .fini_array .jcr .dynamic .got \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard In the sample output, \family typewriter LOAD \family default segment appears twice: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 \end_layout \begin_layout LyX-Code 0x000000000000070c 0x000000000000070c R E 200000 \end_layout \begin_layout LyX-Code LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 \end_layout \begin_layout LyX-Code 0x0000000000000228 0x0000000000000230 RW 200000 \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Why? Notice the permission: \end_layout \begin_layout Itemize the upper \family typewriter LOAD \family default has Read and Execute permission. This is a \emph on text \emph default segment. A text segment contains read-only instructions and read-only data. \end_layout \begin_layout Itemize the lower \family typewriter LOAD \family default has Read and Write permission. This is a \emph on data \emph default segment. It means that this segment can be read and written to, but is not allowed to be used as executable code, for security reason. \end_layout \begin_layout Standard Then, \family typewriter LOAD \family default contains the following sections: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr \end_layout \begin_layout LyX-Code .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini \end_layout \begin_layout LyX-Code .rodata .eh_frame_hdr .eh_frame \end_layout \begin_layout LyX-Code 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The first number is the index of a program header in program header table, and the remaining text is the list of all sections within a segment. Unfortunately, \family typewriter readelf \family default does not print the index, so a user needs to keep track manually which segment is of which index. First segment starts at index 0, second at index 1 and so on. \family typewriter LOAD \family default are segments at index 2 and 3. As can be seen from the two lists of sections, most sections are loadable and is available at runtime. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Section Segments vs sections \end_layout \begin_layout Standard As mentioned earlier, an operating system loads program segments, not sections. However, a question arises: Why doesn't the operating system use sections instead? After all, a section also contains similar information to a program segment, such as the type, the virtual memory address to be loaded, the size, the attributes, the flags and align. As explained before, a segment is the perspective of an operating system, while a section is the perspective of a linker. To understand why, looking into the structure of a segment, we can easily see: \end_layout \begin_layout Itemize A segment is a collection of sections. It means that sections are logically grouped together by their attributes. For example, all sections in a \family typewriter LOAD \family default segment are always loaded by the operating system; all sections have the same permission, either a \family typewriter RE \family default (Read + Execute) for executable sections, or \family typewriter RW \family default (Read + Write) for data sections. \end_layout \begin_layout Itemize By grouping sections into a segment, it is easier for an operating system to batch load sections just once by loading the start and end of a segment, instead of loading section by section. \end_layout \begin_layout Itemize Since a segment is for loading a program and a section is for linking a program, all the sections in a segment is \emph on within its start and end virtual memory addresses of a segment \emph default . \end_layout \begin_layout Standard To see the last point clearer, consider an example of linking two object files. Suppose we have two source files: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("Hello World \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard and: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=C,tabsize=4,title={\texttt{math.c}}" inline false status open \begin_layout Plain Layout int add(int a, int b) { \end_layout \begin_layout Plain Layout return a + b; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard Now, compile the two source files as \emph on object files \emph default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 -c math.c \end_layout \begin_layout Standard \family typewriter $ gcc -m32 -c hello.c \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, we check the sections of \family typewriter math.o \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -S math.o \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code There are 11 section headers, starting at offset 0x1a8: \end_layout \begin_layout LyX-Code Section Headers: \end_layout \begin_layout LyX-Code [Nr] Name Type Addr Off Size ES Flg Lk Inf Al \end_layout \begin_layout LyX-Code [ 0] NULL \color red 00000000 \color inherit 000000 000000 00 0 0 0 \end_layout \begin_layout LyX-Code [ 1] .text PROGBITS \color red 00000000 \color inherit 000034 00000d 00 AX 0 0 1 \end_layout \begin_layout LyX-Code [ 2] .data PROGBITS \color red 00000000 \color inherit 000041 000000 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [ 3] .bss NOBITS \color red 00000000 \color inherit 000041 000000 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [ 4] .comment PROGBITS \color red 00000000 \color inherit 000041 000035 01 MS 0 0 1 \end_layout \begin_layout LyX-Code [ 5] .note.GNU-stack PROGBITS \color red 00000000 \color inherit 000076 000000 00 0 0 1 \end_layout \begin_layout LyX-Code [ 6] .eh_frame PROGBITS \color red 00000000 \color inherit 000078 000038 00 A 0 0 4 \end_layout \begin_layout LyX-Code [ 7] .rel.eh_frame REL \color red 00000000 \color inherit 00014c 000008 08 I 9 6 4 \end_layout \begin_layout LyX-Code [ 8] .shstrtab STRTAB \color red 00000000 \color inherit 000154 000053 00 0 0 1 \end_layout \begin_layout LyX-Code [ 9] .symtab SYMTAB \color red 00000000 \color inherit 0000b0 000090 10 10 8 4 \end_layout \begin_layout LyX-Code [10] .strtab STRTAB \color red 00000000 \color inherit 000140 00000c 00 0 0 1 \end_layout \begin_layout LyX-Code Key to Flags: \end_layout \begin_layout LyX-Code W (write), A (alloc), X (execute), M (merge), S (strings) \end_layout \begin_layout LyX-Code I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) \end_layout \begin_layout LyX-Code O (extra OS processing required) o (OS specific), p (processor specific) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard As shown in the output, all the section virtual memory addresses of every section are set to 0. At this stage, each object file is simply a \emph on block of binary \emph default that contains code and data. Its existence is to serve as a material container for the final product, which is the executable binary. As such, the virtual addresses in \family typewriter hello.o \family default are all zeroes. \end_layout \begin_layout Standard No segment exists at this stage: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -l math.o \end_layout \begin_layout Standard \family typewriter There are no program headers in this file. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The same happens to other object file: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code There are 13 section headers, starting at offset 0x224: \end_layout \begin_layout LyX-Code Section Headers: \end_layout \begin_layout LyX-Code [Nr] Name Type Addr Off Size ES Flg Lk Inf Al \end_layout \begin_layout LyX-Code [ 0] NULL \color red 00000000 \color inherit 000000 000000 00 0 0 0 \end_layout \begin_layout LyX-Code [ 1] .text PROGBITS \color red 00000000 \color inherit 000034 00002e 00 AX 0 0 1 \end_layout \begin_layout LyX-Code [ 2] .rel.text REL \color red 00000000 \color inherit 0001ac 000010 08 I 11 1 4 \end_layout \begin_layout LyX-Code [ 3] .data PROGBITS \color red 00000000 \color inherit 000062 000000 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [ 4] .bss NOBITS \color red 00000000 \color inherit 000062 000000 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [ 5] .rodata PROGBITS \color red 00000000 \color inherit 000062 00000c 00 A 0 0 1 \end_layout \begin_layout LyX-Code [ 6] .comment PROGBITS \color red 00000000 \color inherit 00006e 000035 01 MS 0 0 1 \end_layout \begin_layout LyX-Code [ 7] .note.GNU-stack PROGBITS \color red 00000000 \color inherit 0000a3 000000 00 0 0 1 \end_layout \begin_layout LyX-Code [ 8] .eh_frame PROGBITS \color red 00000000 \color inherit 0000a4 000044 00 A 0 0 4 \end_layout \begin_layout LyX-Code [ 9] .rel.eh_frame REL \color red 00000000 \color inherit 0001bc 000008 08 I 11 8 4 \end_layout \begin_layout LyX-Code [10] .shstrtab STRTAB \color red 00000000 \color inherit 0001c4 00005f 00 0 0 1 \end_layout \begin_layout LyX-Code [11] .symtab SYMTAB \color red 00000000 \color inherit 0000e8 0000b0 10 12 9 4 \end_layout \begin_layout LyX-Code [12] .strtab STRTAB \color red 00000000 \color inherit 000198 000013 00 0 0 1 \end_layout \begin_layout LyX-Code Key to Flags: \end_layout \begin_layout LyX-Code W (write), A (alloc), X (execute), M (merge), S (strings) \end_layout \begin_layout LyX-Code I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) \end_layout \begin_layout LyX-Code O (extra OS processing required) o (OS specific), p (processor specific) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -l hello.o \end_layout \begin_layout Standard \family typewriter There are no program headers in this file. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Only when object files are combined into a final executable binary, sections are fully realized: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 math.o hello.o -o hello \end_layout \begin_layout Standard \family typewriter $ readelf -S hello. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code There are 31 section headers, starting at offset 0x1804: \end_layout \begin_layout LyX-Code Section Headers: \end_layout \begin_layout LyX-Code [Nr] Name Type Addr Off Size ES Flg Lk Inf Al \end_layout \begin_layout LyX-Code [ 0] NULL 00000000 000000 000000 00 0 0 0 \end_layout \begin_layout LyX-Code [ 1] .interp PROGBITS \color green 08048154 \color inherit 000154 000013 00 A 0 0 1 \end_layout \begin_layout LyX-Code [ 2] .note.ABI-tag NOTE \color green 08048168 \color inherit 000168 000020 00 A 0 0 4 \end_layout \begin_layout LyX-Code [ 3] .note.gnu.build-i NOTE \color green 08048188 \color inherit 000188 000024 00 A 0 0 4 \end_layout \begin_layout LyX-Code [ 4] .gnu.hash GNU_HASH \color green 080481ac \color inherit 0001ac 000020 04 A 5 0 4 \end_layout \begin_layout LyX-Code [ 5] .dynsym DYNSYM \color green 080481cc \color inherit 0001cc 000050 10 A 6 1 4 \end_layout \begin_layout LyX-Code [ 6] .dynstr STRTAB \color green 0804821c \color inherit 00021c 00004a 00 A 0 0 1 \end_layout \begin_layout LyX-Code [ 7] .gnu.version VERSYM \color green 08048266 \color inherit 000266 00000a 02 A 5 0 2 \end_layout \begin_layout LyX-Code [ 8] .gnu.version_r VERNEED \color green 08048270 \color inherit 000270 000020 00 A 6 1 4 \end_layout \begin_layout LyX-Code [ 9] .rel.dyn REL \color green 08048290 \color inherit 000290 000008 08 A 5 0 4 \end_layout \begin_layout LyX-Code [10] .rel.plt REL \color green 08048298 \color inherit 000298 000010 08 AI 5 24 4 \end_layout \begin_layout LyX-Code [11] .init PROGBITS \color green 080482a8 \color inherit 0002a8 000023 00 AX 0 0 4 \end_layout \begin_layout LyX-Code [12] .plt PROGBITS \color green 080482d0 \color inherit 0002d0 000030 04 AX 0 0 16 \end_layout \begin_layout LyX-Code [13] .plt.got PROGBITS \color green 08048300 \color inherit 000300 000008 00 AX 0 0 8 \end_layout \begin_layout LyX-Code [14] .text PROGBITS \color green 08048310 \color inherit 000310 0001a2 00 AX 0 0 16 \end_layout \begin_layout LyX-Code [15] .fini PROGBITS \color green 080484b4 \color inherit 0004b4 000014 00 AX 0 0 4 \end_layout \begin_layout LyX-Code [16] .rodata PROGBITS \color green 080484c8 \color inherit 0004c8 000014 00 A 0 0 4 \end_layout \begin_layout LyX-Code [17] .eh_frame_hdr PROGBITS \color green 080484dc \color inherit 0004dc 000034 00 A 0 0 4 \end_layout \begin_layout LyX-Code [18] .eh_frame PROGBITS \color green 08048510 \color inherit 000510 0000ec 00 A 0 0 4 \end_layout \begin_layout LyX-Code [19] .init_array INIT_ARRAY \color green 08049f08 \color inherit 000f08 000004 00 WA 0 0 4 \end_layout \begin_layout LyX-Code [20] .fini_array FINI_ARRAY \color green 08049f0c \color inherit 000f0c 000004 00 WA 0 0 4 \end_layout \begin_layout LyX-Code [21] .jcr PROGBITS \color green 08049f10 \color inherit 000f10 000004 00 WA 0 0 4 \end_layout \begin_layout LyX-Code [22] .dynamic DYNAMIC \color green 08049f14 \color inherit 000f14 0000e8 08 WA 6 0 4 \end_layout \begin_layout LyX-Code [23] .got PROGBITS \color green 08049ffc \color inherit 000ffc 000004 04 WA 0 0 4 \end_layout \begin_layout LyX-Code [24] .got.plt PROGBITS \color green 0804a000 \color inherit 001000 000014 04 WA 0 0 4 \end_layout \begin_layout LyX-Code [25] .data PROGBITS \color green 0804a014 \color inherit 001014 000008 00 WA 0 0 4 \end_layout \begin_layout LyX-Code [26] .bss NOBITS \color green 0804a01c \color inherit 00101c 000004 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [27] .comment PROGBITS 00000000 00101c 000034 01 MS 0 0 1 \end_layout \begin_layout LyX-Code [28] .shstrtab STRTAB 00000000 0016f8 00010a 00 0 0 1 \end_layout \begin_layout LyX-Code [29] .symtab SYMTAB 00000000 001050 000470 10 30 48 4 \end_layout \begin_layout LyX-Code [30] .strtab STRTAB 00000000 0014c0 000238 00 0 0 1 \end_layout \begin_layout LyX-Code Key to Flags: \end_layout \begin_layout LyX-Code W (write), A (alloc), X (execute), M (merge), S (strings) \end_layout \begin_layout LyX-Code I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) \end_layout \begin_layout LyX-Code O (extra OS processing required) o (OS specific), p (processor specific) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Every loadable section is assigned an address, highlighted in \color green green \color inherit . The reason each section got its own address is that in reality, \family typewriter gcc \family default \emph on does not combine an object by itself, but invokes the linker \emph default \family typewriter ld \family default . The linker \family typewriter ld \family default uses the default script that it can find in the system to build the executable binary. In the default script, a segment is assigned a starting address \family typewriter 0x8048000 \family default and sections belong to it. Then: \end_layout \begin_layout Itemize \begin_inset Formula $\mathtt{1^{st}\,section\,address=starting\,segment\,address+section\,offset=0x8048000+0x154=0x08048154}$ \end_inset \end_layout \begin_layout Itemize \begin_inset Formula $\mathtt{2^{nd}\,section\,address=starting\,segment\,address+section\,offset=0x8048000+0x168=0x08048168}$ \end_inset \end_layout \begin_layout Itemize and so on until the last loadable section. \end_layout \begin_layout Standard Indeed, the end address of a segment is also the end address of the final section. We can see this by listing all the segments: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -l hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard And check, for example, \family typewriter LOAD \family default segment which starts at \family typewriter \color red 0x08048000 \family default \color inherit and end at \begin_inset Formula $\mathtt{0x08048000+0x005fc=0x080485fc}$ \end_inset : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x8048310 \end_layout \begin_layout LyX-Code There are 9 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 \end_layout \begin_layout LyX-Code INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 \end_layout \begin_layout LyX-Code [Requesting program interpreter: /lib/ld-linux.so.2] \end_layout \begin_layout LyX-Code LOAD 0x000000 0x08048000 \color red 0x08048000 \color inherit 0x005fc \color blue 0x005fc \color inherit R E 0x1000 \end_layout \begin_layout LyX-Code LOAD 0x000f08 0x08049f08 0x08049f08 0x00114 0x00118 RW 0x1000 \end_layout \begin_layout LyX-Code DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4 \end_layout \begin_layout LyX-Code NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4 \end_layout \begin_layout LyX-Code GNU_EH_FRAME 0x0004dc 0x080484dc 0x080484dc 0x00034 0x00034 R 0x4 \end_layout \begin_layout LyX-Code GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 \end_layout \begin_layout LyX-Code GNU_RELRO 0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R 0x1 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .interp \end_layout \begin_layout LyX-Code 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr \end_layout \begin_layout LyX-Code .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini \end_layout \begin_layout LyX-Code .rodata .eh_frame_hdr .eh_frame \end_layout \begin_layout LyX-Code 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss \end_layout \begin_layout LyX-Code 04 .dynamic \end_layout \begin_layout LyX-Code 05 .note.ABI-tag .note.gnu.build-id \end_layout \begin_layout LyX-Code 06 .eh_frame_hdr \end_layout \begin_layout LyX-Code 07 \end_layout \begin_layout LyX-Code 08 .init_array .fini_array .jcr .dynamic .got \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The last section in the first \family typewriter LOAD \family default segment is \family typewriter .eh_frame \family default . The \family typewriter .eh_frame \family default section starts at \family typewriter 0x0804851 \family default because the start address is \family typewriter 0x08048000 \family default , the offset into the file is \family typewriter 0x510 \family default . The end address of \family typewriter .eh_frame \family default should be: \begin_inset Formula $\mathtt{0x08048000+0x510+0xec=0x080485fc}$ \end_inset because the segment size is \family typewriter 0x \family default ec. This is exactly the same as the end address of the first \family typewriter LOAD \family default segment above: \begin_inset Formula $\mathtt{0x08048000+0x5ec=0x080485fc}$ \end_inset . \end_layout \begin_layout Standard Chapter \begin_inset CommandInset ref LatexCommand ref reference "chap:Linking-and-loading" \end_inset will explore this whole process in detail. \end_layout \begin_layout Chapter Runtime inspection and debug \end_layout \begin_layout Standard A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on debugger \end_layout \end_inset debugger \begin_inset Index idx status open \begin_layout Plain Layout debugger \end_layout \end_inset \emph default is a program that allows inspection of a running program. A debugger can start and run a program then stop at a specific line for examining the state of the program at that point. The point where the debugger stop (but not halt) is called a \emph on breakpoint \emph default . \end_layout \begin_layout Standard We will be using the \series bold \emph on GDB - \series default \series bold G \series default NU \series bold D \series default e \series bold b \series default ugger \emph default for debugging our kernel. \begin_inset Flex Code status open \begin_layout Plain Layout \emph on gdb \end_layout \end_inset is the program name. \begin_inset Flex Code status open \begin_layout Plain Layout \emph on gdb \end_layout \end_inset can do four main kinds of things: \end_layout \begin_layout Itemize Start your program, specifying anything that might affect its behavior. \end_layout \begin_layout Itemize Make your program stop on specified conditions. \end_layout \begin_layout Itemize Examine what has happened, when your program has stopped \end_layout \begin_layout Itemize Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another \end_layout \begin_layout Section A sample program \end_layout \begin_layout Standard There must be an existing program for debugging. The good old \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset program suffices for the educational purpose in this chapter: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("Hello World! \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard We compile it with debugging information with the option \family typewriter -g \family default : \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 -g hello.c -o hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Finally, we start gdb with the program as argument: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \noindent \family typewriter $ gdb hello \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Section Static inspection of a program \end_layout \begin_layout Standard Before inspecting a program at runtime, \family typewriter gdb \family default loads it first. Upon loading into memory (but without running), a lot of useful information can be retrieve for inspection. The commands in this section can be used before the program runs. However, they are also usable when the program runs and can display even more information. \end_layout \begin_layout Subsection Command: \family typewriter info target/info file/info files \end_layout \begin_layout Standard This command prints the information of the target being debugged. A \emph on target \emph default is the debugging program. \end_layout \begin_layout Example The output of the command from \family typewriter hello \family default program, a local target in detail: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red info target \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Symbols from "/tmp/hello". \end_layout \begin_layout LyX-Code Local exec file: \end_layout \begin_layout LyX-Code `/tmp/hello', file type elf32-i386. \end_layout \begin_layout LyX-Code Entry point: 0x8048310 \end_layout \begin_layout LyX-Code 0x08048154 - 0x08048167 is .interp \end_layout \begin_layout LyX-Code 0x08048168 - 0x08048188 is .note.ABI-tag \end_layout \begin_layout LyX-Code 0x08048188 - 0x080481ac is .note.gnu.build-id \end_layout \begin_layout LyX-Code 0x080481ac - 0x080481cc is .gnu.hash \end_layout \begin_layout LyX-Code 0x080481cc - 0x0804821c is .dynsym \end_layout \begin_layout LyX-Code 0x0804821c - 0x08048266 is .dynstr \end_layout \begin_layout LyX-Code 0x08048266 - 0x08048270 is .gnu.version \end_layout \begin_layout LyX-Code 0x08048270 - 0x08048290 is .gnu.version_r \end_layout \begin_layout LyX-Code 0x08048290 - 0x08048298 is .rel.dyn \end_layout \begin_layout LyX-Code 0x08048298 - 0x080482a8 is .rel.plt \end_layout \begin_layout LyX-Code 0x080482a8 - 0x080482cb is .init \end_layout \begin_layout LyX-Code 0x080482d0 - 0x08048300 is .plt \end_layout \begin_layout LyX-Code 0x08048300 - 0x08048308 is .plt.got \end_layout \begin_layout LyX-Code 0x08048310 - 0x080484a2 is .text \end_layout \begin_layout LyX-Code 0x080484a4 - 0x080484b8 is .fini \end_layout \begin_layout LyX-Code 0x080484b8 - 0x080484cd is .rodata \end_layout \begin_layout LyX-Code 0x080484d0 - 0x080484fc is .eh_frame_hdr \end_layout \begin_layout LyX-Code 0x080484fc - 0x080485c8 is .eh_frame \end_layout \begin_layout LyX-Code 0x08049f08 - 0x08049f0c is .init_array \end_layout \begin_layout LyX-Code 0x08049f0c - 0x08049f10 is .fini_array \end_layout \begin_layout LyX-Code 0x08049f10 - 0x08049f14 is .jcr \end_layout \begin_layout LyX-Code 0x08049f14 - 0x08049ffc is .dynamic \end_layout \begin_layout LyX-Code 0x08049ffc - 0x0804a000 is .got \end_layout \begin_layout LyX-Code 0x0804a000 - 0x0804a014 is .got.plt \end_layout \begin_layout LyX-Code 0x0804a014 - 0x0804a01c is .data \end_layout \begin_layout LyX-Code 0x0804a01c - 0x0804a020 is .bss \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The output displayed reports: \end_layout \begin_layout Itemize Path of a symbol file. A \emph on symbol file \emph default is the file that contains the debugging information. Usually, this is the same file as the binary, but it is common to separate between an executable binary and its debugging information into 2 files, especially for remote debugging. In the example, it is this line: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code Symbols from "/tmp/hello". \end_layout \end_deeper \begin_layout Itemize The path of the debugging program and its file type. In the example, it is this line: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code Local exec file: \end_layout \begin_layout LyX-Code `/tmp/hello', file type elf32-i386. \end_layout \end_deeper \begin_layout Itemize The entry point to the debugging program. That is, the very first code the program runs. In the example, it is this line: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code Entry point: 0x8048310 \end_layout \end_deeper \begin_layout Itemize A list of sections with its starting and ending addresses. In the example, it is the remaining output. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example If the debugging program runs in a different machine, it is a remote target and \family typewriter gdb \family default only prints a brief information: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red info target \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Remote serial target in gdb-specific protocol: \end_layout \begin_layout LyX-Code Debugging a target over a serial line. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout LyX-Code \end_layout \begin_layout Subsection Command: \family typewriter maint info sections \end_layout \begin_layout Standard This command is similar to \family typewriter info targe \family default t but give extra information about program sections, specifically the file offset and the flags of each section. \end_layout \begin_layout Example Here is the output when running against \family typewriter hello \family default program: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red maint info sections \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \size footnotesize Exec file: \end_layout \begin_layout LyX-Code \size footnotesize `/tmp/hello', file type elf64-x86-64. \end_layout \begin_layout LyX-Code \size footnotesize [0] 0x00400238->0x00400254 at 0x00000238: \color blue .interp \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [1] 0x00400254->0x00400274 at 0x00000254: \color blue .note.ABI-tag \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [2] 0x00400274->0x00400298 at 0x00000274: \color blue .note.gnu.build-id \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [3] 0x00400298->0x004002b4 at 0x00000298: \color blue .gnu.hash \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [4] 0x004002b8->0x00400318 at 0x000002b8: \color blue .dynsym \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [5] 0x00400318->0x00400355 at 0x00000318: \color blue .dynstr \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [6] 0x00400356->0x0040035e at 0x00000356: \color blue .gnu.version \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [7] 0x00400360->0x00400380 at 0x00000360: \color blue .gnu.version_r \color inherit ALLOC LOAD READONLY DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize ....remaining output omitted.... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard The output is similar to \family typewriter info target \family default , but with more details. Next to the \color blue section names \color inherit are the section flags, which are attributes of a section. Here, we can see that the sections with \family typewriter LOAD \family default flag are from \family typewriter LOAD \family default segment. The command can be combined with the section flags for filtered outputs: \end_layout \begin_layout Description ALLOBJ displays sections for all loaded object files, including shared libraries. Shared libraries are only displayed when the program is already running. \end_layout \begin_layout Description section \begin_inset space ~ \end_inset names displays only named sections. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example The command: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red maint info sections \color blue .text .data .bss \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left only displays \family typewriter \color blue .text \family default \color inherit , \family typewriter \color blue .data \family default \color inherit and \family typewriter \color blue .bss \family default \color inherit sections: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \size footnotesize Exec file: \end_layout \begin_layout LyX-Code \size footnotesize `/tmp/hello', file type elf64-x86-64. \end_layout \begin_layout LyX-Code \size footnotesize [13] 0x00400430->0x004005c2 at 0x00000430: \color blue .text \color inherit ALLOC LOAD READONLY CODE HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [24] 0x00601028->0x00601038 at 0x00001028: \color blue .data \color inherit ALLOC LOAD DATA HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [25] 0x00601038->0x00601040 at 0x00001038: \color blue .bss \color inherit ALLOC \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \end_deeper \begin_layout Description section-flags displays only sections with specified section flags. Note that these section flags are specific to \family typewriter gdb \family default , though it is based on the section attributes defined previously. Currently, \family typewriter gdb \family default understands the following flags: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Description ALLOC Section will have space allocated in the process when loaded. Set for all sections except those containing debug information. \end_layout \begin_layout Description LOAD Section will be loaded from the file into the child process memory. Set for pre-initialized code and data, clear for .bss sections. \end_layout \begin_layout Description RELOC Section needs to be relocated before loading. \end_layout \begin_layout Description READONLY Section cannot be modified by the child process. \end_layout \begin_layout Description CODE Section contains executable code only. \end_layout \begin_layout Description DATA Section contains data only (no executable code). \end_layout \begin_layout Description ROM Section will reside in ROM. \end_layout \begin_layout Description CONSTRUCTOR Section contains data for constructor/destructor lists. \end_layout \begin_layout Description HAS_CONTENTS Section is not empty. \end_layout \begin_layout Description NEVER_LOAD An instruction to the linker to not output the section. \end_layout \begin_layout Description COFF_SHARED_LIBRARY A notification to the linker that the section contains COFF shared library information. COFF is an object file format, similar to ELF. While ELF is the file format for an executable binary, COFF is the file format for an object file. \end_layout \begin_layout Description IS_COMMON Section contains common symbols. \end_layout \begin_layout Example We can restrict the output to only display sections that contain code with the command: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red maint info sections \color blue CODE \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \size footnotesize Exec file: \end_layout \begin_layout LyX-Code \size footnotesize `/tmp/hello', file type elf64-x86-64. \end_layout \begin_layout LyX-Code \size footnotesize [10] 0x004003c8->0x004003e2 at 0x000003c8: .init ALLOC LOAD READONLY \color red CODE \color inherit HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [11] 0x004003f0->0x00400420 at 0x000003f0: .plt ALLOC LOAD READONLY \color red CODE \color inherit HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [12] 0x00400420->0x00400428 at 0x00000420: .plt.got ALLOC LOAD READONLY \color red CODE \color inherit HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [13] 0x00400430->0x004005c2 at 0x00000430: .text ALLOC LOAD READONLY \color red CODE \color inherit HAS_CONTENTS \end_layout \begin_layout LyX-Code \size footnotesize [14] 0x004005c4->0x004005cd at 0x000005c4: .fini ALLOC LOAD READONLY \color red CODE \color inherit HAS_CONTENTS \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \end_deeper \begin_layout Subsection Command: \family typewriter info functions \end_layout \begin_layout Standard This commands list all function names and their loaded addresses. The names can be filtered with a regular expression. \end_layout \begin_layout Example Run the command, we get the following output: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red info functions \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code All defined functions: \end_layout \begin_layout LyX-Code File hello.c: \end_layout \begin_layout LyX-Code \color blue int main(int, char **); \end_layout \begin_layout LyX-Code Non-debugging symbols: \end_layout \begin_layout LyX-Code 0x00000000004003c8 \color blue _init \end_layout \begin_layout LyX-Code 0x0000000000400400 \color blue puts@plt \end_layout \begin_layout LyX-Code 0x0000000000400410 \color blue __libc_start_main@plt \end_layout \begin_layout LyX-Code 0x0000000000400430 \color blue _start \end_layout \begin_layout LyX-Code 0x0000000000400460 \color blue deregister_tm_clones \end_layout \begin_layout LyX-Code 0x00000000004004a0 \color blue register_tm_clones \end_layout \begin_layout LyX-Code 0x00000000004004e0 \color blue __do_global_dtors_aux \end_layout \begin_layout LyX-Code 0x0000000000400500 \color blue frame_dummy \end_layout \begin_layout LyX-Code 0x0000000000400550 \color blue __libc_csu_init \end_layout \begin_layout LyX-Code 0x00000000004005c0 \color blue __libc_csu_fini \end_layout \begin_layout LyX-Code 0x00000000004005c4 \color blue _fini \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter info variables \end_layout \begin_layout Standard This command lists all global and static variable names, or filtered with a regular expression. \end_layout \begin_layout Example If we add a global variable \family typewriter int \family default \family typewriter i \family default into the sample source program and recompile then run the command, we get the following output: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red info variables \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code All defined variables: \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code File hello.c: \end_layout \begin_layout LyX-Code \color blue int i; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code Non-debugging symbols: \end_layout \begin_layout LyX-Code 0x00000000004005d0 \color blue _IO_stdin_used \end_layout \begin_layout LyX-Code 0x00000000004005e4 \color blue __GNU_EH_FRAME_HDR \end_layout \begin_layout LyX-Code 0x0000000000400708 \color blue __FRAME_END__ \end_layout \begin_layout LyX-Code 0x0000000000600e10 \color blue __frame_dummy_init_array_entry \end_layout \begin_layout LyX-Code 0x0000000000600e10 \color blue __init_array_start \end_layout \begin_layout LyX-Code 0x0000000000600e18 \color blue __do_global_dtors_aux_fini_array_entry \end_layout \begin_layout LyX-Code 0x0000000000600e18 \color blue __init_array_end \end_layout \begin_layout LyX-Code 0x0000000000600e20 \color blue __JCR_END__ \end_layout \begin_layout LyX-Code 0x0000000000600e20 \color blue __JCR_LIST__ \end_layout \begin_layout LyX-Code 0x0000000000600e28 \color blue _DYNAMIC \end_layout \begin_layout LyX-Code 0x0000000000601000 \color blue _GLOBAL_OFFSET_TABLE_ \end_layout \begin_layout LyX-Code 0x0000000000601028 \color blue __data_start \end_layout \begin_layout LyX-Code 0x0000000000601028 \color blue data_start \end_layout \begin_layout LyX-Code 0x0000000000601030 \color blue __dso_handle \end_layout \begin_layout LyX-Code 0x000000000060103c \color blue __bss_start \end_layout \begin_layout LyX-Code 0x000000000060103c \color blue _edata \end_layout \begin_layout LyX-Code 0x000000000060103c \color blue completed \end_layout \begin_layout LyX-Code 0x0000000000601040 \color blue __TMC_END__ \end_layout \begin_layout LyX-Code 0x0000000000601040 \color blue _end \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter disassemble/disas \end_layout \begin_layout Standard This command displays the assembly code of the executable file. \end_layout \begin_layout Example \family typewriter gdb \family default can display the assembly code of a function: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red disassemble \color inherit \color blue main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Dump of assembler code for function \color blue main \color inherit : \end_layout \begin_layout LyX-Code 0x0804840b <+0>: lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 0x0804840f <+4>: and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 0x08048412 <+7>: push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048415 <+10>: push ebp \end_layout \begin_layout LyX-Code 0x08048416 <+11>: mov ebp,esp \end_layout \begin_layout LyX-Code 0x08048418 <+13>: push ecx \end_layout \begin_layout LyX-Code 0x08048419 <+14>: sub esp,0x4 \end_layout \begin_layout LyX-Code 0x0804841c <+17>: sub esp,0xc \end_layout \begin_layout LyX-Code 0x0804841f <+20>: push 0x80484c0 \end_layout \begin_layout LyX-Code 0x08048424 <+25>: call 0x80482e0 \end_layout \begin_layout LyX-Code 0x08048429 <+30>: add esp,0x10 \end_layout \begin_layout LyX-Code 0x0804842c <+33>: mov eax,0x0 \end_layout \begin_layout LyX-Code 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 0x08048434 <+41>: leave \end_layout \begin_layout LyX-Code 0x08048435 <+42>: lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048438 <+45>: ret \end_layout \begin_layout LyX-Code End of assembler dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Example It would be more useful if source is included: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red disassemble \color inherit \color blue /s main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Dump of assembler code for function \color blue main \color inherit : \end_layout \begin_layout LyX-Code hello.c: \end_layout \begin_layout LyX-Code \color green 4 { \end_layout \begin_layout LyX-Code 0x0804840b <+0>: lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 0x0804840f <+4>: and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 0x08048412 <+7>: push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048415 <+10>: push ebp \end_layout \begin_layout LyX-Code 0x08048416 <+11>: mov ebp,esp \end_layout \begin_layout LyX-Code 0x08048418 <+13>: push ecx \end_layout \begin_layout LyX-Code 0x08048419 <+14>: sub esp,0x4 \end_layout \begin_layout LyX-Code \color green 5 printf("Hello World! \backslash n"); \end_layout \begin_layout LyX-Code 0x0804841c <+17>: sub esp,0xc \end_layout \begin_layout LyX-Code 0x0804841f <+20>: push 0x80484c0 \end_layout \begin_layout LyX-Code 0x08048424 <+25>: call 0x80482e0 \end_layout \begin_layout LyX-Code 0x08048429 <+30>: add esp,0x10 \end_layout \begin_layout LyX-Code \color green 6 return 0; \end_layout \begin_layout LyX-Code 0x0804842c <+33>: mov eax,0x0 \end_layout \begin_layout LyX-Code \color green 7 } \end_layout \begin_layout LyX-Code 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 0x08048434 <+41>: leave \end_layout \begin_layout LyX-Code 0x08048435 <+42>: lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048438 <+45>: ret \end_layout \begin_layout LyX-Code End of assembler dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Now the high level source (in \color green green \color inherit text) is included as part of the assembly dump. Each line is backed by the corresponding assembly code below it. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example If the option \family typewriter /r \family default is added, raw instructions in hex are included, just like how \family typewriter objdump \family default displays assembly code by default: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red disassemble \color inherit \color blue /rs main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Dump of assembler code for function main: \end_layout \begin_layout LyX-Code hello.c: \end_layout \begin_layout LyX-Code 4 { \end_layout \begin_layout LyX-Code 0x0804840b <+0>: \color green 8d 4c 24 04 \color inherit lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 0x0804840f <+4>: \color green 83 e4 f0 \color inherit and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 0x08048412 <+7>: \color green ff 71 fc \color inherit push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048415 <+10>: \color green 55 \color inherit push ebp \end_layout \begin_layout LyX-Code 0x08048416 <+11>: \color green 89 e5 \color inherit mov ebp,esp \end_layout \begin_layout LyX-Code 0x08048418 <+13>: \color green 51 \color inherit push ecx \end_layout \begin_layout LyX-Code 0x08048419 <+14>: \color green 83 ec 04 \color inherit sub esp,0x4 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout LyX-Code 0x0804841c <+17>: \color green 83 ec 0c \color inherit sub esp,0xc \end_layout \begin_layout LyX-Code 0x0804841f <+20>: \color green 68 c0 84 04 08 \color inherit push 0x80484c0 \end_layout \begin_layout LyX-Code 0x08048424 <+25>: \color green e8 b7 fe ff ff \color inherit call 0x80482e0 \end_layout \begin_layout LyX-Code 0x08048429 <+30>: \color green 83 c4 10 \color inherit add esp,0x10 \end_layout \begin_layout LyX-Code 6 return 0; \end_layout \begin_layout LyX-Code 0x0804842c <+33>: \color green b8 00 00 00 00 \color inherit mov eax,0x0 \end_layout \begin_layout LyX-Code 7 } \end_layout \begin_layout LyX-Code 0x08048431 <+38>: \color green 8b 4d fc \color inherit mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 0x08048434 <+41>: \color green c9 \color inherit leave \end_layout \begin_layout LyX-Code 0x08048435 <+42>: \color green 8d 61 fc \color inherit lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048438 <+45>: \color green c3 \color inherit ret \end_layout \begin_layout LyX-Code End of assembler dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Example A function in a specific file can also be specified: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red disassemble \color inherit \color blue /sr 'hello.c'::main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Dump of assembler code for function \color blue main \color inherit : \end_layout \begin_layout LyX-Code \color blue hello.c \color inherit : \end_layout \begin_layout LyX-Code 4 { \end_layout \begin_layout LyX-Code 0x0804840b <+0>: 8d 4c 24 04 lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 0x0804840f <+4>: 83 e4 f0 and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 0x08048412 <+7>: ff 71 fc push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048415 <+10>: 55 push ebp \end_layout \begin_layout LyX-Code 0x08048416 <+11>: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code 0x08048418 <+13>: 51 push ecx \end_layout \begin_layout LyX-Code 0x08048419 <+14>: 83 ec 04 sub esp,0x4 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout LyX-Code 0x0804841c <+17>: 83 ec 0c sub esp,0xc \end_layout \begin_layout LyX-Code 0x0804841f <+20>: 68 c0 84 04 08 push 0x80484c0 \end_layout \begin_layout LyX-Code 0x08048424 <+25>: e8 b7 fe ff ff call 0x80482e0 \end_layout \begin_layout LyX-Code 0x08048429 <+30>: 83 c4 10 add esp,0x10 \end_layout \begin_layout LyX-Code 6 return 0; \end_layout \begin_layout LyX-Code 0x0804842c <+33>: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code 7 } \end_layout \begin_layout LyX-Code 0x08048431 <+38>: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 0x08048434 <+41>: c9 leave \end_layout \begin_layout LyX-Code 0x08048435 <+42>: 8d 61 fc lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048438 <+45>: c3 ret \end_layout \begin_layout LyX-Code End of assembler dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The filename must be included in a single quote, and the function must be prefixed by double colons e.g. \family typewriter 'hello.c'::main \family default to specify disassembling of the function \family typewriter main \family default in the file \family typewriter hello.c \family default . \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter x \end_layout \begin_layout Standard This command examines the content of a given memory range. \end_layout \begin_layout Example We can examine the raw content in \family typewriter main \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red x \color inherit main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0x804840b
: 0x04244c8d \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard By default, without any argument, the command only prints the content of a single memory address. In this case, that is the starting memory address in \family typewriter main \family default . \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example With format arguments, the command can print a range of memory in a specific format. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red x \color inherit / \color blue 20 \color green b \color inherit main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0x804840b
: 0x8d 0x4c 0x24 0x04 0x83 0xe40xf0 0xff \end_layout \begin_layout LyX-Code 0x8048413 : 0x71 0xfc 0x55 0x89 0xe5 0x510x83 0xec \end_layout \begin_layout LyX-Code 0x804841b : 0x04 0x83 0xec 0x0c \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter / \color red 20 \color green b \color inherit main \family default argument means that the command prints 20 bytes, where \family typewriter main \family default starts in memory. \end_layout \end_deeper \begin_layout Example The general form for format argument is: \family typewriter / \color blue \color green \end_layout \begin_layout Example If the repeated count is not supplied, by default \family typewriter gdb \family default supplies the count as 1. The format letter is one the following values: \end_layout \begin_layout Example \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Letter \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter o \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content in \emph on octal \emph default format. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter x \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content in hex format. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter d \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content in decimal format. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter u \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content in \emph on unsigned decimal \emph default format. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter t \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content in \emph on binary \emph default format. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter f \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content in \emph on float \emph default format. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter a \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content as \emph on memory addresses \emph default . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter i \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content as a series of assembly instructions, similar to \family typewriter disassemble \family default command. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content as an array of ASCII characters. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter s \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Print the memory content as a string \end_layout \end_inset \end_inset \end_layout \begin_layout Example Depends on the circumstance, certain format is advantageous than the others. For example, if a memory region contains floating-point numbers, then it is better to use the format \family typewriter f \family default than viewing the number as separated 1-byte hex numbers. \end_layout \begin_layout Subsection Command: \family typewriter print/p \end_layout \begin_layout Standard Examining raw memory is useful but usually it is better to have a more human-rea dable output. This command does precisely the task: it pretty-prints an expression. An expression can be a global variable, a local variable in current stack frame, a function, a register, a number, etc. \end_layout \begin_layout Section Runtime inspection of a program \end_layout \begin_layout Standard The main use of a debugger is to examine the state of a program, when it is running. \family typewriter gdb \family default provides a set of useful commands for retrieving useful runtime information. \end_layout \begin_layout Subsection Command: \family typewriter run \end_layout \begin_layout Standard This command starts running the program. \end_layout \begin_layout Example Run the hello program: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Hello World! \end_layout \begin_layout LyX-Code [Inferior 1 (process 1002) exited normally] \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The program runs successfully and printed the message \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset . However, it would not be useful if all \family typewriter gdb \family default can do is run a program. \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter break/b \end_layout \begin_layout Standard This command sets a breakpoint at a location in the high-level source code. When \family typewriter gdb \family default runs to a specific location marked by a breakpoint, it stops executing for a programmer to inspect the current state of a program. \end_layout \begin_layout Example A breakpoint can be set on a line as displayed by an editor. Suppose we want to set a breakpoint at line 3 of the program, which is the start of \family typewriter main \family default function: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=C,numbers=left,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout @| \backslash color{red} \backslash bfseries int main(int argc, char *argv[])|@ \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("Hello World! \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard When running a program, instead of running from start to finish, \family typewriter gdb \family default stopped at line 3: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red b \color inherit \color blue 3 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Breakpoint 1 at 0x400535: file hello.c, line 3. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at hello.c:5 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The breakpoint is at line 3, but \family typewriter gdb \family default stopped line 5. The reason is that line 3 does not contain code, but a function signature; \family typewriter gdb \family default only stops where it can execute code. The code in the function starts at line 5, the call to \family typewriter printf \family default , so \family typewriter gdb \family default stops there. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example Line of code is not always the reliable way to specify a breakpoint, as the source code can be changed. What if \family typewriter gdb \family default should always stop at \family typewriter main \family default function? In this case, a better method is to use the function name directly: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \color red b \color inherit \color blue main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, regardless of how the source code changes, \family typewriter gdb \family default always stops at the \family typewriter main \family default function. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example Sometimes, the debugging program does not contain debug info, or \family typewriter gdb \family default is debugging assembly code. In that case, a memory address can be specified as a stop point. To get the function address, \family typewriter print \family default command can be used: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) print main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code $3 = {int (int, char **)} 0x400526
\end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Knowing the address of main, we can easily set a breakpoint with a memory address: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color red b \color inherit \color blue *0x400526 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example \family typewriter gdb \family default can also set breakpoint in any source file. Suppose that \family typewriter hello \family default program is composed not just one file but many files e.g. \family typewriter hello1.c \family default , \family typewriter hello2.c \family default , \family typewriter hello3.c \family default ... In that case, simply add the filename before either a line number: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \color red b \color inherit \color blue hello.c:3 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example A function name in a specific file can also be set: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \color red b \color inherit \color blue hello.c:main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter next/n \end_layout \begin_layout Standard This command executes the current line and stops at the next line. When the current line is a function call, steps over it. \end_layout \begin_layout Example After setting a breakpoint at \family typewriter main \family default , run a program and stop at the first \family typewriter printf \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at hello.c:5 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Then, to proceed to the next statement, we use the \family typewriter next \family default command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red n \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Hello World! \end_layout \begin_layout LyX-Code 6 return 0; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard In the output, the first line shows the output produced after executing line 5; then, the next line shows where \family typewriter gdb \family default stops currently, which is line 6. \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter step/s \end_layout \begin_layout Standard This command executes the current line and stops at the next line. When the current line is a function call, steps into it to the first next line in the called function. \end_layout \begin_layout Example Suppose we have a new function \family typewriter add \family default \begin_inset Foot status collapsed \begin_layout Plain Layout Why should we add a new function and function call instead of using the existing \family typewriter printf \family default call? Stepping into shared library functions is tricky because to make debugging works, the debug info must be installed and loaded. It is not worth the trouble for demonstrating this simple command. \end_layout \end_inset : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int add(int a, int b) { \end_layout \begin_layout Plain Layout return a + b; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout add(1, 2); \end_layout \begin_layout Plain Layout printf("Hello World! \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard If \family typewriter step \family default command is used instead of \family typewriter next \family default on the function call \family typewriter printf \family default , gdb steps inside the function: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, main (argc=1, argv=0xffffd154) at hello.c:11 \end_layout \begin_layout LyX-Code 11 add(1, 2); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code add (a=1, b=2) at hello.c:6 \end_layout \begin_layout LyX-Code 6 return a + b; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard After executing the command \family typewriter \color red s \family default \color inherit , \family typewriter gdb \family default stepped into the \family typewriter add \family default function where the first statement is a \family typewriter return \family default . \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter ni \end_layout \begin_layout Standard At the core, \family typewriter gdb \family default operates on assembly instruction. Source line by line debugging is simply an enhancement to make it friendlier for programmers. Each statement in C translates to one or more assembly instruction, as shown with \family typewriter objdump \family default and \family typewriter disassemble \family default command. With the debug info available, \family typewriter gdb \family default knows how many instructions belong to one line of high-level code; line by line debugging is just a execution of assembly instructions of a line when moving from the current line to the next. \end_layout \begin_layout Standard This command executes the \emph on one \emph default assembly instruction belongs to the current line. Until all assembly instructions of the current line are executed, \family typewriter gdb \family default will not move to the next line. If the current instruction is a \family typewriter call \family default , step over it to the next instruction. \end_layout \begin_layout Example When breakpoint is on the \family typewriter printf \family default call and \family typewriter ni \family default is used, it steps through each assembly instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red disassemble \color inherit \color blue /s main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Dump of assembler code for function main: \end_layout \begin_layout LyX-Code hello.c: \end_layout \begin_layout LyX-Code 4 { \end_layout \begin_layout LyX-Code 0x0804840b <+0>: lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 0x0804840f <+4>: and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 0x08048412 <+7>: push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048415 <+10>: push ebp \end_layout \begin_layout LyX-Code 0x08048416 <+11>: mov ebp,esp \end_layout \begin_layout LyX-Code 0x08048418 <+13>: push ecx \end_layout \begin_layout LyX-Code 0x08048419 <+14>: sub esp,0x4 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout LyX-Code \color blue 0x0804841c \color inherit <+17>: sub esp,0xc \end_layout \begin_layout LyX-Code \color blue 0x0804841f \color inherit <+20>: push 0x80484c0 \end_layout \begin_layout LyX-Code \color blue 0x08048424 \color inherit <+25>: call 0x80482e0 \end_layout \begin_layout LyX-Code \color blue 0x08048429 \color inherit <+30>: add esp,0x10 \end_layout \begin_layout LyX-Code 6 return 0; \end_layout \begin_layout LyX-Code => 0x0804842c <+33>: mov eax,0x0 \end_layout \begin_layout LyX-Code 7 } \end_layout \begin_layout LyX-Code 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 0x08048434 <+41>: leave \end_layout \begin_layout LyX-Code 0x08048435 <+42>: lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048438 <+45>: ret \end_layout \begin_layout LyX-Code End of assembler dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, main (argc=1, argv=0xffffd154) at hello.c:5 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red ni \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color blue 0x0804841f \color inherit 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red ni \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color blue 0x08048424 \color inherit 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red ni \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Hello World! \end_layout \begin_layout LyX-Code \color blue 0x08048429 \color inherit 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 6 return 0; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Upon entering \family typewriter ni \family default , \family typewriter gdb \family default executes current instruction and display the \emph on next \emph default instruction. That's why from the output, \family typewriter gdb \family default only displays 3 addresses: \family typewriter \color blue 0x0804841f \family default \color inherit , \family typewriter \color blue 0x08048424 \family default \color inherit and \family typewriter \color blue 0x08048429 \family default \color inherit . The instruction at \family typewriter \color blue 0x0804841c \family default \color inherit , which is the first instruction of \family typewriter printf \family default , is not displayed because it is the first instruction that \family typewriter gdb \family default stopped at. Assume that \family typewriter gdb \family default stopped at the first instruction of \family typewriter printf \family default at \family typewriter \color blue 0x0804841c \family default \color inherit , the current instruction can be displayed using \family typewriter x \family default command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout LyX-Code (gdb) x/i $eip \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code => \color blue 0x804841c \color inherit : sub esp,0xc \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter si \end_layout \begin_layout Standard Similar to \family typewriter ni \family default , this command executes the current assembly instruction belongs to the current line. But if the current instruction is a \family typewriter call \family default , step into it to the first next instruction in the called function. \end_layout \begin_layout Example Recall that the assembly code generated from \family typewriter printf \family default contains a \family typewriter call \family default instruction: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) disassemble /s main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Dump of assembler code for function main: \end_layout \begin_layout LyX-Code hello.c: \end_layout \begin_layout LyX-Code 4 { \end_layout \begin_layout LyX-Code 0x0804840b <+0>: lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 0x0804840f <+4>: and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 0x08048412 <+7>: push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048415 <+10>: push ebp \end_layout \begin_layout LyX-Code 0x08048416 <+11>: mov ebp,esp \end_layout \begin_layout LyX-Code 0x08048418 <+13>: push ecx \end_layout \begin_layout LyX-Code 0x08048419 <+14>: sub esp,0x4 \end_layout \begin_layout LyX-Code 5 printf("Hello World! \backslash n"); \end_layout \begin_layout LyX-Code 0x0804841c <+17>: sub esp,0xc \end_layout \begin_layout LyX-Code 0x0804841f <+20>: push 0x80484c0 \end_layout \begin_layout LyX-Code \color blue 0x08048424 \color inherit <+25>: \color blue call \color inherit 0x80482e0 \end_layout \begin_layout LyX-Code 0x08048429 <+30>: add esp,0x10 \end_layout \begin_layout LyX-Code 6 return 0; \end_layout \begin_layout LyX-Code => 0x0804842c <+33>: mov eax,0x0 \end_layout \begin_layout LyX-Code 7 } \end_layout \begin_layout LyX-Code 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 0x08048434 <+41>: leave \end_layout \begin_layout LyX-Code 0x08048435 <+42>: lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 0x08048438 <+45>: ret \end_layout \begin_layout LyX-Code End of assembler dump. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard We try instruction by instruction stepping again, but this time by running \family typewriter si \family default at \family typewriter \color blue 0x08048424 \family default \color inherit , where \family typewriter call \family default resides: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red si \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0x0804841f 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red si \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0x08048424 5 printf("Hello World! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) x/i $eip \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code => \color blue 0x8048424 \color inherit : \color blue call \color inherit \color green 0x80482e0 \color inherit \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red si \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color green 0x080482e0 \color inherit in \color green puts \color inherit @plt () \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The next instruction right after \family typewriter \color blue 0x8048424 \family default \color inherit is the first instruction at \family typewriter \color green 0x080482e0 \family default \color inherit in \family typewriter puts \family default function. In other words, \family typewriter gdb \family default stepped into \color green puts \color inherit instead of stepping over it. \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter until \end_layout \begin_layout Standard This command executes until the next line is greater than the current line. \end_layout \begin_layout Example Suppose we have a function that execute a long loop: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int add1000() { \end_layout \begin_layout Plain Layout int total = 0; \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout for (int i = 0; i < 1000; ++i){ \end_layout \begin_layout Plain Layout total += i; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout printf("Done adding! \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return total; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout add1000(1, 2); \end_layout \begin_layout Plain Layout printf("Hello World! \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard Using \family typewriter next \family default command, we need to press 1000 times for finishing the loop. Instead, a faster way is to use \family typewriter until \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) b add1000 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Breakpoint 1 at 0x8048411: file hello.c, line 4. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, add1000 () at hello.c:4 \end_layout \begin_layout LyX-Code 4 int total = 0; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red until \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 5 for (int i = 0; i < 1000; ++i){ \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red until \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 6 total += i; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red until \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 5 for (int i = 0; i < 1000; ++i){ \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red until \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 8 printf("Done adding! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Executing the first \family typewriter until \family default , \family typewriter gdb \family default stopped at line 5 since line 5 is greater than line 4. \end_layout \begin_layout Standard Executing the second \family typewriter until \family default , \family typewriter gdb \family default stopped at line 6 since line 6 is greater than line 5. \end_layout \begin_layout Standard Executing the third \family typewriter until \family default , \family typewriter gdb \family default stopped at line 5 since the loop still continues. Because line 5 is less than line 6, with the fourth \family typewriter until \family default , \family typewriter gdb \family default kept executing until it does not go back to line 5 anymore and stopped at line 8. This is a great way to skip over loop in the middle, instead of setting unneeded breakpoint. \end_layout \begin_layout Example \family typewriter until \family default can be supplied with an argument to explicitly execute to a specific line: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, add1000 () at hello.c:4 \end_layout \begin_layout LyX-Code 4 int total = 0; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red until \color inherit \color blue 8 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code add1000 () at hello.c: \color blue 8 \end_layout \begin_layout LyX-Code \color blue 8 \color inherit printf("Done adding! \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter finish \end_layout \begin_layout Standard This command executes until the end of a function and displays the return value. \family typewriter finish \family default is actually just a more convenient version of \family typewriter until \family default . \end_layout \begin_layout Example Using the \family typewriter add1000 \family default function from the previous example and use \family typewriter finish \family default instead of \family typewriter until \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, add1000 () at hello.c:4 \end_layout \begin_layout LyX-Code 4 int total = 0; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red finish \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color blue Run till exit from #0 add1000 () at hello.c:4 \end_layout \begin_layout LyX-Code Done adding! \end_layout \begin_layout LyX-Code 0x08048466 in main (argc=1, argv=0xffffd154) at hello.c:15 \end_layout \begin_layout LyX-Code 15 add1000(1, 2); \end_layout \begin_layout LyX-Code \color blue Value returned is $1 = 499500 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter bt \end_layout \begin_layout Standard This command prints the \emph on backtrace \emph default of all stack frames. A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on backtrace \end_layout \end_inset backtrace \begin_inset Index idx status open \begin_layout Plain Layout backtrace \end_layout \end_inset \emph default is a list of currently active functions: \end_layout \begin_layout Example Suppose we have a chain of function calls: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout void d(int d) { }; \end_layout \begin_layout Plain Layout void c(int c) { d(0); } \end_layout \begin_layout Plain Layout void b(int b) { c(1); } \end_layout \begin_layout Plain Layout void a(int a) { b(2); } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout a(3); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter bt \family default can visualize such a chain in action: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) b a \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Breakpoint 1 at 0x8048404: file hello.c, line 9. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Breakpoint 1, a (a=3) at hello.c:9 \end_layout \begin_layout LyX-Code 9 void a(int a) { b(2); } \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code b (b=2) at hello.c:7 \end_layout \begin_layout LyX-Code 7 void b(int b) { c(1); } \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code c (c=1) at hello.c:5 \end_layout \begin_layout LyX-Code 5 void c(int c) { d(0); } \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code d (d=0) at hello.c:3 \end_layout \begin_layout LyX-Code 3 void d(int d) { }; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red bt \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color blue #0 d (d=0) at hello.c:3 \end_layout \begin_layout LyX-Code \color blue #1 0x080483eb in c (c=1) at hello.c:5 \end_layout \begin_layout LyX-Code \color blue #2 0x080483fb in b (b=2) at hello.c:7 \end_layout \begin_layout LyX-Code \color blue #3 0x0804840b in a (a=3) at hello.c:9 \end_layout \begin_layout LyX-Code \color blue #4 0x0804841b in main (argc=1, argv=0xffffd154) at hello.c:13 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Most-recent calls are placed on top and least-recent calls are near the bottom. In this case, \family typewriter d \family default is the most current active function, so it has the index 0. Next is \family typewriter c \family default , the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset active function, has the index 1 and so on with function \family typewriter b \family default , function \family typewriter a \family default , and finally function \family typewriter main \family default at the bottom, the least-recent function. That is how we read a backtrace. \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter up \end_layout \begin_layout Standard This command goes up one frame earlier the current frame. \end_layout \begin_layout Example Instead of staying in \family typewriter d \family default function, we can go up to \family typewriter c \family default function and look at its state: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) bt \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code #0 d (d=0) at hello.c:3 \end_layout \begin_layout LyX-Code #1 0x080483eb in c (c=1) at hello.c:5 \end_layout \begin_layout LyX-Code #2 0x080483fb in b (b=2) at hello.c:7 \end_layout \begin_layout LyX-Code #3 0x0804840b in a (a=3) at hello.c:9 \end_layout \begin_layout LyX-Code #4 0x0804841b in main (argc=1, argv=0xffffd154) at hello.c:13 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red up \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code #1 0x080483eb in \color blue c \color inherit (c=1) at hello.c:3 \end_layout \begin_layout LyX-Code 3 void b(int b) { c(1); } \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The output displays the current frame is moved to \family typewriter c \family default and where the call to \family typewriter c \family default is made, which is in function \family typewriter b \family default at line 3. \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter down \end_layout \begin_layout Standard Similar to \family typewriter up \family default , this command goes down one frame later then the current frame. \end_layout \begin_layout Example After inspecting \family typewriter c \family default function, we can go back to \family typewriter d \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) bt \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code #0 d (d=0) at hello.c:3 \end_layout \begin_layout LyX-Code #1 0x080483eb in c (c=1) at hello.c:5 \end_layout \begin_layout LyX-Code #2 0x080483fb in b (b=2) at hello.c:7 \end_layout \begin_layout LyX-Code #3 0x0804840b in a (a=3) at hello.c:9 \end_layout \begin_layout LyX-Code #4 0x0804841b in main (argc=1, argv=0xffffd154) at hello.c:13 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) up \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code #1 0x080483eb in c (c=1) at hello.c:3 \end_layout \begin_layout LyX-Code 3 void b(int b) { c(1); } \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red down \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code #0 \color blue d \color inherit (d=0) at hello.c:1 \end_layout \begin_layout LyX-Code 1 void d(int d) { }; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \begin_layout Subsection Command: \family typewriter info registers \end_layout \begin_layout Standard This command lists the current values in commonly used registers. This command is useful when debugging assembly and operating system code, as we can inspect the current state of the machine. \end_layout \begin_layout Example Executing the command, we can see the commonly used registers: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout LyX-Code (gdb) \color red info registers \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code eax 0xf7faddbc -134554180 \end_layout \begin_layout LyX-Code ecx 0xffffd0c0 -12096 \end_layout \begin_layout LyX-Code edx 0xffffd0e4 -12060 \end_layout \begin_layout LyX-Code ebx 0x0 0 \end_layout \begin_layout LyX-Code esp 0xffffd0a0 0xffffd0a0 \end_layout \begin_layout LyX-Code ebp 0xffffd0a8 0xffffd0a8 \end_layout \begin_layout LyX-Code esi 0xf7fac000 -134561792 \end_layout \begin_layout LyX-Code edi 0xf7fac000 -134561792 \end_layout \begin_layout LyX-Code eip 0x804841c 0x804841c \end_layout \begin_layout LyX-Code eflags 0x286 [ PF SF IF ] \end_layout \begin_layout LyX-Code cs 0x23 35 \end_layout \begin_layout LyX-Code ss 0x2b 43 \end_layout \begin_layout LyX-Code ds 0x2b 43 \end_layout \begin_layout LyX-Code es 0x2b 43 \end_layout \begin_layout LyX-Code fs 0x0 0 \end_layout \begin_layout LyX-Code gs 0x63 99 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The above registers suffice for writing our operating system in later part. \end_layout \end_deeper \begin_layout Section How debuggers work: A brief introduction \end_layout \begin_layout Subsection How breakpoints work \end_layout \begin_layout Standard When a programmer places a breakpoint somewhere in his code, what actually happens is that the \emph on first \emph default opcode of the \emph on first \emph default instruction of a statement is replaced with another instruction, \family typewriter int 3 \family default with opcode \family typewriter CCh \family default : \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Opcode replacement, with \family typewriter int 3 \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter \color red 83 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ec \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\rightarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color red cc \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ec \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter sub esp,0x4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter int 3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter int 3 \family default only costs a single byte, making it efficient for debugging. When \family typewriter int 3 \family default instruction is executed, the operating system calls its breakpoint interrupt handler. The handler then checks what process reaches a breakpoint, pauses it and notifies the debugger it has paused a debugged process. The debugged process is only paused and that means a debugger is free to inspect its internal state, like a surgeon operates on an anesthetic patient. Then, the debugger replaces the \family typewriter int 3 \family default opcode with the original opcode and executes the original instruction normally. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Restore \family typewriter \family default the original opcode, after \family typewriter int 3 \family default was executed \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue cc \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ec \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Formula $\rightarrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \color blue 83 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ec \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 0c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter int 3 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter sub esp,0x4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Example It is simple to see \family typewriter int 3 \family default in action. First, we add an \family typewriter int 3 \family default instruction where we need \family typewriter gdb \family default to stop: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout asm("int 3"); \end_layout \begin_layout Plain Layout printf("Hello World \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter int 3 \family default precedes \family typewriter printf \family default , so \family typewriter gdb \family default is expected to stop at \family typewriter printf \family default . Next, we compile with debug enable and with Intel syntax: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -masm=intel -m32 -g hello.c -o hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Finally, start \family typewriter gdb \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gdb hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Running without setting any breakpoint, \family typewriter gdb \family default stops at \family typewriter printf \family default call, as expected: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color red r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/hello \end_layout \begin_layout LyX-Code Program received signal SIGTRAP, \color blue Trace/breakpoint \color inherit trap. \end_layout \begin_layout LyX-Code main (argc=1, argv=0xffffd154) at hello.c:6 \end_layout \begin_layout LyX-Code 6 \color blue printf("Hello World \backslash n"); \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The \color blue blue \color inherit text indicates that \family typewriter gdb \family default encountered a breakpoint, and indeed it stopped at the right place: the \family typewriter printf \family default call, where \family typewriter int 3 \family default preceded it. \end_layout \end_deeper \begin_layout Subsection Single stepping \end_layout \begin_layout Standard When breakpoint is implemented, it is easy to implement single stepping: a debugger simply places another \family typewriter int 3 \family default opcode in the next instruction. So, when a programmer sets a breakpoint at an instruction, the next instruction is automatically set by the debugger, thus enable instruction by instruction debugging. Similarly, source line by line debugging is just the placements of the very first opcodes in the two statements with two \family typewriter int 3 \family default opcodes. \end_layout \begin_layout Subsection How a debugger understands high level source code \end_layout \begin_layout Standard DWARF is a debugging file format used by many compilers and debuggers to support source level debugging. DWARF contains information that maps between entities in the executable binary with the source files. A program entity can either be data or code. A \series bold DIE \series default , or \series bold \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Debugging Information Entry \end_layout \end_inset D \series default ebugging \series bold I \series default nformation \series bold E \series default ntry \emph default \begin_inset Index idx status open \begin_layout Plain Layout \emph on Debugging Information Entry \end_layout \end_inset , is a description of a program entity. A DIE consists of a tag, which specifies the entity that the DIE describes, and  a list of  attributes that describes the entity. Of all the attributes, these two attributes enables source-level debugging: \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout Where the entity appears in the source files \end_layout \end_inset : which file and which line the entity appears. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout Where the entity appears in the executable binary \end_layout \end_inset : in which memory address the entity is loaded at runtime. With the precise address, \family typewriter gdb \family default can retrieve correct value for a data entity, or place a correct breakpoint and stop accordingly for a code entity. Without the information of these addresses, \family typewriter gdb \family default would not know where the entities are to inspect them. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{Source-binary mapping with DIE} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \family typewriter hello.c \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold DIE \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Line 1 \end_layout \begin_layout Plain Layout \family typewriter \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Line 2 \end_layout \begin_layout Plain Layout \family typewriter \color red \begin_inset Formula $\Rightarrow$ \end_inset Line 3 \end_layout \begin_layout Plain Layout \family typewriter \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Line 5 \end_layout \begin_layout Plain Layout \family typewriter \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset Line 6 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter #include \end_layout \begin_layout Plain Layout \begin_inset space ~ \end_inset \end_layout \begin_layout Plain Layout \family typewriter \color red int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout \family typewriter .......... \end_layout \begin_layout Plain Layout \family typewriter .......... \end_layout \begin_layout Plain Layout \begin_inset space ~ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset space ~ \end_inset \end_layout \begin_layout Plain Layout \begin_inset space ~ \end_inset \end_layout \begin_layout Plain Layout \series bold \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset Formula $\rightarrow$ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter .... \end_layout \begin_layout Plain Layout \family typewriter .... \end_layout \begin_layout Plain Layout \family typewriter main \family default in \family typewriter hello.c \family default is at \family typewriter 0x804840b \family default in \family typewriter hello \end_layout \begin_layout Plain Layout \family typewriter .... \end_layout \begin_layout Plain Layout \family typewriter .... \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset space ~ \end_inset \begin_inset Formula $\downarrow$ \end_inset \begin_inset Formula $\uparrow$ \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter \series bold hello \family default \series default (at \family typewriter \series bold \series default 0x804840b \family default ) \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter ...8d 4c 24 04 83 e4 f0 ff 71 fc .... \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash hfill \backslash break \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \begin_layout Standard In addition to DIEs, another binary-to-source mapping is the \emph on line number table \emph default . The line number table maps between a line in the source code and at which memory address is the start of the line in the executable binary. \end_layout \begin_layout Standard In sum, to successfully enable source-level debugging, a debugger needs to know the precise location of the source files and the load addresses at runtime. Address matching, between the image layout of the ELF binary and the address where it is loaded, is extremely important since debug information relies on correct loading address at runtime. That is, it assumes the addresses as recorded in the binary image at compile-ti me the same as at runtime e.g. if the load address for \family typewriter .text \family default section is recorded in the executable binary at \family typewriter 0x800000 \family default , then when the binary actually runs, \family typewriter .text \family default should really be loaded at \family typewriter 0x800000 \family default for gdb to be able to correctly match running instructions with high-level code statement. Address mismatching makes debug information useless, as actual code at one address is displayed as code at another address. Without this knowledge, we will not be able to build an operating system that can be debugged with \family typewriter gdb \family default . \end_layout \begin_layout Example When an executable binary contains debug info, \family typewriter readelf \family default can display such information in a readable format. Using the good old hello world program: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \emph on \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("Hello World \backslash n"); \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard and compile with debug info: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 -g hello.c -o hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard With the binary ready, we can look at the line number table with the command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readlelf -wL hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \family typewriter -w \family default option prints all the debug information. In combination with its sub-option, only specific information is displayed. For example, with \family typewriter -L, \family default only the line number table is displayed: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Decoded dump of debug contents of section .debug_line: \end_layout \begin_layout LyX-Code CU: hello.c: \end_layout \begin_layout LyX-Code File name Line number Starting address \end_layout \begin_layout LyX-Code hello.c 6 0x804840b \end_layout \begin_layout LyX-Code hello.c 7 0x804841c \end_layout \begin_layout LyX-Code hello.c 9 0x804842c \end_layout \begin_layout LyX-Code hello.c 10 0x8048431 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard From the above output: \end_layout \begin_layout Description CU shorts for \series bold \emph on C \series default ompilation \series bold U \series default nit \emph default , a separately compiled source file. In the example, we only have one file, \family typewriter hello.c \family default . \end_layout \begin_layout Description File \begin_inset space ~ \end_inset name displays the filename of the current compilation unit. \end_layout \begin_layout Description Line \begin_inset space ~ \end_inset number is the line number in the source file of which the line is not an empty line. In the example, line 8 is an empty line, so it does not appear. \end_layout \begin_layout Description Starting \begin_inset space ~ \end_inset address is the memory address where the line actually starts in the executable binary. \end_layout \begin_layout Standard With such crystal clear information, this is how \family typewriter gdb \family default is able to set a breakpoint on a line easily. For placing breakpoints on variables and functions, it is time to look at the DIEs. To get the DIEs information from an executable binary, run the command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readlelf -wi hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter -wi \family default option lists all the DIE entries. This is one typical DIE entry: \end_layout \begin_layout LyX-Code \color red <0> \color blue \color inherit : \color magenta Abbrev Number: 1 \color inherit (DW_TAG_compile_unit) \end_layout \begin_layout LyX-Code \color blue \color inherit \color green DW_AT_ \color inherit producer : (indirect string, offset: 0xe): GNU C11 5.4.0 20160609 -masm=intel -m32 -mtune=generic -march=i686 -g -fstack-protector-strong \end_layout \begin_layout LyX-Code \color blue <10> \color inherit \color green DW_AT_ \color inherit language : 12 (ANSI C99) \end_layout \begin_layout LyX-Code \color blue <11> \color inherit \color green DW_AT_ \color inherit name : (indirect string, offset: 0xbe): \series bold hello.c \end_layout \begin_layout LyX-Code \color blue <15> \color inherit \color green DW_AT_ \color inherit comp_dir : (indirect string, offset: 0x97): \series bold /tmp \end_layout \begin_layout LyX-Code \color blue <19> \color inherit \color green DW_AT_ \color inherit low_pc : \series bold 0x804840b \end_layout \begin_layout LyX-Code \color blue <1d> \color inherit \color green DW_AT_ \color inherit high_pc : \series bold 0x2e \end_layout \begin_layout LyX-Code \color blue <21> \color inherit \color green DW_AT_ \color inherit stmt_list : 0x0 \end_layout \begin_layout Description \family typewriter \color red Red \family default \color inherit This left-most number indicates the current nesting level of a DIE entry. \family typewriter 0 \family default is the outer-most level DIE with its entity is the compilation unit. This means subsequent DIE entries with higher nesting level are all the children of this tag, the compilation unit. It makes sense, as all the entities must originate from a source file. \end_layout \begin_layout Description \family typewriter \color blue Blue \family default \color inherit These numbers in hex format indicate the offsets into \family typewriter .debug_info \family default section. Each meaningful information is displayed along with its offset. When an attribute references to another attribute, the offset is used to precisely identify the referenced attribute. \end_layout \begin_layout Description \color green Green \color inherit These names with \family typewriter \color green DW_AT_ \family default \color inherit prefix are the attributes attached to a DIE that describe an entity. Notable attributes: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Description \family typewriter \color green DW_AT_ \color inherit name \end_layout \begin_layout Description \family typewriter \color green DW_AT_ \color inherit comp_dir \family default The filename of the compilation unit and the directory where compilation occurred. Without the filename and the path, \family typewriter gdb \family default would not be able to display the high-level source, despite the availability of the debug info. Debug info only contains the mapping between source and binary, not the source code itself. \end_layout \begin_layout Description \family typewriter \color green DW_AT_ \color inherit low_pc \end_layout \begin_layout Description \family typewriter \color green DW_AT_ \color inherit high_pc \family default The start and end of the current entity, which is the compilation unit, in the executable binary. The value in \family typewriter \color green DW_AT_ \color inherit low_pc \family default is the starting address. \family typewriter \color green DW_AT_ \color inherit high_pc \family default is the size of the compilation unit, when adding up to \family typewriter \color green DW_AT_ \color inherit low_pc \family default results in the end address of the entity. In this example, code compiled from \family typewriter hello.c \family default starts at \family typewriter 0x804840b \family default and end at \family typewriter \begin_inset Formula $\mathtt{0x804840b+0x2e=0x8048439}$ \end_inset . \family default To really make sure, we verify with \family typewriter objdump \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code int main(int argc, char *argv[]) \end_layout \begin_layout LyX-Code { \end_layout \begin_layout LyX-Code \color red 804840b \color inherit : 8d 4c 24 04 lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 804840f: 83 e4 f0 and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 8048412: ff 71 fc push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 8048415: 55 push ebp \end_layout \begin_layout LyX-Code 8048416: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code 8048418: 51 push ecx \end_layout \begin_layout LyX-Code 8048419: 83 ec 04 sub esp,0x4 \end_layout \begin_layout LyX-Code printf("Hello World \backslash n"); \end_layout \begin_layout LyX-Code 804841c: 83 ec 0c sub esp,0xc \end_layout \begin_layout LyX-Code 804841f: 68 c0 84 04 08 push 0x80484c0 \end_layout \begin_layout LyX-Code 8048424: e8 b7 fe ff ff call 80482e0 \end_layout \begin_layout LyX-Code 8048429: 83 c4 10 add esp,0x10 \end_layout \begin_layout LyX-Code return 0; \end_layout \begin_layout LyX-Code 804842c: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 8048431: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4] \end_layout \begin_layout LyX-Code 8048434: c9 leave \end_layout \begin_layout LyX-Code 8048435: 8d 61 fc lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 8048438: c3 ret \end_layout \begin_layout LyX-Code \color red 8048439 \color inherit : 66 90 xchg ax,ax \end_layout \begin_layout LyX-Code 804843b: 66 90 xchg ax,ax \end_layout \begin_layout LyX-Code 804843d: 66 90 xchg ax,ax \end_layout \begin_layout LyX-Code 804843f: 90 nop \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard It is true: \family typewriter main \family default starts at \family typewriter \color red 804840b \family default \color inherit and end at \family typewriter \color red 8048439 \family default \color inherit , right after the \family typewriter ret \family default instruction at \family typewriter 8048438 \family default . The instructions after \family typewriter \color red 8048439 \family default \color inherit are just padding bytes inserted by \family typewriter gcc \family default for alignment, which do not belong to \family typewriter main \family default . Note that the output from \family typewriter objdump \family default shows much more code past \family typewriter main \family default . It is not counted, as the code is outside of \family typewriter hello.c \family default , added by \family typewriter gcc \family default for the operating system. \family typewriter hello.c \family default contains only one function: \family typewriter main \family default and this is why \family typewriter hello.c \family default also starts and ends the same as \family typewriter main \family default . \end_layout \end_deeper \end_deeper \begin_layout Description \color magenta Pink \color inherit This number displays the abbreviation form of a tag. An abbreviation is the form of a DIE. When debug info is displayed with \family typewriter -wi \family default , the DIEs are displayed with their values. \family typewriter -wa \family default option shows abbreviations in the \family typewriter .debug_abbrev \family default section: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Contents of the .debug_abbrev section: \end_layout \begin_layout LyX-Code Number TAG (0x0) \end_layout \begin_layout LyX-Code 1 DW_TAG_compile_unit [has children] \end_layout \begin_layout LyX-Code DW_AT_producer DW_FORM_strp \end_layout \begin_layout LyX-Code DW_AT_language DW_FORM_data1 \end_layout \begin_layout LyX-Code DW_AT_name DW_FORM_strp \end_layout \begin_layout LyX-Code DW_AT_comp_dir DW_FORM_strp \end_layout \begin_layout LyX-Code DW_AT_low_pc DW_FORM_addr \end_layout \begin_layout LyX-Code DW_AT_high_pc DW_FORM_data4 \end_layout \begin_layout LyX-Code DW_AT_stmt_list DW_FORM_sec_offset \end_layout \begin_layout LyX-Code DW_AT value: 0 DW_FORM value: 0 \end_layout \begin_layout LyX-Code \series bold .... more abbreviations .... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The output is similar to a DIE output, with only attribute names and without any value. We can also say an abbreviation is a \emph on type \emph default of a DIE, as an abbreviation represents the structure of a particular DIE. Many DIEs share the same abbreviation, or structure, thus they are of the same type. An abbreviation number specifies which type a DIE is in the abbreviation table above. Abbreviations improve encoding efficiency (reduce binary size) because each DIE needs not to carry their structure information as pairs of attribute-v alue \begin_inset Foot status collapsed \begin_layout Plain Layout For example, data format such as YAML or JSON encodes its attribute names along with its values. This simplifies encoding, but with overhead. \end_layout \end_inset , but simply refers to an abbreviation for correct decoding. \end_layout \end_deeper \begin_layout Standard Here are all the DIEs of hello represented as a tree: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{figure*} \end_layout \begin_layout Plain Layout \backslash caption{DIE entries visualized as a tree} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Graphics filename images/06/dwarf_tree.svg scale 60 \end_inset \begin_inset CommandInset label LatexCommand label name "dwarf_tree" \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{figure*} \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard In the figure \begin_inset CommandInset ref LatexCommand formatted reference "dwarf_tree" \end_inset , \family typewriter DW_TAG_subprogram \family default represents a function such as \family typewriter main \family default . Its children are the DIEs of \family typewriter argc \family default and \family typewriter argv \family default . With such precise information, matching source to binary is an easy job for \family typewriter gdb \family default . \end_layout \begin_layout Standard If more than one compilation units exist in an executable binary, the DIE entries are sorted according to the compilation order from \family typewriter gcc \family default . For example, suppose we have another \family typewriter test.c \family default source file \begin_inset Foot status open \begin_layout Plain Layout It can contain anything. Just a sample file. \end_layout \end_inset and compile it together with hello: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -masm=intel -m32 -g test.c hello.c -o hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, the all DIE entries in \family typewriter test.c \family default are displayed before the DIE entries in \family typewriter hello.c: \end_layout \begin_layout LyX-Code <0>: Abbrev Number: 1 (DW_TAG_compile_unit) \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code DW_AT_producer : (indirect string, offset: 0x0): GNU C11 5.4.0 20160609 \end_layout \begin_layout LyX-Code -masm=intel -m32 -mtune=generic -march=i686 -g -fstack-protector-strong \end_layout \begin_layout LyX-Code <10> DW_AT_language : 12 (ANSI C99) \end_layout \begin_layout LyX-Code <11> DW_AT_name : (indirect string, offset: 0x64): \color red test.c \end_layout \begin_layout LyX-Code <15> DW_AT_comp_dir : (indirect string, offset: 0x5f): /tmp \end_layout \begin_layout LyX-Code <19> DW_AT_low_pc : 0x804840b \end_layout \begin_layout LyX-Code <1d> DW_AT_high_pc : 0x6 \end_layout \begin_layout LyX-Code <21> DW_AT_stmt_list : 0x0 \end_layout \begin_layout LyX-Code <1><25>: Abbrev Number: 2 (DW_TAG_subprogram) \end_layout \begin_layout LyX-Code <26> DW_AT_external : 1 \end_layout \begin_layout LyX-Code <26> DW_AT_name : bar \end_layout \begin_layout LyX-Code <2a> DW_AT_decl_file : 1 \end_layout \begin_layout LyX-Code <2b> DW_AT_decl_line : 1 \end_layout \begin_layout LyX-Code <2c> DW_AT_low_pc : 0x804840b \end_layout \begin_layout LyX-Code <30> DW_AT_high_pc : 0x6 \end_layout \begin_layout LyX-Code <34> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) \end_layout \begin_layout LyX-Code <36> DW_AT_GNU_all_call_sites: 1 \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code \series bold ....after all DIEs in \color red test.c \color inherit listed.... \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code <0><42>: Abbrev Number: 1 (DW_TAG_compile_unit) \end_layout \begin_layout LyX-Code <43> DW_AT_producer : (indirect string, offset: 0x0): GNU C11 5.4.0 20160609 \end_layout \begin_layout LyX-Code -masm=intel -m32 -mtune=generic -march=i686 -g -fstack-protector-strong \end_layout \begin_layout LyX-Code <47> DW_AT_language : 12 (ANSI C99) \end_layout \begin_layout LyX-Code <48> DW_AT_name : (indirect string, offset: 0xc5): \color blue hello.c \end_layout \begin_layout LyX-Code <4c> DW_AT_comp_dir : (indirect string, offset: 0x5f): /tmp \end_layout \begin_layout LyX-Code <50> DW_AT_low_pc : 0x8048411 \end_layout \begin_layout LyX-Code <54> DW_AT_high_pc : 0x2e \end_layout \begin_layout LyX-Code <58> DW_AT_stmt_list : 0x35 \end_layout \begin_layout LyX-Code \series bold ....then all DIEs in \color blue hello.c \color inherit are listed.... \end_layout \begin_layout LyX-Code \end_layout \end_deeper \begin_layout Part Groundwork \end_layout \begin_layout Chapter Bootloader \begin_inset CommandInset label LatexCommand label name "chap:Bootloader" \end_inset \end_layout \begin_layout Standard A \emph on bootloader \emph default loads an OS, or an application \begin_inset Foot status collapsed \begin_layout Plain Layout Many embedded devices don't use an OS. In embedded systems, the bootloader is simply included in boot firmware and no bootloader is needed. \end_layout \end_inset that runs and communicate directly with hardware. To run an OS, the first thing to write is a bootloader. In this chapter, we are going to write a rudimentary bootloader, as our main focus is writing an operating system, not a bootloader. More interestingly, this chapter will present related tools and techniques that are applicable for writing a bootloader as well as an operating system. \end_layout \begin_layout Section x86 Boot Process \end_layout \begin_layout Standard After the POST process finished, the CPU's program counter is set to the address \family typewriter FFFF:0000h \family default for executing BIOS code. \emph on BIOS - \series bold B \series default asic \series bold I \series default nput/ \series bold O \series default utput \series bold S \series default ystem \emph default is a firmware that performs hardware initialization and provides a set of generic subroutines to control input/output devices. The BIOS checks all available storage devices (floppy disks and hard disks) if any device is bootable, by examining the last two bytes of the first sector whether it has the boot record signature of \family typewriter 0x55 \family default , \family typewriter 0xAA \family default . If so, the BIOS loads the first sector to the address \family typewriter 7C00h \family default , set the program counter to that address and let the CPU executing code from there. \end_layout \begin_layout Standard The first sector is called \series bold \emph on M \series default aster \series bold B \series default oot \series bold R \series default ecord, \emph default or \emph on MBR \emph default . The program in the first sector is called \emph on MBR Bootloader \emph default . \end_layout \begin_layout Section Using BIOS services \end_layout \begin_layout Standard BIOS provides many basic services for controlling the hardware at the boot stage. A service is a group of routines that controls a particular hardware device, or returns information of current system. Each service is given an interrupt number. To call a BIOS routine, an \family typewriter int \family default instruction must be used with an interrupt number. Each BIOS service defines its own numbers for its routines; to call a routine, a specific number must be written to a register required by each service. The list of all BIOS interrupts is available with Ralf Brown's Interrupt List at: \begin_inset Flex URL status collapsed \begin_layout Plain Layout http://www.cs.cmu.edu/~ralf/files.html \end_layout \end_inset . \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout The boot process. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/07/simple_boot_process.pdf scale 80 clip \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Description Example: Interrupt call \family typewriter 13h \family default (diskette service) requires number of sectors to read, track number, sector number, head number and drive number to read from a storage device. The content of the sector is stored in memory at the address defined by the pair of registers \family typewriter ES:BX \family default . The parameters are stored in registers like this: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language={[x86masm]Assembler},numbers=left,showstringspaces=false,tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout ; Store sector content in the buffer 10FF:0000 \end_layout \begin_layout Plain Layout mov dx, 10FFh \end_layout \begin_layout Plain Layout mov es, dx \end_layout \begin_layout Plain Layout xor bx, bx \end_layout \begin_layout Plain Layout mov al, 2 ; read 2 sector \end_layout \begin_layout Plain Layout mov ch, 0 ; read track 0 \end_layout \begin_layout Plain Layout mov cl, 2 ; 2nd sector is read \end_layout \begin_layout Plain Layout mov dh, 0 ; head number \end_layout \begin_layout Plain Layout mov dl, 0 ; drive number. Drive 0 is floppy drive. \end_layout \begin_layout Plain Layout mov ah, 0x02 ; read floppy sector function \end_layout \begin_layout Plain Layout int 0x13 ; call BIOS - Read the sector \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard The BIOS is only available in real mode. However, when switching to protected mode, then BIOS will not be usable anymore and the operating system code is responsible for controlling hardware devices. This is when the operating system stands on its own: it must provide its own kernel drivers for talking to hardware. \end_layout \begin_layout Section Boot process \end_layout \begin_layout Enumerate BIOS transfers control to MBR bootloader by jumping to \family typewriter 0000:7c00h \family default , where bootloader is assumed to exist already. \end_layout \begin_layout Enumerate Setup machine environment for booting by properly initialize segment registers to enable flat memory model. \end_layout \begin_layout Enumerate Load the kernel: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Enumerate Read kernel from disk. \end_layout \begin_layout Enumerate Save it somewhere in the main memory. \end_layout \begin_layout Enumerate Jump to the starting code address of the kernel and execute. \end_layout \end_deeper \begin_layout Enumerate If error occurs, print a message to notify users something went wrong and halt. \end_layout \begin_layout Section Example Bootloader \end_layout \begin_layout Standard Here is a simple bootloader that does nothing, except not crashing the machine but halt it gracefully. If the virtual machine does not halt but text repeatedly flashing, it means the bootloader does not load properly and the machine crashed. The machine crashed because it keeps executing until the near end of physical memory (1 \begin_inset space \thinspace{} \end_inset MB in real mode), which is \family typewriter FFFF:0000h \family default , which starts the whole BIOS boot process all over again. This is effectively a reset, but not fully, since machine environment from previous run is still reserved. For that reason, it is called a \emph on warm reboot \emph default . The opposite of warm reboot is \emph on cold reboot \emph default , in which the machine environment is reset to initial settings when the computer starts from a powerless state. \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[x86masm]Assembler},numbers=left,basicstyle={\ttfamily},showstringspaces=false,tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox,title={\texttt{bootloader.asm}}" inline false status open \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout ; bootloader.asm \end_layout \begin_layout Plain Layout ; A Simple Bootloader \end_layout \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout org 0x7c00 \end_layout \begin_layout Plain Layout bits 16 \end_layout \begin_layout Plain Layout start: jmp boot \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ;; constant and variable definitions \end_layout \begin_layout Plain Layout msg db "Welcome to My Operating System!", 0ah, 0dh, 0h \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout boot: \end_layout \begin_layout Plain Layout cli ; no interrupts \end_layout \begin_layout Plain Layout cld ; all that we need to init \end_layout \begin_layout Plain Layout hlt ; halt the system \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ; We have to be 512 bytes. Clear the rest of the bytes with 0 \end_layout \begin_layout Plain Layout times 510 - ($-$$) db 0 \end_layout \begin_layout Plain Layout dw 0xAA55 ; Boot Signiture \end_layout \end_inset \end_layout \begin_layout Section Compile and load \end_layout \begin_layout Standard We compile the code with \family typewriter nasm \family default and write it to a disk image: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ nasm -f bin bootloader.asm -o bootloader \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, we create a 1.4 MB floppy disk and: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ dd if=/dev/zero of=disk.img bs=512 count=2880 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 2880+0 records in \end_layout \begin_layout LyX-Code 2880+0 records out \end_layout \begin_layout LyX-Code 1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.00625622 s, 236 MB/s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Then, we write the bootloader to the 1 \begin_inset script superscript \begin_layout Plain Layout st \end_layout \end_inset sector: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ dd conv=notrunc if=bootloader of=disk.img bs=512 count=1 seek=0 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 1+0 records in \end_layout \begin_layout LyX-Code 1+0 records out \end_layout \begin_layout LyX-Code 512 bytes copied, 0.000102708 s, 5.0 MB/s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The option \family typewriter conv=notrunc \family default preserves the original size of the floppy disk. Without this option, the 1.4 MB disk image will be completely replaced by the new \family typewriter disk.img \family default with only 512 bytes, and we do not want that happens. \end_layout \begin_layout Standard In the past, developing an operating system is complicated because a programmer needs to understand specific hardware he is using. Even though x86 was ubiquitous, the minute differences between models made some code written for a machine not run on another. Further, if you use the same physical computer you write your operating system take very long between runs, and also difficult to debug. Fortunately, today we can uniformly produce a virtual machine with a particular specification and avoid the incompatibility issue altogether, thus making an OS easier to write and test since everyone can reproduce the same machine environment. \end_layout \begin_layout Standard We will be using \emph on QEMU \emph default , a generic and open source machine emulator and virtualizer. QEMU can emulate various types of machine, not limited to x86_64 only. Debug is easy since you can connect GDB to a virtual machine to debug code that runs on it, through QEMU's built-in GDB server. QEMU can use \family typewriter disk.img \family default as a boot device e.g. a floppy disk: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ \family default \family typewriter qemu-system-i386 -machine q35 -fda disk.img -gdb tcp::26000 -S \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Itemize With option \family typewriter -machine q35 \family default , QEMU emulates a \family typewriter q35 \family default machine model from Intel. \begin_inset Foot status collapsed \begin_layout Plain Layout The following command lists all supported emulated machines from QEMU: \end_layout \begin_layout LyX-Code qemu-system-i386 -machine help \end_layout \end_inset . \end_layout \begin_layout Itemize With option \family typewriter -fda disk.img \family default , QEMU uses \family typewriter disk.img \family default as a floppy disk image. \end_layout \begin_layout Itemize With option \family typewriter -gdb tcp::26000 \family default , QEMU allows \family typewriter gdb \family default to connect to the virtual machine for remote debugging through a tcp socket with port 26000. \end_layout \begin_layout Itemize With option \family typewriter -S \family default , QEMU waits for \family typewriter gdb \family default to connect before it starts running. \end_layout \begin_layout Standard After the command is executed, a new console window that displays the screen output of the virtual machine. Open another terminal, run \family typewriter gdb \family default and set the current architecture to \family typewriter i8086 \family default , since we are running in 16-bit mode: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) set architecture i8086 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter warning: A handler for the OS ABI "GNU/Linux" is not built into this configurati on \end_layout \begin_layout Standard \family typewriter of GDB. Attempting to continue with the default i8086 settings. \end_layout \begin_layout Standard \family typewriter The target architecture is assumed to be i8086 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Then, connect \family typewriter gdb \family default to the waiting virtual machine with this command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) target remote localhost:26000 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter Remote debugging using localhost:26000 \end_layout \begin_layout Standard \family typewriter 0x0000fff0 in ?? () \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Then, place a breakpoint at \family typewriter 0x7c00 \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) b *0x7c00 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter Breakpoint 1 at 0x7c00 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Note the asterick before the memory address. Without the asterisk, \family typewriter gdb \family default treats the address as a symbol in a program rather than an address. Then, for convenience, we use a split layout for viewing the assembly code and registers together: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) layout asm \end_layout \begin_layout Standard \family typewriter (gdb) layout reg \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Finally, run the program: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) c \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard If the virtual machine successfully runs the bootloader, this is what the QEMU screen should look like: \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Boot succeeded. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/07/boot_succeeded.png scale 25 \end_inset \end_layout \end_inset \end_layout \begin_layout Subsection Debugging \end_layout \begin_layout Standard If, for some reason, the sample bootloader cannot get to such screen and \family typewriter gdb \family default does not stop at \family typewriter 0x7c00 \family default , then the following scenarios are likely: \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout The bootloader is invalid \end_layout \end_inset : the message \begin_inset Quotes eld \end_inset Boot failed: not a bootable disk \begin_inset Quotes erd \end_inset appears for floppy disk booting. Make sure the boot signature is at the last 2 bytes of the 512-byte first sector. \end_layout \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout The machine cannot find a boot disk \end_layout \end_inset : the message \begin_inset Quotes eld \end_inset Boot failed: not a bootable disk \begin_inset Quotes erd \end_inset appears for floppy disk booting. Make sure the bootloader is correctly written to the first sector. It can be verify by check the disk with \family typewriter hd \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ hd disk.img | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard If the first 512 bytes are all zeroes, then it is likely that the bootloader is incorrectly written to another sector. \end_layout \end_deeper \begin_layout Itemize \begin_inset Flex Noun status open \begin_layout Plain Layout The machine crashes \end_layout \end_inset : When such scenario happens, it reset back to the beginning at \family typewriter FFFF:0000h \family default . If the QEMU machine starts without waiting for \family typewriter gdb \family default , then the console output window keeps flashing as the machine is repeatedly reset. It is likely some instruction in the bootloader code causing the fault. \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Exercise Print a welcome message \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard We loaded the bootloader successfully. But, it needs to do something useful other than halting our machine. The easiest thing to do is printing something on screen, like how an introducti on to all programming language starts with \begin_inset Quotes eld \end_inset Hello World \begin_inset Quotes erd \end_inset . Our bootloader prints \begin_inset Quotes eld \end_inset Welcome to my operating system \begin_inset Quotes erd \end_inset \begin_inset Foot status open \begin_layout Plain Layout Or whatever message you want. \end_layout \end_inset . In this part, we will build a simple I/O library that allows us to set a cursor anywhere on the screen and print text there. \end_layout \begin_layout Standard First, create a file \series bold io.asm \series default for I/O related routines. Then, write the following routines: \end_layout \begin_layout Enumerate \begin_inset Flex Code status open \begin_layout Plain Layout \size large MovCursor \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \series bold Purpose: \series default Move a cursor to a specific location on screen and remember this location. \end_layout \begin_layout Standard \series bold Parameters: \series default \end_layout \begin_layout Itemize \emph on bh \emph default = Y coordinate \end_layout \begin_layout Itemize \emph on bl \emph default = X coordinate. \end_layout \begin_layout Standard \series bold Return: \series default None \end_layout \end_deeper \begin_layout Enumerate \size large \begin_inset Flex Code status open \begin_layout Plain Layout \size large PutChar \end_layout \end_inset \size default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \series bold Purpose: \series default Print a character on screen, at the cursor position previously set by \begin_inset Flex Code status open \begin_layout Plain Layout MovCursor \end_layout \end_inset . \end_layout \begin_layout Standard \series bold Parameters: \end_layout \begin_layout Itemize \family typewriter al \family default = Character to print \end_layout \begin_layout Itemize \family typewriter bl \family default = text color \end_layout \begin_layout Itemize \family typewriter cx \family default = number of times the character is repeated \end_layout \begin_layout Description Return: None \end_layout \end_deeper \begin_layout Enumerate \begin_inset Flex Code status open \begin_layout Plain Layout \size large Print \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \series bold Purpose: \series default Print a string. \end_layout \begin_layout Standard \series bold Parameters: \end_layout \begin_layout Itemize \family typewriter ds:si \family default = Zero terminated string \end_layout \begin_layout Description Return: None \end_layout \end_deeper \begin_layout Standard Test the routines by putting each in the bootloader source, compile and run. To debug, run GDB and set a breakpoint at a specific routine. The end result is that \begin_inset Flex Code status open \begin_layout Plain Layout Print \end_layout \end_inset should display a welcome message on screen. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Section Loading a program from bootloader \end_layout \begin_layout Standard Now that we get the feel of how to use the BIOS services, it is time for something more complicated. We will place our kernel on 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector onward, and our bootloader reads 30 sectors starting from 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector. Why 30 sectors? Our kernel will grow gradually, so we will preserve 30 sectors and save us time for modifying the bootloader each time the kernel size expands another sector. \end_layout \begin_layout Standard The primary responsibility of a bootloader is to read an operating system from some storage device e.g. hard disk, then loads it into main memory and transfer the control to the loaded operating system, similar to how the BIOS reads and loads a bootloader. At the moment, our bootloader does nothing more than just an assembly program loaded by the BIOS. To make our bootloader a real one, it must perform well the above two tasks: \emph on read \emph default and \emph on load \emph default an operating system. \end_layout \begin_layout Subsection Floppy Disk Anatomy \end_layout \begin_layout Standard To read from a storage device, we must understand how the device works, and the provided interface for controlling it. First of all, a floppy disk is a storage device, similar to RAM, but can store information even when a computer is turned off, thus is called \begin_inset Index idx status open \begin_layout Plain Layout persistent storage device \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on persistent storage device \end_layout \end_inset \emph on persistent storage device \emph default . A floppy disk also a persistent storage device, thus it provides a storage space up to 1.4 MB, or 1,474,560 bytes. When reading from a floppy disk, the smallest unit that can be read is a \emph on \begin_inset Index idx status open \begin_layout Plain Layout sector \end_layout \end_inset sector \emph default , a group of 512 contiguous bytes. A group of 18 sectors is a \emph on \begin_inset Index idx status open \begin_layout Plain Layout track \end_layout \end_inset track \emph default . Each side of a floppy disk consists of 80 tracks. A floppy drive is required to read a floppy disk. Inside a floppy drive contains an arm with 2 \emph on heads \emph default , each head reads a side of a floppy drive; head 0 writes the upper side and head 1 writes the lower side of a floppy disk. \end_layout \begin_layout Standard \begin_inset Float marginfigure wide false sideways false status open \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Sector and Track. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/07/Disk-structure.pdf scale 38 \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard When a floppy drive writes data to a brand new floppy disk, track 0 on the upper side is written first, by head 0. When the upper track 0 is full, the lower track 0 is used by head 1. When both the upper and lower side of a track 0 are full, it goes back to head 0 for writing data again, but this time the upper side of track 1 and so on, until no space left on the device. The same procedure is also applied for reading data from floppy disk. \begin_inset Float marginfigure wide false sideways false status open \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Floppy disk platter with 2 sides. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/07/Disk_heads.pdf scale 60 \end_inset \end_layout \end_inset \end_layout \begin_layout Subsection Read and load sectors from a floppy disk \begin_inset CommandInset label LatexCommand label name "subsec:Read-and-load" \end_inset \end_layout \begin_layout Standard First, we need to a sample program for writing into the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector, so we can experiment with floppy disk reading: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[x86masm]Assembler},numbers=left,basicstyle={\ttfamily},showstringspaces=false,tabsize=4,title={\texttt{sample.asm}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout ; sample.asm \end_layout \begin_layout Plain Layout ; A Sample Program \end_layout \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout mov eax, 1 \end_layout \begin_layout Plain Layout add eax, 1 \end_layout \end_inset \end_layout \begin_layout Standard Such a program is good enough. To simplify and for the purpose of demonstration, we will use the same floppy disk that holds the bootloader to hold our operating system. The operating system image starts from the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector, as the 1 \begin_inset script superscript \begin_layout Plain Layout st \end_layout \end_inset sector is already in use by the bootloader. We compile and write it to the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector with \family typewriter dd \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ nasm -f bin sample.asm -o sample \end_layout \begin_layout Standard \family typewriter $ dd if=sample of=disk.img bs=512 count=1 seek=1 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout The bootloader and the sample program on floppy disk. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold 1 \begin_inset script superscript \begin_layout Plain Layout st \end_layout \end_inset sector \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout ..... \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold 30 \begin_inset script superscript \begin_layout Plain Layout th \end_layout \end_inset sector \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter bootloader \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter sample \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout .... \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout (empty) \end_layout \end_inset \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Next, we need to fix the bootloader for reading from the floppy disk and load a number of arbitrary sectors. Before doing so, a basic understanding of floppy disk is required. To read data from disk, interrupt \family typewriter 13 \family default with \family typewriter AH = 02 \family default is a routine for reading sectors from disk into memory: \end_layout \begin_layout LyX-Code AH = 02 \end_layout \begin_layout LyX-Code AL = number of sectors to read (1-128 dec.) \end_layout \begin_layout LyX-Code CH = track/cylinder number (0-1023 dec., see below) \end_layout \begin_layout LyX-Code CL = sector number (1-17 dec.) \end_layout \begin_layout LyX-Code DH = head number (0-15 dec.) \end_layout \begin_layout LyX-Code DL = drive number (0=A:, 1=2nd floppy, 80h=drive 0, 81h=drive 1) \end_layout \begin_layout LyX-Code ES:BX = pointer to buffer \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code Return: \end_layout \begin_layout LyX-Code AH = status (see INT 13,STATUS) \end_layout \begin_layout LyX-Code AL = number of sectors read \end_layout \begin_layout LyX-Code CF = 0 if successful \end_layout \begin_layout LyX-Code = 1 if error \end_layout \begin_layout Standard Apply the above routine, the bootloader can read the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[x86masm]Assembler},numbers=left,basicstyle={\ttfamily},showstringspaces=false,tabsize=4,title={\texttt{bootloader.asm}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout ; Bootloader.asm \end_layout \begin_layout Plain Layout ; A Simple Bootloader \end_layout \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout org 0x7c00 \end_layout \begin_layout Plain Layout bits 16 \end_layout \begin_layout Plain Layout start: jmp boot \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ;; constant and variable definitions \end_layout \begin_layout Plain Layout msg db "Welcome to My Operating System!", 0ah, 0dh, 0h \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout boot: \end_layout \begin_layout Plain Layout cli ; no interrupts \end_layout \begin_layout Plain Layout cld ; all that we need to init \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout mov ax, 0x50 \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ;; set the buffer \end_layout \begin_layout Plain Layout mov es, ax \end_layout \begin_layout Plain Layout xor bx, bx \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout mov al, 2 ; read 2 sector \end_layout \begin_layout Plain Layout mov ch, 0 ; track 0 \end_layout \begin_layout Plain Layout mov cl, 2 ; sector to read (The second sector) \end_layout \begin_layout Plain Layout mov dh, 0 ; head number \end_layout \begin_layout Plain Layout mov dl, 0 ; drive number \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout mov ah, 0x02 ; read sectors from disk \end_layout \begin_layout Plain Layout int 0x13 ; call the BIOS routine \end_layout \begin_layout Plain Layout jmp 0x50:0x0 ; jump and execute the sector! \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout hlt ; halt the system \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ; We have to be 512 bytes. Clear the rest of the bytes with 0 \end_layout \begin_layout Plain Layout times 510 - ($-$$) db 0 \end_layout \begin_layout Plain Layout dw 0xAA55 ; Boot Signiture \end_layout \end_inset \end_layout \begin_layout Standard The above code jumps to the address \family typewriter 0x50:00 \family default (which is \family typewriter 0x500 \family default ). To test the code, load it on a QEMU virtual machine and connect through \family typewriter gdb \family default , then place a breakpoint at \family typewriter 0x500 \family default . If \family typewriter gdb \family default stops at the address, with the assembly listing is the same code as in \family typewriter sample.asm \family default , then the bootloader successfully loaded the program. This is an important milestone, as we ensure that our operating system are loaded and ran properly. \end_layout \begin_layout Section Improve productivity with scripts \end_layout \begin_layout Subsection Automate build with GNU Make \end_layout \begin_layout Standard Up to this point, the whole development process felt repetitive: whenever a change is made, the same commands are entered again. The commands are also complex. \family typewriter Ctrl+r \family default helps, but it still feels tedious. \end_layout \begin_layout Standard \begin_inset Flex Strong status open \begin_layout Plain Layout GNU Make \end_layout \end_inset is a program that controls and automates the process of building a complex software. For a small program, like a single C source file, invoking \begin_inset Flex Code status open \begin_layout Plain Layout \emph on gcc \end_layout \end_inset is quick and easy. However, soon your software will be more complex, with multiples spanning multiple directories, it is a chore to manually build and link files. To solve such problem, a tool was created to automate away this problem and is called a \emph on build system \emph default . GNU Make is one such of tools. There are various build systems out there, but GNU Make is the most popular in Linux world, as it is used for building the Linux kernel. \end_layout \begin_layout Standard For a comprehensive introduction to make, please refer to the official Introduct ion to Make: \begin_inset Flex URL status collapsed \begin_layout Plain Layout https://www.gnu.org/software/make/manual/html_node/Introduction.html#Introduction \end_layout \end_inset . And that's enough for our project. You can also download the manual in different formats e.g. PDF from the official manual page: \begin_inset Flex URL status open \begin_layout Plain Layout https://www.gnu.org/software/make/manual/ \end_layout \end_inset . \end_layout \begin_layout Standard With Makefile, we can build simpler commands and save time: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},numbers=left,tabsize=4,title={\texttt{Makefile}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout all: bootloader bootdisk \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout bootloader: \end_layout \begin_layout Plain Layout nasm -f bin bootloader.asm -o bootloader.o \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout kernel: \end_layout \begin_layout Plain Layout nasm -f bin sample.asm -o sample.o \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout bootdisk: bootloader.o kernel.o \end_layout \begin_layout Plain Layout dd if=/dev/zero of=disk.img bs=512 count=2880 \end_layout \begin_layout Plain Layout dd conv=notrunc if=bootloader.o of=disk.img bs=512 count=1 seek=0 \end_layout \begin_layout Plain Layout dd conv=notrunc if=sample.o of=disk.img bs=512 count=1 seek=1 \end_layout \end_inset \end_layout \begin_layout Standard Now, with a single command, we can build from start to finish a disk image with a bootloader at 1 \begin_inset script superscript \begin_layout Plain Layout st \end_layout \end_inset sector and the sample program at 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ make bootdisk \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter nasm -f bin bootloader.asm -o bootloader.o \end_layout \begin_layout Standard \family typewriter nasm -f bin sample.asm -o bootloader.o \end_layout \begin_layout Standard \family typewriter dd if=/dev/zero of=disk.img bs=512 count=2880 \end_layout \begin_layout Standard \family typewriter 2880+0 records in \end_layout \begin_layout Standard \family typewriter 2880+0 records out \end_layout \begin_layout Standard \family typewriter 1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.00482188 s, 306 MB/s \end_layout \begin_layout Standard \family typewriter dd conv=notrunc if=bootloader.o of=disk.img bs=512 count=1 seek=0 \end_layout \begin_layout Standard \family typewriter 0+1 records in \end_layout \begin_layout Standard \family typewriter 0+1 records out \end_layout \begin_layout Standard \family typewriter 10 bytes copied, 7.0316e-05 s, 142 kB/s \end_layout \begin_layout Standard \family typewriter dd conv=notrunc if=sample.o of=disk.img bs=512 count=1 seek=1 \end_layout \begin_layout Standard \family typewriter 0+1 records in \end_layout \begin_layout Standard \family typewriter 0+1 records out \end_layout \begin_layout Standard \family typewriter 10 bytes copied, 0.000208375 s, 48.0 kB/s \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Looking at the Makefile, we can see a few problems: \end_layout \begin_layout Standard First, the name \family typewriter disk.img \family default are all over the place. When we want to change the disk image name e.g. \family typewriter floppy_disk.img \family default , all the places with the name \family typewriter disk.img \family default must be changed manually. To solve this problem, we use a variable, and every appearance of \family typewriter disk.img \family default is replaced with the reference to the variable. This way, only one place that is changed - the variable definition - all other places are updated automatically. The following variables are added: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout BOOTLOADER=bootloader.o \end_layout \begin_layout Plain Layout OS=sample.o \end_layout \begin_layout Plain Layout DISK_IMG=disk.img.o \end_layout \end_inset \end_layout \begin_layout Standard The second problem is, the name \family typewriter bootloader \family default and \family typewriter sample \family default appears as part of the filenames of the source files e.g. \family typewriter bootloader.asm \family default and \family typewriter sample.asm \family default , as well as the filenames of the binary files e.g. \family typewriter bootloader \family default and \family typewriter sample \family default . Similar to \family typewriter disk.img \family default , when a name changed, every reference of that name must also be changed manually for both the names of the source files and the names of the binary files e.g. if we change \family typewriter bootloader.asm \family default to \family typewriter loader.asm \family default , then the object file \family typewriter bootloader.o \family default needs changing to \family typewriter loader.o \family default . To solve this problem, instead of changing filenames manually, we create a rule that automatically generate the filenames of one extension to another. In this case, we want any source file that starts with \family typewriter .asm \family default to have its equivalent binary files, without any extension e.g. \family typewriter bootloader.asm \family default \begin_inset Formula $\rightarrow$ \end_inset \family typewriter bootloader.o \family default . Such transformation is common, so GNU Make provides built-in functions: \family typewriter wildcard \family default and \family typewriter patsubst \family default for solving such problems: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout BOOTLOADER_SRCS := $(wildcard *.asm) \end_layout \begin_layout Plain Layout BOOTLOADER_OBJS := $(patsubst %.asm, %.o, $(BOOTLOADER_SRCS)) \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter wildcard \family default matches any \family typewriter .asm \family default file in the current directory, then assigned the list of matched files into the variable \family typewriter BOOTLOADER_SRCS \family default . In this case, \family typewriter BOOTLOADER_SRCS \family default is assigned the value: \end_layout \begin_layout LyX-Code bootloader.asm sample.asm \end_layout \begin_layout Standard \family typewriter patsubst \family default substitutes any filename starts with \family typewriter .asm \family default into a filename \family typewriter .o \family default e.g. \family typewriter bootloader.asm \family default \begin_inset Formula $\rightarrow$ \end_inset \family typewriter bootloader.o \family default . After \family typewriter patsubsts \family default runs, we get a list of object files in \family typewriter BOOTLOADER_OBJS \family default : \end_layout \begin_layout LyX-Code bootloader.o sample.o \end_layout \begin_layout Standard Finally, a recipe for building from \family typewriter .asm \family default to \family typewriter .o \family default are needed: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout %.o: %.asm \end_layout \begin_layout Plain Layout nasm -f bin $< -o $@ \end_layout \end_inset \end_layout \begin_layout Itemize \family typewriter $< \family default is a special variable that refers to the input of the recipe: \family typewriter %.asm \family default . \end_layout \begin_layout Itemize \family typewriter $@ \family default is a special variable that refers to the output of the recipe: \family typewriter %.o \family default . \end_layout \begin_layout Standard When the recipe is executed, the variables are replaced with the actual values. For example, if a transformation is \family typewriter bootloader.asm \family default \begin_inset Formula $\rightarrow$ \end_inset \family typewriter bootloader.o \family default , then the actual command executed when replace the placeholders in the recipe is: \end_layout \begin_layout LyX-Code nasm -f bin bootloader.asm -o bootloader.o \end_layout \begin_layout Standard With the recipe, all the \family typewriter .asm \family default files are built automatically with the \family typewriter nasm \family default command into \family typewriter .o \family default files and we no longer need a separate recipe for each object files. Putting it all together with the new variables, we get a better Makefile: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},numbers=left,tabsize=4,title={\texttt{Makefile}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout BOOTLOADER=bootloader.o \end_layout \begin_layout Plain Layout OS=sample.o \end_layout \begin_layout Plain Layout DISK_IMG=disk.img \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout BOOTLOADER_SRCS := $(wildcard *.asm) \end_layout \begin_layout Plain Layout BOOTLOADER_OBJS := $(patsubst %.asm, %.o, $(BOOTLOADER_SRCS)) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout all: bootdisk \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout %.o: %.asm \end_layout \begin_layout Plain Layout nasm -f bin $< -o $@ \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout bootdisk: $(BOOTLOADER_OBJS) \end_layout \begin_layout Plain Layout dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 \end_layout \begin_layout Plain Layout dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 \end_layout \begin_layout Plain Layout dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=1 seek=1 \end_layout \end_inset \end_layout \begin_layout Standard From here on, any \family typewriter .asm \family default file is compiled automatically, without an explicit recipe for each file. \end_layout \begin_layout Standard The object files are in the same directory as the source files, making it more difficult when working with the source tree. Ideally, object files and source files should live in different directories. We want a better organized directory layout like Figure \begin_inset CommandInset ref LatexCommand formatted reference "project-layout" \end_inset . \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout A better project layout \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "project-layout" \end_inset \end_layout \begin_layout LyX-Code . \end_layout \begin_layout LyX-Code ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   └── bootloader.asm \end_layout \begin_layout LyX-Code │   └── Makefile \end_layout \begin_layout LyX-Code ├── \color blue build \end_layout \begin_layout LyX-Code │   ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   │   └── bootloader.o \end_layout \begin_layout LyX-Code │   ├── disk.img \end_layout \begin_layout LyX-Code │   └── \color blue os \end_layout \begin_layout LyX-Code │   └── sample.o \end_layout \begin_layout LyX-Code ├── Makefile \end_layout \begin_layout LyX-Code └── \color blue os \end_layout \begin_layout LyX-Code ├── Makefile \end_layout \begin_layout LyX-Code └── sample.asm \end_layout \begin_layout Plain Layout The layout can be displayed with \family typewriter tree \family default command: \end_layout \begin_layout Plain Layout \family typewriter $ tree \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter \color blue bootloader/ \family default \color inherit directory holds bootloader source files; \family typewriter \color blue os/ \family default \color inherit holds operating system source files that we are going to write later; \family typewriter \color blue build/ \family default \color inherit holds the object files for both the bootloader, the os and the final disk image \family typewriter disk.img \family default . Notice that \family typewriter \color blue bootloader/ \family default \color inherit directory also has its own Makefile. This Makefile will be responsible for building everything in \family typewriter \color blue bootloader/ \family default \color inherit directory, while the top-level Makefile is released from the burden of building the bootloader, but only the disk image. The content of the Makefile in \family typewriter \color blue bootloader/ \family default \color inherit directory should be: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},numbers=left,tabsize=4,title={\texttt{bootloader/Makefile}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout BUILD_DIR=@| \backslash color{blue} \backslash bfseries ../build/|@bootloader \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout BOOTLOADER_SRCS := $(wildcard *.asm) \end_layout \begin_layout Plain Layout BOOTLOADER_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(BOOTLOADER_SRCS)) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout all: $(BOOTLOADER_OBJS) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout $(BUILD_DIR)/%.o: %.asm \end_layout \begin_layout Plain Layout nasm -f bin $< -o $@ \end_layout \end_inset \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Makefile in \family typewriter \color blue bootloader/ \end_layout \end_inset \end_layout \begin_layout LyX-Code . \end_layout \begin_layout LyX-Code ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   └── bootloader.asm \end_layout \begin_layout LyX-Code │   └── \color red Makefile \end_layout \begin_layout LyX-Code ├── \color blue build \end_layout \begin_layout LyX-Code │   ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   │   └── bootloader.o \end_layout \begin_layout LyX-Code │   ├── disk.img \end_layout \begin_layout LyX-Code │   └── \color blue os \end_layout \begin_layout LyX-Code │   └── sample.o \end_layout \begin_layout LyX-Code ├── Makefile \end_layout \begin_layout LyX-Code └── \color blue os \end_layout \begin_layout LyX-Code ├── Makefile \end_layout \begin_layout LyX-Code └── sample.asm \end_layout \end_inset \end_layout \begin_layout Standard Basically everything related to the bootloader in the top-level Makefile are extracted into this Makefile. When \family typewriter make \family default runs this Makefile, \family typewriter bootloader.o \family default should be built and put into \color blue \family typewriter ../build \family default / \color inherit directory. As a good practice, all references to \family typewriter ../build/ \family default go through \family typewriter BUILD_DIR \family default variable. The recipe for transforming from \family typewriter .asm \family default \begin_inset Formula $\rightarrow$ \end_inset \family typewriter .o \family default is also updated with proper paths, else it will not work. \end_layout \begin_layout Itemize \family typewriter %.asm \family default refers to the assembly source files in the current directory. \end_layout \begin_layout Itemize \family typewriter $(BUILD_DIR)/%.o \family default refers to the output object files in the build directory in the path \family typewriter \color blue ../build/ \family default \color inherit . \end_layout \begin_layout Standard The entire recipe implements the transformation from \family typewriter \family default \begin_inset Formula $\rightarrow$ \end_inset \family typewriter ../build/ \family default . Note that all paths must be correct. If we try to build object files in a different directory e.g. current directory, it will not work since there is no such recipe exists to build objects at such a path. \end_layout \begin_layout Standard We also create a similar Makefile for \family typewriter \color blue os/ \family default \color inherit directory: \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Makefile in \family typewriter \color blue os/ \end_layout \end_inset \end_layout \begin_layout LyX-Code . \end_layout \begin_layout LyX-Code ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   └── bootloader.asm \end_layout \begin_layout LyX-Code │   └── Makefile \end_layout \begin_layout LyX-Code ├── \color blue build \end_layout \begin_layout LyX-Code │   ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   │   └── bootloader.o \end_layout \begin_layout LyX-Code │   ├── disk.img \end_layout \begin_layout LyX-Code │   └── \color blue os \end_layout \begin_layout LyX-Code │   └── sample.o \end_layout \begin_layout LyX-Code ├── Makefile \end_layout \begin_layout LyX-Code └── \color blue os \end_layout \begin_layout LyX-Code ├── \color red Makefile \end_layout \begin_layout LyX-Code └── sample.asm \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},numbers=left,tabsize=4,title={\texttt{os/Makefile}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout BUILD_DIR=../build/os \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout OS_SRCS := $(wildcard *.asm) \end_layout \begin_layout Plain Layout OS_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(OS_SRCS)) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout all: $(OS_OBJS) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout $(BUILD_DIR)/%.o: %.asm \end_layout \begin_layout Plain Layout nasm -f bin $< -o $@ \end_layout \end_inset \end_layout \begin_layout Standard For now, it looks almost identical to the Makefile for bootloader. In the next chapter, we will update it for C code. Then, we update the top-level Makefile: \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Top-level Makefile \end_layout \end_inset \end_layout \begin_layout LyX-Code . \end_layout \begin_layout LyX-Code ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   └── bootloader.asm \end_layout \begin_layout LyX-Code │   └── Makefile \end_layout \begin_layout LyX-Code ├── \color blue build \end_layout \begin_layout LyX-Code │   ├── \color blue bootloader \end_layout \begin_layout LyX-Code │   │   └── bootloader.o \end_layout \begin_layout LyX-Code │   ├── disk.img \end_layout \begin_layout LyX-Code │   └── \color blue os \end_layout \begin_layout LyX-Code │   └── sample.o \end_layout \begin_layout LyX-Code ├── \color red Makefile \end_layout \begin_layout LyX-Code └── \color blue os \end_layout \begin_layout LyX-Code ├── Makefile \end_layout \begin_layout LyX-Code └── sample.asm \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},numbers=left,tabsize=4,title={\texttt{Makefile}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout BUILD_DIR=build \end_layout \begin_layout Plain Layout BOOTLOADER=$(BUILD_DIR)/bootloader/bootloader.o \end_layout \begin_layout Plain Layout OS=$(BUILD_DIR)/os/sample.o \end_layout \begin_layout Plain Layout DISK_IMG=disk.img \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout all: bootdisk \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout .PHONY: bootdisk bootloader os \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout bootloader: \end_layout \begin_layout Plain Layout make -C bootloader \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout os: \end_layout \begin_layout Plain Layout make -C os \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout bootdisk: bootloader os \end_layout \begin_layout Plain Layout dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 \end_layout \begin_layout Plain Layout dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 \end_layout \begin_layout Plain Layout dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=1 seek=1 \end_layout \end_inset \end_layout \begin_layout Standard The build process is now truly modularized: \end_layout \begin_layout Itemize \family typewriter bootloader \family default and \family typewriter os \family default builds are now delegated to child Makefile of respective components. \family typewriter -C \family default option tells \family typewriter make \family default to execute with a Makefile in a supplied directory. In this case, the directories are \color blue \family typewriter bootloader/ \family default \color inherit and \family typewriter \color blue os/ \family default \color inherit . \end_layout \begin_layout Itemize The target \family typewriter all \family default of the top-level Makefile is only responsible for \family typewriter bootdisk \family default target, which is the primary target of this Makefile. \end_layout \begin_layout Standard In many cases, a target is not always a filename, but is just a name for a recipe to be always executed when requested. If a filename is of the same name as a target and the file is up-to-date, \family typewriter make \family default does not execute the target. To solve this problem, \family typewriter .PHONY \family default specifies that some targets are not files. All phony targets will then run when requested, regardless of files of the same names. \end_layout \begin_layout Standard To save time entering the command for starting up a QEMU virtual machine, we also add a target to the top-level Makefile: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout qemu: \end_layout \begin_layout Plain Layout qemu-system-i386 -machine q35 -fda $(DISK_IMG) -gdb tcp::26000 -S \end_layout \end_inset \end_layout \begin_layout Standard One last problem is project cleaning. At the moment, object files need removing manually and this is a repetitive process. Instead, let the Makefile of each component takes care of cleaning its object files, then top-level Makefile performs project cleaning by calling the component Makefile to do the jobs. Each Makefile is added with a \family typewriter clean \family default target at the end: \end_layout \begin_layout Itemize Bootloader Makefile: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout clean: \end_layout \begin_layout Plain Layout rm $(BUILD_DIR)/* \end_layout \end_inset \end_layout \end_deeper \begin_layout Itemize OS Makefile: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout clean: \end_layout \begin_layout Plain Layout rm $(BUILD_DIR)/* \end_layout \end_inset \end_layout \end_deeper \begin_layout Itemize Top-level Makefile: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout clean: \end_layout \begin_layout Plain Layout make -C bootloader clean \end_layout \begin_layout Plain Layout make -C os clean \end_layout \end_inset \end_layout \end_deeper \begin_layout Standard Simply invoking \family typewriter make clean \family default at the project root, all object files the are removed. \end_layout \begin_layout Subsection GNU Make Syntax summary \end_layout \begin_layout Standard GNU Make, at its core, is a domain-specific language for build automation. As any programming language, it needs a way to define data and code. In a Makefile, variables carry data. A variable value is either hard coded or evaluated from invoking a shell such as Bash. All variable values in Make has the same type: a string of text. Number 3 is not a number, but textual representation of the symbol 3. Here are common ways how to define data in a Makefile: \end_layout \begin_layout Standard \noindent \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Syntax \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout A = 1 \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout B = 2 \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout C = $$(expr $(A) + $(B)) \end_layout \end_inset \begin_inset Newline newline \end_inset \end_layout \begin_layout Plain Layout ⇒ \begin_inset Flex Code status open \begin_layout Plain Layout A \end_layout \end_inset is \begin_inset Flex Code status open \begin_layout Plain Layout 1 \end_layout \end_inset , \begin_inset Flex Code status open \begin_layout Plain Layout B \end_layout \end_inset is \begin_inset Flex Code status open \begin_layout Plain Layout 2 \end_layout \end_inset , \begin_inset Flex Code status open \begin_layout Plain Layout C \end_layout \end_inset is \begin_inset Flex Code status open \begin_layout Plain Layout 3 \end_layout \end_inset . \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Declare a variable and assign a textual value to it. the double dollar sign \begin_inset Flex Code status open \begin_layout Plain Layout $$ \end_layout \end_inset means the enclosing expression evaluating by a shell, defined by \begin_inset Flex Code status open \begin_layout Plain Layout /bin/sh \end_layout \end_inset . In this case, the enclosing expression is \begin_inset Flex Code status open \begin_layout Plain Layout (expr $(A) + $(B)) \end_layout \end_inset and is evaluated by Bash. \begin_inset Newline newline \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout PATH = /bin \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout PATH := $PATH:/usr/bin \end_layout \end_inset \begin_inset Newline newline \end_inset \end_layout \begin_layout Plain Layout ⇒ \begin_inset Flex Code status open \begin_layout Plain Layout PATH \end_layout \end_inset is \begin_inset Flex Code status open \begin_layout Plain Layout /bin/:/usr/bin \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Declare a variable and assign to it. However, the difference is that the \begin_inset Flex Code status open \begin_layout Plain Layout = \end_layout \end_inset syntax does not allow refer to a variable to use itself as a value in the right hand side, while this syntax does. \begin_inset Newline newline \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout PATH = /bin \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout PATH += /usr/bin \end_layout \end_inset \begin_inset Newline newline \end_inset \end_layout \begin_layout Plain Layout ⇒ \begin_inset Flex Code status open \begin_layout Plain Layout PATH \end_layout \end_inset is \begin_inset Flex Code status open \begin_layout Plain Layout /bin/:/usr/bin \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Append a new value at the end of a variable. Equivalent to: \end_layout \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout PATH := $PATH:/usr/bin \end_layout \end_inset \begin_inset Newline newline \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout CFLAGS ?= -o \end_layout \end_inset \begin_inset Newline newline \end_inset \end_layout \begin_layout Plain Layout ⇒ \begin_inset Flex Code status open \begin_layout Plain Layout CFLAGS \end_layout \end_inset is assigned the value \begin_inset Flex Code status open \begin_layout Plain Layout -o \end_layout \end_inset if it was not defined. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout This syntax is called \series bold conditional reference \series default . Set a variable to a value if it is undefined. This is useful if a user wants to supply different value for a variable from the command line e.g. add debugging option to \begin_inset Flex Code status open \begin_layout Plain Layout CFLAGS \end_layout \end_inset . Otherwise, Make uses the default defined by \begin_inset Flex Code status open \begin_layout Plain Layout ?= \end_layout \end_inset . \begin_inset Newline newline \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout SRCS = lib1.c lib2.c main.c \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Flex Code status open \begin_layout Plain Layout OBJS := $(SRC:.o=.c) \end_layout \end_inset \begin_inset Newline newline \end_inset \end_layout \begin_layout Plain Layout ⇒ \begin_inset Flex Code status open \begin_layout Plain Layout OBJS \end_layout \end_inset has the value \begin_inset Flex Code status open \begin_layout Plain Layout lib1.o lib2.o main.o \end_layout \end_inset \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout This syntax is called \series bold substitution reference \series default . A part of referenced variable is replaced with something else. In this case, all the \begin_inset Flex Code status open \begin_layout Plain Layout .c \end_layout \end_inset extension is replaced by \begin_inset Flex Code status open \begin_layout Plain Layout .o \end_layout \end_inset extension, thus creating a list of object files for \begin_inset Flex Code status open \begin_layout Plain Layout OBJS \end_layout \end_inset variable from the list of source files from \begin_inset Flex Code status open \begin_layout Plain Layout SRCS \end_layout \end_inset variable. \begin_inset Newline newline \end_inset \end_layout \end_inset \end_inset \end_layout \begin_layout Standard Code in GNU Make is a collection of recipes that it can run. Each recipe is analogous to a function in a programming language, and can be called like a regular function. Each recipe carries a series of shell commands to be executed by a shell e.g. Bash. A recipe has the following format: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout target: prerequisites \end_layout \begin_layout Plain Layout command \end_layout \end_inset \end_layout \begin_layout Standard Each \begin_inset Flex Code status open \begin_layout Plain Layout target \end_layout \end_inset is analogous to a function name. Each \begin_inset Flex Code status open \begin_layout Plain Layout prerequisite \end_layout \end_inset is a call another target. Each command is one of Make's built-in commands or a command that is executable by a shell. All prerequisites must be satisfied before entering main body of \begin_inset Flex Code status open \begin_layout Plain Layout target \end_layout \end_inset ; that is, each prerequisite must not return any error. If any error is returned, Make terminates the whole build process and prints an error on the command line. \end_layout \begin_layout Standard Each time \begin_inset Flex Code status open \begin_layout Plain Layout make \end_layout \end_inset runs, by default if no target is supplied, it starts with \begin_inset Flex Code status open \begin_layout Plain Layout all \end_layout \end_inset target, go through every prerequisites and finally the body of \begin_inset Flex Code status open \begin_layout Plain Layout all \end_layout \end_inset . \begin_inset Flex Code status open \begin_layout Plain Layout all \end_layout \end_inset is analogous to \begin_inset Flex Code status open \begin_layout Plain Layout main \end_layout \end_inset in other programming languages. However, if \begin_inset Flex Code status open \begin_layout Plain Layout make \end_layout \end_inset is given a target, it will start from that target instead of \begin_inset Flex Code status open \begin_layout Plain Layout main \end_layout \end_inset . This feature is useful to automate multiple aspects in a project. For example, one target is for building the project, one target is for generating the documents e.g. test reports, another target for running the whole test suite and \begin_inset Flex Code status open \begin_layout Plain Layout all \end_layout \end_inset runs every main targets. \end_layout \begin_layout Standard \begin_inset Note Note status open \begin_layout Plain Layout [illustration of makefile tree] \end_layout \end_inset \end_layout \begin_layout Subsection Automate debugging steps with GDB script \begin_inset CommandInset label LatexCommand label name "subsec:Automate-debugging-steps" \end_inset \end_layout \begin_layout Standard For the convenience, we save GDB configuration to \family typewriter .gdbinit \family default file at the project root directory. This configuration is just a collection of GDB commands and a few extra commands. When \family typewriter gdb \family default runs, it first loads the \family typewriter .gdbinit \family default file at home directory, then the \family typewriter .gdbinit \family default file at the current directory. Why shouldn't we put commands in \family typewriter ~/.gdbinit \family default ? Because these commands are specific to only this project e.g. not all programs are required a remote connection. \end_layout \begin_layout Standard Our first configuration: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=bash,numbers=left,showstringspaces=false,tabsize=4,title={\texttt{.gdbinit}}" inline false status open \begin_layout Plain Layout define hook-stop \end_layout \begin_layout Plain Layout # Translate the segment:offset into a physical address \end_layout \begin_layout Plain Layout printf "[%4x:%4x] ", $cs, $eip \end_layout \begin_layout Plain Layout x/i $cs*16+$eip \end_layout \begin_layout Plain Layout end \end_layout \end_inset \end_layout \begin_layout Standard The above script displays the memory address in \family typewriter [segment:offset] \family default format, which is necessary for debugging our bootloader and operating system code. \end_layout \begin_layout Standard It is better to use Intel syntax: \end_layout \begin_layout LyX-Code set disassembly-flavor intel \end_layout \begin_layout Standard The following commands set a more convenient layout for debugging assembly code: \end_layout \begin_layout LyX-Code layout asm \end_layout \begin_layout LyX-Code layout reg \end_layout \begin_layout Standard We are currently debugging bootloader code, so it is a good idea to first set it to 16-bit: \end_layout \begin_layout LyX-Code set architecture i8086 \end_layout \begin_layout Standard Every time the QEMU virtual machine starts, \family typewriter gdb \family default must always connect to port \family typewriter 26000 \family default . To avoid the trouble of manually connecting to the virtual machine, add the command: \end_layout \begin_layout LyX-Code target remote localhost:26000 \end_layout \begin_layout Standard Debugging the bootloader needs a breakpoint at 0x7c00, where our bootloader code starts: \end_layout \begin_layout LyX-Code b *0x7c00 \end_layout \begin_layout Standard Now, whenever \family typewriter gdb \family default starts, it automatically set correct architecture based on code, automatically connects to the virtual machine \begin_inset Foot status open \begin_layout Plain Layout The QEMU virtual machine should have already been started before starting \family typewriter gdb \family default . \end_layout \end_inset , displays output in a convenient layout and set a necessary breakpoint. All that need to do is run the program. \end_layout \begin_layout Chapter Linking and loading on bare metal \begin_inset CommandInset label LatexCommand label name "chap:Linking-and-loading" \end_inset \end_layout \begin_layout Standard \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on Relocation \end_layout \end_inset Relocation \begin_inset Index idx status open \begin_layout Plain Layout Relocation \end_layout \end_inset \emph default is the process of replacing symbol references with its actual symbolic definitions in an object file. A symbol reference is the memory address of a symbol. \end_layout \begin_layout Standard If the definition is hard to understand, consider a similar analogy: house relocation. Suppose that a programmer bought a new house and the new house is empty. He must buy furnitures and appliances to fulfill daily needs and thus, he made a list of items to buy, and where to place them. To visualize the placements of new items, he draws a blueprint of the house and the respective places of all items. He then travels to the shops to buy goods. Whenever he visit a shop and sees matched items, he tells the shop owner to note them down. After done selecting, he tells the shop owner to pick up a brand new item instead of the objects on display, then give the address for delivering the goods to his new house. Finally, when the goods arrive, he places the items where he planned at the beginning. \end_layout \begin_layout Standard \begin_inset Note Note status open \begin_layout Plain Layout [illustration of the house relocation process] \end_layout \end_inset \end_layout \begin_layout Standard Now that house relocation is clear, object relocation is similar: \end_layout \begin_layout Itemize The list of items represents the relocation table, where the memory location for each symbol (item) is predetermined. \end_layout \begin_layout Itemize Each item represents a pair of \emph on symbol definition \emph default and its \emph on symbol address \emph default . \end_layout \begin_layout Itemize Each shop represents a compiled object file. \end_layout \begin_layout Itemize Each item on display represents a symbol definition and references in the object file. \end_layout \begin_layout Itemize The new address, where all the goods are delivered, represents the final executable binary or the final object file. Since the items on display are not for sale, the shop owner delivers brand new goods instead. Similarly, the object files are not merged together, but copied all over a new file, the object/executable file. \end_layout \begin_layout Itemize Finally, the goods are placed in the positions according to the shopping list made from the beginning. Similarly, the symbol definitions are placed appropriately in its respective section and the symbol references of the final object/executable file are replaced with the actual memory addresses of the symbol definitions. \end_layout \begin_layout Standard \begin_inset Note Note status open \begin_layout Plain Layout [illustration: relocation process] \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Note Note status open \begin_layout Plain Layout TODO: Convert to table format for clarity. \end_layout \end_inset \end_layout \begin_layout Section Understand relocations with readelf \begin_inset CommandInset label LatexCommand label name "sec:Understand-relocations-with-readelf" \end_inset \end_layout \begin_layout Standard Earlier, when we explore object sections, there exists sections that begins with . \family typewriter rel \family default . These sections are relocation tables that maps between a symbol and its location in the final object file or the final executable binary \begin_inset Foot status open \begin_layout Plain Layout A \family typewriter .rel \family default section is equivalent to a list of items in the house analogy. \end_layout \end_inset . \end_layout \begin_layout Standard Suppose that a function \family typewriter foo \family default is defined in another object file, so \family typewriter main.c \family default declares it as \family typewriter extern \family default : \end_layout \begin_layout Standard \begin_inset listings lstparams "showstringspaces=false,tabsize=4,title={\texttt{main.c}}" inline false status open \begin_layout Plain Layout int i; \end_layout \begin_layout Plain Layout void foo(); \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout i = 5; \end_layout \begin_layout Plain Layout foo(); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout void foo() {} \end_layout \end_inset \end_layout \begin_layout Standard When we compile \family typewriter main.c \family default as object file with this command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 -masm=intel -c main.c \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, we can inspect the relocation tables with this command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -r main.o \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Relocation section '.rel.text' at offset 0x1cc contains 2 entries: \end_layout \begin_layout LyX-Code Offset Info Type Sym.Value Sym. Name \end_layout \begin_layout LyX-Code 000000 \color blue 13 \color inherit 0000 \color magenta 08 \color green 01 \color inherit \color green R_386_32 \color inherit 000000 \color cyan 04 \color inherit \color red i \end_layout \begin_layout LyX-Code 000000 \color blue 1c \color inherit 0000 \color magenta 0a \color green 02 \color inherit \color green R_386_PC32 \color inherit 000000 \color cyan 2e \color inherit \color red foo \end_layout \begin_layout LyX-Code Relocation section '.rel.eh_frame' at offset 0x1dc contains 2 entries: \end_layout \begin_layout LyX-Code Offset Info Type Sym.Value Sym. Name \end_layout \begin_layout LyX-Code 00000020 00000202 R_386_PC32 00000000 .text \end_layout \begin_layout LyX-Code 0000004c 00000202 R_386_PC32 00000000 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Subsection Offset \end_layout \begin_layout Standard An \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on offset \end_layout \end_inset offset \begin_inset Index idx status open \begin_layout Plain Layout offset \end_layout \end_inset \emph default is the location into a section of a binary file, where the actual memory address of a symbol definition is replaced. The section with . \family typewriter rel \family default prefix determines which section to offset into. For example, \family typewriter .rel.text \family default is the relocation \emph on table \emph default of symbols whose address needs correcting in \family typewriter .text \family default section, at a specific offset into \family typewriter .text \family default section. In the example output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 000000 \color blue 1c \color inherit 00000a02 R_386_PC32 0000002e foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The blue number indicates there exists a reference of symbol \family typewriter foo \family default that is \family typewriter 1c \family default bytes into \family typewriter .text \family default section. To see it clearer, we recompile main.c with option -g into the file \family typewriter main_debug.o \family default , then run \family typewriter objdump \family default on it and got: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Disassembly of section .text: \end_layout \begin_layout LyX-Code 00000000
: \end_layout \begin_layout LyX-Code int i; \end_layout \begin_layout LyX-Code void foo(); \end_layout \begin_layout LyX-Code int main(int argc, char *argv[]) \end_layout \begin_layout LyX-Code { \end_layout \begin_layout LyX-Code 0: 8d 4c 24 04 lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 4: 83 e4 f0 and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 7: ff 71 fc push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code a: 55 push ebp \end_layout \begin_layout LyX-Code b: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code d: 51 push ecx \end_layout \begin_layout LyX-Code e: 83 ec 04 sub esp,0x4 \end_layout \begin_layout LyX-Code i = 5; \end_layout \begin_layout LyX-Code 11: c7 05 00 00 00 00 05 mov DWORD PTR ds:0x0,0x5 \end_layout \begin_layout LyX-Code 18: 00 00 00 \end_layout \begin_layout LyX-Code foo(); \end_layout \begin_layout LyX-Code 1b: e8 \color blue fc ff ff ff \color inherit call \color blue 1c \color inherit \end_layout \begin_layout LyX-Code return 0; \end_layout \begin_layout LyX-Code 20: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 25: 83 c4 04 add esp,0x4 \end_layout \begin_layout LyX-Code 28: 59 pop ecx \end_layout \begin_layout LyX-Code 29: 5d pop ebp \end_layout \begin_layout LyX-Code 2a: 8d 61 fc lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 2d: c3 ret \end_layout \begin_layout LyX-Code ....irrelevant content omitted.... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The byte at \family typewriter 1b \family default \begin_inset script superscript \begin_layout Plain Layout \end_layout \end_inset is the opcode \family typewriter e8 \family default , the \family typewriter call \family default instruction; byte at \family typewriter 1c \family default is the value \family typewriter fc \family default . Why is the operand value for \family typewriter e8 \family default is \family typewriter 0xfffffffc \family default , which is equivalent to -4, but the translated instruction \family typewriter call 1c \family default ? It will be explained after a few more sections, but you should pause and think a bit about the reason why. \end_layout \begin_layout Subsection Info \end_layout \begin_layout Standard Info specifies index of a symbol in the symbol table and the type of relocation to perform. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0000001c 0000 \color magenta 0a \color green 02 \color inherit R_386_PC32 0000002e foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The pink number is the index of symbol \family typewriter foo \family default in the symbol table, and the green number is the relocation type. The numbers are written in hex format. In the example, \family typewriter 0a \family default means \family typewriter 10 \family default in decimal, and symbol \family typewriter foo \family default is indeed at index \family typewriter 10 \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code \color magenta 10 \color inherit : 0000002e 6 FUNC GLOBAL DEFAULT 1 foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Subsection Type \end_layout \begin_layout Standard Type represents the type value in textual form. Looking at the type of foo: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0000001c 00000a \color green 02 \color inherit \color green R_386_PC32 \color inherit 0000002e foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The green number is type in its numeric form, and \family typewriter R_386_PC32 \family default is the name assigned to that value. Each value represents a relocation method of calculation. For example, with the type \family typewriter \color green R_386_PC32 \family default \color inherit , the following formula is applied for relocation (Inteli386 psABI): \end_layout \begin_layout Standard \begin_inset Formula \[ Relocated\,Offset=S+A-P \] \end_inset \end_layout \begin_layout Standard To understand the formula, it is necessary to understand symbol values. \end_layout \begin_layout Subsection Sym.Value \end_layout \begin_layout Standard This field shows the \emph on symbol value \emph default . A symbol value is a value assigned to a symbol, whose meaning depends on the \family typewriter Ndx \family default field: \end_layout \begin_layout Description \begin_inset Flex Noun status open \begin_layout Plain Layout A \begin_inset space ~ \end_inset symbol \begin_inset space ~ \end_inset whose \begin_inset space ~ \end_inset section \begin_inset space ~ \end_inset index \begin_inset space ~ \end_inset is \family typewriter \begin_inset space ~ \end_inset COMMON \end_layout \end_inset , \family typewriter \family default its symbol value holds alignment constraints. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example In the symbol table, the variable \color red i \color inherit is identified as \family typewriter \color blue COM \family default \color inherit (uninitialized variable): \begin_inset Foot status collapsed \begin_layout Plain Layout The command for listing symbol table is (assume the object file is \family typewriter hello.o \family default ): \end_layout \begin_layout LyX-Code readelf -s hello.o \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Symbol table '.symtab' contains 16 entries: \end_layout \begin_layout LyX-Code Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \end_layout \begin_layout LyX-Code 1: 00000000 0 FILE LOCAL DEFAULT ABS hello2.c \end_layout \begin_layout LyX-Code 2: 00000000 0 SECTION LOCAL DEFAULT 1 \end_layout \begin_layout LyX-Code 3: 00000000 0 SECTION LOCAL DEFAULT 3 \end_layout \begin_layout LyX-Code 4: 00000000 0 SECTION LOCAL DEFAULT 4 \end_layout \begin_layout LyX-Code 5: 00000000 0 SECTION LOCAL DEFAULT 5 \end_layout \begin_layout LyX-Code 6: 00000000 0 SECTION LOCAL DEFAULT 7 \end_layout \begin_layout LyX-Code 7: 00000000 0 SECTION LOCAL DEFAULT 8 \end_layout \begin_layout LyX-Code 8: 00000000 0 SECTION LOCAL DEFAULT 10 \end_layout \begin_layout LyX-Code 9: 00000000 0 SECTION LOCAL DEFAULT 12 \end_layout \begin_layout LyX-Code 10: 00000000 0 SECTION LOCAL DEFAULT 14 \end_layout \begin_layout LyX-Code 11: 00000000 0 SECTION LOCAL DEFAULT 15 \end_layout \begin_layout LyX-Code 12: 00000000 0 SECTION LOCAL DEFAULT 13 \end_layout \begin_layout LyX-Code 13: \color green 00000004 \color inherit 4 OBJECT GLOBAL DEFAULT \color blue COM \color inherit \color red i \end_layout \begin_layout LyX-Code 14: 00000000 46 FUNC GLOBAL DEFAULT 1 main \end_layout \begin_layout LyX-Code 15: 0000002e 6 FUNC GLOBAL DEFAULT 1 foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard so its symbol value is a memory alignment for assigning a proper memory address that conforms to the alignment in the final memory address. In the case of \family typewriter \color red i \family default \color inherit , the value is \family typewriter \color green 4 \family default \color inherit , so the starting memory address of \family typewriter \color red i \family default \color inherit in the final binary file will be a multiple of 4. \end_layout \end_deeper \end_deeper \begin_layout Description \begin_inset Flex Noun status open \begin_layout Plain Layout A \begin_inset space ~ \end_inset symbol \begin_inset space ~ \end_inset whose \family typewriter \begin_inset space ~ \end_inset Ndx \family default \begin_inset space ~ \end_inset identifies \begin_inset space ~ \end_inset a \begin_inset space ~ \end_inset specific \begin_inset space ~ \end_inset section \end_layout \end_inset , its symbol value holds a section offset. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example In the symbol table, \family typewriter main \family default and \family typewriter foo \family default belong to section 1: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 14: 00000000 46 FUNC GLOBAL DEFAULT \color blue 1 \color inherit \color red main \end_layout \begin_layout LyX-Code 15: 0000002e 6 FUNC GLOBAL DEFAULT \color blue 1 \color inherit \color red foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard which is \family typewriter \color blue .text \color inherit \begin_inset Foot status open \begin_layout Plain Layout \family typewriter .text \family default holds program code and read-only data. \end_layout \end_inset \family default section \begin_inset Foot status collapsed \begin_layout Plain Layout The command for listing sections is (assume the object file is \family typewriter hello.o \family default ): \end_layout \begin_layout LyX-Code readelf -S hello.o \end_layout \end_inset : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code There are 20 section headers, starting at offset 0x558: \end_layout \begin_layout LyX-Code Section Headers: \end_layout \begin_layout LyX-Code [Nr] Name Type Addr Off Size ES Flg Lk Inf Al \end_layout \begin_layout LyX-Code [ 0] NULL 00000000 000000 000000 00 0 0 0 \end_layout \begin_layout LyX-Code \color blue [ 1] \color inherit \color blue .text \color inherit PROGBITS 00000000 000034 000034 00 AX 0 0 1 \end_layout \begin_layout LyX-Code [ 2] .rel.text REL 00000000 000414 000010 08 I 18 1 4 \end_layout \begin_layout LyX-Code [ 3] .data PROGBITS 00000000 000068 000000 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [ 4] .bss NOBITS 00000000 000068 000000 00 WA 0 0 1 \end_layout \begin_layout LyX-Code [ 5] .debug_info PROGBITS 00000000 000068 000096 00 0 0 1 \end_layout \begin_layout LyX-Code ..... remaining output omitted for clarity.... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \end_deeper \end_deeper \begin_layout Description \begin_inset Flex Noun status open \begin_layout Plain Layout In \begin_inset space ~ \end_inset the \begin_inset space ~ \end_inset final \begin_inset space ~ \end_inset executable \begin_inset space ~ \end_inset and \begin_inset space ~ \end_inset shared \begin_inset space ~ \end_inset object \begin_inset space ~ \end_inset files \end_layout \end_inset , instead of the above values, a symbol value holds a memory address. \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Example After compiling hello.o into the final executable hello, the symbol table now contains the memory address for each symbol \begin_inset Foot status collapsed \begin_layout Plain Layout The command to compile the object file \family typewriter hello.o \family default into the executable \family typewriter hello \family default : \end_layout \begin_layout LyX-Code gcc -g -m32 -masm=intel hello.o -o hello \end_layout \end_inset : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Symbol table '.symtab' contains 75 entries: \end_layout \begin_layout LyX-Code Num: Value Size Type Bind Vis Ndx Name \end_layout \begin_layout LyX-Code 0: 00000000 0 NOTYPE LOCAL DEFAULT UND \end_layout \begin_layout LyX-Code 1: 08048154 0 SECTION LOCAL DEFAULT 1 \end_layout \begin_layout LyX-Code 2: 08048168 0 SECTION LOCAL DEFAULT 2 \end_layout \begin_layout LyX-Code 3: 08048188 0 SECTION LOCAL DEFAULT 3 \end_layout \begin_layout LyX-Code ....output omitted... \end_layout \begin_layout LyX-Code 64: \color blue 08048409 \color inherit 6 FUNC GLOBAL DEFAULT 14 \color red foo \end_layout \begin_layout LyX-Code 65: 0804a020 0 NOTYPE GLOBAL DEFAULT 26 _end \end_layout \begin_layout LyX-Code 66: 080482e0 0 FUNC GLOBAL DEFAULT 14 _start \end_layout \begin_layout LyX-Code 67: 08048488 4 OBJECT GLOBAL DEFAULT 16 _fp_hw \end_layout \begin_layout LyX-Code 68: \color blue 0804a01c \color inherit 4 OBJECT GLOBAL DEFAULT 26 \color red i \end_layout \begin_layout LyX-Code 69: 0804a018 0 NOTYPE GLOBAL DEFAULT 26 __bss_start \end_layout \begin_layout LyX-Code 70: \color blue 080483db \color inherit 46 FUNC GLOBAL DEFAULT 14 \color red main \end_layout \begin_layout LyX-Code ...ouput omitted... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Unlike the values of the symbols \family typewriter \color red foo \family default \color inherit , \family typewriter \color red i \family default \color inherit and \family typewriter \color red main \family default \color inherit as in the hello.o object file, the complete memory addresses are in place. \end_layout \end_deeper \end_deeper \begin_layout Standard Now it suffices to understand relocation types. Previously, we mentioned the type \family typewriter \color green R_386_PC32 \family default \color inherit . The following formula is applied for relocation (Inteli386 psABI): \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align center \begin_inset Formula $Relocated\,Offset=S+A-P$ \end_inset \end_layout \begin_layout Standard where \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout S \end_layout \end_inset represents the value of the symbol. In the final executable binary, it is the address of the symbol. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout A \end_layout \end_inset represents the addend, an extra value added to the value of a symbol. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout P \end_layout \end_inset Represents the memory address to be fixed. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout Relocate \begin_inset space ~ \end_inset Offset \end_layout \end_inset is the distance between a relocating location \begin_inset Foot status collapsed \begin_layout Plain Layout where the referenced memory address is to be fixed. \end_layout \end_inset and the actual memory location of a symbol definition, or a memory address. \end_layout \begin_layout Standard But why do we waste time in calculating a distance instead of replacing with a direct memory address? The reason is that x86 architecture does not use employ any addressing mode that uses an absolute memory address, as listed in table \begin_inset CommandInset ref LatexCommand ref reference "mod-rm-32" \end_inset . All addressing modes in x86 are relative. In some assembly language, an absolute address can be used simply because it is a syntactic sugar that is later transformed into one of the relative addressing mode provided by the x86 hardware by the assembler. \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example For the \family typewriter foo \family default symbol: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 000000 \color blue 1c \color inherit 00000a02 R_386_PC32 000000 \color cyan 2e \color inherit foo \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The distance between the usage of \family typewriter foo \family default in \family typewriter main.o \family default and its definition, applying the formula \begin_inset Formula $S+A-P$ \end_inset is: \begin_inset Formula $\mathtt{2e+0-1c=12}$ \end_inset . That is, the place where memory fixing starts is \family typewriter 0x12 \family default or 18 bytes away from \emph on the definition \emph default of the symbol \family typewriter foo \family default . However, to make an instruction works properly, we must also subtract 4 from \family typewriter 0x12 \family default and results in \family typewriter 0xe \family default . Why the extra \family typewriter -4 \family default ? Because the relative address starts at \emph on the end \emph default of an instruction, \emph on not the address where memory fixing starts \emph default . For that reason, we must also exclude the 4 bytes of the overwritten address. \end_layout \begin_layout Standard Indeed, looking at the \family typewriter objdump \family default output of the object file \family typewriter hello.o \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Disassembly of section .text: \end_layout \begin_layout LyX-Code 00000000
: \end_layout \begin_layout LyX-Code 0: 8d 4c 24 04 lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 4: 83 e4 f0 and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 7: ff 71 fc push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code a: 55 push ebp \end_layout \begin_layout LyX-Code b: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code d: 51 push ecx \end_layout \begin_layout LyX-Code e: 83 ec 04 sub esp,0x4 \end_layout \begin_layout LyX-Code 11: c7 05 00 00 00 00 05 mov DWORD PTR ds:0x0,0x5 \end_layout \begin_layout LyX-Code 18: 00 00 00 \end_layout \begin_layout LyX-Code \color red 1b \color inherit : e8 \color blue fc ff ff ff \color inherit call \color blue 1c \color inherit \end_layout \begin_layout LyX-Code 20: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code 25: 83 c4 04 add esp,0x4 \end_layout \begin_layout LyX-Code 28: 59 pop ecx \end_layout \begin_layout LyX-Code 29: 5d pop ebp \end_layout \begin_layout LyX-Code 2a: 8d 61 fc lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 2d: c3 ret \end_layout \begin_layout LyX-Code 0000002e : \end_layout \begin_layout LyX-Code \color red 2e \color inherit : 55 push ebp \end_layout \begin_layout LyX-Code 2f: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code 31: 90 nop \end_layout \begin_layout LyX-Code 32: 5d pop ebp \end_layout \begin_layout LyX-Code 33: c3 ret \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The place where memory fixing starts is after the opcode \family typewriter e8 \family default , with the mock value \family typewriter \color blue fc ff ff ff \family default \color inherit , which is \family typewriter -4 \family default in decimal. However, the assembly code, the value is displayed as \family typewriter 1c \family default . The memory address right after \family typewriter e8 \family default . The reason is that the instruction \family typewriter e8 \family default starts at \family typewriter 1b \family default and ends at \family typewriter 20 \family default \begin_inset Foot status collapsed \begin_layout Plain Layout The end of an instruction is the memory address right after its last operand. The whole instruction e8 spans from the address \family typewriter 1b \family default to the address \family typewriter 1f \family default . \end_layout \end_inset . \family typewriter -4 \family default means 4 bytes backward from the end of instruction, that is: \begin_inset Formula $\mathtt{20-4=1c}$ \end_inset . After linking, the output of the final executable file is displayed with the actual memory fixing: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 080483db
: \end_layout \begin_layout LyX-Code 80483db: 8d 4c 24 04 lea ecx,[esp+0x4] \end_layout \begin_layout LyX-Code 80483df: 83 e4 f0 and esp,0xfffffff0 \end_layout \begin_layout LyX-Code 80483e2: ff 71 fc push DWORD PTR [ecx-0x4] \end_layout \begin_layout LyX-Code 80483e5: 55 push ebp \end_layout \begin_layout LyX-Code 80483e6: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code 80483e8: 51 push ecx \end_layout \begin_layout LyX-Code 80483e9: 83 ec 04 sub esp,0x4 \end_layout \begin_layout LyX-Code 80483ec: c7 05 1c a0 04 08 05 mov DWORD PTR ds:0x804a01c,0x5 \end_layout \begin_layout LyX-Code 80483f3: 00 00 00 \end_layout \begin_layout LyX-Code \color red 80483f6 \color inherit : e8 \color blue 0e \color inherit \color blue 00 00 00 \color inherit call \color blue 8048409 \color inherit \end_layout \begin_layout LyX-Code 80483fb: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code 8048400: 83 c4 04 add esp,0x4 \end_layout \begin_layout LyX-Code 8048403: 59 pop ecx \end_layout \begin_layout LyX-Code 8048404: 5d pop ebp \end_layout \begin_layout LyX-Code 8048405: 8d 61 fc lea esp,[ecx-0x4] \end_layout \begin_layout LyX-Code 8048408: c3 ret \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code 08048409 : \end_layout \begin_layout LyX-Code \color blue 8048409 \color inherit : 55 push ebp \end_layout \begin_layout LyX-Code 804840a: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code 804840c: 90 nop \end_layout \begin_layout LyX-Code 804840d: 5d pop ebp \end_layout \begin_layout LyX-Code 804840e: c3 ret \end_layout \begin_layout LyX-Code 804840f: 90 nop \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard In the final output, the opcode \family typewriter e8 \family default previously at \family typewriter 1b \family default now starts at the address \family typewriter \color red 80483f6 \family default \color inherit . The mock value \family typewriter \color blue fc ff ff ff \family default \color inherit is replaced with the actual value \family typewriter \color blue 0e \color inherit \color blue 00 00 00 \family default \color inherit using the same calculating method from its object file: opcode e8 is at \family typewriter \color red 80483f6 \family default \color inherit . The definition of \family typewriter foo \family default is at \family typewriter \color blue 8048409 \family default \color inherit . The offset from the next address after e8 is \family typewriter \begin_inset Formula $\mathtt{8048409+0-80483f7-4=0e}$ \end_inset \family default . However, for readability, the assembly is displayed as \family typewriter call \color blue 8048409 \color inherit \family default , since \family typewriter GNU as \begin_inset Foot status collapsed \begin_layout Plain Layout Or any current assembler in use today. \end_layout \end_inset \family default assembler allows specifying the actual memory address of a symbol definition. Such address is later translated into relative addressing mode, saving the programmer the trouble of calculating offset manually. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Subsection Sym. \begin_inset space ~ \end_inset Name \end_layout \begin_layout Standard This field displays the name of a symbol to be relocated. The named symbol is the same as written in a high level language such as C. \end_layout \begin_layout Section Crafting ELF binary with linker scripts \end_layout \begin_layout Standard A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on linker \end_layout \end_inset linker \begin_inset Index idx status open \begin_layout Plain Layout linker \end_layout \end_inset \emph default is a program that combines separated object files into a final binary file. When \family typewriter gcc \family default is invoked, it runs \family typewriter ld \family default underneath to turn object files into the final executable file.. \end_layout \begin_layout Standard A \emph on \begin_inset Index idx status open \begin_layout Plain Layout linker script \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \series bold \emph on linker script \end_layout \end_inset linker script \emph default is a text file that instructs how a linker should combine object files. When \family typewriter gcc \family default runs, it uses its default linker script to build the memory layout of a compiled binary file. Standardized memory layout is called \emph on object file format \emph default e.g. ELF includes program headers, section headers and their attributes. The default linker script is made for running in the current operating system environment \begin_inset Foot status collapsed \begin_layout Plain Layout To view the default script, use \family typewriter --verbose \family default option: \end_layout \begin_layout LyX-Code ld --verbose \end_layout \end_inset . Running on bare metal, the default script cannot be used as it is not designed for such environment. For that reason, a programmer needs to supply his own linker script for such environments. \end_layout \begin_layout Standard Every linker script consists of a series of commands with the following format: \end_layout \begin_layout LyX-Code COMMAND \end_layout \begin_layout LyX-Code { \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code sub-command 1 \end_layout \begin_layout LyX-Code sub-command 2 \end_layout \begin_layout LyX-Code .... more sub-command.... \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout Standard Each sub-command is specific to only the top-level command. The simplest linker script needs only one command: \family typewriter SECTION \family default , that consumes input sections from object files and produces output sections of the final binary file \begin_inset Foot status collapsed \begin_layout Plain Layout Recall that sections are chunks of code or data, or both. \end_layout \end_inset . \end_layout \begin_layout Subsection Example linker script \end_layout \begin_layout Standard Here is a minimal example of a linker script: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout SECTIONS /* Command */ \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout . = 0x10000; /* sub-command 1 */ \end_layout \begin_layout Plain Layout .text : { *(.text) } /* sub-command 2 */ \end_layout \begin_layout Plain Layout . = 0x8000000; /* sub-command 3 */ \end_layout \begin_layout Plain Layout .data : { *(.data) } /* sub-command 4 */ \end_layout \begin_layout Plain Layout .bss : { *(.bss) } /* sub-command 5 */ \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \series bold Code Dissection: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{table*} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Code \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter SECTION \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Top-level command that declares a list of custom program sections. \family typewriter ld \family default provides a set of such commands. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter . = 0x10000; \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Set location counter to the address \family typewriter 0x10000 \family default . Location counter specifies the base address for subsequent commands. In this example, subsequent commands will use \family typewriter 0x10000 \family default onward. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter .text : { *(.text) } \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Since location counter is set to \family typewriter 0x10000 \family default , the output \family typewriter .text \family default in the final binary file will starts at the address \family typewriter 0x10000 \family default . This command combines all \family typewriter .text \family default sections from all object files with \family typewriter *(.text) \family default syntax into a final \family typewriter .text \family default section. The \family typewriter * \family default is the wildcard which matches any file name. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter . = 0x8000000; \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Again, the location counter is set to \family typewriter 0x8000000 \family default . Subsequent commands will use this address for working with sections. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter .data : { *(.data) } \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout All \family typewriter .data \family default section are combined into one \family typewriter .data \family default section in the final binary file. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter .bss : { *(.bss) } \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout All \family typewriter .bss \family default section are combined into one \family typewriter .bss \family default section in the final binary file. \end_layout \end_inset \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{table*} \end_layout \end_inset \end_layout \begin_layout Standard The addresses \family typewriter 0x10000 \family default and \family typewriter 0x8000000 \family default are called \emph on Virtual Memory Address \emph default . A \emph on \begin_inset Index idx status collapsed \begin_layout Plain Layout virtual memory address \end_layout \end_inset \begin_inset Marginal status collapsed \begin_layout Plain Layout \emph on virtual memory address \end_layout \end_inset virtual memory address \emph default is the address where a section is loaded in memory when a program runs. To use the linker script, we save it as a file e.g. \family typewriter main.lds \family default \begin_inset Foot status collapsed \begin_layout Plain Layout \family typewriter .lds \family default is the extension for linker script. \end_layout \end_inset ; then, we need a sample program in a file, e.g. \family typewriter main.c \family default : \end_layout \begin_layout Standard \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4,title={\texttt{main.c}}" inline false status open \begin_layout Plain Layout void test() {} \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard Then, we compile the file and explicitly invoke \family typewriter ld \family default with the linker script: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc -m32 -g -c main.c \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard In the \family typewriter ld \family default command, the options are similar to \family typewriter gcc \family default : \end_layout \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Option \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter -m \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Specify object file format that \family typewriter ld \family default produces. In the example, elf_i386 means a 32-bit ELF is to be produced. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter -o \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Specify the name of the final executable binary. \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter -T \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Specify the linker script to use. In the example, it is \family typewriter main.lds \family default . \end_layout \end_inset \end_inset \end_layout \begin_layout Standard The remaining input is a list of object files for linking. After the command \family typewriter ld \family default is executed, the final executable binary - \family typewriter main \family default - is produced. If we try running it: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ./main \end_layout \begin_layout Standard \family typewriter Segmentation fault \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The reason is that when linking manually, the entry address must be explicitly set, or else \family typewriter ld \family default sets it to the start of \family typewriter .text \family default section by default. We can verify from the \family typewriter readelf \family default output: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -h main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ELF Header: \end_layout \begin_layout LyX-Code Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 \end_layout \begin_layout LyX-Code Class: ELF64 \end_layout \begin_layout LyX-Code Data: 2's complement, little endian \end_layout \begin_layout LyX-Code Version: 1 (current) \end_layout \begin_layout LyX-Code OS/ABI: UNIX - System V \end_layout \begin_layout LyX-Code ABI Version: 0 \end_layout \begin_layout LyX-Code Type: EXEC (Executable file) \end_layout \begin_layout LyX-Code Machine: Advanced Micro Devices X86-64 \end_layout \begin_layout LyX-Code Version: 0x1 \end_layout \begin_layout LyX-Code Entry point address: \color red 0x10000 \end_layout \begin_layout LyX-Code Start of program headers: 64 (bytes into file) \end_layout \begin_layout LyX-Code Start of section headers: 2098144 (bytes into file) \end_layout \begin_layout LyX-Code Flags: 0x0 \end_layout \begin_layout LyX-Code Size of this header: 64 (bytes) \end_layout \begin_layout LyX-Code Size of program headers: 56 (bytes) \end_layout \begin_layout LyX-Code Number of program headers: 3 \end_layout \begin_layout LyX-Code Size of section headers: 64 (bytes) \end_layout \begin_layout LyX-Code Number of section headers: 14 \end_layout \begin_layout LyX-Code Section header string table index: 11 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The entry point address is set to \family typewriter \color red 0x10000 \family default \color inherit , which is the beginning of \family typewriter .text \family default section. Using objdump to examine the address: \end_layout \begin_layout Standard \noindent \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -z -M intel -S -D prog | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard we see that the address \family typewriter 0x10000 \family default does not start at \family typewriter main \family default function when the program runs: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Disassembly of section .text: \end_layout \begin_layout LyX-Code \color red 00010000 : \end_layout \begin_layout LyX-Code int a = 5; \end_layout \begin_layout LyX-Code int i; \end_layout \begin_layout LyX-Code void \color red test \color inherit (){} \end_layout \begin_layout LyX-Code 10000: 55 push ebp \end_layout \begin_layout LyX-Code 10001: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code 10003: 90 nop \end_layout \begin_layout LyX-Code 10004: 5d pop ebp \end_layout \begin_layout LyX-Code 10005: c3 ret \end_layout \begin_layout LyX-Code \color blue 00010006
: \end_layout \begin_layout LyX-Code int \color blue main \color inherit (int argc, char *argv[]) \end_layout \begin_layout LyX-Code { \end_layout \begin_layout LyX-Code 10006: 55 push ebp \end_layout \begin_layout LyX-Code 10007: 89 e5 mov ebp,esp \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code return 0; \end_layout \begin_layout LyX-Code 10009: b8 00 00 00 00 mov eax,0x0 \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code 1000e: 5d pop ebp \end_layout \begin_layout LyX-Code 1000f: c3 ret \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The start of . \family typewriter text \family default section at \family typewriter \color red 0x10000 \family default \color inherit is the function \family typewriter \color red test \family default \color inherit , not \family typewriter \color blue main \family default \color inherit ! To enable the program to run at \family typewriter \color blue main \family default \color inherit properly, we need to set the entry point in the linker script with the following line at the beginning of the file: \end_layout \begin_layout LyX-Code ENTRY(main) \end_layout \begin_layout Standard Recompile the executable binary file \family typewriter \color blue main \family default \color inherit again. This time, the output from \family typewriter readelf \family default is different: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ELF Header: \end_layout \begin_layout LyX-Code Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 \end_layout \begin_layout LyX-Code Class: ELF32 \end_layout \begin_layout LyX-Code Data: 2's complement, little endian \end_layout \begin_layout LyX-Code Version: 1 (current) \end_layout \begin_layout LyX-Code OS/ABI: UNIX - System V \end_layout \begin_layout LyX-Code ABI Version: 0 \end_layout \begin_layout LyX-Code Type: EXEC (Executable file) \end_layout \begin_layout LyX-Code Machine: Intel 80386 \end_layout \begin_layout LyX-Code Version: 0x1 \end_layout \begin_layout LyX-Code Entry point address: \color blue 0x10006 \end_layout \begin_layout LyX-Code Start of program headers: 52 (bytes into file) \end_layout \begin_layout LyX-Code Start of section headers: 9168 (bytes into file) \end_layout \begin_layout LyX-Code Flags: 0x0 \end_layout \begin_layout LyX-Code Size of this header: 52 (bytes) \end_layout \begin_layout LyX-Code Size of program headers: 32 (bytes) \end_layout \begin_layout LyX-Code Number of program headers: 3 \end_layout \begin_layout LyX-Code Size of section headers: 40 (bytes) \end_layout \begin_layout LyX-Code Number of section headers: 14 \end_layout \begin_layout LyX-Code Section header string table index: 11 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The program now executes code at the address \family typewriter \color red 0x10006 \family default \color inherit when it starts. \family typewriter \color blue 0x10006 \family default \color inherit is where \family typewriter \color blue main \family default \color inherit starts! To make sure we really starts at \family typewriter main \family default , we run the program with \family typewriter gdb \family default , set two breakpoints at \family typewriter main \family default and \family typewriter test \family default functions: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gdb ./main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code .... output omitted .... \end_layout \begin_layout LyX-Code Reading symbols from ./main...done. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) \color green b \color inherit \color red test \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Breakpoint 1 at 0x10003: file main.c, line 1. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) b \color blue main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Breakpoint 2 at 0x10009: file main.c, line 5. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) r \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Starting program: /tmp/main \end_layout \begin_layout LyX-Code Breakpoint 2, \color blue main \color inherit (argc=-11493, argv=0x0) at main.c:5 \end_layout \begin_layout LyX-Code 5 return 0; \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard As displayed in the output, \family typewriter gdb \family default stopped at the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset breakpoint first. Now, we run the program normally, without \family typewriter gdb \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ./main \end_layout \begin_layout Standard \family typewriter Segmentation fault \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard We still get a segmentation fault. It is to be expected, as we ran a custom binary without C runtime support from the operating system. The last statement in the \family typewriter main \family default function: \family typewriter return 0 \family default , simply returns to a random place \begin_inset Foot status collapsed \begin_layout Plain Layout Return address is above the current \family typewriter ebp \family default . However, when we enter \family typewriter main \family default , no return value is pushed on the stack. So, when return is executed, it simply retrieves any value above \family typewriter ebp \family default and use as a return address. \end_layout \end_inset . The C runtime ensures that the program exit properly. In Linux, the \family typewriter _exit() \family default function is implicitly called when \family typewriter main \family default returns. To fix this problem, we simply change the program to exit properly: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=C,numbers=left,showstringspaces=false,tabsize=4,title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout void test() {} \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout asm("mov eax, 0x1 \backslash n" \end_layout \begin_layout Plain Layout "mov ebx, 0x0 \backslash n" \end_layout \begin_layout Plain Layout "int 0x80"); \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard Inline assembly is required because interrupt \family typewriter 0x80 \family default is defined for system calls in Linux. Since the program uses no library, there is no other way to call system functions, aside from using assembly. However, when writing our operating system, we will not need such code, as there is no environment for exiting properly yet. \end_layout \begin_layout Standard Now that we can precisely control where the program runs initially, it is easy to bootstrap the kernel from the bootloader. Before we move on to the next section, note how \family typewriter readelf \family default and \family typewriter objdump \family default can be applied to debug a program even before it runs. \end_layout \begin_layout Subsection Understand the custom ELF structure \end_layout \begin_layout Standard In the example, we manage to create a runnable ELF executable binary from a custom linker script, as opposed to the default one provided by \family typewriter gcc \family default . To make it convenient to look into its structure: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -e main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter -e \family default option is the combination of 3 options \family typewriter -h -l -S \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ....... ELF header output omitted ....... \end_layout \begin_layout LyX-Code Section Headers: \end_layout \begin_layout LyX-Code [Nr] Name Type Addr Off Size ES Flg Lk Inf Al \end_layout \begin_layout LyX-Code [ 0] NULL 00000000 000000 000000 00 0 0 0 \end_layout \begin_layout LyX-Code \color red \color inherit [ 1] \color red .text \color inherit PROGBITS \color blue 00010000 \color inherit 001000 \color magenta 000010 \color inherit 00 AX 0 0 1 \end_layout \begin_layout LyX-Code [ 2] .eh_frame PROGBITS \color blue 00010010 \color inherit 001010 \color magenta 000058 \color inherit 00 A 0 0 4 \end_layout \begin_layout LyX-Code [ 3] .debug_info PROGBITS 00000000 001068 000087 00 0 0 1 \end_layout \begin_layout LyX-Code [ 4] .debug_abbrev PROGBITS 00000000 0010ef 000074 00 0 0 1 \end_layout \begin_layout LyX-Code [ 5] .debug_aranges PROGBITS 00000000 001163 000020 00 0 0 1 \end_layout \begin_layout LyX-Code [ 6] .debug_line PROGBITS 00000000 001183 000038 00 0 0 1 \end_layout \begin_layout LyX-Code [ 7] .debug_str PROGBITS 00000000 0011bb 000078 01 MS 0 0 1 \end_layout \begin_layout LyX-Code [ 8] .comment PROGBITS 00000000 001233 000034 01 MS 0 0 1 \end_layout \begin_layout LyX-Code [ 9] .shstrtab STRTAB 00000000 00133a 000074 00 0 0 1 \end_layout \begin_layout LyX-Code [10] .symtab SYMTAB 00000000 001268 0000c0 10 11 10 4 \end_layout \begin_layout LyX-Code [11] .strtab STRTAB 00000000 001328 000012 00 0 0 1 \end_layout \begin_layout LyX-Code Key to Flags: \end_layout \begin_layout LyX-Code W (write), A (alloc), X (execute), M (merge), S (strings) \end_layout \begin_layout LyX-Code I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) \end_layout \begin_layout LyX-Code O (extra OS processing required) o (OS specific), p (processor specific) \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code LOAD 0x001000 \color blue 0x00010000 \color inherit \color blue 0x00010000 \color inherit \color magenta 0x00068 \color inherit \color magenta 0x00068 \color inherit R E 0x1000 \end_layout \begin_layout LyX-Code GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 .text .eh_frame \end_layout \begin_layout LyX-Code 01 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The structure is incredibly simple. Both the segment and section listings can be contained within one screen. This is not the case with default ELF executable binary. From the output, there are only 11 sections, and only two are loaded at runtime: \family typewriter .text \family default and \family typewriter .eh_frame \family default because both section are assigned with an actual memroy addresses, \family typewriter \color blue 0x10000 \family default \color inherit and \family typewriter \color blue 0x10010 \family default \color inherit respectively. The remaining sections are assigned with \family typewriter 0 \family default \emph on in the final executable binary \emph default \begin_inset Foot status collapsed \begin_layout Plain Layout As opposed to the object files, where memory addresses are always 0 and only assigned with actual values in the linking process. \end_layout \end_inset , which mean they are not loaded at runtime. It makes sense, as those sections are related to versioning \begin_inset Foot status collapsed \begin_layout Plain Layout It is the .comment section. It can be viewed with the comment \family typewriter readelf -p .comment main \family default . \end_layout \end_inset , debugging \begin_inset Foot status collapsed \begin_layout Plain Layout The ones starts with \family typewriter .debug \family default prefix. \end_layout \end_inset and linking \begin_inset Foot status collapsed \begin_layout Plain Layout The symbol tables and string table. \end_layout \end_inset . \end_layout \begin_layout Standard The program segment header table is even simpler. It only contains 2 segments: \family typewriter LOAD \family default and \family typewriter GNU_STACK \family default . By default, if the linker script does not supply the instructions for building program segments, \family typewriter ld \family default provides reasonable default segments. As in this case, \family typewriter .text \family default should be in the \family typewriter LOAD \family default segment. \family typewriter GNU_STACK \family default segment is a GNU extension used by the Linux kernel to control the state of the program stack. We will not need this segment, along with \family typewriter .eh_frame \family default , which is for exception handling, as we write our own operating system from scratch. To achieve these goals, we will need to create our own program headers instead of letting \family typewriter ld \family default handles the task, and instruct ld to remove \family typewriter .eh_frame \family default . \end_layout \begin_layout Subsection Manipulate the program segments \end_layout \begin_layout Standard First, we need to craft our own program header table by using the following syntax: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout [ FILEHDR ] [ PHDRS ] [ AT ( address ) ] \end_layout \begin_layout Plain Layout [ FLAGS ( flags ) ] ; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter PHDRS \family default command, similar to \family typewriter SECTION \family default command, but for declaring a list of custom program segments with a predefined syntax. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout name \end_layout \end_inset is the header name for later referenced by a section declared in \family typewriter SECTION \family default command. \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout type \end_layout \end_inset is the ELF segment type, as described in section \begin_inset CommandInset ref LatexCommand formatted reference "sec:Program-header-table" \end_inset , with added prefix \family typewriter PT_ \family default . For example, instead of \family typewriter NULL \family default or \family typewriter LOAD \family default as displayed by \family typewriter readelf \family default , it is \family typewriter PT_NULL \family default or \family typewriter PT_LOAD \family default . \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example With only \family typewriter name \family default and \family typewriter type \family default , we can create any number of program segments. For example, we can add the \family typewriter NULL \family default program segment and remove the \family typewriter GNU_STACK \family default segment: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,numbers=left,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout null PT_NULL; \end_layout \begin_layout Plain Layout code PT_LOAD; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout SECTIONS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout . = 0x10000; \end_layout \begin_layout Plain Layout .text : { *(.text) } :code \end_layout \begin_layout Plain Layout . = 0x8000000; \end_layout \begin_layout Plain Layout .data : { *(.data) } \end_layout \begin_layout Plain Layout .bss : { *(.bss) } \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard The content of \family typewriter PHDRS \family default command tells that the final executable binary contains 2 program segments: \family typewriter NULL \family default and \family typewriter LOAD \family default . The \family typewriter NULL \family default segment is given the name \family typewriter null \family default and \family typewriter LOAD \family default segment given the name code to signify this \family typewriter LOAD \family default segment contains program code. Then, to put a section into a segment, we use the syntax \family typewriter : \family default , where \family typewriter phdr \family default is the name given to a segment earlier. In this example, \family typewriter .text \family default section is put into \family typewriter code \family default segment. We compile and see the result (assuming \family typewriter main.o \family default compiled earlier remains): \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x10000 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00010000 0x00010000 0x00010 0x00010 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Those 2 segments are now \family typewriter NULL \family default and \family typewriter LOAD \family default instead of \family typewriter LOAD \family default and \family typewriter GNU_STACK \family default . \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example We can add as many segments of the same type, as long as they are given different names: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,numbers=left,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout null1 PT_NULL; \end_layout \begin_layout Plain Layout null2 PT_NULL; \end_layout \begin_layout Plain Layout code1 PT_LOAD; \end_layout \begin_layout Plain Layout code2 PT_LOAD; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout SECTIONS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout . = 0x10000; \end_layout \begin_layout Plain Layout .text : { *(.text) } :code1 \end_layout \begin_layout Plain Layout .eh_frame : { *(.eh_frame) } :code2 \end_layout \begin_layout Plain Layout . = 0x8000000; \end_layout \begin_layout Plain Layout .data : { *(.data) } \end_layout \begin_layout Plain Layout .bss : { *(.bss) } \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard After amending the \family typewriter PHDRS \family default content earlier with this new segment listing, we put \family typewriter .text \family default into \family typewriter code1 \family default segment and \family typewriter .eh_frame \family default into \family typewriter code2 \family default segment, we compile and see the new segments: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x10000 \end_layout \begin_layout LyX-Code There are 4 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 \end_layout \begin_layout LyX-Code NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00010000 0x00010000 0x00010 0x00010 R E 0x1000 \end_layout \begin_layout LyX-Code LOAD 0x001010 0x00010010 0x00010010 0x00058 0x00058 R 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 \end_layout \begin_layout LyX-Code 02 .text \end_layout \begin_layout LyX-Code 03 .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Now \family typewriter .text \family default and \family typewriter .eh_frame \family default are in different segments. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout FILEHDR \end_layout \end_inset is an optional keyword, when added specifies that a program segment includes the ELF file header of the executable binary. However, this attribute should only added for the first program segment, as it drastically alters the size and starting address of a segment because the ELF header is always at the beginning of a binary file, recall that a segment starts at the address of its first content, which is in most of the cases (except for this case, which is the file header), the first section. \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "-4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example Adding the \family typewriter FILEHDR \family default keyword changes the size of \family typewriter NULL \family default segment: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout null PT_NULL FILEHDR; \end_layout \begin_layout Plain Layout code PT_LOAD; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout ..... content is the same ..... \end_layout \end_inset \end_layout \begin_layout Standard We link it again and see the result: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x10000 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code NULL 0x000000 0x00000000 0x00000000 \color red 0x00034 \color inherit \color red 0x00034 \color inherit R 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00010000 0x00010000 0x00068 0x00068 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard In previous examples, the file size and memory size of the \family typewriter NULL \family default section are always 0, now they are both \family typewriter 34 \family default bytes, which is the size of an ELF header. \end_layout \end_deeper \begin_layout Standard \begin_inset Separator parbreak \end_inset \end_layout \begin_layout Example If we assign \family typewriter FILEHDR \family default to a non-starting segment, its size and starting address changes significantly: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout null PT_NULL; \end_layout \begin_layout Plain Layout code PT_LOAD FILEHDR; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout ..... content is the same ..... \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x10000 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 \end_layout \begin_layout LyX-Code LOAD 0x000000 \color red 0x0000f000 \color inherit \color red 0x0000f000 \color inherit \color blue 0x01068 \color inherit \color blue 0x01068 \color inherit R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The size of the \family typewriter LOAD \family default segment in the previous example is only \family typewriter 0x68 \family default , the same size as the total sizes of \family typewriter .text \family default and \family typewriter .eh_frame \family default sections in it. But now, it is \family typewriter \color blue 0x01068 \family default \color inherit , got \family typewriter 0x1000 \family default bytes larger. What is the reason for these extra bytes? A simple answer: segment alignment. From the output, the alignment of this segment is \family typewriter 0x1000 \family default ; it means that regardless of which address is the start of this segment, it must be divisible by \family typewriter 0x1000 \family default . For that reason, the starting address of \family typewriter LOAD \family default is \family typewriter \color red 0xf000 \family default \color inherit because it is divisible by \family typewriter 0x1000 \family default . \end_layout \begin_layout Standard Another question arises: why is the starting address \family typewriter \color red 0xf000 \family default \color inherit instead of \family typewriter 0x10000 \family default ? \family typewriter .text \family default is the first section, which starts at \family typewriter 0x10000 \family default , so the segment should start at \family typewriter 0x10000 \family default . The reason is that we include \family typewriter FILEHDR \family default as part of the segment, it must expand to include the ELF file header, which is at the very start of an ELF executable binary. To satisfy this constraint and the alignment constraint, \family typewriter \color red 0xf000 \family default \color inherit is the closest address. Note that the virtual and physical memory addresses are the addresses at runtime, not the locations of the segment in the file on disk. As the \family typewriter FileSiz \family default field shows, the segment only consumes \family typewriter \color blue 0x1068 \family default \color inherit bytes on disk. Figure \begin_inset CommandInset ref LatexCommand formatted reference "LOAD_segment" \end_inset illustrates the difference between the memory layouts with and without \family typewriter FILEHDR \family default keyword. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \family typewriter LOAD \family default segment on disk and in memory. \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "LOAD_segment" \end_inset \end_layout \begin_layout Plain Layout \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Without \family typewriter \series bold FILEHDR \family default \series default . \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/08/no_FILEHDR.pdf scale 120 \end_inset \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout With \family typewriter \series bold FILEHDR \family default \series default . \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset Graphics filename images/08/with_FILEHDR.pdf scale 120 \end_inset \end_layout \end_inset \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Standard \begin_inset VSpace vfill \end_inset \end_layout \begin_layout Standard \begin_inset Newpage pagebreak \end_inset \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout PHDRS \end_layout \end_inset is an optional keyword, when added specifies that a program segment is a program segment header table. \end_layout \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "0ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example The first segment of the default executable binary generated by \family typewriter gcc \family default is a \family typewriter PHDR \family default since the program segment header table appears right after the ELF header. It is also a convenient segment to put the ELF header into using the \family typewriter FILEHDR \family default keyword. We replace the unused \family typewriter NULL \family default segment earlier with a \family typewriter PHDR \family default segment: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout headers PT_PHDR FILEHDR PHDRS; \end_layout \begin_layout Plain Layout code PT_LOAD FILEHDR; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout ..... content is the same ..... \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x10000 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code \color red PHDR \color inherit 0x000000 0x00000000 0x00000000 \color blue 0x00074 \color inherit \color blue 0x00074 \color inherit R 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00010000 0x00010000 0x00068 0x00068 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard As shown in the output, the first segment is of type \family typewriter \color red PHDR \family default \color inherit . Its size is \family typewriter \color blue 0x74 \family default \color inherit , which includes: \end_layout \begin_layout Itemize \family typewriter 0x34 \family default bytes for ELF header. \end_layout \begin_layout Itemize \family typewriter 0x40 \family default bytes for the program segment header table, with 2 entries, each is \family typewriter 0x20 \family default bytes (32 bytes) in length. \end_layout \begin_layout Standard The above number is consistent with ELF header output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ELF Header: \end_layout \begin_layout LyX-Code Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 \end_layout \begin_layout LyX-Code Class: ELF32 \end_layout \begin_layout LyX-Code ....... output omitted ...... \end_layout \begin_layout LyX-Code Size of this header: \color red 52 \color inherit (bytes) \series bold \size large --> 0x34 bytes \end_layout \begin_layout LyX-Code Size of program headers: \color red 32 \color inherit (bytes) \series bold \size large --> \size default \size large 0x20 bytes each program header \end_layout \begin_layout LyX-Code Number of program headers: \color red 2 \color inherit \series bold \size large --> \size default \size large 0x40 \series default \series bold bytes in total \end_layout \begin_layout LyX-Code Size of section headers: 40 (bytes) \end_layout \begin_layout LyX-Code Number of section headers: 12 \end_layout \begin_layout LyX-Code Section header string table index: 9 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout AT \begin_inset space ~ \end_inset ( \begin_inset space ~ \end_inset address \begin_inset space ~ \end_inset ) \end_layout \end_inset specifies the load memory address where the segment is placed. Every segment or section has a \emph on virtual memory address \emph default and a \emph on load memory address \emph default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Itemize A \emph on \begin_inset Marginal status open \begin_layout Plain Layout \emph on virtual memory address \end_layout \end_inset virtual memory address \begin_inset Index idx status open \begin_layout Plain Layout virtual memory address \end_layout \end_inset \emph default is a starting address of a segment or a section when a program is in memory and running. The memory address is called virtual because it does not map to the actual memory cell that corresponds to the address number, but any random memory cell, which depends on how the underlying operating system translates the address. For example, the virtual memory address \family typewriter 0x1 \family default might map to the memory cell with the physical address \family typewriter 0x1000 \family default . \end_layout \begin_layout Itemize A \emph on \begin_inset Index idx status open \begin_layout Plain Layout load memory address \end_layout \end_inset \begin_inset Marginal status open \begin_layout Plain Layout \emph on load memory address \end_layout \end_inset load memory address \emph default is the physical memory address, where a program is loaded but not yet running. \end_layout \begin_layout Standard The load memory address is specified by \family typewriter AT \family default syntax. Normally both types of addresses are the same, and the physical address can be ignored. They differ when loading and running are purposely divided into two distinct phases that require different address regions. \end_layout \begin_layout Standard For example, a program can be designed to load into a ROM \begin_inset Foot status open \begin_layout Plain Layout Read-Only Memory \end_layout \end_inset at a fixed address. But when loading into RAM for a bare-metal application or an operating system to use, the program needs a load address that accommodates the addressin g scheme of the target application or operating system. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "0ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example We can specify a load memory address for the segment \family typewriter LOAD \family default with AT syntax: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout headers PT_PHDR FILEHDR PHDRS AT(0x500); \end_layout \begin_layout Plain Layout code PT_LOAD; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout ..... content is the same ..... \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x4000 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 \color red 0x00000500 \color inherit 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00004000 0x00002000 0x00068 0x00068 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard It depends on an operating system whether to use the address or not. For our operating system, the virtual memory address and load are the same, so an explicit load address is none of our concern. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Description \begin_inset Flex Strong status open \begin_layout Plain Layout FLAGS \begin_inset space ~ \end_inset (flags) \end_layout \end_inset assigns permissions to a segment. Each flag is an integer that represents a permission and can be combined with OR operations. Possible values: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset Tabular \begin_inset Text \begin_layout Plain Layout \series bold Permission \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Value \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \series bold Description \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout R \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 1 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Readable \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout W \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 2 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Writable \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout E \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout \family typewriter 4 \end_layout \end_inset \begin_inset Text \begin_layout Plain Layout Executable \end_layout \end_inset \end_inset \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "0ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Example We can create a LOAD segment with Read, Write and Execute permissions enabled: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout headers PT_PHDR FILEHDR PHDRS AT(0x500); \end_layout \begin_layout Plain Layout code PT_LOAD FILEHDR FLAGS(0x1 | 0x2 | 0x4); \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout ..... content is the same ..... \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x0 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000500 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00000000 0x00000000 0x00010 0x00010 \color red RWE \color inherit 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text .eh_frame \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter LOAD \family default segment now gets all the \family typewriter \color red RWE \family default \color inherit permissions, as shown above. \begin_inset Separator latexpar \end_inset \end_layout \end_deeper \begin_layout Standard \noindent \align left \begin_inset CommandInset line LatexCommand rule offset "4ex" width "100col%" height "1.5pt" \end_inset \end_layout \begin_layout Standard Finally, we want to remove the \family typewriter .eh_frame \family default or any unwanted section, we add a special section called \family typewriter /DISCARD/ \family default : \end_layout \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout ... program segment header table remains the same ... \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout SECTIONS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout /* . = 0x10000; */ \end_layout \begin_layout Plain Layout .text : { *(.text) } :code \end_layout \begin_layout Plain Layout . = 0x8000000; \end_layout \begin_layout Plain Layout .data : { *(.data) } \end_layout \begin_layout Plain Layout .bss : { *(.bss) } \end_layout \begin_layout Plain Layout /DISCARD/ : { *(.eh_frame) } \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard Any section putting in \family typewriter /DISCARD/ \family default disappears in the final executable binary: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ld -m elf_i386 -o main -T main.lds main.o \end_layout \begin_layout Standard \family typewriter $ readelf -l main \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x0 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000500 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD 0x001000 0x00000000 0x00000000 0x00010 0x00010 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard As can be seen, \family typewriter .eh_frame \family default is nowhere to be found. \end_layout \begin_layout Section C Runtime: Hosted vs Freestanding \begin_inset CommandInset label LatexCommand label name "sec:C-Runtime" \end_inset \end_layout \begin_layout Standard The purpose of . \family typewriter init \family default , \family typewriter .init_array \family default , \family typewriter .fini_array \family default and \family typewriter .preinit_array \family default section is to initialize a C Runtime environment that supports the C standard libraries. Why does C need a runtime environment, when it is supposed to be a compiled language? The reason is that many of the standard functions depend on the underlying operating system, which is of itself a big runtime environment. For example, I/O related functions such as reading from keyboard with \family typewriter gets() \family default , reading from file with \family typewriter open() \family default , printing on screen with \family typewriter printf() \family default , managing system memory with \family typewriter malloc() \family default , \family typewriter free() \family default , etc. \end_layout \begin_layout Standard A C implementation cannot provide such routines without a running operating system, which is a \emph on hosted environment \emph default . A \emph on \begin_inset Index idx status open \begin_layout Plain Layout hosted environment \end_layout \end_inset hosted environment \emph default is a runtime environment that: \end_layout \begin_layout Itemize provides a default implementation of C libraries that includes system-dependent data and routines. \end_layout \begin_layout Itemize perform resource allocations to prepare an environment for a program to run. \end_layout \begin_layout Standard This process is similar to the hardware initialization process: \end_layout \begin_layout Itemize When first powered up, a desktop computer loads its basic system routines from a read-only memory stored on the motherboard. \end_layout \begin_layout Itemize Then, it starts initializing an environment, such as setting default values for various registers in CPU and devices, before executing the any code. \end_layout \begin_layout Standard In contrast, a \emph on \begin_inset Index idx status open \begin_layout Plain Layout freestanding environment \end_layout \end_inset freestanding environment \emph default is an environment that does not provide system-dependent data and routines. As a consequence, almost no C library exists and the environment can run code compiled written from pure C syntax. For a free standing environment to become a host environment, it must implement standard C system routines. But for a \emph on conforming \emph default freestanding environment, it only needs these header files available: \family typewriter \family default , \family typewriter \family default , \family typewriter \family default and \family typewriter \family default (according to GCC manual). \end_layout \begin_layout Standard For a typical desktop x86 program, C runtime environment is initialized by a compiler so a program runs normal. However, for an embedded platform where a program runs directly on it, this is not the case. The typical C runtime environment used in desktop operating systems cannot be used on the embedded platforms, because architectural differences and resource constraints. As such, the software writer must implement a custom C runtime environment suitable for the targeted platform. For the embedded platform, \end_layout \begin_layout Standard In writing our operating system, the first step is to create a freestanding environment before creating a hosted one. \end_layout \begin_layout Section Debuggable bootloader on bare metal \end_layout \begin_layout Standard Currently, the bootloader is compiled as a flat binary file. Although \family typewriter gdb \family default can display the assembly code, it is not always the same as the source code. In the assembly source code, there exists variable names and labels. These symbols are lost when compiled as a flat binary file, making debugging more difficult. Another issue is the mismatch between the written assembly source code and the displayed assembly source code. The written code might contain higher level syntax that is assembler-specific and is generated into lower-level assembly code as displayed by \family typewriter gdb \family default . Finally, with debug information available, the command \family typewriter next/n \family default and \family typewriter prev/p \family default can be used instead of \family typewriter ni \family default and \family typewriter si \family default . \end_layout \begin_layout Standard To enable debug information, we modify the bootloader Makefile: \end_layout \begin_layout Enumerate The bootloader must be compiled as a ELF binary. Open the Makefile in bootloader/ directory and change this line under \family typewriter $(BUILD_DIR)/%.o: %.asm \family default recipe: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4" inline false status open \begin_layout Plain Layout nasm -f bin $< -o $@ \end_layout \end_inset \end_layout \begin_layout Standard to this line: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4" inline false status open \begin_layout Plain Layout nasm -f elf $< -F dwarf -g -o $@ \end_layout \end_inset \end_layout \begin_layout Standard In the updated recipe, \family typewriter bin \family default format is replaced with \family typewriter elf \family default format to enable debugging information to be properly produced. \family typewriter -F \family default option specifies the debug information format, which is \family typewriter dwarf \family default in this case. Finally, \family typewriter -g \family default option causes \family typewriter nasm \family default to actually generate debug information in selected format. \end_layout \end_deeper \begin_layout Enumerate Then, \family typewriter ld \family default consumes the ELF bootloader binary and produces another ELF bootloader binary, with proper \family typewriter \family default starting memory address of \family typewriter .text \family default section that match the actual address of the bootloader at runtime, when QEMU virtual machine loads it at \family typewriter 0x7c00 \family default . We need \family typewriter ld \family default because when compiled by \family typewriter nasm \family default , the starting address is assumed to be \family typewriter 0 \family default , not \family typewriter 0x7c00 \family default . \end_layout \begin_layout Enumerate Finally, we use \family typewriter objcopy \family default to separate extract only the flat binary content as the original bootloader by adding this line to \family typewriter $(BUILD_DIR)/%.o: %.asm \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4" inline false status open \begin_layout Plain Layout objcopy -O binary $(BUILD_DIR)/bootloader.o.elf $@ \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter objcopy \family default , as its name implies, is a program that copies and translates object files. Here, we copy the original ELF bootloader and translate it into a flat binary file. \end_layout \end_deeper \begin_layout Standard The updated recipe should look like: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4" inline false status open \begin_layout Plain Layout $(BUILD_DIR)/%.o: %.asm \end_layout \begin_layout Plain Layout nasm -f elf $< -F dwarf -g -o $@ \end_layout \begin_layout Plain Layout ld -m elf_i386 -T bootloader.lds $@ -o $@.elf \end_layout \begin_layout Plain Layout objcopy -O binary $(BUILD_DIR)/bootloader.o.elf $@ \end_layout \end_inset \end_layout \begin_layout Standard Now we test the bootloader with debug information available: \end_layout \begin_layout Enumerate Start the QEMU machine: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ make qemu \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \end_deeper \begin_layout Enumerate Start \family typewriter gdb \family default with the debug information stored in \family typewriter bootloader.o.elf \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gdb build/bootloader/bootloader.o.elf \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard After getting into \family typewriter gdb \family default , press the \family typewriter Enter \family default key and if the sample \family typewriter .gdbinit \family default section \begin_inset CommandInset ref LatexCommand ref reference "subsec:Automate-debugging-steps" \end_inset is used, the output should look like: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ---Type to continue, or q to quit--- \end_layout \begin_layout LyX-Code [f000:fff0] 0x0000fff0 in ?? () \end_layout \begin_layout LyX-Code Breakpoint 1 at \color red 0x7c00 \color inherit : \color blue file bootloader.asm, line 6. \end_layout \begin_layout LyX-Code (gdb) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter gdb \family default now understand where the instruction at address \family typewriter \color red 0x7c00 \family default \color inherit is in the assembly source file, thanks to the debug information. \end_layout \end_deeper \begin_layout Section Debuggable program on bare metal \end_layout \begin_layout Standard The process of building a debug-ready executable binary is similar to that of a bootloader, except more involved. Recall that for a debugger to work properly, its debugging information must contain correct address mappings between memory addresses and the source code. \family typewriter gcc \family default stores such mapping information in DIE entries, in which it tells \family typewriter gdb \family default at which code address corresponds to a line in a source file, so that breakpoin ts work properly. \end_layout \begin_layout Standard But first, we need a sample C source file, a very simple one: \end_layout \begin_layout Standard \begin_inset listings lstparams "title={\texttt{os.c}}" inline false status open \begin_layout Plain Layout void main() {} \end_layout \end_inset \end_layout \begin_layout Standard Because this is a free standing environment, standard libraries that involve system functions such as \family typewriter printf() \family default would not work, because a C runtime does not exist. At this stage, the goal is to correctly jump to main with source code displayed properly in \family typewriter gdb \family default , so no fancy C code is needed yet. \end_layout \begin_layout Standard The next step is updating \family typewriter os/Makefile \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4" inline false status open \begin_layout Plain Layout BUILD_DIR=../build \end_layout \begin_layout Plain Layout OS=$(BUILD_DIR)/os \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout @| \backslash color{red} \backslash bfseries CFLAGS+=-ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3|@ \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout OS_SRCS := $(wildcard *.c) \end_layout \begin_layout Plain Layout OS_OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(OS_SRCS)) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout all: $(OS) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout $(BUILD_DIR)/%.o: %.c \end_layout \begin_layout Plain Layout gcc $(CFLAGS) -c $< -o $@ \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout $(OS): $(OS_OBJS) \end_layout \begin_layout Plain Layout ld -m elf_i386 -T@| \backslash color{blue} \backslash bfseries os.lds|@ $(OS_OBJS) -o $@ \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout clean: \end_layout \begin_layout Plain Layout rm $(OS_OBJS) \end_layout \end_inset \end_layout \begin_layout Standard We updated the Makefile with the following changes: \end_layout \begin_layout Itemize Add a \family typewriter CFLAGS \family default variable for passing options to \family typewriter gcc \family default . \end_layout \begin_layout Itemize Instead of the rule to build assembly source code earlier, it is replaced with a C version with a recipe to build C source files. The \family typewriter CFLAGS \family default variable makes the \family typewriter gcc \family default command in the recipe looks cleaner regardless how many options are added. \end_layout \begin_layout Itemize Add a linking command for building the final executable binary of the operating system with a custom linker script \family typewriter \color blue os.lds \family default \color inherit . \end_layout \begin_layout Standard Everything looks good, except for the linker script part. Why is it needed? The linker script is required for controlling at which physical memory address the operating system binary appears in the memory, so the linker can jump to the operating system code and execute it. To complete this requirement, the default linker script used by \family typewriter gcc \family default would not work as it assumes the compiled executable runs inside an existing operating system, while we are writing an operating system itself. \end_layout \begin_layout Standard The next question is, what will be the content in the linker script? To answer this question, we must understand what goals to achieve with the linker script: \end_layout \begin_layout Itemize For the bootloader to correctly jump to and execute the operating system code. \end_layout \begin_layout Itemize For \family typewriter gdb \family default to debug correctly with the operating system source code. \end_layout \begin_layout Standard To achieve the goals, we must devise a design of a suitable memory layout for the operating system. Recall that the bootloader developed in chapter \begin_inset CommandInset ref LatexCommand ref reference "chap:Bootloader" \end_inset can already load a simple binary compiled from the sample Assembly program \family typewriter sample.asm \family default . To load the operating system, we can simply throw binary compiled from \family typewriter sample.asm \family default with the binary compiled from \family typewriter os.c \family default above. \end_layout \begin_layout Standard If only it is that simple. The idea is correctly, but not enough. The goals implies the following constraints: \end_layout \begin_layout Enumerate The operating system code is written in C and compiled as an ELF executable binary. It means, the bootloader needs to retrieve correct entry address from the ELF header. \end_layout \begin_layout Enumerate To debug properly with \family typewriter gdb \family default , the debug info must contain correct mappings between instruction addresses and source code. \end_layout \begin_layout Standard Thanks to the understanding of ELF and DWARF acquire in the earlier chapters, we can certainly modify the bootloader and create an executable binary that satisfy the above constraint. We will solve these problems one by one. \end_layout \begin_layout Subsection Loading an ELF binary from a bootloader \end_layout \begin_layout Standard Earlier we examined that an ELF header contains a entry address of a program. That information is 0x18 bytes away from the beginning of an ELF header, according to \family typewriter man elf \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language=C,showstringspaces=false,tabsize=4" inline false status open \begin_layout Plain Layout typedef struct { \end_layout \begin_layout Plain Layout unsigned char e_ident[EI_NIDENT]; \end_layout \begin_layout Plain Layout uint16_t e_type; \end_layout \begin_layout Plain Layout uint16_t e_machine; \end_layout \begin_layout Plain Layout uint32_t e_version; \end_layout \begin_layout Plain Layout ElfN_Addr e_entry; \end_layout \begin_layout Plain Layout ElfN_Off e_phoff; \end_layout \begin_layout Plain Layout ElfN_Off e_shoff; \end_layout \begin_layout Plain Layout uint32_t e_flags; \end_layout \begin_layout Plain Layout uint16_t e_ehsize; \end_layout \begin_layout Plain Layout uint16_t e_phentsize; \end_layout \begin_layout Plain Layout uint16_t e_phnum; \end_layout \begin_layout Plain Layout uint16_t e_shentsize; \end_layout \begin_layout Plain Layout uint16_t e_shnum; \end_layout \begin_layout Plain Layout uint16_t e_shstrndx; \end_layout \begin_layout Plain Layout } ElfN_Ehdr; \end_layout \end_inset \end_layout \begin_layout Standard The offset from the start of the struct to the start of \family typewriter e_entry \family default is: \end_layout \begin_layout Itemize 16 bytes of \family typewriter e_ident[EI_NIDENT]: \family default \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout LyX-Code #define EI_NIDENT 16 \end_layout \end_deeper \begin_layout Itemize 2 bytes of e_type \end_layout \begin_layout Itemize 2 bytes of e_machine \end_layout \begin_layout Itemize 4 bytes of e_version \end_layout \begin_layout Standard \noindent \align center \begin_inset Formula \[ \mathtt{Offset=16+2+2+4=24=0x18} \] \end_inset \end_layout \begin_layout Standard \family typewriter e_entry \family default is of type \family typewriter ElfN_Addr \family default , in which \family typewriter N \family default is either \family typewriter 32 \family default or \family typewriter 64 \family default . We are writing 32-bit operating system, in this case \begin_inset Formula $N=32$ \end_inset and so \family typewriter ElfN_Addr \family default is \family typewriter Elf32_Addr \family default , which is 4 bytes long. \end_layout \begin_layout Example With any program, such as this simple one: \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset listings lstparams "title={\texttt{hello.c}}" inline false status open \begin_layout Plain Layout #include \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout int main(int argc, char *argv[]) \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout printf("hello world! \backslash n"); \end_layout \begin_layout Plain Layout return 0; \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard We can retrieve the entry address with a human-readable presentation using \family typewriter readelf \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gcc hello.c -o hello \end_layout \begin_layout Standard \family typewriter $ readelf -h hello \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ELF Header: \end_layout \begin_layout LyX-Code Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 \end_layout \begin_layout LyX-Code .... output omitted .... \end_layout \begin_layout LyX-Code Entry point address: \color red 0x400430 \end_layout \begin_layout LyX-Code .... output omitted .... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Or in raw binary with \family typewriter hd \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ hd hello | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| \end_layout \begin_layout LyX-Code 00000010 02 00 3e 00 01 00 00 00 \color red 30 04 40 00 \color inherit 00 00 00 00 |..>.....0.@.....| \end_layout \begin_layout LyX-Code ......... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The offset \family typewriter 0x18 \family default is the start of the least-significant byte of \family typewriter e_entry \family default , which is \family typewriter \color red 0x30 \family default \color inherit , followed by \color red 04 40 00 \color inherit , together in reverse makes the address \family typewriter \color red 0x00400430 \family default \color inherit . \end_layout \end_deeper \begin_layout Standard Now that we know where the position of the entry address in the ELF header, it is easy to modify the bootloader made in section \begin_inset CommandInset ref LatexCommand ref reference "subsec:Read-and-load" \end_inset to retrieve and jump to the address: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[x86masm]Assembler},basicstyle={\ttfamily},showstringspaces=false,tabsize=4,title={\texttt{bootloader.asm}},commentstyle={\color{mygray}\itshape},frame=shadowbox" inline false status open \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout ; Bootloader.asm \end_layout \begin_layout Plain Layout ; A Simple Bootloader \end_layout \begin_layout Plain Layout ;****************************************** \end_layout \begin_layout Plain Layout bits 16 \end_layout \begin_layout Plain Layout start: jmp boot \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ;; constant and variable definitions \end_layout \begin_layout Plain Layout msg db "Welcome to My Operating System!", 0ah, 0dh, 0h \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout boot: \end_layout \begin_layout Plain Layout cli ; no interrupts \end_layout \begin_layout Plain Layout cld ; all that we need to init \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout mov ax, 50h \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ;; set the buffer \end_layout \begin_layout Plain Layout mov es, ax \end_layout \begin_layout Plain Layout xor bx, bx \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout mov al, 2 ; read 2 sector \end_layout \begin_layout Plain Layout mov ch, 0 ; we are reading the second sector past us, \end_layout \begin_layout Plain Layout ; so its still on track 0 \end_layout \begin_layout Plain Layout mov cl, 2 ; sector to read (The second sector) \end_layout \begin_layout Plain Layout mov dh, 0 ; head number \end_layout \begin_layout Plain Layout mov dl, 0 ; drive number. Remember Drive 0 is floppy drive. \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout mov ah, 0x02 ; read floppy sector function \end_layout \begin_layout Plain Layout int 0x13 ; call BIOS - Read the sector \end_layout \begin_layout Plain Layout jmp @| \backslash color{blue} \backslash bfseries [500h + 18h]|@ ; jump and execute the sector! \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout hlt ; halt the system \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout ; We have to be 512 bytes. Clear the rest of the bytes with 0 \end_layout \begin_layout Plain Layout times 510 - ($-$$) db 0 \end_layout \begin_layout Plain Layout dw 0xAA55 ; Boot Signiture \end_layout \end_inset \end_layout \begin_layout Standard It is as simple as that! First, we load the operating system binary at \family typewriter 0x500 \family default , then we retrieve the entry address at the offset \family typewriter 0x18 \family default from \family typewriter 0x500 \family default , by first calculating the expression \begin_inset Formula $500h+18h=518h$ \end_inset to get the actual in-memory address, then retrieve the content by dereference it. \end_layout \begin_layout Standard The first part is done. For the next part, we need to build an ELF operating system image for the bootloader to load. The first step is to create a linker script: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout @| \backslash color{blue} \backslash bfseries ENTRY(main);|@ \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout headers PT_PHDR FILEHDR PHDRS; \end_layout \begin_layout Plain Layout code PT_LOAD; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout SECTIONS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout .text @| \backslash color{blue} \backslash bfseries 0x500|@: { *(.text) } :code \end_layout \begin_layout Plain Layout .data : { *(.data) } \end_layout \begin_layout Plain Layout .bss : { *(.bss) } \end_layout \begin_layout Plain Layout /DISCARD/ : { *(.eh_frame) } \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard The script is straight-forward and remains almost the same as before. The only differences are: \end_layout \begin_layout Itemize \family typewriter main \family default are explicitly specified as the entry point by specifying \family typewriter \color red ENTRY(main) \family default \color inherit . \end_layout \begin_layout Itemize . \family typewriter text \family default is explicitly specified with \family typewriter 0x500 \family default as its \emph on virtual memory address \emph default since we load the operating system image at \family typewriter \color blue 0x500 \family default \color inherit . \end_layout \begin_layout Standard After putting the script, we compile with \family typewriter make \family default and it should work smoothly: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ make clean; make \end_layout \begin_layout Standard \family typewriter $ readelf -l build/os/os \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point \color red 0x500 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD 0x000500 \color red 0x00000500 \color inherit \color red 0x00000500 \color inherit 0x00040 0x00040 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard All looks good, until we run it. We begin by starting the QEMU virtual machine: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ make qemu \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then, start \family typewriter gdb \family default and load the debug info (which is also in the same binary file) and set a breakpoint at \family typewriter main \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) symbol-file build/os/os \end_layout \begin_layout Standard \family typewriter Reading symbols from build/os/os...done. \end_layout \begin_layout Standard \family typewriter (gdb) b main \end_layout \begin_layout Standard \family typewriter Breakpoint 2 at 0x500 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Then we start the program: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) symbol-file build/os/os \end_layout \begin_layout Standard \family typewriter Reading symbols from build/os/os...done. \end_layout \begin_layout Standard \family typewriter (gdb) b main \end_layout \begin_layout Standard \family typewriter Breakpoint 2 at 0x500 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard Keep the programming running until it stops at \family typewriter main \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) c \end_layout \begin_layout Standard \family typewriter Continuing. \end_layout \begin_layout Standard \family typewriter [ 0:7c00] \end_layout \begin_layout Standard \family typewriter Breakpoint 1, 0x00007c00 in ?? () \end_layout \begin_layout Standard \family typewriter (gdb) c \end_layout \begin_layout Standard \family typewriter Continuing. \end_layout \begin_layout Standard \family typewriter [ 0: 500] \end_layout \begin_layout Standard \family typewriter Breakpoint 2, main () at main.c:1 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard At this point, we switch the layout to the C source code instead of the registers: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) layout split \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter layout split \family default creates a layout that consists of 3 smaller windows: \end_layout \begin_layout Itemize Source window at the top. \end_layout \begin_layout Itemize Assembly window in the middle. \end_layout \begin_layout Itemize Command window at the bottom. \end_layout \begin_layout Standard After the command, the layout should look like this: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ┌──main.c───────────────────────────────────────────────────────┐ \end_layout \begin_layout LyX-Code B+>│1 void main(){} │ \end_layout \begin_layout LyX-Code │2 │ \end_layout \begin_layout LyX-Code │3 │ \end_layout \begin_layout LyX-Code │4 │ \end_layout \begin_layout LyX-Code │5 │ \end_layout \begin_layout LyX-Code │6 │ \end_layout \begin_layout LyX-Code │7 │ \end_layout \begin_layout LyX-Code │8 │ \end_layout \begin_layout LyX-Code │9 │ \end_layout \begin_layout LyX-Code │10 │ \end_layout \begin_layout LyX-Code │11 │ \end_layout \begin_layout LyX-Code │12 │ \end_layout \begin_layout LyX-Code │13 │ \end_layout \begin_layout LyX-Code │14 │ \end_layout \begin_layout LyX-Code │15 │ \end_layout \begin_layout LyX-Code │16 │ \end_layout \begin_layout LyX-Code └───────────────────────────────────────────────────────────────┘ \end_layout \begin_layout LyX-Code B+>│ \color red 0x500
jg 0x547 \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x502 dec sp \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x503 inc si \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x504 add WORD PTR [bx+di],ax \color inherit │ \end_layout \begin_layout LyX-Code │0x506 add WORD PTR [bx+si],ax │ \end_layout \begin_layout LyX-Code │0x508 add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x50a add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x50c add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x50e add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x510 add al,BYTE PTR [bx+si] │ \end_layout \begin_layout LyX-Code │0x512 add ax,WORD PTR [bx+si] │ \end_layout \begin_layout LyX-Code │0x514 add WORD PTR [bx+si],ax │ \end_layout \begin_layout LyX-Code │0x516 add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x518 add BYTE PTR [di],al │ \end_layout \begin_layout LyX-Code │0x51a add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x51c xor al,0x0 │ \end_layout \begin_layout LyX-Code │0x51e add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code └───────────────────────────────────────────────────────────────┘ \end_layout \begin_layout LyX-Code remote Thread 1 In: main L1 PC: 0x500 \end_layout \begin_layout LyX-Code [f000:fff0] 0x0000fff0 in ?? () \end_layout \begin_layout LyX-Code Breakpoint 1 at 0x7c00 \end_layout \begin_layout LyX-Code (gdb) symbol-file build/os/os \end_layout \begin_layout LyX-Code Reading symbols from build/os/os...done. \end_layout \begin_layout LyX-Code (gdb) b main \end_layout \begin_layout LyX-Code Breakpoint 2 at 0x500: file main.c, line 1. \end_layout \begin_layout LyX-Code (gdb) c \end_layout \begin_layout LyX-Code Continuing. \end_layout \begin_layout LyX-Code [ 0:7c00] \end_layout \begin_layout LyX-Code Breakpoint 1, 0x00007c00 in ?? () \end_layout \begin_layout LyX-Code (gdb) c \end_layout \begin_layout LyX-Code Continuing. \end_layout \begin_layout LyX-Code [ 0: 500] \end_layout \begin_layout LyX-Code Breakpoint 2, main () at main.c:1 \end_layout \begin_layout LyX-Code (gdb) layout split \end_layout \begin_layout LyX-Code (gdb) \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Something wrong is going on here. It is not the generated assembly code for function call as it is known in section \begin_inset CommandInset ref LatexCommand ref reference "subsec:Function-Call-and" \end_inset . It is definitely wrong, verified with \family typewriter objdump \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -D build/os/os | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code /home/tuhdo/workspace/os/build/os/os: file format elf32-i386 \end_layout \begin_layout LyX-Code Disassembly of section .text: \end_layout \begin_layout LyX-Code 00000500
: \end_layout \begin_layout LyX-Code 500: 55 push %ebp \end_layout \begin_layout LyX-Code 501: 89 e5 mov %esp,%ebp \end_layout \begin_layout LyX-Code 503: 90 nop \end_layout \begin_layout LyX-Code 504: 5d pop %ebp \end_layout \begin_layout LyX-Code 505: c3 ret \end_layout \begin_layout LyX-Code .... remaining output omitted .... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The assembly code of \family typewriter main \family default is completely different. This is why understanding assembly code and its relation to high-level languages are important. Without the knowledge, we would have used \family typewriter gdb \family default as a simple source-level debugger without bother looking at the assembly code from the split layout. As a consequence, the true cause of the non-working code could never been discovered. \end_layout \begin_layout Subsection Debugging the memory layout \end_layout \begin_layout Standard What is the reason for the incorrect Assembly code in \family typewriter main \family default displayed by \family typewriter gdb \family default ? There can only be one cause: the bootloader jumped to the wrong addresses. But why was the address wrong? We made the \family typewriter .text \family default section at address \family typewriter 0x500 \family default , in which \family typewriter main \family default code is in the first byte for executing, and instructed the bootloader to retrieve the address at the offset \family typewriter 0x18 \family default , then jump to the entry address. \begin_inset Float marginfigure wide false sideways false status collapsed \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Memory state after loading 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector. \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "mem-state-bootloader" \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/08/mem_after_load_os.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard Then, it might be possible for the bootloader to load the operating system address at the wrong address. But then, we explicitly set the load address to \family typewriter 50h:00 \family default , which is \family typewriter 0x500 \family default , and so the correct address was used. After the bootloader loas the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector, the in-memory state should look like the figure \begin_inset CommandInset ref LatexCommand ref reference "mem-state-bootloader" \end_inset : \end_layout \begin_layout Standard Here is the problem: \family typewriter 0x500 \family default is the start of the ELF header. The bootloader actually loads the 2 \begin_inset script superscript \begin_layout Plain Layout nd \end_layout \end_inset sector, which stores the executable as a whole, to \family typewriter 0x500 \family default . Clearly, . \family typewriter text \family default section, where \family typewriter main \family default resides, is far from \family typewriter 0x500 \family default . Since the in-memory entry address of the executable binary is \family typewriter 0x500 \family default , \family typewriter .text \family default should be at \family typewriter \begin_inset Formula $\mathtt{0x500+0x500=0xa00}$ \end_inset \family default . However, the entry address recorded in the ELF header remains \family typewriter 0x500 \family default and as a result, the bootloader jumped there instead of \family typewriter 0xa00 \family default . This is one of the issues that must be fixed. \end_layout \begin_layout Standard The other issue is the mapping between debug info and the memory address. Because the debug info is compiled with the assumed offset \family typewriter 0x500 \family default that is the start of \family typewriter .text \family default section, but due to actual loading, the offset is pushed another \family typewriter 0x500 \family default bytes, making the address actually is at \family typewriter 0xa00 \family default . This memory mismatch renders the debug info useless. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout Wrong symbol-memory mappings in debug info. \end_layout \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/08/debug_info_bad_position.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard In summary, we have 2 problems to overcome: \end_layout \begin_layout Itemize Fix the entry address to account for the extra offset when loading into memory. \end_layout \begin_layout Itemize Fix the debug info to account for the extra offset when loading into memory. \end_layout \begin_layout Standard First, we need to know the actual layout of the compiled executable binary:l \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ readelf -l build/os/os \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point \color blue 0x500 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x000500 \color inherit \color blue 0x00000500 \color inherit 0x00000500 0x00040 0x00040 R E 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Notice the \family typewriter Offset \family default and the \family typewriter VirtAddress \family default fields: both have the same value. This is problematic, as the entry address and the memory addresses in the debug info depend on \family typewriter VirtAddr \family default field, but the \family typewriter Offset \family default having the same value destroys the validity of \family typewriter VirtAddr \family default \begin_inset Foot status collapsed \begin_layout Plain Layout The offset is the distance in bytes between the beginning of the file, the address 0, to the beginning address of a segment or a section. \end_layout \end_inset because it means that the real in-memory address will always be greater than the \family typewriter VirtAddr \family default . \end_layout \begin_layout Standard If we try to adjust the virtual memory address of the \family typewriter .text \family default section in the linker script \family typewriter os.lds \family default , whatever value we set also sets the \family typewriter Offset \family default to the same value, until we set it to some value equal or greater than \family typewriter 0x1074 \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x1074 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x000074 \color inherit \color blue 0x00001074 \color inherit 0x00001074 0x00006 0x00006 R E \color magenta 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard If we adjust the virtual address to \family typewriter 0x1073 \family default , both the \family typewriter Offset \family default and \family typewriter VirtAddr \family default still share the same value: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x1073 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x001073 \color inherit \color blue 0x00001073 \color inherit 0x00001073 0x00006 0x00006 R E \color magenta 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The key to answer such phenonemon is in the \family typewriter Align \family default field. The value \family typewriter 0x1000 \family default indicates that the offset address of the segment should be divisible by \family typewriter 0x1000 \family default , or if the distance between segment is divisible by \family typewriter 0x1000 \family default , the linker removes such distance to save the binary size. We can do some experiments to verify this claim \begin_inset Foot status collapsed \begin_layout Plain Layout All the outputs are produced by the command: \end_layout \begin_layout Plain Layout \family typewriter $ readelf -l build/os/os \end_layout \end_inset : \end_layout \begin_layout Itemize By setting the virtual address of \family typewriter .text \family default to \family typewriter 0x0 \family default to \family typewriter 0x73 \family default (in \family typewriter os.lds \family default ), the offset starts from \family typewriter 0x1000 \family default to \family typewriter 0x1073 \family default , accordingly. For example, by setting it to \family typewriter 0x0 \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x0 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 \color blue 0x00074 \color inherit 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x001000 \color inherit 0x00000000 0x00000000 0x00006 0x00006 R E \color magenta 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard By default, if we do not specify any virtual address, the offset stays at \family typewriter 0x1000 \family default because \family typewriter 0x1000 \family default is the perfect offset to satisfy the alignment constraint. Any addition from \family typewriter 0x1 \family default to \family typewriter 0x73 \family default makes the segment misaligned, but the linker keeps it anyway because it is told so. \end_layout \end_deeper \begin_layout Itemize By setting the virtual address of \family typewriter .text \family default to \family typewriter 0x74 \family default (in \family typewriter os.lds \family default ): \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point 0x74 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x000074 \color inherit 0x00000074 0x00000074 0x00006 0x00006 R E \color magenta 0x1000 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter PHDR \family default is \family typewriter 0x74 \family default bytes in size, so if \family typewriter LOAD \family default starts at \family typewriter 0x1074 \family default , the distance between the \family typewriter PHDR \family default segment and \family typewriter LOAD \family default segment is \family typewriter \begin_inset Formula $\mathtt{0x1074-0x74=0x1000}$ \end_inset \family default bytes. To save space, it removes that extra \family typewriter 0x1000 \family default bytes. \end_layout \end_deeper \begin_layout Itemize By setting the virtual address of \family typewriter .text \family default to any value between \family typewriter 0x75 \family default and \family typewriter 0x1073 \family default (in \family typewriter os.lds \family default ), the offset takes the exact values specified, as can be seen in the case of setting to \family typewriter 0x1073 \family default above. \end_layout \begin_layout Itemize By setting the virtual address of \family typewriter .text \family default to any value equal or greater than \family typewriter 0x1074 \family default : it starts all over again at \family typewriter 0x74 \family default , where the distance is equal to \family typewriter 0x1000 \family default bytes. \end_layout \begin_layout Standard Now we get a hint how to control the values of \family typewriter Offset \family default and \family typewriter VirtAddr \family default to produce a desired binary layout. What we need is to change the \family typewriter Align \family default field to a value with smaller value for finer grain control. It might work out with a binary layout like this: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point \color blue 0x600 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x000100 \color inherit \color blue 0x00000600 \color inherit 0x00000600 0x00006 0x00006 R E \color magenta 0x100 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout LyX-Code \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard The binary will look like figure \begin_inset CommandInset ref LatexCommand ref reference "fig-good-bin-layout" \end_inset in memory: \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout A good binary layout. \end_layout \end_inset \begin_inset CommandInset label LatexCommand label name "fig-good-bin-layout" \end_inset \end_layout \begin_layout Plain Layout \begin_inset space \hfill{} \end_inset \begin_inset Graphics filename images/08/binary_layout_good.pdf \end_inset \begin_inset space \hfill{} \end_inset \end_layout \end_inset \end_layout \begin_layout Standard If we set the \family typewriter Offset \family default field to \family typewriter 0x100 \family default from the beginning of the file and the \family typewriter VirtAddr \family default to \family typewriter 0x600 \family default , when loading in memory, the actual memory of .text is \begin_inset Formula $\mathtt{0x500+0x100=0x600}$ \end_inset ; \family typewriter 0x500 \family default is the memory location where the bootloader loads into the physical memory and \family typewriter 0x100 \family default is the offset from the end of ELF header to \family typewriter .text \family default . The entry address and the debug info will then take the value \family typewriter 0x600 \family default from the \family typewriter VirtAddr \family default field above, which totally matches the actual physical layout. We can do it by changing \family typewriter os.lds \family default as follow: \end_layout \begin_layout Standard \begin_inset listings lstparams "language=bash,showstringspaces=false,tabsize=4,title={\texttt{main.lds}}" inline false status open \begin_layout Plain Layout @| \backslash color{blue} \backslash bfseries ENTRY(main);|@ \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout PHDRS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout headers PT_PHDR FILEHDR PHDRS; \end_layout \begin_layout Plain Layout code PT_LOAD; \end_layout \begin_layout Plain Layout } \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout SECTIONS \end_layout \begin_layout Plain Layout { \end_layout \begin_layout Plain Layout .text @| \backslash color{blue} \backslash bfseries 0x600|@: @| \backslash color{magenta} ALIGN(0x100)|@ { *(.text) } :code \end_layout \begin_layout Plain Layout .data : { *(.data) } \end_layout \begin_layout Plain Layout .bss : { *(.bss) } \end_layout \begin_layout Plain Layout /DISCARD/ : { *(.eh_frame) } \end_layout \begin_layout Plain Layout } \end_layout \end_inset \end_layout \begin_layout Standard The \family typewriter ALIGN \family default keyword, as it implies, tells the linker to align a section, thus the segment containing it. However, to make the \family typewriter ALIGN \family default keyword has any effect, automatic alignment must be disabled. According to \family typewriter man ld \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code -n \end_layout \begin_layout LyX-Code --nmagic \end_layout \begin_layout LyX-Code Turn off page alignment of sections, and disable linking against shared \end_layout \begin_layout LyX-Code libraries. If the output format supports Unix style magic numbers, mark the \end_layout \begin_layout LyX-Code output as "NMAGIC" \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard That is, by default, each section is aligned by an operating system page, which is \family typewriter 4096 \family default , or \family typewriter 0x1000 \family default bytes in size. The \family typewriter -n \family default or \family typewriter -nmagic \family default option disables this behavior, which is needed. We amend the \family typewriter ld \family default command used in \family typewriter os/Makefile \family default : \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,title={\texttt{os/Makefile}}" inline false status open \begin_layout Plain Layout ..... above content omitted .... \end_layout \begin_layout Plain Layout $(OS): $(OS_OBJS) \end_layout \begin_layout Plain Layout ld -m elf_i386 @| \backslash color{red} \backslash bfseries -nmagic|@ -Tos.lds $(OS_OBJS) -o $@ \end_layout \end_inset \end_layout \begin_layout Standard Finally, we also need to update the top-level Makefile to write more than one sector into the disk image for the operating system binary, as its size exceeds one sector: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ ls -l build/os/os \end_layout \begin_layout Standard \family typewriter -rwxrwxr-x 1 tuhdo tuhdo \color red 9060 \color inherit Feb 13 21:37 build/os/os \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard We update the rule so that the sectors are automatically calculated: \begin_inset Separator latexpar \end_inset \end_layout \begin_layout Standard \noindent \align left \begin_inset listings lstparams "language={[gnu]make},tabsize=4,title={\texttt{os/Makefile}}" inline false status open \begin_layout Plain Layout ..... above content omitted .... \end_layout \begin_layout Plain Layout bootdisk: bootloader os \end_layout \begin_layout Plain Layout dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 \end_layout \begin_layout Plain Layout dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 \end_layout \begin_layout Plain Layout dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=$$(($(shell stat --printf= "%s" $(OS))/512)) seek=1 \end_layout \end_inset \end_layout \begin_layout Standard After updating the everything, recompiling the executable binary and we get the desired offset and virtual memory at \family typewriter 0x100 \family default and \family typewriter 0x600 \family default , respectively: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code Elf file type is EXEC (Executable file) \end_layout \begin_layout LyX-Code Entry point \color blue 0x600 \end_layout \begin_layout LyX-Code There are 2 program headers, starting at offset 52 \end_layout \begin_layout LyX-Code Program Headers: \end_layout \begin_layout LyX-Code Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align \end_layout \begin_layout LyX-Code PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 \end_layout \begin_layout LyX-Code LOAD \color red 0x000100 \color inherit \color blue 0x00000600 \color inherit 0x00000600 0x00006 0x00006 R E \color magenta 0x100 \end_layout \begin_layout LyX-Code Section to Segment mapping: \end_layout \begin_layout LyX-Code Segment Sections... \end_layout \begin_layout LyX-Code 00 \end_layout \begin_layout LyX-Code 01 .text \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Subsection Testing the new binary \end_layout \begin_layout Standard First, we start the QEMU machine: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ make qemu \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard In another terminal, we start \family typewriter gdb \family default , loading the debug info and set a breakpoint at \family typewriter main \family default : \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ gdb \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The following output should be produced: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ---Type to continue, or q to quit--- \end_layout \begin_layout LyX-Code [f000:fff0] 0x0000fff0 in ?? () \end_layout \begin_layout LyX-Code Breakpoint 1 at 0x7c00 \end_layout \begin_layout LyX-Code Breakpoint 2 at \color blue 0x600 \color inherit : file main.c, line 1. \end_layout \begin_layout LyX-Code \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Then, let \family typewriter gdb \family default runs until it hits the \family typewriter main \family default function, then we change to the split layout between source and assembly: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) layout split \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard The final terminal output should look like this: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code ┌──main.c───────────────────────────────────────────────────────┐ \end_layout \begin_layout LyX-Code B+>│1 void main(){} │ \end_layout \begin_layout LyX-Code │2 │ \end_layout \begin_layout LyX-Code │3 │ \end_layout \begin_layout LyX-Code │4 │ \end_layout \begin_layout LyX-Code │5 │ \end_layout \begin_layout LyX-Code │6 │ \end_layout \begin_layout LyX-Code │7 │ \end_layout \begin_layout LyX-Code │8 │ \end_layout \begin_layout LyX-Code │9 │ \end_layout \begin_layout LyX-Code │10 │ \end_layout \begin_layout LyX-Code │11 │ \end_layout \begin_layout LyX-Code │12 │ \end_layout \begin_layout LyX-Code │13 │ \end_layout \begin_layout LyX-Code │14 │ \end_layout \begin_layout LyX-Code │15 │ \end_layout \begin_layout LyX-Code │16 │ \end_layout \begin_layout LyX-Code └───────────────────────────────────────────────────────────────┘ \end_layout \begin_layout LyX-Code B+>│ \color red 0x600
push bp \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x601 mov bp,sp \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x603 nop \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x604 pop bp \color inherit │ \end_layout \begin_layout LyX-Code │ \color red 0x605 ret \color inherit │ \end_layout \begin_layout LyX-Code │0x606 aaa │ \end_layout \begin_layout LyX-Code │0x607 add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x609 add BYTE PTR [si],al │ \end_layout \begin_layout LyX-Code │0x60b add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x60d add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x60f add BYTE PTR [si],al │ \end_layout \begin_layout LyX-Code │0x611 add ax,bp │ \end_layout \begin_layout LyX-Code │0x613 push ss │ \end_layout \begin_layout LyX-Code │0x614 add BYTE PTR [bx+si],al │ \end_layout \begin_layout LyX-Code │0x616 or al,0x67 │ \end_layout \begin_layout LyX-Code │0x618 adc al,BYTE PTR [bx+si] │ \end_layout \begin_layout LyX-Code │0x61a add BYTE PTR [bx+si+0x2],al │ \end_layout \begin_layout LyX-Code └───────────────────────────────────────────────────────────────┘ \end_layout \begin_layout LyX-Code remote Thread 1 In: main L1 PC: 0x600 \end_layout \begin_layout LyX-Code (gdb) c \end_layout \begin_layout LyX-Code Continuing. \end_layout \begin_layout LyX-Code [ 0:7c00] \end_layout \begin_layout LyX-Code Breakpoint 1, 0x00007c00 in ?? () \end_layout \begin_layout LyX-Code (gdb) c \end_layout \begin_layout LyX-Code Continuing. \end_layout \begin_layout LyX-Code [ 0: 600] \end_layout \begin_layout LyX-Code Breakpoint 2, main () at main.c:1 \end_layout \begin_layout LyX-Code (gdb) layout split \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Now, the displayed assembly is the same as in \family typewriter objdump \family default , except the registers are 16-bit ones. This is normal, as \family typewriter gdb \family default is operating in 16-bit mode, while \family typewriter objdump \family default displays code in 32-bit mode. To make sure, we verify the raw opcode by using \family typewriter x \family default command: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter (gdb) x/16xb 0x600 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code 0x600
: \color red 0x55 0x89 0xe5 0x90 0x5d 0xc3 \color inherit 0x37 \end_layout \begin_layout LyX-Code 0x00 \end_layout \begin_layout LyX-Code 0x608: 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00 \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard From the assembly window, \family typewriter main \family default stops at the address \family typewriter 0x605 \family default . As such, the corresponding bytes from \family typewriter 0x600 \family default to \family typewriter 0x605 \family default are highlighted in red from the output of the command \family typewriter x/16xb 0x600 \family default . Then, the raw opcode from the \family typewriter objdump \family default output: \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \family typewriter $ objdump -z -M intel -S -D build/os/os | less \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shellcommand} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout LyX-Code build/os/os: file format elf32-i386 \end_layout \begin_layout LyX-Code Disassembly of section .text: \end_layout \begin_layout LyX-Code 00000600
: \end_layout \begin_layout LyX-Code void main(){} \end_layout \begin_layout LyX-Code 600: \color red 55 \color inherit push ebp \end_layout \begin_layout LyX-Code 601: \color red 89 e5 \color inherit mov ebp,esp \end_layout \begin_layout LyX-Code 603: \color red 90 \color inherit nop \end_layout \begin_layout LyX-Code 604: \color red 5d \color inherit pop ebp \end_layout \begin_layout LyX-Code 605: \color red c3 \color inherit ret \end_layout \begin_layout LyX-Code Disassembly of section .debug_info: \end_layout \begin_layout LyX-Code ...... output omitted ...... \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash end{shelloutput16.6} \end_layout \end_inset \end_layout \begin_layout Standard Both raw opcode displayed by the two programs are the same. In this case, it proved that \family typewriter gdb \family default correctly jumped to the address in \family typewriter main \family default for a proper debugging. This is an extremely important milestone. Being able to debug in bare metal will help tremendously in writing an operating system, as a debugger allows a programmer to inspect the internal state of a running machine at each step to verify his code, step by step, to gradually build up a solid understanding. Some professional programmers do not like debuggers, but it is because they understand their domain deep enough to not need to rely on a debugger to verify their code. When encountering new domains, a debugger is indispensable learning tool because of its verifiability. \end_layout \begin_layout Standard However, even with the aid of debugger, writing an operating system is still not a walk in the park. The debugger may give the access to the machine at one point in time, but it does not give the cause. To find out the root cause, is up to the ability of a programmer. Later in the book, we will learn how to use other debugging techniques, such as using QEMU logging facility to debug CPU exceptions. \end_layout \begin_layout Part Kernel Programming \end_layout \begin_layout Chapter x86 Descriptors \end_layout \begin_layout Section Basic operating system concepts \end_layout \begin_layout Standard The first and foremost, OS manages hardware resources. It's easy to see the core features of an OS based on Von Neumann diagram: \end_layout \begin_layout Description CPU \begin_inset space ~ \end_inset management: allows programs to share CPU for multitasking. \end_layout \begin_layout Description Memory \begin_inset space ~ \end_inset management: allocates enough storage for programs to run. \end_layout \begin_layout Description Devices \begin_inset space ~ \end_inset management: detects and communicates with different devices \end_layout \begin_layout Standard Any OS should be good at the above fundamentals tasks. \end_layout \begin_layout Standard Another important feature of an OS is to provide an software interface layer, that hides away hardware interfaces, to interface with applications that run on top of that OS. The benefits of such a layer: \end_layout \begin_layout Itemize reusability: that is, the same software API can be reused across programs, thus simplifying software development process \end_layout \begin_layout Itemize separation of concerns: bugs appear either in application programs, or in the OS; a programmer needs to isolate where the bugs are. \end_layout \begin_layout Itemize simplify software development process: provides an easier to use software interface layer with a uniform access to hardware resources across devices, instead of directly using the hardware interface of a particular device. \end_layout \begin_layout Subsection Hardware Abstraction Layer \end_layout \begin_layout Standard There are so many hardware devices out there, so it's best to leave the hardware engineers how the devices talk to an OS. To achieve this goal, the OS only provides a set of agreed software interfaces between itself and the device driver writers and is called \emph on Hardware Abstraction \emph default \emph on Layer \emph default . \end_layout \begin_layout Standard In C, this software interface is implemented through a structure function pointers. \end_layout \begin_layout Standard [illustrate with Linux example] \end_layout \begin_layout Subsection System programming interface \end_layout \begin_layout Standard \emph on System programming interfaces \emph default are standard interfaces that an OS provides application programs to use its services. For example, if a program wishes to read a file on disk, then it must call a function like \emph on open() \emph default and let the OS handle the details of talking to the hard disk for retrieving the file. \end_layout \begin_layout Subsection The need for an Operating System \end_layout \begin_layout Standard In a way, OS is an overhead, but a necessary one, for a user to tell a computer what to do. When resources in a computer system (CPU, GPU, memory, hard drive...) became big and more complicated, it's tedious to manually manage all the resources. \end_layout \begin_layout Standard Imagine we have to manually load programs on a computer with 3 \begin_inset space \thinspace{} \end_inset GB of RAM. We would have to load programs at various fix addresses, and for each program a size must be manually calculated to avoid wasting memory resource, and enough for programs to not overriding each other. \end_layout \begin_layout Standard Or, when we want to give computer input through the keyboard, without an OS, an application also has to carry code to facilitate the communication with keyboard hardware; each application then handles such keyboard communicati on on its own. Why should there be such duplications across applications for such standard feature? If you write an accounting software, why should a programmer concern writing a keyboard driver, totally irrelevant to the problem domain? \end_layout \begin_layout Standard That's why a crucial job of an OS is to hide the complexity of hardware devices, so a program is freed from the burden of maintaining its own code for hardware communication by having a standardized set of interfaces and thus, reduce potential bugs along with faster development time. \end_layout \begin_layout Standard To write an OS effectively, a programmer need to understand well the underlying computer architecture that programmer are writing an OS for. The first reason is, many OS concepts are supported by the architecture e.g. the concepts of virtual memory are well supported by x86 architecture. If the underlying computer architecture is not well-understood, OS developers are doomed to reinvent it in your OS, and such software-implemented solutions run slower than the hardware version. \end_layout \begin_layout Section Drivers \end_layout \begin_layout Standard Drivers are programs that enable an OS to communicate and use features of hardware devices. For example, a keyboard driver enables an OS to get input from keyboard; or a network driver allows a network card to send and receive data packets to and from the Internet. \end_layout \begin_layout Standard If you only write application programs, you may wonder how can software control hardware devices? As mentioned in Chapter 2, through the hardware-softw are interface: by writing to a device's registers or to write to ports of a device, through the use of CPU's instructions. \end_layout \begin_layout Section Userspace and kernel space \end_layout \begin_layout Standard \emph on Kernel space \emph default refers to the working environment of an OS that only the kernel can access. Kernel space includes the direct communication with hardware, or manipulate privileged memory regions (such as kernel code and data). \end_layout \begin_layout Standard In contrast, \emph on userspace \emph default refers to less privileged processes that run above the OS, and is supervised by the OS. To access the kernel facility, user program must go through the standardized system programming interfaces provided by the OS. \end_layout \begin_layout Section Memory Segment \end_layout \begin_layout Section Segment Descriptor \end_layout \begin_layout Section Types of Segment Descriptors \end_layout \begin_layout Subsection Code and Data descriptors \end_layout \begin_layout Subsection Task Descriptor \end_layout \begin_layout Subsection Interrupt Descriptor \end_layout \begin_layout Section Descriptor Scope \end_layout \begin_layout Subsection Global Descriptor \end_layout \begin_layout Subsection Local Descriptor \end_layout \begin_layout Section Segment Selector \end_layout \begin_layout Section Enhancement: Bootloader with descriptors \end_layout \begin_layout Chapter Process \end_layout \begin_layout Section Concepts \end_layout \begin_layout Section Process \end_layout \begin_layout Subsection Task \end_layout \begin_layout Standard A \emph on task \emph default is a unit of work that an OS needs to do, similar to how human have tasks to do daily. From a user point of view, a task for a computer to do can be web browsing, document editing, gaming, sending and receiving emails, etc. Since a CPU can only execute sequentially, one instruction after another (fetching from main memory), there must be some way to do many meaningful tasks at once. For that reason, the computer must share the resources e.g. registers, stack, memory, etc, between tasks, since we have many tasks but single and limited resources. \end_layout \begin_layout Subsection Process \end_layout \begin_layout Standard \emph on Process \emph default is a data structure that keeps track of the execution state of a task. Task is a general concept, and process is the implementation of a task. In a general-purpose OS, a task is usually a program. For example, when you run Firefox, a process structure is created to keep track of where the stack and the heap allocated for firefox are, where Firefox's code area is and which instruction EIP is holding to execute next, etc. The typical process structure looks like this: \end_layout \begin_layout Standard [insert process image] \end_layout \begin_layout Standard Process is a virtual computer, but much more primitive than the virtual machine in virtualization software like Virtual Box, and that's a good thing. Imagine having to run a full-fledged virtual machine for every task; how wasteful of machine resources that would be.. In the view of a running process, its code executes as if it runs directly on hardware. Each process has its own set of register values, which are kept tracked by the OS, and its own contiguous virtual memory space (which is discontiguous in actual physical memory). The code in a process is given virtual memory addresses to read and write from. \end_layout \begin_layout Standard [ illustrate: - a process looks like a mini Von Neumann - with contiguous memory, each with a color; each cell of a process mapped to distant memory cell in physical memory ] \end_layout \begin_layout Standard A process can run so much until the OS tells it to temporary stop for other tasks to use the hardware resources. The suspended process can then wait until further notice from the OS. This whole switching process is so fast that a computer user think his computer actually runs tasks in parallel. The program that does the switching between tasks is called a *scheduler*. \end_layout \begin_layout Subsection Scheduler \end_layout \begin_layout Standard An OS needs to perform a wide range of different functionalities, e.g. web browsing, document editing, gaming, etc. A \emph on scheduler \emph default decides which tasks got to run before the others and, for how long, in an efficient manner. Scheduler enables your computer to become a \emph on time sharing system \emph default , because tasks share CPU execution time and no one process can monopolize the CPU (in practice, it still happens regularly). Without a scheduler, only a single task can be performed at a time. \end_layout \begin_layout Subsection Context switch \end_layout \begin_layout Standard When a process is prepared to be switched out for another process to take its place, certain hardware resources i.e. current open files, current register values, etc. must be backed up to later resume that process's execution. \end_layout \begin_layout Subsection Priority \end_layout \begin_layout Standard \emph on Priority \emph default is an important metric for OS to decide which task is scheduled to run before the others to allocate appropriate CPU execution time for each task. \end_layout \begin_layout Subsection Preemptive vs Non-preemptive \end_layout \begin_layout Standard A \emph on preemptive \emph default OS can interrupt an executing process and switch to another process. \end_layout \begin_layout Standard A \emph on non-preemtive \emph default OS, a task runs until its completion. \end_layout \begin_layout Subsection Process states \end_layout \begin_layout Standard \emph on State \emph default is a particular condition of a process, triggered by an action from the scheduler. A process goes through various states during its life cycle. A process typically has these states: \end_layout \begin_layout Description Run indicating CPU is executing code in this process. \end_layout \begin_layout Description Sleep (or Suspended): indicating CPU is executing some process else. \end_layout \begin_layout Description Destroyed: process is done and waiting to be destroyed completely. \end_layout \begin_layout Subsection procfs \end_layout \begin_layout Section Threads \end_layout \begin_layout Standard \emph on Threads \emph default are units of work inside a process that shares the execution environment. A process creates a whole new execution environment with code of its own: \end_layout \begin_layout Standard [illustration between process and thread, with each process is a big rectangle box and threads nested boxes point to different code region] \end_layout \begin_layout Standard Instead of creating a completely new process structure in memory, OS simply let the thread uses some of the resources of the parent process that created it. A thread has its own registers, program counter, stack pointer, and its own call stack. Everything else is shared between the threads, such as an address space, heap, static data, and code segments, and file descriptors. Because thread simply reuses existing resources and involve no context switching, it is much faster to create and switch between processes. \end_layout \begin_layout Standard However, note that the above scheme is just an implementation of thread concept. You can completely treat thread the same as process (hence you can call all processes threads and vice versa). Or you can just back up some resources, whlie leaving some resources shared. It's up to the OS designer to distinguish between threads and processes. Threads are usually implemented as a component of a process. \end_layout \begin_layout Standard On Linux, a thread is simply a process that shares resources with its parent process; for that reason, a Linux thread is also called *light-weight process*. Or put it another way, a thread in Linux is merely an implementation of a single-threaded process that execute its main program code. A multi-threaded program in Linux is just a process with shared with its single-threaded children processes, each points to different code region of its parent process. \end_layout \begin_layout Standard [TODO: turn the above table into a diagram] \end_layout \begin_layout Standard On Windows, threads and processes are two separated entities, so the above description for Linux does not apply. However, the general idea: a thread shares the execution environment, holds. \end_layout \begin_layout Section Task: x86 concept of a process \end_layout \begin_layout Section Task Data Structure \end_layout \begin_layout Subsection Task State Segment \end_layout \begin_layout Subsection Task Descriptor \end_layout \begin_layout Section Process Implementation \end_layout \begin_layout Subsection Requirements \end_layout \begin_layout Subsection Major Plan \end_layout \begin_layout Subsection Stage 1: Switch to a task from bootloader \end_layout \begin_layout Subsection Stage 2: Switch to a task with one function from kernel \end_layout \begin_layout Subsection Stage 3: Switch to a task with many functions from kernel \end_layout \begin_layout Standard To implement the concept of a process, a kernel needs to be able to save and restore its machine states for different tasks. \end_layout \begin_layout Description Description \begin_inset Separator latexpar \end_inset \end_layout \begin_deeper \begin_layout Standard [Describe task switching mechanism involving LDT and GDT] \end_layout \begin_layout Standard qasdfasdf asd \end_layout \end_deeper \begin_layout Description Constraints \end_layout \begin_layout Description Design \end_layout \begin_layout Description Implementation \begin_inset space ~ \end_inset plan \end_layout \begin_layout Section Milestone: Code Refactor \end_layout \begin_layout Chapter Interrupt \end_layout \begin_layout Chapter Memory management \end_layout \begin_layout Subsection Address Space \end_layout \begin_layout Standard \emph on Address space \emph default is the set of all addressable memory locations. There are 2 types of address spaces in physical memory address: \end_layout \begin_layout Itemize One for memory: \end_layout \begin_layout Itemize One for I/O: \end_layout \begin_layout Standard Each process has its own address space to do whatever it wants, as long as the physical memory is not exhausted. This address space is called \emph on virtual memory \emph default . \end_layout \begin_layout Subsection Virtual Memory \end_layout \begin_layout Standard Physical memory is a contagious memory locations that has a simple mapping between a physical memory address and its corresponding location in memory, decoded by memory controller. On the other hand, *virtual memory* does not have direct mapping between a memory address and the corresponding physical memory location, even though it appears contagious from the view of an userspace program. Instead, virtual memory address is translated by OS into an actual physical memory address. For that reason, even addresses appear next to each other in virtual memory space, they are scattered through out the physical memory. \end_layout \begin_layout Standard Why virtual memory is needed? Because virtual memory reduces the complexity of programming, by giving each program an illusion that it has its own separate "physical" memory to work with. Without virtual memory, programs must know and agree with each other their own memory regions to not accidentally destroy each other. \end_layout \begin_layout Standard [illustration a world without virtual memory] \end_layout \begin_layout Standard Virtual memory also enables a more secured OS, as application programs cannot manipulate main memory directly, so malicious programs won't cause havocs by destroying main memory and possibly hardware devices, by gaining access to hardware I/O ports. \end_layout \begin_layout Standard Another benefit is that virtual memory can extend beyond physical memory, by storing its data to hard disk. By swapping some of unused memory (i.e. inactive memory of a sleeping process), the system gains some free memory to continue running, so no data is destroyed. Otherwise, the OS is forced to kill a random user process to free up some memory, and you may lose unsaved work that belongs to the killed process. However, this process can significantly slow down the whole system because of Von Neumann bottleneck. In the old days, when memory was scarce, it was useful. \end_layout \begin_layout Chapter File System \end_layout \begin_layout Standard \emph on File system \emph default is a mechanism on how raw bytes in a storage device can be meaningfully managed. That is, a group of bytes at specific locations in a storage device can be allocated for a purpose e.g. storing raw ASCII document, and later the exact chunks of bytes can be retrieved correctly. File system manages many such groups of bytes. It's helpful to think a file system as a database that maps between high level information and specific locations in a hard disk, similar to how business information is mapped to a specific row in a table. The high level information that is relevant to a file system is organized as *files* and *directories*. \end_layout \begin_layout Standard [illustration between a file system and a database table to see how they are similar] \end_layout \begin_layout Standard \emph on File \emph default is an entity that includes two components: metadata and the actual raw data. \emph on Metadata \emph default is the information describes the properties of the raw data associated with the file; raw data are real content of a file. \emph on Directory \emph default is a file that holds a group of files and also child directories. Together, they create a file hierarchy system as commonly seen in Windows or Linux. \end_layout \begin_layout Subsection Example: Ex2 filesystem \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash bookmarksetup{startatroot} % this is it \end_layout \begin_layout Plain Layout \backslash addtocontents{toc}{ \backslash bigskip}% perhaps as well \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset CommandInset index_print LatexCommand printindex type "idx" name "Index" literal "true" \end_inset \end_layout \begin_layout Chapter* Bibliography \emph on \begin_inset ERT status open \begin_layout Plain Layout \backslash addcontentsline{toc}{chapter}{Biblography} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset CommandInset bibtex LatexCommand bibtex btprint "btPrintCited" bibfiles "references" options "plainnat" \end_inset \end_layout \end_body \end_document ================================================ FILE: book_src/Operating Systems From 0 to 1.txt ================================================ Operating Systems: From 0 to 1 Tu, Do Hoang Table of Contents Preface Why another book on Operating Systems? Prerequisites What you will learn in this book What this book is not about The organization of the book Acknowledgments Part I Preliminary Domain documents Problem domains Documents for implementing a problem dom Software Requirement Document Software Specification Documents for writing an x86 Operating S The physical implementation of a bit MOSFET transistors Beyond transistors: digital logic gates The theory behind logic gates Logic Gate implementation: CMOS circuit Beyond Logic Gates: Machine Language Machine language Assembly Language Programming Languages Abstraction Why abstraction works Why abstraction reduces complexity Computer Architecture What is a computer? Server Desktop Computer Mobile Computer Game Consoles Embedded Computer Field Gate Programmable Array Application-Specific Integrated Circuit Computer Architecture Instruction Set Architecture Computer organization Hardware x86 architecture Intel Q35 Chipset x86 Execution Environment x86 Assembly and C objdump Reading the output Intel manuals Experiment with assembly code Anatomy of an Assembly Instruction Understand an instruction in detail Example: jmp instruction Examine compiled data Fundamental data types Pointer Data Types Bit Field Data Type String Data Types Examine compiled code Data Transfer Expressions Stack Automatic variables Function Call and Return Loop Conditional The Anatomy of a Program Reference documents: ELF header Section header table Understand Section in-depth Program header table Segments vs sections Runtime inspection and debug A sample program Static inspection of a program Command: info target/info file/info file Command: maint info sections Command: info functions Command: info variables Command: disassemble/disas Command: x Command: print/p Runtime inspection of a program Command: run Command: break/b Command: next/n Command: step/s Command: ni Command: si Command: until Command: finish Command: bt Command: up Command: down Command: info registers How debuggers work: A brief introduction How breakpoints work Single stepping How a debugger understands high level so Part II Groundwork Bootloader x86 Boot Process Using BIOS services Boot process Example Bootloader Compile and load Debugging Loading a program from bootloader Floppy Disk Anatomy Read and load sectors from a floppy disk Improve productivity with scripts Automate build with GNU Make GNU Make Syntax summary Automate debugging steps with GDB script Linking and loading on bare metal Understand relocations with readelf Offset Info Type Sym.Value Sym. Name Crafting ELF binary with linker scripts Example linker script Understand the custom ELF structure Manipulate the program segments C Runtime: Hosted vs Freestanding Debuggable bootloader on bare metal Debuggable program on bare metal Loading an ELF binary from a bootloader Debugging the memory layout Testing the new binary Part III Kernel Programming x86 Descriptors Basic operating system concepts Hardware Abstraction Layer System programming interface The need for an Operating System Drivers Userspace and kernel space Memory Segment Segment Descriptor Types of Segment Descriptors Code and Data descriptors Task Descriptor Interrupt Descriptor Descriptor Scope Global Descriptor Local Descriptor Segment Selector Enhancement: Bootloader with descriptors Process Concepts Process Task Process Scheduler Context switch Priority Preemptive vs Non-preemptive Process states procfs Threads Task: x86 concept of a process Task Data Structure Task State Segment Task Descriptor Process Implementation Requirements Major Plan Stage 1: Switch to a task from bootloade Stage 2: Switch to a task with one funct Stage 3: Switch to a task with many func Milestone: Code Refactor Interrupt Memory management Address Space Virtual Memory File System Example: Ex2 filesystem Bibliography Preface Greetings! You've probably asked yourself at least once how an operating system is written from the ground up. You might even have years of programming experience under your belt, yet your understanding of operating systems may still be a collection of abstract concepts not grounded in actual implementation. To those who've never built one, an operating system may seem like magic: a mysterious thing that can control hardware while handling a programmer's requests via the API of their favorite programming language. Learning how to build an operating system seems intimidating and difficult; no matter how much you learn, it never feels like you know enough. You're probably reading this book right now to gain a better understanding of operating systems to be a better software engineer. If that is the case, this book is for you. By going through this book, you will be able to find the missing pieces that are essential and enable you to implement your own operating system from scratch! Yes, from scratch, without going through any existing operating system layer to prove to yourself that you are an operating system developer. You may ask,“Isn't it more practical to learn the internals of Linux?”. Yes... and no. Learning Linux can help your workflow at your day job. However, if you follow that route, you still won't achieve the ultimate goal of writing an actual operating system. By writing your own operating system, you will gain knowledge that you will not be able to glean just from learning Linux. Here's a list of some benefits of writing your own OS: • You will learn how a computer works at the hardware level, and you will learn to write software to manage that hardware directly. • You will learn the fundamentals of operating systems, allowing you to adapt to any operating system, not just Linux • To hack on Linux internals suitably, you'll need to write at least one operating system on your own. This is just like applications programming: to write a large application, you'll need to start with simple ones. • You will open pathways to various low-level programming domains such as reverse engineering, exploits, building virtual machines, game console emulation and more. Assembly language will become one of your most indispensable tools for low-level analysis. (But that does not mean you have to write your operating system in Assembly!) • Writing an operating system is fun! Why another book on Operating Systems? There are many books and courses on this topic made by famous professors and experts out there already. Who am I to write a book on such an advanced topic? While it's true that many quality resources exist, I find them lacking. Do any of them show you how to compile your C code and the C runtime library independent of an existing operating system? Most books on operating system design and implementation only discuss the software side; how the operating system communicates with the hardware is skipped. Important hardware details are skipped, and it's difficult for a self-learner to find relevant resources on the Internet. The aim of this book is to bridge that gap: not only will you learn how to program hardware directly, but also how to read official documents from hardware vendors to program it. You no longer have to seek out resources to help yourself interpret hardware manuals and documentation: you can do it yourself. Lastly, I wrote this book from an autodidact's perspective. I made this book as self-contained as possible so you can spend more time learning and less time guessing or seeking out information on the Internet. One of the core focuses of this book is to guide you through the process of reading official documentation from vendors to implement your software. Official documents from hardware vendors like Intel are critical for implementing an operating system or any other software that directly controls the hardware. At a minimum, an operating system developer needs to be able to comprehend these documents and implement software based on a set of hardware requirements. Thus, the first chapter is dedicated to discussing relevant documents and their importance. Another distinct feature of this book is that it is “Hello World” centric. Most examples revolve around variants of a “Hello World” program, which will acquaint you with core concepts. These concepts must be learned before attempting to write an operating system. Anything beyond a simple “Hello World” example gets in the way of teaching the concepts, thus lengthening the time spent on getting started writing an operating system. Let's dive in. With this book, I hope to provide enough foundational knowledge that will open doors for you to make sense of other resources. This book will be especially beneficial to students who've just finished their first C/C++ course. Imagine how cool it would be to show prospective employers that you've already built an operating system. Prerequisites • Basic knowledge of circuits – Basic Concepts of Electricity: atoms, electrons, proton, neutron, current flow. – Ohm's law If you are unfamiliar with these concepts, you can quickly learn them here: http://www.allaboutcircuits.com/textbook/, by reading chapter 1 and chapter 2. • C programming. In particular: – Variable and function declarations/definitions – While and for loops – Pointers and function pointers – Fundamental algorithms and data structures in C • Linux basics: – Know how to navigate directory with the command line – Know how to invoke a command with options – Know how to pipe output to another program • Touch typing. Since we are going to use Linux, touch typing helps. I know typing speed does not relate to problem-solving, but at least your typing speed should be fast enough to not let it get in the way and degrade the learning experience. In general, I assume that the reader has basic C programming knowledge, and can use an IDE to build and run a program. What you will learn in this book • How to write an operating system from scratch by reading hardware datasheets. In the real world, you will not be able to consult Google for a quick answer. • Write code independently. It's pointless to copy and paste code. Real learning happens when you solve problems on your own. Some examples are provided to help kick start your work, but most problems are yours to conquer. However, the solutions are available online for you after giving a good try. • A big picture of how each layer of a computer related to each other, from hardware to software. • How to use Linux as a development environment and common tools for low-level programming. • How a program is structured so that an operating system can run. • How to debug a program running directly on hardware with gdb and QEMU. • Linking and loading on bare metal x86_64, with pure C. No standard library. No runtime overhead. What this book is not about • Electrical Engineering: The book discusses some concepts from electronics and electrical engineering only to the extent of how software operates on bare metal. • How to use Linux or any OS types of books: Though Linux is used as a development environment and as a medium to demonstrate high-level operating system concepts, it is not the focus of this book. • Linux Kernel development: There are already many high-quality books out there on this subject. • Operating system books focused on algorithms: This book focuses more on actual hardware platform - Intel x86_64 - and how to write an OS that utilizes of OS support from the hardware platform. The organization of the book Part 1 provides a foundation for learning operating system. • Chapter 1 briefly explains the importance of domain documents. Documents are crucial for the learning experience, so they deserve a chapter. • Chapter 2 explains the layers of abstractions from hardware to software. The idea is to provide insight into how code runs physically. • Chapter 3 provides the general architecture of a computer, then introduces a sample computer model that you will use to write an operating system. • Chapter 4 introduces the x86 assembly language through the use of the Intel manuals, along with commonly used instructions. This chapter gives detailed examples of how high-level syntax corresponds to low-level assembly, enabling you to read generated assembly code comfortably. It is necessary to read assembly code when debugging an operating system. • Chapter 5 dissects ELF in detail. Only by understanding how the structure of a program at the binary level, you can build one that runs on bare metal. • Chapter 6 introduces gdb debugger with extensive examples for commonly used commands. After acquainting the reader with gdb, it then provides insight on how a debugger works. This knowledge is essential for building a debuggable program on the bare metal. Part 2 presents how to write a bootloader to bootstrap a kernel. Hence the name “Groundwork”. After mastering this part, the reader can continue with the next part, which is a guide for writing an operating system. However, if the reader does not like the presentation, he or she can look elsewhere, such as the OSDev Wiki: http://wiki.osdev.org/. • Chapter 7 introduces what the bootloader is, how to write one in assembly, and how to load it on QEMU, a hardware emulator. This process involves typing repetitive and long commands, so GNU Make is applied to improve productivity by automating the repetitive parts and simplifying the interaction with the project. This chapter also demonstrates the use of GNU Make in context. • Chapter 8 introduces linking by explaining the relocation process when combining object files. In addition to a bootloader and an operating system written in C, this is the last piece of the puzzle required for building debuggable programs on bare metal, including the bootloader written in Assembly and an operating system written in C. Part 3 provides guidance on how to write an operating system, as you should implement an operating system on your own and be proud of your creation. The guidance consists of simpler and coherent explanations of necessary concepts, from hardware to software, to implement the features of an operating system. Without such guidance, you will waste time gathering information spread through various documents and the Internet. It then provides a plan on how to map the concepts to code. Acknowledgments Thank you, my beloved family. Thank you, the contributors. Preliminary Domain documents Problem domains In the real world, software engineering is not only focused on software, but also the problem domain it is trying to solve. A problem domain[margin: problem domain ]problem domain is the part of the world where the computer is to produce effects, together with the means available to produce them, directly or indirectly. (Kovitz, 1999) A problem domainproblem domain is anything outside of programming that a software engineer needs to understand to produce correct code that can achieve the desired effects. “Directly” means include anything that the software can control to produce the desired effects, e.g. keyboards, printers, monitors, other software... “Indirectly” means anything not part of the software but relevant to the problem domain e.g. appropriate people to be informed by the software when some event happens, students that move to correct classrooms according to the schedule generated by the software. To write a finance application, a software engineer needs to learn sufficient finance concepts to understand the [margin: requirements ]requirementsrequirements of a customer and implement such requirements, correctly. Requirements are the effects that the machine is to exert in the problem domain by virtue of its programming. Programming alone is not too complicated; programming to solve a problem domain, is [footnote: We refer to the concept of “programming” here as someone able to write code in a language, but not necessary know any or all software engineering knowledge. ]. Not only a software engineer needs to understand how to implement the software, but also the problem domain that it tries to solve, which might require in-depth expert knowledge. The software engineer must also select the right programming techniques that apply to the problem domain he is trying to solve because many techniques that are effective in one domain might not be in another. For example, many types of applications do not require performant written code, but a short time to market. In this case, interpreted languages are widely popular because it can satisfy such need. However, for writing huge 3D games or operating system, compiled languages are dominant because it can generate the most efficient code required for such applications. Often, it is too much for a software engineer to learn non-trivial domains (that might require a bachelor degree or above to understand the domains). Also, it is easier for a domain expert domain expert to learn enough programming to break down the problem domain into parts small enough for the software engineers to implement. Sometimes, domain experts implement the software themselves. [float Figure: [Figure 0.1: Problem domains: Software and Non-software. ] ] One example of such scenario is the domain that is presented in this book: operating system. A certain amount of electrical engineering (EE) knowledge is required to implement an operating system. If a computer science (CS) curriculum that does not include minimum EE courses, students in the curriculum have little chance to implement a working operating system. Even if they can implement one, either they need to invest a significant amount of time to study on their own, or they fill code in a predefined framework just to understand high-level algorithms. For that reason, EE students have an easier time to implement an OS, as they only need to study a few core CS courses. In fact, only “C programming” and “Algorithms and Data Structures” classes are usually enough to get them started writing code for device drivers, and later generalize it into an operating system. [float Figure: [Figure 0.2: Operating System domain. ] ] One thing to note is that software is its own problem domain. A problem domain does not necessarily divide between software and itself. Compilers, 3D graphics, games, cryptography, artificial intelligence, etc., are parts of software engineering domains (actually it is more of a computer science domain than a software engineering domain). In general, a software-exclusive domain creates software to be used by other software. Operating System is also a domain, but is overlapped with other domains such as electrical engineering. To effectively implement an operating system, it is required to learn enough of the external domain. How much learning is enough for a software engineer? At the minimum, a software engineer should be knowledgeable enough to understand the documents prepared by hardware engineers for using (i.e. programming) their devices. Learning a programming language, even C or Assembly, does not mean a software engineer can automatically be good at hardware programming or any related low-level programming domains. One can spend 10 years, 20 years or his entire life writing C/C++ code, and he still cannot write an operating system, simply because of the ignorance of relevant domain knowledge. Just like learning English does not mean a person automatically becomes good at reading Math books written in English. Much more than that is needed. Knowing one or two programming languages is not enough. If a programmer writes software for a living, he had better be specialized in one or two problem domains outside of software if he does not want his job taken by domain experts who learn programming in their spare time. Documents for implementing a problem domain Documents are essential for learning a problem domain (and actually, anything) since information can be passed down in a reliable way. It is evident that this written text has been used for thousands of years to pass knowledge from generation to generation. Documents are integral parts of non-trivial projects. Without the documents: • New people will find it much harder to join a project. • It is harder to maintain a project because people may forget important unresolved bugs or quirks in their system. • It is challenging for customers to understand the product they are going to use. However, documents do not need to be written in book format. It can be anything from HTML format to database format to be displayed by a graphical user interface. Important information must be stored somewhere safe, readily accessible. There are many types of documents. However, to facilitate the understanding of a problem domain, these two documents need to be written: software requirement document and software specification. Software Requirement Document Software requirement document[margin: Software requirement ]Software requirement document includes both a list of requirements and a description of the problem domain (Kovitz, 1999) . A software solves a business problem. But, which problems to solve, are requested by a customer. Many of these requests make a list of requirements that our software needs to fulfill. However, an enumerated list of features is seldom useful in delivering software. As stated in the previous section, the tricky part is not programming alone but programming according to a problem domain. The bulk of software design and implementation depends upon the knowledge of the problem domain. The better understood the domain, the higher quality software can be. For example, building a house is practiced over thousands of years and is well understood, and it is easy to build a high-quality house; software is no different. Code that is difficult to understand is usually due to the author's ignorance of a problem domain. In the context of this book, we seek to understand the low-level working of various hardware devices. Because software quality depends upon an understanding of the problem domain, a software requirement document should always include a description of the problem domain. Be aware that software requirements are not: What vs How “what” and “how” are vague terms. What is the “what”? Is it nouns only? If so, what if a customer requires his software to perform specific steps of operations, such as purchasing procedure for a customer on a website. Does it include “verbs” now? However, isn't the “how” supposed to be step by step operations? Anything can be the “what” and anything can be the “ how”. Sketches Software requirement document is all about the problem domain. It should not be a high-level description of an implementation. Some problems might seem straightforward to map directly from its domain description to the structure of an implementation. For example: • Users are given a list of books in a drop-down menu to choose. • Books are stored in a linked list”. • ... In the future, instead of a drop-down menu, all books are listed directly on a page in thumbnails. Books might be reimplemented as a graph, and each node is a book for finding related books, as a recommender is going to be added in the next version. The requirement document needs updating again to remove all the outdated implementation details, thus required additional efforts to maintain the requirement document, and when the effort for syncing with the implementation is too much, the developers give up documentation, and everyone starts ranting how useless documentation is. More often than not there is no straightforward one-to-one mapping. For example, a regular computer user expects an OS to be something that runs some program with GUI, or their favorite computer games. But for such requirements, an operating system is implemented as multiple layers, each hiding the details from the upper layers. To implement an operating system, a large body of knowledge from multiple fields is required, especially if the operating system runs on non-PC devices. It's best to include informat related to the problem domain in the requirement document. A good way to test the quality of a requirement document is to provide it to a domain expert for proofreading, to ensure he can understand the material. thoroughly. A requirement document is also useful as a help document later, or for writing one much easier. Software Specification Software specification[margin: Software specification ]Software specification document states rules relating desired behavior of the output devices to all possible behavior of the input devices, as well as any rules that other parts of the problem domain must obey.Kovitz (1999) Simply put, software specification is interface design, with constraints for the problem domain to follow e.g. the software can accept certain types of input such as the software is designed to accept English but no other language. For a hardware device, a specification is always needed, as software depends on its hardwired behaviors. And in fact, it is mostly the case that hardware specifications are well-defined, with the tiniest details in it. It needs to be that way because once hardware is physically manufactured, there's no going back, and if defects exist, it's a devastating damage to the company on both finance and reputation. Note that, similar to a requirement document, a specification only concerns interface design. If implementation details leak in, it is a burden to sync between the actual implementation and the specification, and soon to be abandoned. Another important remark is that, though a specification document is important, it does not have to be produced before the implementation. It can be prepared in any order: before or after a complete implementation; or at the same time with the implementation, when some part is done, and the interface is ready to be recorded in the specification. Regardless of methods, what matter is a complete specification at the end. Documents for writing an x86 Operating System When problem domain is different from software domain, requirement document and specification are usually separated. However, if the problem domain is inside software, specification most often includes both, and content of both can be mixed with each other. As demonstrated by previous sections the importance of documents, to implement an OS, we will need to collect relevant documents to gain sufficient domain knowledge. These documents are as follow: • Intel® 64 and IA-32 Architectures Software Developer’s Manual (Volume 1, 2, 3) • Intel® 3 Series Express Chipset Family Datasheet • System V Application Binary Interface Aside from the Intel's official website, the website of this book also hosts the documents for convenience[footnote: Intel may change the links to the documents as they update their website, so this book doesn't contain any link to the documents to avoid confusion for readers. ]. Intel documents divide the requirement and specification sections clearly, but call the sections with different names. The corresponding to the requirement document is a section called “ Functional Description”, which consists mostly of domain description; for specification, “Register Description” section describes all programming interfaces. Both documents carry no unnecessary implementation details[footnote: As it should be, those details are trade secret. ]. Intel documents are also great examples of how to write well requirements/specifications, as explained in this chapter. Other than the Intel documents, other documents will be introduced in the relevant chapters. This chapter gives an intuition on how hardware and software connected together, and how software is represented physically. The physical implementation of a bit All electronic devices, from simple to complex, manipulate this flow to achieve desired effects in the real world. Computers are no exception. When we write software, we indirectly manipulate electrical current at the physical level, in such a way that the underlying machine produces desired effects. To understand the process, we consider a simple light bulb. A light bulb can change two states between on and off with a switch, periodically: an off means number 0, and an on means 1.[float MarginFigure: [MarginFigure 1: A lightbulb ] ] However, one problem is that such a switch requires manual intervention from a human. What is required is an automatic switch based on the voltage level, as described above. To enable automatic switching of electrical signals, a device called transistor, invented by William Shockley, John Bardeen and Walter Brattain. This invention started the whole computer industry. At the core, a [margin: transistor ]transistortransistor is just a resistor whose values can vary based on an input voltage value[float MarginFigure: [MarginFigure 2: Modern transistor ] ]. With this property, a transistor can be used as a current amplifier (more voltage, less resistance) or switch electrical signals off and on (block and unblock an electron flow) based on a voltage level. At 0 v, no current can pass through a transistor, thus it acts like a circuit with an open switch (light bulb off) because the resistor value is enough to block the electrical flow. Similarly, at +3.5 v, current can flow through a transistor because the resistor value is lessened, effectively enables electron flow, thus acts like a circuit with a closed switch.[margin: If you want a deeper explanation of transistors e.g. how electrons move, you should look at the video “How semiconductors work” on Youtube, by Ben Eater. ] A bit has two states: 0 and 1, which is the building block of all digital systems and software. Similar to a light bulb that can be turned on and off, bits are made out of this electrical stream from the power source: Bit 0 are represented with 0 v (no electron flow), and bit 1 is +3.5 v to +5 v (electron flow). Transistor implements a bit correctly, as it can regulate the electron flow based on voltage level. MOSFET transistors The classic transistors invented open a whole new world of micro digital devices. Prior to the invention, vacuum tubes - which are just fancier light bulbs - were used to present 0 and 1, and required human to turn it on and off. [margin: MOSFET ]MOSFETMOSFET, or Metal–Oxide–Semiconductor Field-Effect Transistor, invented in 1959 by Dawon Kahng and Martin M. (John) Atalla at Bell Labs, is an improved version of classic transistors that is more suitable for digital devices, as it requires shorter switching time between two states 0 and 1, more stable, consumes less power and easier to produce. There are also two types of MOSFETs analogous to two types of transistors: n-MOSFET and p-MOSFET. n-MOSFET and p-MOSFET are also called NMOS and PMOS transistors for short. Beyond transistors: digital logic gates All digital devices are designed with logic gates. A logic gate[margin: logic gate ]logic gate is a device that implements a boolean function. Each logic gate includes a number of inputs and an output. All computer operations are built from the combinations of logic gates, which are just combinations of boolean functions. [float MarginFigure: [MarginFigure 3: Example: NAND gate ] ] The theory behind logic gates Logic gates accept only binary inputs[footnote: Input that is either a 0 or 1. ] and produce binary outputs. In other words, logic gates are functions that transform binary values. Fortunately, a branch of math that deals exclusively with binary values already existed, called Boolean Algebra, developed in the 19[superscript:th]century by George Boole. With a sound mathematical theory as a foundation logic gates were created. As logic gates implement Boolean functions, a set of Boolean functions is functionally complete [margin: functionally complete ]functionally complete, if this set can construct all other Boolean functions can be constructed from. Later, Charles Sanders Peirce (during 1880 -- 1881) proved that either Boolean function of NOR or NAND alone is enough to create all other Boolean logic functions. Thus NOR and NAND gates are functionally complete Peirce (1933) . Gates are simply the implementations of Boolean logic functions, therefore NAND or NOR gate is enough to implement all other logic gates. The simplest gates CMOS circuit can implement are inverters (NOT gates) and from the inverters, comes NAND gates. With NAND gates, we are confident to implement everything else. This is why the inventions of transistors, then CMOS circuit revolutionized computer industry.[margin: If you want to understand why and how from NAND gate we can create all Boolean functions and a computer, I suggest the course Build a Modern Computer from First Principles: From Nand to Tetris available on Coursera: https://www.coursera.org/learn/build-a-computer . Go even further, after the course, you should take the series Computational Structures on Edx. ] We should realize and appreciate how powerful boolean functions are available in all programming languages. Logic Gate implementation: CMOS circuit Underlying every logic gate is a circuit called [margin: CMOS ]CMOSCMOS - Complementary MOSFET. CMOS consists of two complementary transistors, NMOS and PMOS. The simplest CMOS circuit is an inverter or a NOT gate: From NOT gate, a NAND gate can be created: From NAND gate, we have all other gates. As demonstrated, such a simple circuitry performs the logical operators in day-to-day program languages e.g. NOT operator ~ is executed directly by an inverter circuit, and operator & is executed by an AND circuit and so on. Code does not run on a magic black box. In contrast, code execution is precise and transparent, often as simple as running some hardwired circuit. When we write software, we simply manipulate electrical current at the physical level to run appropriate circuits to produce desired outcomes. However, this whole process somehow does not relate to any thought involving electrical current. That is the real magic and will be explained soon. One interesting property of CMOS is that a k-input gate uses k PMOS and k NMOS transistors (Wakerly, 1999). All logic gates are built by pairs of NMOS and PMOS transistors, and gates are the building blocks of all digital devices from simple to complex, including any computer. Thanks to this pattern, it is possible to separate between the actual physical circuit implementation and logical implementation. Digital designs are done by designing with logic gates then later be “compiled” into physical circuits. In fact, later we will see that logic gates become a language that describes how circuits operate. Understanding how CMOS works is important to understand how a computer is designed, and as a consequence, how a computer works[footnote: Again, if you want to understand how logic gates make a computer, consider the suggested courses on Coursera and Edx earlier. ]. Finally, an implemented circuit with its wires and transistors is stored physically in a package called a chip. A chipchip is a substrate that an integrated circuit is etched onto. However, a chip also refers to a completely packaged integrated circuit in consumer market. Depends on the context, it is understood differently.[float MarginFigure: [MarginFigure 4: 74HC00 chip physical view ] ] ------------------------------------------- 74HC00 is a chip with four 2-input NAND gates. The chip comes with 8 input pins and 4 output pins, 1 pin for connecting to a voltage source and 1 pin for connecting to the ground. This device is the physical implementation of NAND gates that we can physically touch and use. But instead of just a single gate, the chip comes with 4 gates that can be combined. Each combination enables a different logic function, effective creating other logic gates. This feature is what make the chip popular. [float Figure: [Figure 0.3: 74HC00 logic diagrams (Source: 74HC00 datasheet, https://neurophysics.ucsd.edu/courses/physics_120/74HC00_QUAD_NAND.pdf ) ] [float Figure: [Sub-Figure a: Logic diagram of 74HC00 ] ] [float Figure: [Sub-Figure b: Logic diagram of one NAND gate ] ] ] Each of the gates above is just a simple NAND circuit with the electron flows, as demonstrated earlier. Yet, many these NAND-gates chips combined can build a simple computer. Software, at the physical level, is just electron flows. How can the above gates can be created with 74HC00? It is simple: as every gate has 2 input pins and 1 output pin, we can write the output of 1 NAND gate to an input of another NAND gate, thus chaining NAND gates together to produce the diagrams as above. ------------------------------------------- Beyond Logic Gates: Machine Language Machine language Being built upon gates, as gates only accept a series of 0 and 1, a hardware device only understands 0 and 1. However, a device only takes 0 and 1 in a systematic way. [margin: Machine language ]Machine languageMachine language is a collection of unique bit patterns that a device can identify and perform a corresponding action. A machine instruction is a unique bit pattern that a device can identify. In a computer system, a device with its language is called CPU - Central Processing Unit, which controls all activities going inside a computer. For example, in the x86 architecture, the pattern 10100000 means telling a CPU to add two numbers, or 000000101 to halt a computer. In the early days of computers, people had to write completely in binary. Why does such a bit pattern cause a device to do something? The reason is that underlying each instruction is a small circuit that implements the instruction. Similar to how a function/subroutine in a computer program is called by its name, a bit pattern is a name of a little function inside a CPU that got executed when the CPU finds one. Note that CPU is not the only device with its language. CPU is just a name to indicate a hardware device that controls a computer system. A hardware device may not be a CPU but still has its language. A device with its own machine language is a programmable device, since a user can use the language to command the device to perform different actions. For example, a printer has its set of commands for instructing it how to print a page. ------------------------------------------- A user can use 74HC00 chip without knowing its internal, but only the interface for using the device. First, we need to know its layout: [float Figure: [Figure 0.4: 74HC00 Pin Layout (Source: 74HC00 datasheet, http://www.nxp.com/documents/data_sheet/74HC_HCT00.pdf ) ] ] Then, the functionality of each pin: [float Table: [Table 1: Pin Description (Source: 74HC00 datasheet, http://www.nxp.com/documents/data_sheet/74HC_HCT00.pdf ) ] +-----------------------------+---------------+-----------------+ | Symbol | Pin | Description | +------------------------------+---------------+----------------+ | 1A to 4A | 1, 4, 9, 12 | data input | +------------------------------+---------------+----------------+ | 1B to 4B | 2, 5, 10, 13 | data input | +------------------------------+---------------+----------------+ | 1Y to 4Y | 3, 6, 8, 11 | data output | +------------------------------+---------------+----------------+ | GND | 7 | ground (0 V) | +------------------------------+---------------+----------------+ | V[subscript:cc][subscript:] | 14 | supply voltage | +------------------------------+---------------+----------------+ ] Finally, how to use the pins: [float Table: [Table 2: Functional Description ] +------------+--------+ | Input | Output | +-----+------+--------+ | nA | nB | nY | +-----+------+--------+ | L | L | H | +-----+------+--------+ | L | X | H | +-----+------+--------+ | X | L | H | +-----+------+--------+ | H | H | L | +-----+------+--------+ ] [margin: • n is a number, either 1, 2, 3, or 4 • H = HIGH voltage level; L = LOW voltage level; X = don’t care. ]The functional description provides a truth table with all possible pin inputs and outputs, which also describes the usage of all pins in the device. A user needs not to know the implementation, but on such a table to use the device. We can say that the truth table above is the machine language of the device. Since the device is digital, its language is a collection of binary strings: • The device has 8 input pins, and this means it accepts binary strings of 8 bits. • The device has 4 output pins, and this means it produces binary strings of 4 bits from the 8-bit inputs. The number of input strings is what the device understand, and the number of output strings is what the device can speak. Together, they make the language of the device. Even though this device is simple, yet the language it can accept contains quite many binary strings: 2^{8}+2^{4}=272 . However, the number is a tiny fraction of a complex device like a CPU, with hundreds of pins. When leaving as is, 74HC00 is simply a NAND device with two 4-bit inputs[footnote: Or simply 4-bit NAND gate, as it can only accept 4 bits of input at the maximum. ]. +--------+-----------------------------------------------+----------------------+ | | Input | Output | +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ | Pin | 1A | 1B | 2A | 2B | 3A | 3B | 4A | 4B | 1Y | 2Y | 3Y | 4Y | +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ | Value | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ The inputs and outputs as visually presented: [float Figure: [Figure 0.5: Pins when receiving digital signals that correspond to a binary string. Green signals are inputs; blue signals are outputs. ] ] On the other hand, if OR gate is implemented, we can only build a 2-input OR gate from 74HC00, as it requires 3 NAND gates: 2 input NAND gates and 1 output NAND gate. Each input NAND gate represents only a 1-bit input of the OR gate. In the following figure, the pins of each input NAND gates are always set to the same values (either both inputs are A or both inputs are B) to represent a single bit input for the final OR gate: [float Table: [Table 3: Truth table of OR logic diagram. ] +----+----+----+----+---+ | A | B | C | D | Y | +----+----+----+----+---+ | 0 | 0 | 1 | 1 | 0 | +----+----+----+----+---+ | 0 | 1 | 1 | 0 | 1 | +----+----+----+----+---+ | 1 | 0 | 0 | 1 | 1 | +----+----+----+----+---+ | 1 | 1 | 0 | 0 | 1 | +----+----+----+----+---+ ] ------------------------------------------- To implement a 4-bit OR gate, we need a total of four of 74HC00 chips configured as OR gates, packaged as a single chip as in figure [or-chip-74hc00]. [float Figure: [Figure 0.6: 4-bit OR chip made from four 74HC00 devices ] ] Assembly Language Assembly language is the symbolic representation of binary machine code, by giving bit patterns mnemonic names. It was a vast improvement when programmers had to write 0 and 1. For example, instead of writing 000000101, a programmer simply write hlt to stop a computer. Such an abstraction makes instructions executed by a CPU easier to remember, and thus more instructions could be memorized, less time spent looking up CPU manual to find instructions in bit forms and as a result, code was written faster. Understand assembly language is crucial for low-level programming domains, even to this day. The more instructions a programmer want to understand, the deeper understanding of machine architecture is required. We can build a device with 2 assembly instructions: or , nand , • or accepts two 4-bit operands. This corresponds to a 4-input OR gate device built from 4 74HC00 chips. • nand accepts two 4-bit operands. This corresponds to a single 74HC00 chips, leave as is. Essentially, the gates in the example [exa:74HC00-chip-can] implements the instructions. Up to this point, we only specify input and output and manually feed it to a device. That is, to perform an operation: • Pick a device by hands. • Manually put electrical signals into pins. First, we want to automate the process of device selection. That is, we want to simply write assembly instruction and the device that implements the instruction is selected correctly. Solving this problem is easy: • Give each instruction an index in binary code, called operation code or opcode for short, and embed it as part of input. The value for each instruction is specified as in table [ex-ins-ops].[float MarginTable: [MarginTable 1: Instruction-Opcode mapping. ] +--------------+-------------+ | Instruction | Binary Code | +--------------+-------------+ +--------------+-------------+ | nand | 00 | +--------------+-------------+ | or | 01 | +--------------+-------------+ ] Each input now contains additional data at the beginning: an opcode. For example, the instruction: nand 1100, 1100 corresponds to the binary string: 0011001100. The first two bits 00 encodes a nand instruction, as listed in the table above. • Add another device to select a device, based on a binary code peculiar to an instruction. Such a device is called a decoder, an important component in a CPU that decides which circuit to use. In the above example, when feeding 0011001100 to the decoder, because the opcode is 00, data are sent to NAND device for computing. Finally, writing assembly code is just an easier way to write binary strings that a device can understand. When we write assembly code and save in a text file, a program called an [margin: assembler ]assemblerassembler translates the text file into binary strings that a device can understand. So, how can an assembler exist in the first place? Assume this is the first assembler in the world, then it is written in binary code. In the next version, life is easier: the programmers write the assembler in the assembly code, then use the first version to compile itself. These binary strings are then stored in another device that later can be retrieved and sent to a decoder. A storage device[margin: storage device ]storage device is the device that stores machine instructions, which is an array of circuits for saving 0 and 1 states. A decoder is built out of logic gates similar to other digital devices. However, a storage device can be anything that can store 0 and 1 and is retrievable. A storage device can be a magnetized device that uses magnetism to store information, or it can be made out of electrical circuits using. Regardless of the technology used, as long as the device can store data and is accessible to retrieve data, it suffices. Indeed, the modern devices are so complex that it is impossible and unnecessary to understand every implementation detail. Instead, we only need to learn the interfaces, e.g. the pins, that the devices expose. A computer essentially implements this process: • Fetch an instruction from a storage device. • Decode the instruction. • Execute the instruction. Or in short, a fetch -- decode -- executefetch -- decode -- execute cycle. The above device is extremely rudimentary, but it already represents a computer with a fetch -- decode -- execute cycle. More instructions can be implemented by adding more devices and allocating more opcodes for the instructions, then update the decoder accordingly. The Apollo Guidance Computer, a digital computer produced for the Apollo space program from 1961 -- 1972, was built entirely with NOR gates - the other choice to NAND gate for creating other logic gates. Similarly, if we keep improving our hypothetical device, it eventually becomes a full-fledge computer. Programming Languages Assembly language is a step up from writing 0 and 1. As time goes by, people realized that many pieces of assembly code had repeating patterns of usages. It would be nice if instead of writing all the repeating blocks of code all over again in all places, we simply refer to such blocks of code with easier to use text forms. For example, a block of assembly code checks whether one variable is greater than another and if so, execute a block of code, else execute another block of code; in C, such block of assembly code is represented by an if statement that is close to human language. [float Figure: [Figure 0.7: Repeated assembly patterns are generalized into a new language. ] ] People created text forms to represent common blocks of assembly code, such as the if syntax above, then write a program to translate the text forms into assembly code. The program that translates such text forms to machine code is called a [margin: compiler ]compilercompiler: Any software logic a programming language can implement, hardware can also implement. The reverse is also true: any hardware logic that is implemented in a circuit can be reimplemented in a programming language. The simple reason is that programming languages, or assembly languages, or machine languages, or logic gates are just languages to express computations. It is impossible for software to implement something hardware is incapable of because programming language is just a simpler way to use the underlying hardware. At the end of the day, programming languages are translated to machine instructions that are valid to a CPU. Otherwise, code is not runnable, thus a useless software. In reverse, software can do everything hardware (that run the software) can, as programming languages are just an easier way to use the hardware. In reality, even though all languages are equivalent in power, not all of them are capable of express programs of each other. Programming languages vary between two ends of a spectrum: high level and low level. The higher level a programming language is, the more distant it becomes from the hardware. In some high-level programming languages, such as Python, a programmer cannot manipulate underlying hardware, despite being able to deliver the same computations as low-level programming languages. The reason is that high-level languages want to hide hardware details to free programmers from dealing with irrelevant details not related to current problem domains. Such convenience, however, is not free: it requires software to carry an extra code for managing hardware details (e.g. memory) thus making the code run slower, and it makes hardware programming difficult or impossible. The more abstractions a programming language imposes, the more difficult it is for writing low-level software, such as hardware drivers or an operating system. This is the reason why C is usually a language of choice for writing an operating system, since C is just a thin wrapper of the underlying hardware, making it easy to understand how exactly a hardware device runs when executing a certain piece of C code. Each programming language represents a way of thinking about programs. Higher-level programming languages help to focus on problem domains that are not related to hardware at all, and where programmer performance is more important than computer performance. Lower-level programming languages help to focus on the inner-working of a machine, thus are best suited for problem domains that are related to control hardware. That is why so many languages exist. Use the right tools for the right job to achieve the best results. Abstraction AbstractionAbstraction is a technique for hiding complexity that is irrelevant to the problem in context. For example, writing programs without any other layer except the lowest layer: with circuits. Not only a person needs an in-depth understanding of how circuits work, making it much more obscure to design a circuit because the designer must look at the raw circuits but think in higher-level such as logic gates. It is a distracting process, as a designer must constantly translate the idea into circuits. It is possible for a designer simply thinks his high-level ideas straight, and later translate the ideas into circuits. Not only it is more efficient, but it is also more accurate as a designer can focus all his efforts into verifying the design with high-level thinking. When a new designer arrives, he can easily understand the high-level designs, thus can continue to develop or maintain existing systems. Why abstraction works In all the layers, abstractions manifest itself: • Logic gates abstract away the details of CMOS. • Machine language abstracts away the details of logic gates. • Assembly language abstracts away the details of machine languages. • Programming language abstracts away the details of assembly languages. We see repeating patterns of how lower-layers build upper-layers: • A lower layer has a recurring pattern. Then, this recurring pattern is taken out and built a language on top of it. • A higher layer strips away layer-specific (non-recurring) details to focus on the recurring details. • The recurring details are given a new and simpler language than the languages of the lower layers. What to realize is that every layer is just a more convenient language to describe the lower layer. Only after a description is fully created with the language of the higher layer, it is then be implemented with the language of the lower layer. • CMOS layer has a recurring pattern that makes sure logic gates are reliably translated to CMOS circuits: a k-input gate uses k PMOS and k NMOS transistors (Wakerly, 1999). Since digital devices use CMOS exclusively, a language arose to describe higher level ideas while hiding CMOS circuits: Logic Gates. • Logic Gates hides the language of circuits and focuses on how to implement primitive Boolean functions and combine them to create new functions. All logic gates receive input and generate output as binary numbers. Thanks to this recurring patterns, logic gates are hidden away for the new language: Assembly, which is a set of predefined binary patterns that cause the underlying gates to perform an action. • Soon, people realized that many recurring patterns arisen from within Assembly language. Repeated blocks of Assembly code appear in Assembly source files that express the same or similar idea. There were many such ideas that can be reliably translated into Assembly code. Thus, the ideas were extracted for building into the high level programming languages that everyone programmer learns today. Recurring patterns are the key to abstraction. Recurring patterns are why abstraction works. Without them, no language can be built, and thus no abstraction. Fortunately, human already developed a systematic discipline for studying patterns: Mathematics. As quoted from the British mathematician G. H. Hardy (2005): A mathematician, like a painter or a poet, is a maker of patterns. If his patterns are more permanent than theirs, it is because they are made with ideas. Isn't that a mathematical formula a representation of a pattern? A variable represents values with the same properties given by constraints? Mathematics provides a formal system to identify and describe existing patterns in nature. For that reason, this system can certainly be applied in the digital world, which is just a subset of the real world. Mathematics can be used as a common language to help translation between layers easier, and help with the understanding of layers. Why abstraction reduces complexity Abstraction by building language certainly leverages productivity by stripping irrelevant details to a problem. Imagine writing programs without any other layout except the lowest layer: with circuits. This is how complexity emerges: when high-level ideas are expressed with lower-level language, as the example above demonstrated. Unfortunately, this is the case with software as programming languages at the moment are more emphasized on software rather than the problem domains. That is, without prior knowledge, code written in a language is unable to express itself the knowledge of its target domain. In other words, a language is expressive if its syntax is designed to express the problem domain it is trying to solve. Consider this example: That is, the what it will do rather the how it will do. ------------------------------------------- Graphviz (http://www.graphviz.org/) is a visualization software that provides a language, called dot, for describing graph: As can be seen, the code perfectly expresses itself how the graph is connected. Even a non-programmer can understand and use such language easily. An implementation in C would be more troublesome, and that's assuming that the functions for drawing graphs are already available. To draw a line, in C we might write something like: draw_line(a, b); However, it is still verbose compared with: a -> b; Also, a and b must be defined in C, compared to the implicit nodes in the dot language. However, if we do not factor in the verbosity, then C still has a limitation: it cannot change its syntax to suit the problem domain. A domain-specific language might even be more verbose, but it makes a domain more understandable. If a problem domain must be expressed in C, then it is constraint by the syntax of C. Since C is not a specialized language for a problem domain that, but is a general-purpose programming language, the domain knowledge is buried within the implementation details. As a result, a C programmer is needed to decipher and extract the domain knowledge out. If the domain knowledge cannot be extracted, then the software cannot be further developed. Linux is full of applications controlled by many domain-specific languages and are placed in /etc directory, such as a web server. Instead of reprogramming the software, a domain-agnostic language is made for it. ------------------------------------------- In general, code that can express a problem domain must be understandable by a domain expert. Even within the software domain, building a language out of repeated programming patterns is useful. It helps people aware the existence of such patterns in code and thus making software easier to maintain, as software structure is visible as a language. Only a programming language that is capable of morphing itself to suit a problem domain can achieve that goal. Such language is called a programmable programming language. Unfortunately, this approach of turning software structure visible is not favored among programmers, as a new language must be made out of it along with new toolchain to support it. Thus, software structure and domain knowledge are buried within code written in the syntax of a general-purpose language, and if a programmer is not familiar or even aware of the existence of a code pattern, then it is hopeless to understand the code. A prime example is reading C code that controls hardware, e.g. an operating system: if a programmer knows absolutely nothing about hardware, then it is impossible to read and write operating system code in C, even if he could have 20 years of writing application C code. With abstraction, a software engineer can also understand the inner-working of a device without specialized knowledge of physical circuit design, enables the software engineer to write code that controls a device. The separation between logical and physical implementation also entails that gate designs can be reused even when the underlying technologies changed. For example, in some distant future biological computer could be a reality, and gates might not be implemented as CMOS but some kind of biological cells e.g. as living cells; in either technology: electrical or biological, as long as logic gates are physically realized, the same computer design could be implemented. Computer Architecture To write lower level code, a programmer must understand the architecture of a computer. It is similar to when one writes programs in a software framework, he must know what kinds of problems the framework solves, and how to use the framework by its provided software interfaces. But before getting to the definition of what computer architecture is, we must understand what exactly is a computer, as many people still think that a computer is a regular computer we put on a desk, or at best, a server. Computers come in various shapes and sizes and are devices that people never imagine they are computers, and that code can run on such devices. What is a computer? A [margin: computer ]computercomputer is a hardware device that consists of at least a processor (CPU), a memory device and input/output interfaces. All the computers can be grouped into two types: Single-purpose computer is a computer built at the hardware level for specific tasks. For example, dedicated application encoders/decoders , timer, image/video/sound processors. General-purpose computer is a computer that can be programmed (without modifying its hardware) to emulate various features of single-purpose computers. Server A server[margin: server ]server is a general-purpose high-performance computer with huge resources to provide large-scale services for a broad audience. The audience are people with their personal computer connected to a server. [float Figure: [Figure 0.8: Blade servers. Each blade server is a computer with a modular design optimize for the use of physical space and energy. The enclosure of blade servers is called a chassis.(Source: [https://commons.wikimedia.org/wiki/File:Wikimedia_Foundation_Servers-8055_35.jpg||Wikimedia] , author: Victorgrigas) ] ] Desktop Computer A [margin: desktop computer ]desktop computerdesktop computer is a general-purpose computer with an input and output system designed for a human user, with moderate resources enough for regular use. The input system usually includes a mouse and a keyboard, while the output system usually consists of a monitor that can display a large mount of pixels. The computer is enclosed in a chassis large enough for putting various computer components such as a processor, a motherboard, a power supply, a hard drive, etc. [float Figure: [Figure 0.9: A typical desktop computer. ] ] Mobile Computer A mobile computer[margin: mobile computer ]mobile computer is similar to a desktop computer with fewer resources but can be carried around. Game Consoles Game consoles are similar to desktop computers but are optimized for gaming. Instead of a keyboard and a mouse, the input system of a game console are game controllers, which is a device with a few buttons for controlling on-screen objects; the output system is a television. The chassis is similar to a desktop computer but is smaller. Game consoles use custom processors and graphic processors but are similar to ones in desktop computers. For example, the first Xbox uses a custom Intel Pentium III processor. Handheld game consoles are similar to game consoles, but incorporate both the input and output systems along with the computer in a single package. Embedded Computer An [margin: embedded computer ]embedded computerembedded computer is a single-board or single-chip computer with limited resources designed for integrating into larger hardware devices. [float MarginFigure: [MarginFigure 5: An Intel 82815 Graphics and Memory Controller Hub embedded on a PC motherboard. (Source: [https://commons.wikimedia.org/wiki/File:Intel_82815_GMCH.jpg||Wikimedia] , author: Qurren) ] ][float MarginFigure: [MarginFigure 6: A PIC microcontroller. (Soure: [http://www.microchip.com/wwwproducts/en/PIC18F4620||Microchip] ) ] ] A [margin: microcontroller ]microcontrollerMicrocontroller is an embedded computer designed for controlling other hardware devices. A microcontroller is mounted on a chip. Microcontrollers are general-purpose computers, but with limited resources so that it is only able to perform one or a few specialized tasks. These computers are used for a single purpose, but they are still general-purpose since it is possible to program them to perform different tasks, depends on the requirements, without changing the underlying hardware. Another type of embedded computer is system-on-chip. A system-on-chipsystem-on-chip is a full computer on a single chip. Though a microcontroller is housed on a chip, its purpose is different: to control some hardware. A microcontroller is usually simpler and more limited in hardware resources as it specializes only in one purpose when running, whereas a system-on-chip is a general-purpose computer that can serve multiple purposes. A system-on-chip can run like a regular desktop computer that is capable of loading an operating system and run various applications. A system-on-chip typically presents in a smartphone, such as Apple A5 SoC used in Ipad2 and iPhone 4S, or Qualcomm Snapdragon used in many Android phones.[float MarginFigure: [MarginFigure 7: Apple A5 SoC ] ] Be it a microcontroller or a system-on-chip, there must be an environment where these devices can connect to other devices. This environment is a circuit board called a PCBPCB -- Printed Circuit Board Printed Circuit Board. A printed circuit boardPrinted Circuit Board is a physical board that contains lines and pads to enable electron flows between electrical and electronics components. Without a PCB, devices cannot be combined to create a larger device. As long as these devices are hidden inside a larger device and contribute to a larger device that operates at a higher level layer for a higher level purpose, they are embedded devices. Writing a program for an embedded device is therefore called embedded programmingembedded programming. Embedded computers are used in automatically controlled devices including power tools, toys, implantable medical devices, office machines, engine control systems, appliances, remote controls and other types of embedded systems. The line between a microcontroller and a system-on-chip is blurry. If hardware keeps evolving more powerful, then a microcontroller can get enough resources to run a minimal operating system on it for multiple specialized purposes. In contrast, a system-on-chip is powerful enough to handle the job of a microcontroller. However, using a system-on-chip as a microcontroller would not be a wise choice as price will rise significantly, but we also waste hardware resources since the software written for a microcontroller requires little computing resources. Field Gate Programmable Array [margin: Field Programmable Gate Array ]Field Programmable Gate ArrayField Gate Programmable Array (FPGA FPGA) is a hardware an array of reconfigurable gates that makes circuit structure programmable after it is shipped away from the factory[footnote: This is why it is called Field Gate Programmable Array. It is changeable “in the field” where it is applied. ]. Recall that in the previous chapter, each 74HC00 chip can be configured as a gate, and a more sophisticated device can be built by combining multiple 74HC00 chips. In a similar manner, each FPGA device contains thousands of chips called logic blocks, which is a more complicated chip than a 74HC00 chip that can be configured to implement a Boolean logic function. These logic blocks can be chained together to create a high-level hardware feature. This high-level feature is usually a dedicated algorithm that needs high-speed processing. [float Figure: [Figure 0.10: FPGA Architecture (Source: [http://www.ni.com/tutorial/6097/en/||National Instruments] ) ] ] Digital devices can be designed by combining logic gates, without regarding actual circuit components, since the physical circuits are just multiples of CMOS circuits. Digital hardware, including various components in a computer, is designed by writing code, like a regular programmer, by using a language to describe how gates are wired together. This language is called a Hardware Description LanguageHardware Description Language. Later the hardware description is compiled to a description of connected electronic components called a netlistnetlist, which is a more detailed description of how gates are connected. The difference between FPGA and other embedded computers is that programs in FPGA are implemented at the digital logic level, while programs in embedded computers like microcontrollers or system-on-chip devices are implemented at assembly code level. An algorithm written for a FPGA device is a description of the algorithm in logic gates, which the FPGA device then follows the description to configure itself to run the algorithm. An algorithm written for a microcontroller is in assembly instructions that a processor can understand and act accordingly. FPGA is applied in the cases where the specialized operations are unsuitable and costly to run on a regular computer such as real-time medical image processing, cruise control system, circuit prototyping, video encoding/decoding, etc. These applications require high-speed processing that is not achievable with a regular processor because a processor wastes a significant amount of time in executing many non-specialized instructions - which might add up to thousands of instructions or more - to implement a specialized operation, thus more circuits at physical level to carry the same operation. A FPGA device carries no such overhead; instead, it runs a single specialized operation implemented in hardware directly. Application-Specific Integrated Circuit An Application-Specific Integrated CircuitApplication-Specific Integrated Circuit (or ASICASIC) is a chip designed for a particular purpose rather than for general-purpose use. ASIC does not contain a generic array of logic blocks that can be reconfigured to adapt to any operation like an FPGA; instead, every logic block in an ASIC is made and optimized for the circuit itself. FPGA can be considered as the prototyping stage of an ASIC, and ASIC as the final stage of circuit production. ASIC is even more specialized than FPGA, so it can achieve even higher performance. However, ASICs are very costly to manufacture and once the circuits are made, if design errors happen, everything is thrown away, unlike the FPGA devices which can simply be reprogrammed because of the generic gate array. Computer Architecture The previous section examined various classes of computers. Regardless of shapes and sizes, every computer is designed for an architect from high level to low level. Computer\,Architecture=Instruction\,Set\,Architecture+Computer\,Organization+Hardware At the highest-level is the Instruction Set Architecture. At the middle-level is the Computer Organization. At the lowest-level is the Hardware. Instruction Set Architecture An instruction setinstruction set is the basic set of commands and instructions that a microprocessor understands and can carry out. An Instruction Set ArchitectureInstruction Set Architecture, or ISA ISA, is the design of an environment that implements an instruction set. Essentially, a runtime environment similar to those interpreters of high-level languages. The design includes all the instructions, registers, interrupts, memory models (how memory are arranged to be used by programs), addressing modes, I/O... of a CPU. The more features (e.g. more instructions) a CPU has, the more circuits are required to implement it. Computer organization [margin: Computer organization ]Computer organizationComputer organization is the functional view of the design of a computer. In this view, hardware components of a computer are presented as boxes with input and output that connects to each other and form the design of a computer. Two computers may have the same ISA, but different organizations. For example, both AMD and Intel processors implement x86 ISA, but the hardware components of each processor that make up the environments for the ISA are not the same. Computer organizations may vary depend on a manufacturer's design, but they are all originated from the Von Neumann architecture[footnote: John von Neumann was a mathematician and physicist who invented a computer architecture. ]: [float Figure: [Figure 0.11: Von-Neumann Architecture ] ] CPUCPU fetches instructions continuously from main memory and execute. MemoryMemory stores program code and data. BusBus are electrical wires for sending raw bits between the above components. I/O DevicesI/O Devices are devices that give input to a computer i.e. keyboard, mouse, sensor... and takes the output from a computer i.e. monitor takes information sent from CPU to display it, LED turns on/off according to a pattern computed by CPU... The Von-Neumann computer operates by storing its instructions in main memory, and CPU repeatedly fetches those instructions into its internal storage for executing, one after another. Data are transferred through a data bus between CPU, memory and I/O devices, and where to store in the devices is transferred through the address bus by the CPU. This architecture completely implements the fetch -- decode -- executefetch -- decode -- execute cycle. The earlier computers were just the exact implementations of the Von Neumann architecture, with CPU and memory and I/O devices communicate through the same bus. Today, a computer has more buses, each is specialized in a type of traffic. However, at the core, they are still Von Neumann architecture. To write an OS for a Von Neumann computer, a programmer needs to be able to understand and write code that controls the cores components: CPU, memory, I/O devices, and bus. CPUCPU, or Central Processing UnitCentral Processing Unit, is the heart and brain of any computer system. Understand a CPU is essential to writing an OS from scratch: • To use these devices, a programmer needs to controls the CPU to use the programming interfaces of other devices. CPU is the only way, as CPU is the only direct device a programmer can use and the only device that understand code written by a programmer. • In a CPU, many OS concepts are already implemented directly in hardware, e.g. task switching, paging. A kernel programmer needs to know how to use the hardware features, to avoid duplicating such concept in software, thus wasting computer resources. • CPU built-in OS features boost both OS performance and developer productivity because those features are actual hardware, the lowest possible level, and developers are free to implement such features. • To effectively use the CPU, a programmer needs to understand the documentation provided from CPU manufacturer. For example, [[http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html||Intel® 64 and IA-32 Architectures Software Developer Manuals] . • After understanding one CPU architecture well, it is easier to learn other CPU architectures. A CPU is an implementation of an ISA, effectively the implementation of an assembly language (and depending on the CPU architecture, the language may vary). Assembly language is one of the interfaces that are provided for software engineers to control a CPU, thus control a computer. But how can every computer device be controlled with only the access to the CPU? The simple answer is that a CPU can communicate with other devices through these two interfaces, thus commanding them: Registers Registers[margin: Registers ]are a hardware component for high-speed data access and communication with other hardware devices. Registers allow software to control hardware directly by writing to registers of a device, or receive information from hardware device when reading from registers of a device. Not all registers are used for communication with other devices. In a CPU, most registers are used as high-speed storage for temporary data. Other devices that a CPU can communicate always have a set of registers for interfacing with the CPU. Port Port[margin: Port ]is a specialized register in a hardware device used for communication with other devices. When data is written to a port, it causes a hardware device to perform some operation according to the value written to a port. The difference between a port and a register is that a port does not store data, but delegates data to some other circuit. These two interfaces are extremely important, as they are the only interfaces for controlling hardware with software. Writing device drivers is essentially learning the functionality of each register and how to use them properly to control the device. [margin: Memory ]MemoryMemory is a storage device that stores information. Memory consists of many cells. Each cell is a byte with its address number, so a CPU can use such address number to access an exact location in memory. Memory is where software instructions (in the form of machine language) are stored and retrieved to be executed by the CPU; memory also stores data needed by some software. Memory in a Von Neumann machine does not distinguish between which bytes are data and which bytes are software instructions. It's up to the software to decide, and if somehow data bytes are fetched and executed as instructions, CPU still does it if such bytes represent valid instructions, but will produce undesirable results. To a CPU, there's no code and data; both are merely different types of instructions for it to act on: one tells it how to do something in a specific manner, and one is necessary materials for it to carry out such an action. RAM is controlled by a device called a memory controllermemory controller . Currently, most processors have this device embedded, so the CPU has a dedicated memory bus connecting the processor to the RAM. On older CPUs[footnote: Prior to the CPU's produced in 2009 ], however, this device was located in a chip also known as MCH or Memory Controller HubMemory Controller Hub. In this case, the CPU does not communicate directly with the RAM, but with the MCH chip, and this chip then accesses the memory to read or write data. The first option provides better performance since there is no middleman in the communications between the CPU and the memory. At the physical level, RAM is implemented as a grid of cells that each contain a transistor and an electrical device called a [margin: capacitor ]capacitorcapacitor, which stores charge for short periods of time. The transistor controls access to the capacitor; when switched on, it allows a small charge to be read from or written to the capacitor. The charge on the capacitor slowly dissipates, requiring the inclusion of a refresh circuit to periodically read values from the cells and write them back after amplification from an external power source. Bus[margin: Bus ]Bus is a subsystem that transfers data between computer components or between computers. Physically, buses are just electrical wires that connect all components together with each wire transfering a single big chunk of data. The total number of wires is called bus width[margin: bus width ]bus width, and is dependent on how many wires a CPU can support. If a CPU can only accept 16 bits at a time, then the bus has 16 wires connecting from a component to the CPU, which means the CPU can only retrieve 16 bits of data a time. Hardware Hardware is a specific implementation of a computer. A line of processors implement the same instruction set architecture and use nearly identical organizations but differ in hardware implementation. For example, the Core i7 family provides a model for desktop computers that is more powerful but consumes more energy, while another model for laptops is less performant but more energy efficient. To write software for a hardware device, seldom we need to understand a hardware implementation if documents are available. Computer organization and especially the instruction set architecture are more relevant to an operating system programmer. For that reason, the next chapter is devoted to study the x86 instruction set architecture in depth. x86 architecture A chipsetchipset is a chip with multiple functions. Historically, a chipset is actually a set of individual chips, and each is responsible for a function, e.g. memory controller, graphic controllers, network controller, power controller, etc. As hardware progressed, the set of chips were incorporated into a single chip, thus more space, energy, and cost efficient. In a desktop computer, various hardware devices are connected to each other through a PCB called a motherboardmotherboard. Each CPU needs a compatible motherboard that can host it. Each motherboard is defined by its chipset model that determines the environment that a CPU can control. This environment typically consists of • a slot or more for CPU • a chipset of two chips which are the Northbridge and Southbridge chips – Northbridge chip is responsible for the high-performance communication between CPU, main memory and the graphic card. – Southbridge chip is responsible for the communication with I/O devices and other devices that are not performance sensitive. • slots for memory sticks • a slot or more for graphic cards. • generic slots for other devices, e.g. network card, sound card. • ports for I/O devices, e.g. keyboard, mouse, USB. [float Figure: [Figure 0.12: Motherboard organization. ] ] To write a complete operating system, a programmer needs to understand how to program these devices. After all, an operating system manages hardware automatically to free application programs doing so. However, of all the components, learning to program the CPU is the most important, as it is the component present in any computer, regardless of what type a computer is. For this reason, the primary focus of this book will be on how to program an x86 CPU. Even solely focused on this device, a reasonably good minimal operating system can be written. The reason is that not all computers include all the devices as in a normal desktop computer. For example, an embedded computer might only have a CPU and limited internal memory, with pins for getting input and producing an output; yet, operating systems were written for such devices. However, learning how to program an x86 CPU is a daunting task, with 3 primary manuals written for it: almost 500 pages for volume 1, over 2000 pages for volume 2 and over 1000 pages for volume 3. It is an impressive feat for a programmer to master every aspect of x86 CPU programming. Intel Q35 Chipset Q35 is an Intel chipset released September 2007. Q35 is used as an example of a high-level computer organization because later we will use QEMU to emulate a Q35 system, which is latest Intel system that QEMU can emulate. Though released in 2007, Q35 is relatively modern to the current hardware, and the knowledge can still be reused for current chipset model. With a Q35 chipset, the emulated CPU is also relatively up-to-date with features presented in current day CPUs so we can use the latest software manuals from Intel. Figure [mobo-organization] is a typical current-day motherboard organization, in which Q35 shares similar organization. x86 Execution Environment An execution environmentexecution environment is an environment that provides the facility to make code executable. The execution environment needs to address the following questions: • Supported operations? data transfer, arithmetic, control, floating-point... • Where are operands stored? registers, memory, stack, accumulator • How many explicit operands are there for each instruction? 0, 1, 2, or 3 • How is the operand location specified? register, immediate, indirect, . . . • What type and size of operands are supported? byte, int, float, double, string, vector... • etc. For the remain of this chapter, please carry on the reading to chapter 3 in Intel Manual Volume 1, “Basic Execution Environment” . x86 Assembly and C In this chapter, we will explore assembly language, and how it connects to C. But why should we do so? Isn't it better to trust the compiler, plus no one writes assembly anymore? Not quite. Surely, the compiler at its current state of the art is trustworthy, and we do not need to write code in assembly, most of the time. A compiler can generate code, but as mentioned previously, a high-level language is a collection of patterns of a lower-level language. It does not cover everything that a hardware platform provides. As a consequence, not every assembly instruction can be generated by a compiler, so we still need to write assembly code for these circumstances to access hardware-specific features. Since hardware-specific features require writing assembly code, debugging requires reading it. We might spend even more time reading than writing. Working with low-level code that interacts directly with hardware, assembly code is unavoidable. Also, understand how a compiler generates assembly code could improve a programmer's productivity. For example, if a job or school assignment requires us to write assembly code, we can simply write it in C, then let gcc does the hard working of writing the assembly code for us. We merely collect the generated assembly code, modify as needed and be done with the assignment. We will learn objdump extensively, along with how to use Intel documents to aid in understanding x86 assembly code. objdump objdumpobjdump is a program that displays information about object files. It will be handy later to debug incorrect layout from manual linking. Now, we use objdump to examine how high level source code maps to assembly code. For now, we ignore the output and learn how to use the command first. It is simple to use objdump : $ objdump -d hello -d option only displays assembled contents of executable sections. A sectionsection is a block of memory that contains either program code or data. A code section is executable by the CPU, while a data section is not executable. Non-executable sections, such as .data and .bss (for storing program data), debug sections... are not displayed. We will learn more about section when studying ELF binary file format in chapter [chap:The-Anatomy-of-a-program] . On the other hand: $ objdump -D hello where -D option displays assembly contents of all sections. If -D , -d is implicitly assumed. objdump is mostly used for inspecting assembly code, so -d is the most useful and thus is set by default. The output overruns the terminal screen. To make it easy for reading, send all the output to less: $ objdump -d hello | less To intermix source code and assembly, the binary must be compiled with -g option to include source code in it, then add -S option: $ objdump -S hello | less The default syntax used by objdump is AT&T syntax. To change it to the familiar Intel syntax: $ objdump -M intel -D hello | less When using -M option, option -D or -d must be explicitly supplied. Next, we will use objdump to examine how compiled C data and code are represented in machine code. Finally, we will write a 32-bit kernel, therefore we will need to compile a 32-bit binary and examine it in 32-bit mode: $ objdump -M i386,intel -D hello | less -M i386 tells objdump to display assembly content using 32-bit layout. Knowing the difference between 32-bit and 64-bit is crucial for writing kernel code. We will examine this matter later on when writing our kernel. Reading the output At the start of the output displays the file format of the object file: hello: file format elf64-x86-64 After the line is a series of disassembled sections: Disassembly of section .interp: ... Disassembly of section .note.ABI-tag: ... Disassembly of section .note.gnu.build-id: ... ... etc Finally, each disassembled section displays its actual content - which is a sequence of assembly instructions - with the following format: 4004d6: 55 push rbp • The first column is the address of an assembly instruction. In the above example, the address is 0x4004d6. • The second column is assembly instruction in raw hex values. In the above example, the address is 0x55. • The third column is the assembly instruction. Depends on the section, the assembly instruction might be meaningful or meaningless. For example, if the assembly instructions are in a .text section, then the assembly instructions are actual program code. On the other hand, if the assembly instructions are displayed in a .data section, then we can safely ignore the displayed instructions. The reason is that objdump doesn't know which hex values are code and which are data, so it blindly translates every hex values into assembly instructions. In the above example, the assembly instruction is push %rbp. • The optional fourth column is a comment - appears when there is a reference to an address - to inform where the address originates. For example, the comment in blue:     lea r12,[rip+0x2008ee] # 600e10 <__frame_dummy_init_array_entry> is to inform that the referenced address from [rip+0x2008ee] is 0x600e10, where the variable __frame_dummy_init_array_entry resides. In a disassembled section, it may also contain labels. A label is a name given to an assembly instruction. The label denotes the purpose of an assembly block to a human reader, to make it easier to understand. For example, .text section carries many of such labels to denote where code in a program start; .text section below carries two functions: _start and deregister_tm_clones. The _start function starts at address 4003e0, is annotated to the left of the function name. Right below _start label is also the instruction at address 4003e0. This whole thing means that a label is simply a name of a memory address. The function deregister_tm_clones also shares the same format as every function in the section. 00000000004003e0 <_start>: 4003e0: 31 ed xor ebp,ebp 4003e2: 49 89 d1 mov r9,rdx 4003e5: 5e pop rsi ...more assembly code.... 0000000000400410 : 400410: b8 3f 10 60 00 mov eax,0x60103f 400415: 55 push rbp 400416: 48 2d 38 10 60 00 sub rax,0x601038 ...more assembly code.... Intel manuals The best way to understand and use assembly language properly is to understand precisely the underlying computer architecture and what each machine instruction does. To do so, the most reliable source is to refer to documents provided by vendors. After all, hardware vendors are the one who made their machines. To understand Intel's instruction set, we need the document “Intel 64 and IA-32 architectures software developer's manual combined volumes 2A, 2B, 2C, and 2D: Instruction set reference, A-Z”. The document can be retrieved here: https://software.intel.com/en-us/articles/intel-sdm . • Chapter 1 provides brief information about the manual, and the comment notations used in the book. • Chapter 2 provides an in-depth explanation of the anatomy of an assembly instruction, which we will investigate in the next section. • Chapter 3 - 5 provide the details of every instruction of the x86_64 architecture. • Chapter 6 provides information about safer mode extensions. We won't need to use this chapter. The first volume “Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture” describes the basic architecture and programming environment of Intel processors. In the book, Chapter 5 gives the summary of all Intel instructions, by listing instructions into different categories. We only need to learn general-purpose instructions listed chapter 5.1 for our OS. Chapter 7 describes the purpose of each category. Gradually, we will learn all of these instructions. Read section 1.3 in volume 2, exclude sections 1.3.5 and 1.3.7. Experiment with assembly code The subsequent sections examine the anatomy of an assembly instruction. To fully understand, it is necessary to write code and see the code in its actual form displayed as hex numbers. For this purpose, we use nasm assembler to write a few line of assembly code and see the generated code. ------------------------------------------- Suppose we want to see the machine code generated for this instruction: jmp eax Then, we use an editor e.g. Emacs, then create a new file, write the code and save it in a file, e.g. test.asm. Then, in the terminal, run the command: $ nasm -f bin test.asm -o test -f option specifies the file format, e.g. ELF, of the final output file. But in this case, the format is bin, which means this file is just a flat binary output without any extra information. That is, the written assembly code is translated to machine code as is, without the overhead of the metadata from file format like ELF. Indeed, after compiling, we can examine the output using this command: $ hd test hd (short for hexdump) is a program that displays the content of a file in hex format[margin: Though its name is short for hexdump, hd can display in different base, e.g. binary, other than hex. ]. And get the following output: 00000000 66 ff e0 |f..| 00000003 The file only consists of 3 bytes: 66 ff e0, which is equivalent to the instruction jmp eax. ------------------------------------------- If we were to use elf as file format: $ nasm -f elf test.asm -o test It would be more challenging to learn and understand assembly instructions with all the added noise[footnote: The output from hd. ]: 00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 01 00 03 00 01 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 40 00 00 00 00 00 00 00 34 00 00 00 00 00 28 00 |@.......4.....(.| 00000030 05 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000060 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................| 00000070 06 00 00 00 00 00 00 00 10 01 00 00 02 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 |................| 00000090 07 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| 000000a0 20 01 00 00 21 00 00 00 00 00 00 00 00 00 00 00 | ...!...........| 000000b0 01 00 00 00 00 00 00 00 11 00 00 00 02 00 00 00 |................| 000000c0 00 00 00 00 00 00 00 00 50 01 00 00 30 00 00 00 |........P...0...| 000000d0 04 00 00 00 03 00 00 00 04 00 00 00 10 00 00 00 |................| 000000e0 19 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| 000000f0 80 01 00 00 0d 00 00 00 00 00 00 00 00 00 00 00 |................| 00000100 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000110 ff e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000120 00 2e 74 65 78 74 00 2e 73 68 73 74 72 74 61 62 |..text..shstrtab| 00000130 00 2e 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62 |..symtab..strtab| 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000160 01 00 00 00 00 00 00 00 00 00 00 00 04 00 f1 ff |................| 00000170 00 00 00 00 00 00 00 00 00 00 00 00 03 00 01 00 |................| 00000180 00 74 65 73 74 2e 61 73 6d 00 00 00 00 00 00 00 |.disp8-5.asm....| 00000190 Thus, it is better just to use flat binary format in this case, to experiment instruction by instruction. With such a simple workflow, we are ready to investigate the structure of every assembly instruction. Note: Using the bin format puts nasm by default into 16-bit mode. To enable 32-bit code to be generated, we must add this line at the beginning of an nasm source file: bits 32 Anatomy of an Assembly Instruction Chapter 2 of the instruction reference manual provides an in-depth of view of instruction format. But, the information is too much that it can overwhelm beginners. This section provides an easier instruction before reading the actual chapter in the manual. Recall that an assembly instruction is simply a fixed-size series of bits. The length of an instruction varies and depends on how complicated an instruction is. What every instruction shares is a common format described in the figure above that divides the bits of an instruction into smaller parts that encode different types of information. These parts are: Instruction Prefixes appears at the beginning of an instruction. Prefixes are optional. A programmer can choose to use a prefix or not because in practice, a so-called prefix is just another assembly instruction to be inserted before another assembly instruction that such prefix is applicable. Instructions with 2 or 3-bytes opcodes include the prefixes by default. Opcode is a unique number that identifies an instruction. Each opcode is given an mnemonic name that is human readable, e.g. one of the opcodes for instruction add is 04. When a CPU sees the number 04 in its instruction cache, it sees instruction add and execute accordingly. Opcode can be 1,2 or 3 bytes long and includes an additional 3-bit field in the ModR/M byte when needed. This instruction: jmp [0x1234] generates the machine code: ff 26 34 12 The very first byte, 0xff is the opcode, which is unique to jmp instruction. ModR/M specifies operands of an instruction. Operand can either be a register, a memory location or an immediate value. This component of an instruction consists of 3 smaller parts: • mod field, or modifier field, is combined with r/m field for a total of 5 bits of information to encode 32 possible values: 8 registers and 24 addressing modes. • reg/opcode field encodes either a register operand, or extends the Opcode field with 3 more bits. • r/m field encodes either a register operand or can be combined with mod field to encode an addressing mode. The tables [mod-rm-16] and [mod-rm-32] list all possible 256 values of ModR/M byte and how each value maps to an addressing mode and a register, in 16-bit and 32-bit modes. +---------------------------------------------+-------+-------+-------+-------+-------+-------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | r8(/r) | AL | CL | DL | BL | AH | CH | DH | BH | | r16(/r) | AX | CX | DX | BX | SP | BP¹ | SI | DI | | r32(/r) | EAX | ECX | EDX | EBX | ESP | EBP | ESI | EDI | | mm(/r) | MM0 | MM1 | MM2 | MM3 | MM4 | MM5 | MM6 | MM7 | | xmm(/r) | XMM0 | XMM1 | XMM2 | XMM3 | XMM4 | XMM5 | XMM6 | XMM7 | | (In decimal) /digit (Opcode) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | (In binary) REG = | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | +---------------------------+--------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |        Effective Address |   Mod |   R/M | Values of ModR/M Byte (In Hexadecimal) | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [BX + SI] | 00 | 000 | 00 | 08 | 10 | 18 | 20 | 28 | 30 | 38 | | [BX + DI] | | 001 | 01 | 09 | 11 | 19 | 21 | 29 | 31 | 39 | | [BP + SI] | | 010 | 02 | 0A | 12 | 1A | 22 | 2A | 32 | 3A | | [BP + DI] | | 011 | 03 | 0B | 13 | 1B | 23 | 2B | 33 | 3B | | [SI] | | 100 | 04 | 0C | 14 | 1C | 24 | 2C | 34 | 3C | | [DI] | | 101 | 05 | 0D | 15 | 1D | 25 | 2D | 35 | 3D | | disp16² | | 110 | 06 | 0E | 16 | 1E | 26 | 2E | 36 | 3E | | [BX] | | 111 | 07 | 0F | 17 | 1F | 27 | 2F | 37 | 3F | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [BX + SI] + disp8³ | 01 | 000 | 40 | 48 | 50 | 58 | 60 | 68 | 70 | 78 | | [BX + DI] + disp8 | | 001 | 41 | 49 | 51 | 59 | 61 | 69 | 71 | 79 | | [BP + SI] + disp8 | | 010 | 42 | 4A | 52 | 5A | 62 | 6A | 72 | 7A | | [BP + DI] + disp8 | | 011 | 43 | 4B | 53 | 5B | 63 | 6B | 73 | 7B | | [SI] + disp8 | | 100 | 44 | 4C | 54 | 5C | 64 | 6C | 74 | 7C | | [DI] + disp8 | | 101 | 45 | 4D | 55 | 5D | 65 | 6D | 75 | 7D | | [BP] + disp8 | | 110 | 46 | 4E | 56 | 5E | 66 | 6E | 76 | 7E | | [BX] + disp8 | | 111 | 47 | 4F | 57 | 5F | 67 | 6F | 77 | 7F | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [BX + SI] + disp16 | 10 | 000 | 80 | 88 | 90 | 98 | A0 | A8 | B0 | B8 | | [BX + DI] + disp16 | | 001 | 81 | 89 | 91 | 99 | A1 | A9 | B1 | B9 | | [BP + SI] + disp16 | | 010 | 82 | 8A | 92 | 9A | A2 | AA | B2 | BA | | [BP + DI] + disp16 | | 011 | 83 | 8B | 93 | 9B | A3 | AB | B3 | BB | | [SI] + disp16 | | 100 | 84 | 8C | 94 | 9C | A4 | AC | B4 | BC | | [DI] + disp16 | | 101 | 85 | 8D | 95 | 9D | A5 | AD | B5 | BD | | [BP] + disp16 | | 110 | 86 | 8E | 96 | 9E | A6 | AE | B6 | BE | | [BX] + disp16 | | 111 | 87 | 8F | 97 | 9F | A7 | AF | B7 | BF | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | EAX/AX/AL/MM0/XMM0 | 11 | 000 | C0 | C8 | D0 | D8 | E0 | E8 | F0 | F8 | | ECX/CX/CL/MM1/XMM1 | | 001 | C1 | C9 | D1 | D9 | E1 | E9 | F1 | F9 | | EDX/DX/DL/MM2/XMM2 | | 010 | C2 | CA | D2 | DA | E2 | EA | F2 | FA | | EBX/BX/BL/MM3/XMM3 | | 011 | C3 | CB | D3 | DB | E3 | EB | F3 | FB | | ESP/SP/AHMM4/XMM4 | | 100 | C4 | CC | D4 | DC | E4 | EC | F4 | FC | | EBP/BP/CH/MM5/XMM5 | | 101 | C5 | CD | D5 | DD | E5 | ED | F5 | FD | | ESI/SI/DH/MM6/XMM6 | | 110 | C6 | CE | D6 | DE | E6 | EE | F6 | FE | | EDI/DI/BH/MM7/XMM7 | | 111 | C7 | CF | D7 | DF | E7 | EF | F7 | FF | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1. The default segment register is SS for the effective addresses containing a BP index, DS for other effective addresses. 2. The disp16 nomenclature denotes a 16-bit displacement that follows the ModR/M byte and that is added to the index. 3. The disp8 nomenclature denotes an 8-bit displacement that follows the ModR/M byte and that is sign-extended and added to the index. +---------------------------------------------+-------+-------+-------+-------+-------+-------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | r8(/r) | AL | CL | DL | BL | AH | CH | DH | BH | | r16(/r) | AX | CX | DX | BX | SP | BP | SI | DI | | r32(/r) | EAX | ECX | EDX | EBX | ESP | EBP | ESI | EDI | | mm(/r) | MM0 | MM1 | MM2 | MM3 | MM4 | MM5 | MM6 | MM7 | | xmm(/r) | XMM0 | XMM1 | XMM2 | XMM3 | XMM4 | XMM5 | XMM6 | XMM7 | | (In decimal) /digit (Opcode) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | (In binary) REG = | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | +---------------------------+--------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |        Effective Address |   Mod |   R/M | Values of ModR/M Byte (In Hexadecimal) | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX] | 00 | 000 | 00 | 08 | 10 | 18 | 20 | 28 | 30 | 38 | | [ECX] | | 001 | 01 | 09 | 11 | 19 | 21 | 29 | 31 | 39 | | [EDX] | | 010 | 02 | 0A | 12 | 1A | 22 | 2A | 32 | 3A | | [EBX] | | 011 | 03 | 0B | 13 | 1B | 23 | 2B | 33 | 3B | | [-][-]¹ | | 100 | 04 | 0C | 14 | 1C | 24 | 2C | 34 | 3C | | disp32² | | 101 | 05 | 0D | 15 | 1D | 25 | 2D | 35 | 3D | | [ESI] | | 110 | 06 | 0E | 16 | 1E | 26 | 2E | 36 | 3E | | [EDI] | | 111 | 07 | 0F | 17 | 1F | 27 | 2F | 37 | 3F | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX] + disp8³ | 01 | 000 | 40 | 48 | 50 | 58 | 60 | 68 | 70 | 78 | | [ECX] + disp8 | | 001 | 41 | 49 | 51 | 59 | 61 | 69 | 71 | 79 | | [EDX] + disp8 | | 010 | 42 | 4A | 52 | 5A | 62 | 6A | 72 | 7A | | [EBX] + disp8 | | 011 | 43 | 4B | 53 | 5B | 63 | 6B | 73 | 7B | | [-][-] + disp8 | | 100 | 44 | 4C | 54 | 5C | 64 | 6C | 74 | 7C | | [EBP] + disp8 | | 101 | 45 | 4D | 55 | 5D | 65 | 6D | 75 | 7D | | [ESI] + disp8 | | 110 | 46 | 4E | 56 | 5E | 66 | 6E | 76 | 7E | | [EDI] + disp8 | | 111 | 47 | 4F | 57 | 5F | 67 | 6F | 77 | 7F | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX] + disp32 | 10 | 000 | 80 | 88 | 90 | 98 | A0 | A8 | B0 | B8 | | [ECX] + disp32 | | 001 | 81 | 89 | 91 | 99 | A1 | A9 | B1 | B9 | | [EDX] + disp32 | | 010 | 82 | 8A | 92 | 9A | A2 | AA | B2 | BA | | [EBX] + disp32 | | 011 | 83 | 8B | 93 | 9B | A3 | AB | B3 | BB | | [-][-] + disp32 | | 100 | 84 | 8C | 94 | 9C | A4 | AC | B4 | BC | | [EBP] + disp32 | | 101 | 85 | 8D | 95 | 9D | A5 | AD | B5 | BD | | [ESI] + disp32 | | 110 | 86 | 8E | 96 | 9E | A6 | AE | B6 | BE | | [EDI] + disp32 | | 111 | 87 | 8F | 97 | 9F | A7 | AF | B7 | BF | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | EAX/AX/AL/MM0/XMM0 | 11 | 000 | C0 | C8 | D0 | D8 | E0 | E8 | F0 | F8 | | ECX/CX/CL/MM/XMM1 | | 001 | C1 | C9 | D1 | D9 | E1 | E9 | F1 | F9 | | EDX/DX/DL/MM2/XMM2 | | 010 | C2 | CA | D2 | DA | E2 | EA | F2 | FA | | EBX/BX/BL/MM3/XMM3 | | 011 | C3 | CB | D3 | DB | E3 | EB | F3 | FB | | ESP/SP/AH/MM4/XMM4 | | 100 | C4 | CC | D4 | DC | E4 | EC | F4 | FC | | EBP/BP/CH/MM5/XMM5 | | 101 | C5 | CD | D5 | DD | E5 | ED | F5 | FD | | ESI/SI/DH/MM6/XMM6 | | 110 | C6 | CE | D6 | DE | E6 | EE | F6 | FE | | EDI/DI/BH/MM7/XMM7 | | 111 | C7 | CF | D7 | DF | E7 | EF | F7 | FF | +---------------------------+--------+--------+-------+-------+-------+-------+-------+-------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1. The [-][-] nomenclature means a SIB follows the ModR/M byte. 2. The disp32 nomenclature denotes a 32-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is added to the index. 3. The disp8 nomenclature denotes an 8-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is sign-extended and added to the index. How to read the table: In an instruction, next to the opcode is a ModR/M byte. Then, look up the byte value in this table to get the corresponding operands in the row and column. ------------------------------------------- An instruction uses this addressing mode: jmp [0x1234] Then, the machine code is: ff 26 34 12 0xff is the opcode. Next to it, 0x26 is the ModR/M byte. Look up in the 16-bit table [margin: Remember, using bin format generates 16-bit code by default ], the first operand is in the row, equivalent to a disp16, which means a 16-bit offset. Since the instruction does not have a second operand, the column can be ignored. An instruction uses this addressing mode: add eax, ecx Then the machine code is: 01 c8 0x01 is the opcode. Next to it, c8 is the ModR/M byte. Look up in the 16-bit table at c8 value, the row tells the first operand is ax [margin: Remember, using bin format generates 16-bit code by default ], the column tells the second operand is cx; the column can't be ignored as the second operand is in the instruction. Why is the first operand in the row and the second in a column? Let's break down the ModR/M byte, with an example value c8, into bits: +----------+---------------------+-------------+ | mod | reg/opcode | r/m | +----------+---------------------+-------------+ +----+-----+----+----+-----------+----+----+---+ | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | +----+-----+----+----+-----------+----+----+---+ The mod field divides addressing modes into 4 different categories. Further combines with the r/m field, exactly one addressing mode can be selected from one of the 24 rows. If an instruction only requires one operand, then the column can be ignored. Then the reg/opcode field finally provides the if an instruction requires one. ------------------------------------------- SIB is Scale-Index-Base byte. This byte encodes ways to calculate the memory position into an element of an array. SIB is the name that is based on this formula for calculating an effective address: \mathtt{Effective\,address=scale*index+base} • Index is an offset into an array. • Scale is a factor of Index. Scale is one of the values 1, 2, 4 or 8; any other value is invalid. To scale with values other than 2, 4 or 8, the scale factor must be set to 1, and the offset must be calculated manually. For example, if we want to get the address of the n[superscript:th] element in an array and each element is 12-bytes long. Because each element is 12-bytes long instead of 1, 2, 4 or 8, Scale is set to 1 and a compiler needs to calculate the offset: \mathtt{Effective\,address=1*(12*n)+base} Why do we bother with SIB when we can manually calculate the offset? The answer is that in the above scenario, an additional mul instruction must be executed to get the offset, and the mul instruction consumes more than 1 byte, while the SIB only consumes 1 byte. More importantly, if the element is repeatedly accessed many times in a loop, e.g. millions of times, then an extra mul instruction can detriment the performance as the CPU must spend time executing millions of these additional mul instructions. The values 2, 4 and 8 are not random chosen. They map to 16-bit (or 2 bytes), 32-bit (or 4 bytes) and 64-bit (or 8 bytes) numbers that are often used for intensive numeric calculations. • Base is the starting address. Below is the table listing all 256 values of SIB byte, with the lookup rule similar to ModR/M tables: +--------------------------------------------+------+------+-------+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | r32(/r) | EAX | ECX | EDX | EBX | ESP | EBP | ESI | EDI | | (In decimal) /digit (Opcode) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | (In binary) REG = | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | +---------------------------+-------+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |        Effective Address |   SS |   R/M | Values of SIB Byte (In Hexadecimal) | +---------------------------+-------+--------+------+------+-------+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX] | 00 | 000 | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | | [ECX] | | 001 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F | | [EDX] | | 010 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | | [EBX] | | 011 | 18 | 19 | 1A | 1B | 1C | 1D | 1E | 1F | | none | | 100 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | | [EBP] | | 101 | 28 | 29 | 2A | 2B | 2C | 2D | 2E | 2F | | [ESI] | | 110 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | | [EDI] | | 111 | 38 | 39 | 3A | 3B | 3C | 3D | 3E | 3F | +---------------------------+-------+--------+------+------+-------+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX*2] | 01 | 000 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | | [ECX*2] | | 001 | 48 | 49 | 4A | 4B | 4C | 4D | 4E | 4F | | [EDX*2] | | 010 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | | [EBX*2] | | 011 | 58 | 59 | 5A | 5B | 5C | 5D | 5E | 5F | | none | | 100 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | | [EBP*2] | | 101 | 68 | 69 | 6A | 6B | 6C | 6D | 6E | 6F | | [ESI*2] | | 110 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | | [EDI*2] | | 111 | 78 | 79 | 7A | 7B | 7C | 7D | 7E | 7F | +---------------------------+-------+--------+------+------+-------+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX*4] | 10 | 000 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | | [ECX*4] | | 001 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F | | [EDX*4] | | 010 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | | [EBX*4] | | 011 | 98 | 99 | 9A | 9B | 9C | 9D | 9E | 9F | | none | | 100 | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | | [EBP*4] | | 101 | A8 | A9 | AA | AB | AC | AD | AE | AF | | [ESI*4] | | 110 | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | | [EDI*4] | | 111 | B8 | B9 | BA | BB | BC | BD | BE | BF | +---------------------------+-------+--------+------+------+-------+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | [EAX*8] | 11 | 000 | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | | [ECX*8] | | 001 | C8 | C9 | CA | CB | CC | CD | CE | CF | | [EDX*8] | | 010 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | | [EBX*8] | | 011 | D8 | D9 | DA | DB | DC | DD | DE | DF | | none | | 100 | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 | | [EBP*8] | | 101 | E8 | E9 | EA | EB | EC | ED | EE | EF | | [ESI*8] | | 110 | F0 | F1 | F2 | F3 | F4 | F5 | F6 | F7 | | [EDI*8] | | 111 | F8 | F9 | FA | FB | FC | FD | FE | FF | +---------------------------+-------+--------+------+------+-------+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1. The [*] nomenclature means a disp32 with no base if the MOD is 00B. Otherwise, [*] means disp8 or disp32 + [EBP]. This provides the following address modes: +-----------+---------------------------------+ | MOD bits | Effective Address | +-----------+---------------------------------+ +-----------+---------------------------------+ | 00 | [scaled index] + disp32 | +-----------+---------------------------------+ | 01 | [scaled index] + disp8 + [EBP] | +-----------+---------------------------------+ | 10 | [scaled index] + disp32 + [EBP] | +-----------+---------------------------------+ This instruction: jmp [eax*2 + ebx] generates the following code: 00000000 67 ff 24 43 First of all, the first byte, 0x67 is not an opcode but a prefix. The number is a predefined prefix for address-size override prefix. After the prefix, comes the opcode 0xff and the ModR/M byte 0x24. The value from ModR/M suggests that there exists a SIB byte that follows. The SIB byte is 0x43. Look up in the SIB table, the row tells that eax is scaled by 2, and the column tells that the base to be added is in ebx. Displacement is the offset from the start of the base index. This instruction: jmp [0x1234] generates machine code is: ff 26 34 12 0x1234, which is generated as 34 12 in raw machine code, is the displacement and stands right next to 0x26, which is the ModR/M byte. This instruction: jmp [eax * 4 + 0x1234] generates the machine code: 67 ff 24 8d 34 12 00 00 • 0x67 is an address-size override prefix. Its meaning is that if an instruction runs a default address size e.g. 16-bit, the use of prefix enables the instruction to use non-default address size, e.g. 32-bit or 64-bit. Since the binary is supposed to be 16-bit, 0x67 changes the instruction to 32-bit mode. • 0xff is the opcode. • 0x24 is the ModR/M byte. The value suggests that a SIB byte follows, according to table [mod-rm-32]. • 34 12 00 00 is the displacement. As can be seen, the displacement is 4 bytes in size, which is equivalent to 32-bit, due to address-size override prefix. Immediate When an instruction accepts a fixed value, e.g. 0x1234, as an operand, this optional field holds the value. Note that this field is different from displacement: the value is not necessary used an offset, but an arbitrary value of anything. This instruction: mov eax, 0x1234 generates the code: 66 b8 34 12 00 00 • 0x66 is operand-sized override prefix. Similar to address-size override prefix, this prefix enables operand-size to be non-default. • 0xb8 is one of the opcodes for mov instruction. • 0x1234 is the value to be stored in register eax. It is just a value for storing directly into a register, and nothing more. On the other hand, displacement value is an offset for some address calculation. Read section 2.1 in Volume 2 for even more details. Skim through section 5.1 in volume 1. Read chapter 7 in volume 1. If there are terminologies that you don't understand e.g. segmentation, don't worry as the terms will be explained in later chapters or ignored. Understand an instruction in detail In the instruction reference manual (Volume 2), from chapter 3 onward, every x86 instruction is documented in detail. Whenever the precise behavior of an instruction is needed, we always consult this document first. However, before using the document, we must know the writing conventions first. Every instruction has the following common structure for organizing information: Opcode table lists all possible opcodes of an assembly instruction. Each table contains the following fields, and can have one or more rows: +---------------------------------------------------------------------------------------+ | Opcode Instruction Op/En 64/32-bit Mode CPUID Feature flag Description | +---------------------------------------------------------------------------------------+ Opcode shows a unique hexadecimal number assigned to an instruction. There can be more than one opcode for an instruction, each encodes a variant of the instruction. For example, one variant requires one operand, but another requires two. In this column, there can be other notations aside from hexadecimal numbers. For example, /r indicates that the ModR/M byte of the instruction contains a reg operand and an r/m operand. The detail listing is in section 3.1.1.1 and 3.1.1.2 in the Intel's manual, volume 2. Instruction gives the syntax of the assembly instruction that a programmer can use for writing code. Aside from the mnemonic representation of the opcode, e.g. jmp, other symbols represent operands with specific properties in the instruction. For example, rel8 represents a relative address from 128 bytes before the end of the instruction to 127 bytes after the end of instruction; similarly rel16/rel32 also represents relative addresses, but with the operand size of 16/32-bit instead of 8-bit like rel8. For a detailed listing, please refer to section 3.1.1.3 of volume 2. Op/En is short for Operand/Encoding. An operand encoding specifies how a ModR/M byte encodes the operands that an instruction requires. If a variant of an instruction requires operands, then an additional table named “Instruction Operand Encoding” is added for explaining the operand encoding, with the following structure: +--------+------------+------------+------------+-----------+ | Op/En | Operand 1 | Operand 2 | Operand 3 | Operand 4 | +--------+------------+------------+------------+-----------+ Most instructions require one to two operands. We make use of these instructions for our OS and skip the instructions that require three or four operands. The operands can be readable or writable or both. The symbol (r) denotes a readable operand, and (w) denotes a writable operand. For example, when Operand 1 field contains ModRM:r/m (r), it means the first operand is encoded in r/m field of ModR/M byte, and is only readable. 64/32-bit mode indicates whether the opcode sequence is supported in a 64-bit mode and possibly 32-bit mode. CPUID Feature Flag indicates a particular CPU feature must be available to enable the instruction. An instruction is invalid if a CPU does not support the required feature.[margin: In Linux, the command: cat /proc/cpuinfo lists the information of available CPUs and its features in flags field. ] Compat/Leg Mode Many instructions do not have this field, but instead is replaced with Compat/Leg Mode, which stands for Compatibility or Legacy Mode. This mode enables 64-bit variants of instructions to run normally in 16 or 32-bit mode. [float MarginTable: [MarginTable 2: Notations in Compat/Leg Mode ] +-----------+----------------------------------------------------------------------------------+ | Notation | Description | +-----------+----------------------------------------------------------------------------------+ +-----------+----------------------------------------------------------------------------------+ | Valid | Supported | +-----------+----------------------------------------------------------------------------------+ | I | Not supported | +-----------+----------------------------------------------------------------------------------+ | N.E. | The 64-bit opcode cannot be encoded as it overlaps with existing 32-bit opcode. | +-----------+----------------------------------------------------------------------------------+ ] Description briefly explains the variant of an instruction in the current row. Description specifies the purpose of the instructions and how an instruction works in detail. Operation is pseudo-code that implements an instruction. If a description is vague, this section is the next best source to understand an assembly instruction. The syntax is described in section 3.1.1.9 in volume 2. Flags affected lists the possible changes to system flags in EFLAGS register. Exceptions list the possible errors that can occur when an instruction cannot run correctly. This section is valuable for OS debugging. Exceptions fall into one of the following categories: • Protected Mode Exceptions • Real-Address Mode Exception • Virtual-8086 Mode Exception • Floating-Point Exception • SIMD Floating-Point Exception • Compatibility Mode Exception • 64-bit Mode Exception For our OS, we only use Protected Mode Exceptions and Real-Address Mode Exceptions. The details are in section 3.1.1.13 and 3.1.1.14, volume 2. Example: jmp instruction Let's look at our good old jmp instruction. First, the opcode table: +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | Opcode | Instruction | Op/ En | 64-bit Mode | Compat/Leg Mode | Description | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | EB cb | JMP rel8 | D | Valid | Valid | Jump short, RIP = RIP + 8-bit displacement sign extended to 64-bits | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | E9 cw | JMP rel16 | D | N.S. | Valid | Jump near, relative, displacement relative to next instruction. Not supported in 64-bit mode. | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | E9 cd | JMP rel32 | D | Valid | Valid | Jump near, relative, RIP = RIP + 32-bit displacement sign extended to 64-bits | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | FF /4 | JMP r/m16 | M | N.S. | Valid | Jump near, absolute indirect, address = zero- extended r/m16. Not supported in 64-bit mode | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | FF /4 | JMP r/m32 | M | N.S. | Valid | Jump near, absolute indirect, address given in r/m32. Not supported in 64-bit mode | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | FF /4 | JMP r/m64 | M | Valid | N.E | Jump near, absolute indirect, RIP = 64-Bit offset from register or memory | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | EA cd | JMP ptr16:16 | D | Inv. | Valid | Jump far, absolute, address given in operand | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | EA cp | JMP ptr16:32 | D | Inv. | Valid | Jump far, absolute, address given in operand | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | FF /5 | JMP m16:16 | D | Valid | Valid | Jump far, absolute indirect, address given in m16:16 | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | FF /5 | JMP m16:32 | D | Valid | Valid | Jump far, absolute indirect, address given in m16:32 | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ | REX.W + FF /5 | JMP m16:64 | D | Valid | N.E. | Jump far, absolute indirect, address given in m16:64 | +-----------------+---------------+----------+--------------+------------------+------------------------------------------------------------------------------------------------+ Each row lists a variant of jmp instruction. The first column has the opcode EB cb, with an equivalent symbolic form jmp rel8. Here, rel8 means 128 bytes offset, counting from the end of the instruction. The end of an instruction is the next byte after the last byte of an instruction. To make it more concrete, consider this assembly code: main: jmp main jmp main2 jmp main main2: jmp 0x1234 generates the machine code: [float Table: [Table 4: Memory address of each opcode ] +-------------------+ +-------------------------+ | main | | main2 | +-------------------+ +-------------------------+ \downarrow \downarrow +----------+--------------+-----+-----+-----+-----+-----+--------------+-----+-----+----+ | Address | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | +---------- +-----+-----+-----+-----+-----+--------------+-----+-----+----+ +----------+--------------+-----+-----+-----+-----+-----+--------------+-----+-----+----+ | Opcode | eb | fe | eb | 02 | eb | fa | e9 | 2b | 12 | 00 | +----------+--------------+-----+-----+-----+-----+-----+--------------+-----+-----+----+ ] The first jmp main instruction is generated into eb fe and occupies the addresses 00 and 01; the end of the first jmp main is at address 02, past the last byte of the first jmp main which is located at the address 01. The value fe is equivalent to -2, since eb opcode uses only a byte (8 bits) for relative addressing. The offset is -2, and the end address of the first jmp main is 02, adding them together we get 00 which is the destination address for jumping to. Similarly, the jmp main2 instruction is generated into eb 02, which means the offset is +2; the end address of jmp main2 is at 04, and adding together with the offset we get the destination address is 06, which is the start instruction marked by the label main2. The same rule can be applied to rel16 and rel32 encoding. In the example code, jmp 0x1234 uses rel16 (which means 2-byte offset) and is generated into e9 2b 12. As the table [jmp-instruction] shows, e9 opcode takes a cw operand, which is a 2-byte offset (section 3.1.1.1, volume 2). Notice one strange issue here: the offset value is 2b 12, while it is supposed to be 34 12. There is nothing wrong. Remember, rel8/rel16/rel32 is an offset, not an address. A offset is a distance from a point. Since no label is given but a number, the offset is calculated from the start of a program. In this case, the start of the program is the address 00, the end of jmp 0x1234 is the address 09[footnote: which means 9 bytes was consumed, starting from address 0. ], so the offset is calculated as 0x1234 - 0x9 = 0x122b. That solved the mystery! The jmp instructions with opcode FF /4 enable jumping to a near, absolute address stored in a general-purpose register or a memory location; or in short, as written in the description, absolute indirect. The symbol /4 is the column with digit 4 in table [mod-rm-16] [footnote: The column with the following fields: AH SP ESP M45 XMM4 4 100 ]. For example: jmp [0x1234] is generated into: ff 26 34 12 Since this is 16-bit code, we use table [mod-rm-16]. Looking up the table, ModR/M value 26 means disp16, which means a 16-bit offset from the start of current index[footnote: Look at the note under the table. ], which is the base address stored in DS register. In this case, jmp [0x1234] is implicitly understood as jmp [ds:0x1234], which means the destination address is 0x1234 bytes away from the start of a data segment. The jmp instruction with opcode FF /5 enables jumping to a far, absolute address stored in a memory location (as opposed to /4, which means stored in a register); in short, a far pointer. To generate such instruction, the keyword far is needed to tell nasm we are using a far pointer: jmp far [eax] is generated into: 67 ff 28 Since 28 is the value in the 5th column of the table [mod-rm-32][footnote: Remember the prefix 67 indicates the instruction is used as 32-bit. The prefix only added if the default environment is assumed as 16-bit when generating code by an assembler. ] that refers to [eax], we successfully generate an instruction for a far jump. After CPU runs the instruction, the program counter eip and code segment register cs is set to the memory address, stored in the memory location that eax points to, and CPU starts fetching code from the new address in cs and eip. To make it more concrete, here is an example: The far address consumes total of 6 bytes in size for a 16-bit segment and 32-bit address, which is encoded as m16:32 from the table [jmp-instruction]. As can be seen from the figure above, the blue part is a segment address, loaded into cs register with the value 0x5678; the red part is the memory address within that segment, loaded into eip register with the value 0x1234 and start executing from there. Finally, the jmp instructions with EA opcode jump to a direct absolute address. For example, the instruction: jmp 0x5678:0x1234 is generated into: ea 34 12 78 56 The address 0x5678:0x1234 is right next to the opcode, unlike FF /5 instruction that needs an indirect address in eax register. We skip the jump instruction with REX prefix, as it is a 64-bit instruction. Examine compiled data In this section, we will examine how data definition in C maps to its assembly form. The generated code is extracted from .bss section. That means, the assembly code displayed has no[footnote: Actually, code is just a type of data, and is often used for hijacking into a running program to execute such code. However, we have no use for it in this book. ], aside from showing that such a value has an equivalent assembly opcode that represents an instruction. The code-assembly listing is not random, but is based on Chapter 4 of Volume 1, “Data Type”. The chapter lists fundamental data types that x86 hardware operates on, and through learning the generated assembly code, it can be understood how close C maps its syntax to hardware, and then a programmer can see why C is appropriate for OS programming. The specific objdump command used in this section will be: $ objdump -z -M intel -S -D -j .data -j .bss | less Note: zero bytes are hidden with three dot symbols: ... To show all the zero bytes, we add -z option. Fundamental data types The most basic types that x86 architecture works with are based on sizes, each is twice as large as the previous one: 1 byte (8 bits), 2 bytes (16 bits), 4 bytes (32 bits), 8 bytes (64 bits) and 16 bytes (128 bits). These types are simplest: they are just chunks of memory at different sizes that enables CPU to access memory efficiently. From the manual, section 4.1.1, volume 1: Words, doublewords, and quadwords do not need to be aligned in memory on natural boundaries. The natural boundaries for words, double words, and quadwords are even-numbered addresses, addresses evenly divisible by four, and addresses evenly divisible by eight, respectively. However, to improve the performance of programs, data structures (especially stacks) should be aligned on natural boundaries whenever possible. The reason for this is that the processor requires two memory accesses to make an unaligned memory access; aligned accesses require only one memory access. A word or doubleword operand that crosses a 4-byte boundary or a quadword operand that crosses an 8-byte boundary is considered unaligned and requires two separate memory bus cycles for access. Some instructions that operate on double quadwords require memory operands to be aligned on a natural boundary. These instructions generate a general-protection exception (#GP) if an unaligned operand is specified. A natural boundary for a double quadword is any address evenly divisible by 16. Other instructions that operate on double quadwords permit unaligned access (without generating a general-protection exception). However, additional memory bus cycles are required to access unaligned data from memory. In C, the following primitive types (must include stdint.h) maps to the fundamental types: Source #include uint8_t @|\color{red}\bfseries byte|@ = 0x12; uint16_t @|\color{blue}\bfseries word|@ = 0x1234; uint32_t @|\color{green}\bfseries dword|@ = 0x12345678; uint64_t @|\color{magenta}\bfseries qword|@ = 0x123456789abcdef; unsigned __int128 @|\color{cyan}\bfseries dqword1|@ = (__int128) 0x123456789abcdef; unsigned __int128 @|\color{cyan}\bfseries dqword2|@ = (__int128) 0x123456789abcdef << 64; int main(int argc, char *argv[]) { return 0; } Assembly 0804a018 : 804a018: 12 00 adc al,BYTE PTR [eax] 0804a01a : 804a01a: 34 12 xor al,0x12 0804a01c : 804a01c: 78 56 js 804a074 <_end+0x48> 804a01e: 34 12 xor al,0x12 0804a020 : 804a020: ef out dx,eax 804a021: cd ab int 0xab 804a023: 89 67 45 mov DWORD PTR [edi+0x45],esp 804a026: 23 01 and eax,DWORD PTR [ecx] 0000000000601040 : 601040: ef out dx,eax 601041: cd ab int 0xab 601043: 89 67 45 mov DWORD PTR [rdi+0x45],esp 601046: 23 01 and eax,DWORD PTR [rcx] 601048: 00 00 add BYTE PTR [rax],al 60104a: 00 00 add BYTE PTR [rax],al 60104c: 00 00 add BYTE PTR [rax],al 60104e: 00 00 add BYTE PTR [rax],al 0000000000601050 : 601050: 00 00 add BYTE PTR [rax],al 601052: 00 00 add BYTE PTR [rax],al 601054: 00 00 add BYTE PTR [rax],al 601056: 00 00 add BYTE PTR [rax],al 601058: ef out dx,eax 601059: cd ab int 0xab 60105b: 89 67 45 mov DWORD PTR [rdi+0x45],esp 60105e: 23 01 and eax,DWORD PTR [rcx] gcc generates the variables byte, word, dword, qword, dqword1, dword2, written earlier, with their respective values highlighted in the same colors; variables of the same type are also highlighted in the same color. Since this is data section, the assembly listing carries no meaning. When byte is declared with uint8_t, gcc guarantees that the size of byte is always 1 byte. But, an alert reader might notice the 00 value next to the 12 value in the byte variable. This is normal, as gcc avoid memory misalignment by adding extra padding bytespadding bytes. To make it easier to see, we look at readelf output of .data section: $ readelf -x .data hello the output is (the colors mark which values belong to which variables): Hex dump of section '.data': 0x00601020 00000000 00000000 00000000 00000000 ................ 0x00601030 12003412 78563412 efcdab89 67452301 ..4.xV4.....gE#. 0x00601040 efcdab89 67452301 00000000 00000000 ....gE#......... 0x00601050 00000000 00000000 efcdab89 67452301 ............gE#. As can be seen in the readelf output, variables are allocated storage space according to their types and in the declared order by the programmer (the colors correspond the the variables). Intel is a little-endian machine, which means smaller addresses hold bytes with smaller values, larger addresses hold byte with larger values. For example, 0x1234 is displayed as 34 12; that is, 34 appears first at address 0x601032, then 12 at 0x601033. The decimal values within a byte is unchanged, so we see 34 12 instead of 43 21. This is quite confusing at first, but you will get used to it soon. Also, isn't it redundant when char type is always 1 byte already and why do we bother adding int8_t? The truth is, char type is not guaranteed to be 1 byte in size, but only the minimum of 1 byte in size. In C, a byte is defined to be the size of a char, and a char is defined to be smallest addressable unit of the underlying hardware platform. There are hardware devices that the smallest addressable unit is 16 bit or even bigger, which means char is 2 bytes in size and a “byte” in such platforms is actually 2 units of 8-bit bytes. Not all architectures support the double quadword type. Still, gcc does provide support for 128-bit number and generate code when a CPU supports it (that is, a CPU must be 64-bit). By specifying a variable of type __int128 or unsigned __int128, we get a 128-bit variable. If a CPU does not support 64-bit mode, gcc throws an error. The data types in C, which represents the fundamental data types, are also called unsigned numbers. Other than numerical calculations, unsigned numbers are used as a tool for structuring data in memory; we will see this application later on in the book, when various data structures are organized into bit groups. In all the examples above, when the value of a variable with smaller size is assigned to a variable with larger size, the value easily fits in the larger variable. On the contrary, the value of a variable with larger size is assigned to a variable with smaller size, two scenarios occur: • The value is greater than the maximum value of the variable with smaller layout, so it needs truncating to the size of the variable and causing incorrect value. • The value is smaller than the maximum value of the variable with a smaller layout, so it fits the variable. However, the value might be unknown until runtime and can be value, it is best not to let such implicit conversion handled by the compiler, but explicitly controlled by a programmer. Otherwise it will cause subtle bugs that are hard to catch as the erroneous values might rarely be used to reproduce the bugs. Pointer Data Types Pointers are variables that hold memory addresses. x86 works with 2 types of pointers: Near pointer is a 16-bit/32-bit offset within a segment, also called effective address. Far pointer is also an offset like a near pointer, but with an explicit segment selector. C only provides support for near pointers, since far pointers are platform dependent. In application code, you can assume that the address of current segment starts at 0, so the offset is actually any memory address from 0 to the maximum address. Source #include int8_t i = 0; int8_t @|\color{red}\bfseries *p1|@ = (int8_t *) 0x1234; int8_t @|\color{blue}\bfseries *p2|@ = &i; int main(int argc, char *argv[]) { return 0; } Assembly 0000000000601030 : 601030: 34 12 xor al,0x12 601032: 00 00 add BYTE PTR [rax],al 601034: 00 00 add BYTE PTR [rax],al 601036: 00 00 add BYTE PTR [rax],al 0000000000601038 : 601038: 41 10 60 00 adc BYTE PTR [r8+0x0],spl 60103c: 00 00 add BYTE PTR [rax],al 60103e: 00 00 add BYTE PTR [rax],al Disassembly of section .bss: 0000000000601040 <__bss_start>: 601040: 00 00 add BYTE PTR [rax],al 0000000000601041 : 601041: 00 00 add BYTE PTR [rax],al 601043: 00 00 add BYTE PTR [rax],al 601045: 00 00 add BYTE PTR [rax],al 601047: 00 .byte 0x0 The pointer p1 holds a direct address with the value 0x1234. The pointer p2 holds the address of the variable i. Note that both the pointers are 8 bytes in size (or 4-byte, if 32-bit). Bit Field Data Type A bit fieldbit field is a contiguous sequence of bits. Bit fields allow data structuring at bit level. For example, a 32-bit data can hold multiple bit fields that represent multiples different pieces of information, such as bits 0-4 specifies the size of a data structure, bit 5-6 specifies permissions and so on. Data structures at the bit level are common for low-level programming. Source struct bit_field { int data1:8; int data2:8; int data3:8; int data4:8; }; struct bit_field2 { int data1:8; int data2:8; int data3:8; int data4:8; char data5:4; }; struct normal_struct { int data1; int data2; int data3; int data4; }; struct normal_struct @|\color{red}\bfseries ns|@ = { .data1 = @|\color{red}\bfseries 0x12345678|@, .data2 = @|\color{red}\bfseries 0x9abcdef0|@, .data3 = @|\color{red}\bfseries 0x12345678|@, .data4 = @|\color{red}\bfseries 0x9abcdef0|@, }; int @|\color{blue}\bfseries i|@ = 0x12345678; struct bit_field @|\color{magenta}\bfseries bf|@ = { .data1 = @|\color{magenta}\bfseries 0x12|@, .data2 = @|\color{magenta}\bfseries 0x34|@, .data3 = @|\color{magenta}\bfseries 0x56|@, .data4 = @|\color{magenta}\bfseries 0x78|@ }; struct bit_field2 @|\color{green}\bfseries bf2|@ = { .data1 = @|\color{green}\bfseries 0x12|@, .data2 = @|\color{green}\bfseries 0x34|@, .data3 = @|\color{green}\bfseries 0x56|@, .data4 = @|\color{green}\bfseries 0x78|@, .data5 = @|\color{green}\bfseries 0xf|@ }; int main(int argc, char *argv[]) { return 0; } Assembly Each variable and its value are given a unique color in the assembly listing below: 0804a018 : 804a018: 78 56 js 804a070 <_end+0x34> 804a01a: 34 12 xor al,0x12 804a01c: f0 de bc 9a 78 56 34 lock fidivr WORD PTR [edx+ebx*4+0x12345678] 804a023: 12 804a024: f0 de bc 9a 78 56 34 lock fidivr WORD PTR [edx+ebx*4+0x12345678] 804a02b: 12 0804a028 : 804a028: 78 56 js 804a080 <_end+0x44> 804a02a: 34 12 xor al,0x12 0804a02c : 804a02c: 12 34 56 adc dh,BYTE PTR [esi+edx*2] 804a02f: 78 12 js 804a043 <_end+0x7> 0804a030 : 804a030: 12 34 56 adc dh,BYTE PTR [esi+edx*2] 804a033: 78 0f js 804a044 <_end+0x8> 804a035: 00 00 add BYTE PTR [eax],al 804a037: 00 .byte 0x0 The sample code creates 4 variables: ns, i, bf, bf2. The definition of normal_struct and bit_field structs both specify 4 integers. bit_field specifies additional information next to its member name, separated by a colon, e.g. .data1 : 8. This extra information is the bit width of each bit group. It means, even though defined as an int, .data1 only consumes 8 bit of information. If additional data members are specified after .data1, two scenarios happen: • If the new data members fit within the remaining bits after .data, which are 24 bits[footnote: Since .data1 is declared as an int, 32 bits are still allocated, but .data1 can only access 8 bits of information. ], then the total size of bit_field struct is still 4 bytes, or 32 bits. • If the new data members don't fit, then the remaining 24 bits (3 bytes) are still allocated. However, the new data members are allocated brand new storages, without using the previous 24 bits. In the example, the 4 data members: .data1, .data2, .data3 and .data4, each can access 8 bits of information, and together can access all of 4 bytes of the integer first declared by .data1. As can be seen by the generated assembly code, the values of bf are follow natural order as written in the C code: 12 34 56 78, since each value is a separate members. In contrast, the value of i is a number as a whole, so it is subject to the rule of little endianess and thus contains the value 78 56 34 12. Note that at 804a02f, is the address of the final byte in bf, but next to it is a number 12, despite 78 is the last number in it. This extra number 12 does not belong to the value of bf. objdump is just being confused that 78 is an opcode; 78 corresponds to js instruction, and it requires an operand. For that reason, objdump grabs whatever the next byte after 78 and put it there. objdump is a tool to display assembly code after all. A better tool to use is gdb that we will learn in the next chapter. But for this chapter, objdump suffices. Unlike bf, each data member in ns is allocated fully as an integer, 4 bytes each, 16 bytes in total. As we can see, bit field and normal struct are different: bit field structure data at the bit level, while normal struct works at byte level. Finally, the struct of bf2[footnote: bit_field2 ] is the same of bf[footnote: bit_field ], except it contains one more data member: .data5, and is defined as an integer. For this reason, another 4 bytes are allocated just for .data5, even though it can only access 8 bits of information, and the final value of bf2 is: 12 34 56 78 0f 00 00 00. The remaining 3 bytes must be accessed by the mean of a pointer, or casting to another data type that can fully access all 4 bytes.. What happens when the definition of bit_field struct and bf variable are changed to: struct bit_field { int data1:8; }; struct bit_field bf = { .data1 = 0x1234, }; What will be the value of .data1? What happens when the definition of bit_field2 struct is changed to: struct bit_field2 { int data1:8; int data5:32; }; What is layout of a variable of type bit_field2? String Data Types Although share the same name, string as defined by x86 is different than a string in C. x86 defines string as “continuous sequences of bits, bytes, words, or doublewords”. On the other hand, C defines a string as an array of 1-byte characters with a zero as the last element of the array to make a null-terminated string. This implies that strings in x86 are arrays, not C strings. A programmer can define an array of bytes, words or doublewords with char or uint8_t, short or uint16_t and int or uint32_t, except an array of bits. However, such a feature can be easily implemented, as an array of bits is essentially any array of bytes, or words or doublewords, but operates at the bit level. The following code demonstrates how to define array (string) data types: Source #include uint8_t @|\color{red}\bfseries a8[2]|@ = {0x12, 0x34}; uint16_t @|\color{blue}\bfseries a16[2]|@ = {0x1234, 0x5678}; uint32_t @|\color{magenta}\bfseries a32[2]|@ = {0x12345678, 0x9abcdef0}; uint64_t @|\color{green}\bfseries a64[2]|@ = {0x123456789abcdef0, 0x123456789abcdef0}; int main(int argc, char *argv[]) { return 0; } Assembly 0804a018 : 804a018: 12 34 00 adc dh,BYTE PTR [eax+eax*1] 804a01b: 00 34 12 add BYTE PTR [edx+edx*1],dh 0804a01c : 804a01c: 34 12 xor al,0x12 804a01e: 78 56 js 804a076 <_end+0x3a> 0804a020 : 804a020: 78 56 js 804a078 <_end+0x3c> 804a022: 34 12 xor al,0x12 804a024: f0 de bc 9a f0 de bc lock fidivr WORD PTR [edx+ebx*4-0x65432110] 804a02b: 9a 0804a028 : 804a028: f0 de bc 9a 78 56 34 lock fidivr WORD PTR [edx+ebx*4+0x12345678] 804a02f: 12 804a030: f0 de bc 9a 78 56 34 lock fidivr WORD PTR [edx+ebx*4+0x12345678] 804a037: 12 Despite a8 is an array with 2 elements, each is 1-byte long, but it is still allocated with 4 bytes. Again, to ensure natural alignment for best performance, gcc pads extra zero bytes. As shown in the assembly listing, the actual value of a8 is 12 34 00 00, with a8[0] equals to 12 and a8[1] equals to 34. Then it comes a16 with 2 elements, each is 2-byte long. Since 2 elements are 4 bytes in total, which is in the natural alignment, gcc pads no byte. The value of a16 is 34 12 78 56, with a16[0] equals to 34 12 and a16[1] equals to 78 56. Note that, objdump is confused again, as de is the opcode for the instruction fidivr (short of reverse divide) that requires another operand, so objdump grabs whatever the next bytes that makes sense to it for creating “an operand”. Only the highlighted values belong to a32. Next is a32, with 2 elements, 4 bytes each. Similar to above arrays, the value of a32[0] is 78 56 34 12, the value of a32[1] is f0 de bc 9a, exactly what is assigned in the C code. Finally is a64, also with 2 elements, but 8 bytes each. The total size of a64 is 16 bytes, which is in the natural alignment, therefore no padding bytes added. The values of both a64[0] and a64[1] are the same: f0 de bc 9a 78 56 34 12, that got misinterpreted to fidivr instruction. [float Figure: [Figure 0.13: a8, a16, a32 and a64 memory layouts ] a8:   +----------+ | 12 | 34 | +----------+ a16: +--------------------+ | 34 12   | 78 56    | +--------------------+ a32: +----------------------------------------+ | 78 56 34 12       | f0 de bc 9a        | +----------------------------------------+ a64: +---------------------------------------------------------------------------------+ | f0 de bc 9a 78 56 34 12               | f0 de bc 9a 78 56 34 12                 | +---------------------------------------------------------------------------------+ ] However, beyond one-dimensional arrays that map directly to hardware string type, C provides its own syntax for multi-dimensional arrays: Source #include uint8_t @|\color{red}\bfseries a2[2][2]|@ = { {0x12, 0x34}, {0x56, 0x78} }; uint8_t @|\color{blue}\bfseries a3[2][2][2]|@ = { {{0x12, 0x34}, {0x56, 0x78}}, {{0x9a, 0xbc}, {0xde, 0xff}}, }; int main(int argc, char *argv[]) { return 0; } Assembly 0804a018 : 804a018: 12 34 56 adc dh,BYTE PTR [esi+edx*2] 804a01b: 78 12 js 804a02f <_end+0x7> 0804a01c : 804a01c: 12 34 56 adc dh,BYTE PTR [esi+edx*2] 804a01f: 78 9a js 8049fbb <_DYNAMIC+0xa7> 804a021: bc .byte 0xbc 804a022: de ff fdivrp st(7),st Technically, multi-dimensional arrays are like normal arrays: in the end, the total size is translated into flat allocated bytes. A 2 x 2 array is allocated with 4 bytes; a 2\times2\times2 array is allocated with 8 bytes, as can be seen in the assembly listing of a2[footnote: Again, objdump is confused and put the number 12 next to 78 in a3 listing. ] and a3. In low-level assembly code, the representation is the same between a[4] and a[2][2]. However, in high-level C code, the difference is tremendous. The syntax of multi-dimensional array enables a programmer to think with higher level concepts, instead of translating manually from high-level concepts to low-level code and work with high-level concepts in his head at the same time. The following two-dimensional array can hold a list of 2 names with the length of 10: char names[2][10] = { "John Doe", "Jane Doe" }; To access a name, we simply adjust the column index[footnote: The left index is called column index since it changes the index based on a column. ] e.g. names[0], names[1]. To access individual character within a name, we use the row index[footnote: Same with column index, the right index is called row index since it changes the index based on a row. ] e.g. names[0][0] gives the character “J”, names[0][1] gives the character “o” and so on. Without such syntax, we need to create a 20-byte array e.g. names[20], and whenever we want to access a character e.g. to check if the names contains with a number in it, we need to calculate the index manually. It would be distracting, since we constantly need to switch thinkings between the actual problem and the translate problem. Since this is a repeating pattern, C abstracts away this problem with the syntax for define and manipulating multi-dimensional array. Through this example, we can clearly see the power of abstraction through language can give us. It would be ideal if a programmer is equipped with such power to define whatever syntax suitable for a problem at hands. Not many languages provide such capacity. Fortunately, through C macro, we can partially achieve that goal . In all cases, an array is guaranteed to generate contiguous bytes of memory, regardless of the dimensions it has. What is the difference between a multi-dimensional array and an array of pointers, or even pointers of pointers? Examine compiled code This section will explore how compiler transform high level code into assembly code that CPU can execute, and see how common assembly patterns help to create higher level syntax. -S option is added to objdump to better demonstrate the connection between high and low level code. In this section, the option --no-show-raw-insn is added to objdump command to omit the opcodes for clarity: $ objdump --no-show-raw-insn -M intel -S -D | less Data Transfer Previous section explores how various types of data are created, and how they are laid out in memory. Once memory storages are allocated for variables, they must be accessible and writable. Data transfer instructions move data (bytes, words, doublewords or quadwords) between memory and registers, and between registers, effectively read from a storage source and write to another storage source. Source #include int32_t i = 0x12345678; int main(int argc, char *argv[]) { int j = i; int k = 0xabcdef; return 0; } Assembly 080483db
: #include int32_t i = 0x12345678; int main(int argc, char *argv[]) { 80483db: push ebp 80483dc: mov ebp,esp 80483de: sub esp,0x10 int j = i; 80483e1: mov eax,ds:0x804a018 80483e6: mov DWORD PTR [ebp-0x8],eax int k = 0xabcdef; 80483e9: mov DWORD PTR [ebp-0x4],0xabcdef return 0; 80483f0: mov eax,0x0 } 80483f5: leave 80483f6: ret 80483f7: xchg ax,ax 80483f9: xchg ax,ax 80483fb: xchg ax,ax 80483fd: xchg ax,ax 80483ff: nop The general data movement is performed with the mov instruction. Note that despite the instruction being called mov, it actually copies data from one destination to another. The red instruction copies data from the register esp to the register ebp. This mov instruction moves data between registers and is assigned the opcode 89. The blue instructions copies data from one memory location (the i variable) to another (the j variable). There exists no data movement from memory to memory; it requires two mov instructions, one for copying the data from a memory location to a register, and one for copying the data from the register to the destination memory location. The pink instruction copies an immediate value into memory. Finally, the green instruction copies immediate data into a register. Expressions Source int expr(int i, int j) { int add = i + j; int sub = i - j; int mul = i * j; int div = i / j; int mod = i % j; int neg = -i; int and = i & j; int or = i | j; int xor = i ^ j; int not = ~i; int shl = i << 8; int shr = i >> 8; char equal1 = (i == j); int equal2 = (i == j); char greater = (i > j); char less = (i < j); char greater_equal = (i >= j); char less_equal = (i <= j); int logical_and = i && j; int logical_or = i || j; ++i; --i; int i1 = i++; int i2 = ++i; int i3 = i--; int i4 = --i; return 0; } int main(int argc, char *argv[]) { return 0; } Assembly The full assembly listing is really long. For that reason, we examine expression by expression. Expression: int add = i + j; 80483e1: mov edx,DWORD PTR [ebp+0x8] 80483e4: mov eax,DWORD PTR [ebp+0xc] 80483e7: add eax,edx 80483e9: mov DWORD PTR [ebp-0x34],eax The assembly code is straight forward: variable i and j are stored in eax and edx respectively, then added together with the add instruction, and the final result is stored into eax. Then, the result is saved into the local variable add, which is at the location [ebp-0x34]. Expression: int sub = i - j; 80483ec: mov eax,DWORD PTR [ebp+0x8] 80483ef: sub eax,DWORD PTR [ebp+0xc] 80483f2: mov DWORD PTR [ebp-0x30],eax Similar to add instruction, x86 provides a sub instruction for subtraction. Hence, gcc translates a subtraction into sub instruction, with eax is reloaded with i, as eax still carries the result from previous expression. Then, j is subtracted from i. After the subtraction, the value is saved into the variable sub, at location [ebp-0x30]. Expression: int mul = i * j; 80483f5: mov eax,DWORD PTR [ebp+0x8] 80483f8: imul eax,DWORD PTR [ebp+0xc] 80483fc: mov DWORD PTR [ebp-0x34],eax Similar to sub instruction, only eax is reloaded, since it carries the result of previous calculation. imul performs signed multiply[footnote: Unsigned multiply is perform by mul instruction. ]. eax is first loaded with i, then is multiplied with j and stored the result back into eax, then stored into the variable mul at location [ebp-0x34]. Expression: int div = i / j; 80483ff: mov eax,DWORD PTR [ebp+0x8] 8048402: cdq 8048403: idiv DWORD PTR [ebp+0xc] 8048406: mov DWORD PTR [ebp-0x30],eax Similar to imul, idiv performs sign divide. But, different from imul above idiv only takes one operand: 1. First, i is reloaded into eax. 2. Then, cdq converts the double word value in eax into a quadword value stored in the pair of registers edx:eax, by copying the signed (bit 31[superscript:th]) of the value in eax into every bit position in edx. The pair edx:eax is the dividend, which is the variable i, and the operand to idiv is the divisor, which is the variable j. 3. After the calculation, the result is stored into the pair edx:eax registers, with the quotient in eax and remainder in edx. The quotient is stored in the variable div, at location [ebp-0x30]. Expression: int mod = i % j; 8048409: mov eax,DWORD PTR [ebp+0x8] 804840c: cdq 804840d: idiv DWORD PTR [ebp+0xc] 8048410: mov DWORD PTR [ebp-0x2c],edx The same idiv instruction also performs the modulo operation, since it also calculates a remainder and stores in the variable mod, at location [ebp-0x2c]. Expression: int neg = -i; 8048413: mov eax,DWORD PTR [ebp+0x8] 8048416: neg eax 8048418: mov DWORD PTR [ebp-0x28],eax neg replaces the value of operand (the destination operand) with its two's complement (this operation is equivalent to subtracting the operand from 0). In this example, the value i in eax is replaced replaced with -i using neg instruction. Then, the new value is stored in the variable neg at [ebp-0x28]. Expression: int and = i & j; 804841b: mov eax,DWORD PTR [ebp+0x8] 804841e: and eax,DWORD PTR [ebp+0xc] 8048421: mov DWORD PTR [ebp-0x24],eax and performs a bitwise AND operation on two operands, and stores the result in the destination operand, which is the variable and at [ebp-0x24]. Expression: int or = i | j; 8048424: mov eax,DWORD PTR [ebp+0x8] 8048427: or eax,DWORD PTR [ebp+0xc] 804842a: mov DWORD PTR [ebp-0x20],eax Similar to and instruction, or performs a bitwise OR operation on two operands, and stores the result in the destination operand, which is the variable or at [ebp-0x20] in this case. Expression: int xor = i ^ j; 804842d: mov eax,DWORD PTR [ebp+0x8] 8048430: xor eax,DWORD PTR [ebp+0xc] 8048433: mov DWORD PTR [ebp-0x1c],eax Similar to and/or instruction, xor performs a bitwise XOR operation on two operands, and stores the result in the destination operand, which is the variable xor at [ebp-0x1c]. Expression: int not = ~i; 8048436: mov eax,DWORD PTR [ebp+0x8] 8048439: not eax 804843b: mov DWORD PTR [ebp-0x18],eax not performs a bitwise NOT operation (each 1 is set to 0, and each 0 is set to 1) on the destination operand and stores the result in the destination operand location, which is the variable not at [ebp-0x18]. Expression: int shl = i << 8; 804843e: mov eax,DWORD PTR [ebp+0x8] 8048441: shl eax,0x8 8048444: mov DWORD PTR [ebp-0x14],eax shl (shift logical left) shifts the bits in the destination operand to the left by the number of bits specified in the source operand. In this case, eax stores i and shl shifts eax by 8 bits to the left. A different name for shl is sal (shift arithmetic left). Both can be used synonymous. Finally, the result is stored in the variable shl at [ebp-0x14]. Here is a visual demonstration of shl/sal and shr instructions: After shifting to the left, the right most bit is set for Carry Flag in EFLAGS register. Expression: int shr = i >> 8; 8048447: mov eax,DWORD PTR [ebp+0x8] 804844a: sar eax,0x8 804844d: mov DWORD PTR [ebp-0x10],eax sar is similar to shl/sal, but shift bits to the right and extends the sign bit. For right shift, shr and sar are two different instructions. shr differs to sar is that it does not extend the sign bit. Finally, the result is stored in the variable shr at [ebp-0x10]. In the figure (b), notice that initially, the sign bit is 1, but after 1-bit and 10-bit shiftings, the shifted-out bits are filled with zeros. [float Figure: [Figure 0.14: SAR Instruction Operation (Source: Figure 7-8, Volume 1) ] ] With sar, the sign bit (the most significant bit) is preserved. That is, if the sign bit is 0, the new bits always get the value 0; if the sign bit is 1, the new bits always get the value 1. Expression: char equal1 = (i == j); 8048450: mov eax,DWORD PTR [ebp+0x8] 8048453: cmp eax,DWORD PTR [ebp+0xc] 8048456: sete al 8048459: mov BYTE PTR [ebp-0x41],al cmp and variants of the variants of set instructions make up all the logical comparisons. In this expression, cmp compares variable i and j; then sete stores the value 1 to al register if the comparison from cmp earlier is equal, or stores 0 otherwise. The general name for variants of set instruction is called SETcc. The suffix cc denotes the condition being tested for in EFLAGS register. Appendix B in volume 1, “EFLAGS Condition Codes”, lists the conditions it is possible to test for with this instruction. Finally, the result is stored in the variable equal1 at [ebp-0x41]. Expression: int equal2 = (i == j); 804845c: mov eax,DWORD PTR [ebp+0x8] 804845f: cmp eax,DWORD PTR [ebp+0xc] 8048462: sete al 8048465: movzx eax,al 8048468: mov DWORD PTR [ebp-0xc],eax Similar to equality comparison, this expression also compares for equality, with an exception that the result is stored in an int type. For that reason, one more instruction is a added: movzx instruction, a variant of mov that copies the result into a destination operand and fills the remaining bytes with 0. In this case, since eax is 4-byte wide, after copying the first byte in al, the remaining bytes of eax are filled with 0 to ensure the eax carries the same value as al. [float Figure: [Figure 0.15: movzx instruction ] [float Figure: [Sub-Figure a: eax before movzx ] +-----+-----+-----+----+ | 12 | 34 | 56 | 78 | +-----+-----+-----+----+ ] [float Figure: [Sub-Figure b: after movzx eax, al ] +-----+-----+-----+----+ | 00 | 00 | 00 | 78 | +-----+-----+-----+----+ ] ] Expression: char greater = (i > j); 804846b: mov eax,DWORD PTR [ebp+0x8] 804846e: cmp eax,DWORD PTR [ebp+0xc] 8048471: setg al 8048474: mov BYTE PTR [ebp-0x40],al Similar to equality comparison, but used setg for greater comparison instead. Expression: char less = (i < j); 8048477: mov eax,DWORD PTR [ebp+0x8] 804847a: cmp eax,DWORD PTR [ebp+0xc] 804847d: setl al 8048480: mov BYTE PTR [ebp-0x3f],al Applied setl for less comparison. Expression: char greater_equal = (i >= j); 8048483: mov eax,DWORD PTR [ebp+0x8] 8048486: cmp eax,DWORD PTR [ebp+0xc] 8048489: setge al 804848c: mov BYTE PTR [ebp-0x3e],al Applied setge for greater or equal comparison. Expression: char less_equal = (i <= j); 804848f: mov eax,DWORD PTR [ebp+0x8] 8048492: cmp eax,DWORD PTR [ebp+0xc] 8048495: setle al 8048498: mov BYTE PTR [ebp-0x3d],al Applied setle for less than or equal comparison. Expression: int logical_and = (i && j); 804849b: cmp DWORD PTR [ebp+0x8],0x0 804849f: je 80484ae 80484a1: cmp DWORD PTR [ebp+0xc],0x0 80484a5: je 80484ae 80484a7: mov eax,0x1 80484ac: jmp 80484b3 80484ae: mov eax,0x0 80484b3: mov DWORD PTR [ebp-0x8],eax Logical AND operator && is one of the syntaxes that is made entirely in software[footnote: That is, there is no equivalent assembly instruction implemented in hardware. ] with simpler instructions. The algorithm from the assembly code is simple: 1. First, check if i is 0 with the instruction at 0x804849b. (a) If true, jump to 0x80484ae and set eax to 0. (b) Set the variable logical_and to 0, as it is the next instruction after 0x80484ae. 2. If i is not 0, check if j is 0 with the instruction at 0x80484a1. (a) If true, jump to 0x80484ae and set eax to 0. (b) Set the variable logical_and to 0, as it is the next instruction after 0x80484ae. 3. If both i and j are not 0, the result is certainly 1, or true. (a) Set it accordingly with the instruction at 0x80484a7. (b) Then jump to the instruction at 0x80484b3 to set the variable logical_and at [ebp-0x8] to 1. Expression: int logical_or = (i || j); 80484b6: cmp DWORD PTR [ebp+0x8],0x0 80484ba: jne 80484c2 80484bc: cmp DWORD PTR [ebp+0xc],0x0 80484c0: je 80484c9 80484c2: mov eax,0x1 80484c7: jmp 80484ce 80484c9: mov eax,0x0 80484ce: mov DWORD PTR [ebp-0x4],eax Logical OR operator || is similar to logical and above. Understand the algorithm is left as an exercise for readers. Expression: ++i; and --i; (or i++ and i--) 80484d1: add DWORD PTR [ebp+0x8],0x1 80484d5: sub DWORD PTR [ebp+0x8],0x1 The syntax of increment and decrement is similar to logical AND and logical OR in that it is made from existing instruction, that is add. The difference is that the CPU actually does has a built-in instruction, but gcc decided not to use the instruction because inc and dec cause a partial flag register stall, occurs when an instruction modifies a part of the flag register and the following instruction is dependent on the outcome of the flags (section 3.5.2.6, Intel Optimization Manual, 2016 ). The manual even suggests that inc and dec should be replaced with add and sub instructions (section 3.5.1.1, Intel Optimization Manual, 2016 ). Expression: int i1 = i++; 80484d9: mov eax,DWORD PTR [ebp+0x8] 80484dc: lea edx,[eax+0x1] 80484df: mov DWORD PTR [ebp+0x8],edx 80484e2: mov DWORD PTR [ebp-0x10],eax First, i is copied into eax at 80484d9. Then, the value of eax + 0x1 is copied into edx as an effective address at 80484dc. The lea (load effective address) instruction copies a memory address into a register. According to Volume 2, the source operand is a memory address specified with one of the processors addressing modes. This means, the source operand must be specified by the addressing modes defined in 16-bit/32-bit ModR/M Byte tables, [mod-rm-16] and [mod-rm-32] . After loading the incremented value into edx, the value of i is increased by 1 at 80484df. Finally, the previous i value is stored back to i1 at [ebp-0x8] by the instruction at 80484e2. Expression: int i2 = ++i; 80484e5: add DWORD PTR [ebp+0x8],0x1 80484e9: mov eax,DWORD PTR [ebp+0x8] 80484ec: mov DWORD PTR [ebp-0xc],eax The primary differences between this increment syntax and the previous one are: • add is used instead of lea to increase i directly. • the newly incremented i is stored into i2 instead of the old value. • the expression only costs 3 instructions instead of 4. This prefix-increment syntax is faster than the post-fix one used previously. It might not matter much which version to use if the increment is only used once or a few hundred times in a small loop, but it matters when a loop runs millions or more times. Also, depends on different circumstances, it is more convenient to use one over the other e.g. if i is an index for accessing an array, we want to use the old value for accessing previous array element and newly incremented i for current element. Expression: int i3 = i--; 80484ef: mov eax,DWORD PTR [ebp+0x8] 80484f2: lea edx,[eax-0x1] 80484f5: mov DWORD PTR [ebp+0x8],edx 80484f8: mov DWORD PTR [ebp-0x8],eax Similar to i++ syntax, and is left as an exercise to readers. Expression: int i4 = --i; 80484fb: sub DWORD PTR [ebp+0x8],0x1 80484ff: mov eax,DWORD PTR [ebp+0x8] 8048502: mov DWORD PTR [ebp-0x4],eax Similar to ++i syntax, and is left as an exercise to readers. Read section 3.5.2.4, “Partial Register Stalls” to understand register stalls in general. Read the sections from 7.3.1 to 7.3.7 in volume 1. Stack A stack is a contiguous array of memory locations that holds a collection of discrete data. When a new element is added, a stack grows down in memory toward lesser addresses, and shrinks up toward greater addresses when an element is removed. x86 uses the esp register to point to the top of the stack, at the newest element. A stack can be originated anywhere in main memory, as esp can be set to any memory address. x86 provides two operations for manipulating stacks: • push instruction and its variants add a new element on top of the stack • pop instructions and its variants remove the top-most element from the stack. +----------+----+ | 0x10000 | 00 | +----------+----+ | 0x10001 | 00 | +----------+----+ | 0x10002 | 00 | +----------+----+ | 0x10003 | 00 | +----------+----+ +-----+ | 0x10004 | 12 | \leftarrow | esp | +----------+----+ +-----+ +----------+----+ | 0x10000 | 00 | +----------+----+ | 0x10001 | 00 | +----------+----+ +-----+ | 0x10002 | 78 | \leftarrow | esp | +-----+ +----------+----+ | 0x10003 | 56 | +----------+----+ | 0x10004 | 12 | +----------+----+ +----------+----+ | 0x10000 | 00 | +----------+----+ | 0x10001 | 00 | +----------+----+ | 0x10002 | 00 | +----------+----+ | 0x10003 | 00 | +----------+----+ +-----+ | 0x10004 | 12 | \leftarrow | esp | +----------+----+ +-----+ Automatic variables Local variables are variables that exist within a scope. A scope is delimited by a pair of braces: {..}. The most common scope to define local variables is at function scope. However, scope can be unnamed, and variables created inside an unnamed scope do not exist outside of its scope and its inner scope. Function scope: void foo() { int a; int b; } a and b are variables local to the function foo. Unnamed scope: int foo() { int i; { int a = 1; int b = 2; { return i = a + b; } } } a and b are local to where it is defined and local into its inner child scope that return i = a + b. However, they do not exist at the function scope that creates i. When a local variable is created, it is pushed on the stack; when a local variable goes out of scope, it is pop out of the stack, thus destroyed. When an argument is passed from a caller to a callee, it is pushed on the stack; when a callee returns to the caller, the arguments are popped out the stack. The local variables and arguments are automatically allocated upon enter a function and destroyed after exiting a function, that's why it's called automatic variables. A base frame pointer points to the start of the current function frame, and is kept in ebp register. Whenever a function is called, it is allocated with its own dedicated storage on stack, called stack frame. A stack frame is where all local variables and arguments of a function are placed on a stack[footnote: Data and only data are exclusively allocated on stack for every stack frame. No code resides here. ]. When a function needs a local variable or an argument, it uses ebp to access a variable: • All local variables are allocated after the ebp pointer. Thus, to access a local variable, a number is subtracted from ebp to reach the location of the variable. • All arguments are allocated before ebp pointer. To access an argument, a number is added to ebp to reach the location of the argument. • The ebp itself pointer points to the return address of its caller. +--------------------------------------+---------------------------------------------------------------------------+ | Previous Frame | Current Frame | +--------------------------------------+-----------------------------+----------+----------------------------------+ | Function Arguments | | ebp | Local variables | +-----+-----+-----+-----------+--------+-----------------------------+----------+-----+-----+-----+-----------+----+ | A1 | A2 | A3 | ........ | An | Return Address | Old ebp | L1 | L2 | L3 | ........ | Ln | +-----+-----+-----+-----------+--------+-----------------------------+----------+-----+-----+-----+-----------+----+ A = Argument L = Local Variable Here is an example to make it more concrete: Source int add(int @|\color{red}\bfseries a|@, int @|\color{green}\bfseries b|@) { int @|\color{blue}\bfseries i|@ = @|\color{red}\bfseries a|@ + @|\color{green}\bfseries b|@; return i; } Assembly 080483db : #include int add(int a, int b) { 80483db: push ebp 80483dc: mov ebp,esp 80483de: sub esp,0x10 int i = a + b; 80483e1: mov edx,DWORD PTR [ebp+0x8] 80483e4: mov eax,DWORD PTR [ebp+0xc] 80483e7: add eax,edx 80483e9: mov DWORD PTR [ebp-0x4],eax return i; 80483ec: mov eax,DWORD PTR [ebp-0x4] } 80483ef: leave 80483f0: ret In the assembly listing, [ebp-0x4] is the local variable i, since it is allocated after ebp, with the length of 4 bytes (an int). On the other hand, a and b are arguments and can be accessed with ebp: • [ebp+0x8] accesses a. • [ebp+0xc] access b. For accessing arguments, the rule is that the closer a variable on stack to ebp, the closer it is to a function name. +-------------------+ +-------------------+ +-------------------+ +-------------------+ | ebp+0xc | | ebp+0x8 | | ebp+0x4 | | ebp | +-------------------+ +-------------------+ +-------------------+ +-------------------+ --------------- \downarrow \downarrow \downarrow \downarrow +----------+-----+-----+-----+--------------+-----+-----+-----+--------------+-----+-----+-----+--------------+-----+-----+-----+-------------+ | | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f | +----------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+ | 0x10000 | b | a | Return Address | Old ebp | +----------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+ +-------------------+ +-------------------+ | ebp+0x8 | | ebp+0x4 | +-------------------+ +-------------------+ \downarrow \downarrow +----------+-----+-----+-----+--------------+-----+-----+-----+--------------+-----+-----+-----+--------------+-----+-----+-----+-------------+ | | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f | +----- +----- +-------------+ +----------+-----+-----+-----+--------------+-----+-----+-----+--------------+-----+-----+-----+--------------+-------------------------------+ |  0xffe0 | | | | | | | | | | | | N | i | +----------+-----+-----+-----+--------------+-----+-----+-----+--------------+-----+-----+-----+--------------+-------------------------------+ N = Next local variable starts here From the figure, we can see that a and b are laid out in memory with the exact order as written in C, relative to the return address. Function Call and Return Source #include int add(int a, int b) { int local = 0x12345; return a + b; } int main(int argc, char *argv[]) { add(1,1); return 0; } Assembly For every function call, gcc pushes arguments on the stack in reversed order with the push instructions. That is, the arguments pushed on stack are in reserved order as it is written in high level C code, to ensure the relative order between arguments, as seen in previous section how function arguments and local variables are laid out. Then, gcc generates a call instruction, which then implicitly pushes a return address before transferring the control to add function: 080483f2
: int main(int argc, char *argv[]) { 80483f2: push ebp 80483f3: mov ebp,esp add(1,2); 80483f5: push 0x2 80483f7: push 0x1 80483f9: call 80483db 80483fe: add esp,0x8 return 0; 8048401: mov eax,0x0 } 8048406: leave 8048407: ret Upon finishing the call to add function, the stack is restored by adding 0x8 to stack pointer esp (which is equivalent to 2 pop instructions). Finally, a leave instruction is executed and main returns with a ret instruction. A ret instruction transfers the program execution back to the caller to the instruction right after the call instruction, the add instruction. The reason ret can return to such location is that the return address implicitly pushed by the call instruction, which is the address right after the call instruction; whenever the CPU executes ret instruction, it retrieves the return address that sits right after all the arguments on the stack: At the end of a function, gcc places a leave instruction to clean up all spaces allocated for local variables and restore the frame pointer to frame pointer of the caller. 080483db : #include int add(int a, int b) { 80483db: push ebp 80483dc: mov ebp,esp 80483de: sub esp,0x10 int local = 0x12345; 80483e1: DWORD PTR [ebp-0x4],0x12345 return a + b; 80483e8: mov edx,DWORD PTR [ebp+0x8] 80483eb: mov eax,DWORD PTR [ebp+0xc] 80483ee: add eax,edx } 80483f0: leave 80483f1: ret The above code that gcc generated for function calling is actually the standard method x86 defined. Read chapter 6, “ Produce Calls, Interrupts, and Exceptions”, Intel manual volume 1. Loop Loop is simply resetting the instruction pointer to an already executed instruction and starting from there all over again. A loop is just one application of jmp instruction. However, because looping is a pervasive pattern, it earned its own syntax in C. Source #include int main(int argc, char *argv[]) { for (int i = 0; i < 10; i++) { } return 0; } Assembly 080483db
: #include int main(int argc, char *argv[]) { 80483db: push ebp 80483dc: mov ebp,esp 80483de: sub esp,0x10 for (int i = 0; i < 10; i++) { 80483e1: mov DWORD PTR [ebp-0x4],0x0 80483e8: jmp 80483ee 80483ea: add DWORD PTR [ebp-0x4],0x1 80483ee: cmp DWORD PTR [ebp-0x4],0x9 80483f2: jle 80483ea } return 0; 80483f4: b8 00 00 00 00 mov eax,0x0 } 80483f9: c9 leave 80483fa: c3 ret 80483fb: 66 90 xchg ax,ax 80483fd: 66 90 xchg ax,ax 80483ff: 90 nop The colors mark corresponding high level code to assembly code: 1. The red instruction initialize i to 0. 2. The green instructions compare i to 10 by using jle and compare it to 9. If true, jump to 80483ea for another iteration. 3. The blue instruction increase i by 1, making the loop able to terminate once the terminate condition is satisfied. Why does the increment instruction (the blue instruction) appears before the compare instructions (the green instructions)? What assembly code can be generated for while and do...while? Conditional Again, conditional in C with if...else... construct is just another application of jmp instruction under the hood. It is also a pervasive pattern that earned its own syntax in C. Source #include int main(int argc, char *argv[]) { int i = 0; if (argc) { i = 1; } else { i = 0; } return 0; } Assembly int main(int argc, char *argv[]) { 80483db: push ebp 80483dc: mov ebp,esp 80483de: sub esp,0x10 int i = 0; 80483e1: mov DWORD PTR [ebp-0x4],0x0 if (argc) { 80483e8: cmp DWORD PTR [ebp+0x8],0x0 80483ec: je 80483f7 i = 1; 80483ee: mov DWORD PTR [ebp-0x4],0x1 80483f5: jmp 80483fe } else { i = 0; 80483f7: mov DWORD PTR [ebp-0x4],0x0 } return 0; 80483fe: mov eax,0x0 } 8048403: leave 8048404: ret The generated assembly code follows the same order as the corresponding high level syntax: • red instructions represents if branch. • blue instructions represents else branch. • green instruction is the exit point for both if and else branch. if branch first compares whether argc is false (equal to 0) with cmp instruction. If true, it proceeds to else branch at 80483f7. Otherwise, if branch continues with the code of its branch, which is the next instruction at 80483ee for copying 1 to i. Finally, it skips over else branch and proceeds to 80483fe, which is the next instruction pasts the if..else... construct. else branch is entered when cmp instruction from if branch is true. else branch starts at 80483f7, which is the first instruction of else branch. The instruction copies 0 to i, and proceeds naturally to the next instruction pasts the if...else... construct without any jump. The Anatomy of a Program Every program consists of code and data, and only those two components made up a program. However, if a program consists purely code and data of its own, from the perspective of an operating system (as well as human), it does not know in a program, which block of binary is a program and which is just raw data, where in the program to start execution, which region of memory should be protected and which is free to modify. For that reason, each program carries extra metadata to communicate with the operating system how to handle the program. When a source file is compiled, the generated machine code is stored into an object file[margin: object file ]object file, which is just a block of binary. One or more object files can be combined to produce an executable binary[margin: executable binary ]executable binary, which is a complete program runnable in an operating system. readelf is a program that recognizes and displays the ELF metadata of a binary file, be it an object file or an executable binary. ELF, or Executable and Linkable Format, is the content at the very beginning of an executable to provide an operating system necessary information to load into main memory and run the executable. ELF can be thought of similar to the table of contents of a book. In a book, a table of contents list the page numbers of the main sections, subsections, sometimes even figures and tables for easy lookup. Similarly, ELF lists various sections used for code and data, and the memory addresses of each symbol along with other information. An ELF binary is composed of: • An ELF header[margin: ELF header ]ELF header: the very first section of an executable that describes the file's organization. • A Program header table[margin: program header table ]program header table: is an array of fixed-size structures that describes segments of an executable. • A Section header table[margin: section header table ]section header table: is an array of fixed-size structures that describes sections of an executable. • Segments and section[margin: Segments and sections ]Segments and sections are the main content of an ELF binary, which are the code and data, divided into chunks of different purposes. A segmentsegment is a composition of zero or more sections and is directly loaded by an operating system at runtime. A sectionsection is a block of binary that is either: – actual program code and data that is available in memory when a program runs. – metadata about other sections used only in the linking process, and disappear from the final executable. Linker uses sections to build segments. [float Figure: [Figure 0.16: ELF - Linking View vs Executable View (Source: Wikipedia) ] ] Later we will compile our kernel as an ELF executable with GCC, and explicitly specify how segments are created and where they are loaded in memory through the use a linker script, a text file to instruct how a linker should generate a binary. For now, we will examine the anatomy of an ELF executable in detail. Reference documents: The [margin: ELF specification ]ELF specification is bundled as a man page in Linux: $ man elf It is a useful resource to understand and implement ELF. However, it will be much easier to use after you finish this chapter, as the specification mixes implementation details in it. The default specification is a generic one, in which every ELF implementation follows. However, each platform provides extra features unique to it. The ELF specification for x86 is currently maintained on Github by H.J. Lu: https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI . Platform-dependent details are referred to as “processor specific” in the generic ELF specification. We will not explore these details, but study the generic details, which are enough for crafting an ELF binary image for our operating system. ELF header To see the information of an ELF header: $ readelf -h hello The output: ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400430 Start of program headers: 64 (bytes into file) Start of section headers: 6648 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 9 Size of section headers: 64 (bytes) Number of section headers: 31 Section header string table index: 28 Let's go through each field: Magic Displays the raw bytes that uniquely addresses a file is an ELF executable binary. Each byte gives a brief information. In the example, we have the following magic bytes: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Examine byte by byte:   Byte Description ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 7f 45 4c 46 Predefined values. The first byte is always 7F, the remaining 3 bytes represent the string “ELF”. 02 See Class field below. 01 See Data field below. 01 See Version field below. 00 See OS/ABI field below. 00 00 00 00 00 00 00 00 Padding bytes. These bytes are unused and are always set to 0. Padding bytes are added for proper alignment, and is reserved for future use when more information is needed. Class A byte in Magic field. It specifies the class or capacity of a file. Possible values:   Value Description --------------------------- 0 Invalid class 1 32-bit objects 2 64-bit objects Data A byte in Magic field. It specifies the data encoding of the processor-specific data in the object file. Possible values:   Value Description ------------------------------------------ 0 Invalid data encoding 1 Little endian, 2's complement 2 Big endian, 2's complement Version A byte in Magic. It specifies the ELF header version number. Possible values:   Value Description ---------------------------- 0 Invalid version 1 Current version OS/ABI A byte in Magic field. It specifies the target operating system ABI. Originally, it was a padding byte. Possible values: Refer to the latest ABI document, as it is a long list of different operating systems. Type Identifies the object file type.   Value Description ----------------------------------- --------------------------------------------- 0 No file type 1 Relocatable file 2 Executable file 3 Shared object file 4 Core file 0xff00 Processor specific, lower bound 0xffff Processor specific, upper bound The values from 0xff00 to 0xffff are reserved for a processor to define additional file types meaningful to it. Machine Specifies the required architecture value for an ELF file e.g. x86_64, MIPS, SPARC, etc. In the example, the machine is of x86_64 architecture. Possible values: Please refer to the latest ABI document, as it is a long list of different architectures. Version Specifies the version number of the current object file (not the version of the ELF header, as the above Version field specified). Entry point address Specifies the memory address where the very first code to be executed. The address of main function is the default in a normal application program, but it can be any function by explicitly specifying the function name to gcc. For the operating system we are going to write, this is the single most important field that we need to retrieve to bootstrap our kernel, and everything else can be ignored. Start of program headers The offset of the program header table, in bytes. In the example, this number is 64 bytes, which means the 65th byte, or + 64, is the start address of the program header table. That is, if a program is loaded at address 0x10000 in memory, then the start address is 0x10000 (the very first byte of Magic field, where the value 0x7f resides) and the start address of program header table is 0x10000 + 0x40 = 0x10040 . Start of section headers The offset of the section header table in bytes, similar to the start of program headers. In the example, it is 6648 bytes into file. Flags Hold processor-specific flags associated with the file. When the program is loaded, in a x86 machine, EFLAGS register is set according to this value. In the example, the value is 0x0, which means EFLAGS register is in a clear state. Size of this header Specifies the total size of ELF header's size in bytes. In the example, it is 64 bytes, which is equivalent to Start of program headers. Note that these two numbers are not necessarily equivalent, as program header table might be placed far away from the ELF header. The only fixed component in the ELF executable binary is the ELF header, which appears at the very beginning of the file. Size of program headers Specifies the size of each program header in bytes. In the example, it is 64 bytes. Number of program headers Specifies the total number of program headers. In the example, the file has a total of 9 program headers. Size of section headers Specifies the size of each section header in bytes. In the example, it is 64 bytes. Number of section headers Specifies the total number of section headers. In the example, the file has a total of 31 section headers. In a section header table, the first entry in the table is always an empty section. Section header string table index Specifies the index of the header in the section header table that points to the section that holds all null-terminated strings. In the example, the index is 28, which means it's the 28[superscript:th] entry of the table. Section header table As we know already, code and data compose a program. However, not all types of code and data have the same purpose. For that reason, instead of a big chunk of code and data, they are divided into smaller chunks, and each chunk must satisfy these conditions (according to gABI): • Every section in an object file has exactly one section header describing it. But, section headers may exist that do not have a section. • Each section occupies one contiguous (possibly empty) sequence of bytes within a file. That means, there's no two regions of bytes that are the same section. • Sections in a file may not overlap. No byte in a file resides in more than one section. • An object file may have inactive space. The various headers and the sections might not “cover” every byte in an object file. The contents of the inactive data are unspecified. To get all the headers from an executable binary e.g. hello, use the following command: $ readelf -S hello Here is a sample output (do not worry if you don't understand the output. Just skim to get your eyes familiar with it. We will dissect it soon enough): There are 31 section headers, starting at offset 0x19c8: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 0 0 4 [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0000000000400298 00000298 000000000000001c 0000000000000000 A 5 0 8 [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 0000000000000048 0000000000000018 A 6 1 8 [ 6] .dynstr STRTAB 0000000000400300 00000300 0000000000000038 0000000000000000 A 0 0 1 [ 7] .gnu.version VERSYM 0000000000400338 00000338 0000000000000006 0000000000000002 A 5 0 2 [ 8] .gnu.version_r VERNEED 0000000000400340 00000340 0000000000000020 0000000000000000 A 6 1 8 [ 9] .rela.dyn RELA 0000000000400360 00000360 0000000000000018 0000000000000018 A 5 0 8 [10] .rela.plt RELA 0000000000400378 00000378 0000000000000018 0000000000000018 AI 5 24 8 [11] .init PROGBITS 0000000000400390 00000390 000000000000001a 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 00000000004003b0 000003b0 0000000000000020 0000000000000010 AX 0 0 16 [13] .plt.got PROGBITS 00000000004003d0 000003d0 0000000000000008 0000000000000000 AX 0 0 8 [14] .text PROGBITS 00000000004003e0 000003e0 0000000000000192 0000000000000000 AX 0 0 16 [15] .fini PROGBITS 0000000000400574 00000574 0000000000000009 0000000000000000 AX 0 0 4 [16] .rodata PROGBITS 0000000000400580 00000580 0000000000000004 0000000000000004 AM 0 0 4 [17] .eh_frame_hdr PROGBITS 0000000000400584 00000584 000000000000003c 0000000000000000 A 0 0 4 [18] .eh_frame PROGBITS 00000000004005c0 000005c0 0000000000000114 0000000000000000 A 0 0 8 [19] .init_array INIT_ARRAY 0000000000600e10 00000e10 0000000000000008 0000000000000000 WA 0 0 8 [20] .fini_array FINI_ARRAY 0000000000600e18 00000e18 0000000000000008 0000000000000000 WA 0 0 8 [21] .jcr PROGBITS 0000000000600e20 00000e20 0000000000000008 0000000000000000 WA 0 0 8 [22] .dynamic DYNAMIC 0000000000600e28 00000e28 00000000000001d0 0000000000000010 WA 6 0 8 [23] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 0 0 8 [24] .got.plt PROGBITS 0000000000601000 00001000 0000000000000020 0000000000000008 WA 0 0 8 [25] .data PROGBITS 0000000000601020 00001020 0000000000000010 0000000000000000 WA 0 0 8 [26] .bss NOBITS 0000000000601030 00001030 0000000000000008 0000000000000000 WA 0 0 1 [27] .comment PROGBITS 0000000000000000 00001030 0000000000000034 0000000000000001 MS 0 0 1 [28] .shstrtab STRTAB 0000000000000000 000018b6 000000000000010c 0000000000000000 0 0 1 [29] .symtab SYMTAB 0000000000000000 00001068 0000000000000648 0000000000000018 30 47 8 [30] .strtab STRTAB 0000000000000000 000016b0 0000000000000206 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) The first line: There are 31 section headers, starting at offset 0x19c8 summarizes the total number of sections in the file, and where the address where it starts. Then, comes the listing section by section with the following header, is also the format of each section output: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align Each section has two lines with different fields: Nr The index of each section. Name The name of each section. Type This field (in a section header) identifies the type of each section. Types classify sections (similar to types in programming languages are used by a compiler). Address The starting virtual address of each section. Note that the addresses are virtual only when a program runs in an OS with support for virtual memory enabled. In our OS, since we run on bare metal, the addresses will all be physical. Offset The offset of each section into a file. An [margin: offset ]offsetoffset is a distance in bytes, from the first byte of a file to the start of an object, such as a section or a segment in the context of an ELF binary file. Size The size in bytes of each section. EntSize Some sections hold a table of fixed-size entries, such as a symbol table. For such a section, this member gives the size in bytes of each entry. The member contains 0 if the section does not hold a table of fixed-size entries. Flags describes attributes of a section. Flags together with a type defines the purpose of a section. Two sections can be of the same type, but serve different purposes. For example, even though .data and .text share the same type, .data holds the initialized data of a program while .text holds executable instructions of a program. For that reason, .data is given read and write permission, but not executable. Any attempt to execute code in .data is denied by the running OS: in Linux, such invalid section usage gives a segmentation fault. ELF gives information to enable an OS with such protection mechanism. However, running on bare metal, nothing can prevent from doing anything. Our OS can execute code in data section, and vice versa, writing to code section. [Table 5: Section Flags ] +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Flag | Descriptions | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | W | Bytes in this section are writable during execution. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | A | Memory is allocated for this section during process execution. Some control sections do not reside in the memory image of an object file; this attribute is off for those sections. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | X | The section contains executable instructions. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | M | The data in the section may be merged to eliminate duplication. Each element in the section is compared against other elements in sections with the same name, type and flags. Elements that would have identical values at program run-time may be merged. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | S | The data elements in the section consist of null-terminated character strings. The size of each character is specified in the section header's EntSize field. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | l | Specific large section for x86_64 architecture. This flag is not specified in the Generic ABI but in x86_64 ABI. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | I | The Info field of this section header holds an index of a section header. Otherwise, the number is the index of something else. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | L | Preserve section ordering when linking. If this section is combined with other sections in the output file, it must appear in the same relative order with respect to those sections, as the linked-to section appears with respect to sections the linked-to section is combined with. Apply when the Link field of this section's header references another section (the linked-to section) | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | G | This section is a member (perhaps the only one) of a section group. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | T | This section holds Thread-Local Storage, meaning that each thread has its own distinct instance of this data. A thread is a distinct execution flow of code. A program can have multiple threads that pack different pieces of code and execute separately, at the same time. We will learn more about threads when writing our kernel. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | E | Link editor is to exclude this section from executable and shared library that it builds when those objects are not to be further relocated. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | x | Unknown flag to readelf. It happens because the linking process can be done manually with a linker like GNU ld (we will later later). That is, section flags can be specified manually, and some flags are for a customized ELF that the open-source readelf doesn't know of. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | O | This section requires special OS-specific processing (beyond the standard linking rules) to avoid incorrect behavior. A link editor encounters sections whose headers contain OS-specific values it does not recognize by Type or Flags values defined by ELF standard, the link editor should combine those sections. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | o | All bits included in this flag are reserved for operating system-specific semantics. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | p | All bits included in this flag are reserved for processor-specific semantics. If meanings are specified, the processor supplement explains them. | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Link and Info are numbers that references the indexes of sections, symbol table entries, hash table entries. Link field holds the index of a section, while Info field holds an index of a section, a symbol table entry or a hash table entry, depends on the type of a section. Later when writing our OS, we will handcraft the kernel image by explicitly linking the object files (produced by gcc) through a linker script. We will specify the memory layout of sections by specifying at what addresses they will appear in the final image. But we will not assign any section flag and let the linker take care of it. Nevertheless, knowing which flag does what is useful. Align is a value that enforces the offset of a section should be divisible by the value. Only 0 and positive integral powers of two are allowed. Values 0 and 1 mean the section has no alignment constraint. Output of .interp section: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1 Nr is 1. Type is PROGBITS, which means this section is part of the program. Address is 0x0000000000400238, which means the program is loaded at this virtual memory address at runtime. Offset is 0x00000238 bytes into file. Size is 0x000000000000001c in bytes. EntSize is 0, which means this section does not have any fixed-size entry. Flags are A (Allocatable), which means this section consumes memory at runtime. Info and Link are 0 and 0, which means this section links to no section or entry in any table. Align is 1, which means no alignment. Output of the .text section: [14] .text PROGBITS 00000000004003e0 000003e0 0000000000000192 0000000000000000 AX 0 0 16 Nr is 14. Type is PROGBITS, which means this section is part of the program. Address is 0x00000000004003e0, which means the program is loaded at this virtual memory address at runtime. Offset is 0x000003e0 bytes into file. Size is 0x0000000000000192 in bytes. EntSize is 0, which means this section does not have any fixed-size entry. Flags are A (Allocatable) and X (Executable), which means this section consumes memory and can be executed as code at runtime. Info and Link are 0 and 0, which means this section links to no section or entry in any table. Align is 16, which means the starting address of the section should be divisible by 16, or 0x10. Indeed, it is: \mathtt{0x3e0/0x10=0x3e} . Understand Section in-depth In this section, we will learn different details of section types and the purposes of special sections e.g. .bss, .text, .data... by looking at each section one by one. We will also examine the content of each section as a hexdump with the commands: $ readelf -x
For example, if you want to examine the content of section with index 25 (the .bss section in the sample output) in the file hello: $ readelf -x 25 hello Equivalently, using name instead of index works: $ readelf -x .data hello If a section contains strings e.g. string symbol table, the flag -x can be replaced with -p. NULL marks a section header as inactive and does not have an associated section. NULL section is always the first entry of section header table. It means, any useful section starts from 1. The sample output of NULL section: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 Examining the content, the section is empty: Section '' has no data to dump. NOTE marks a section with special information that other programs will check for conformance, compatibility... by a vendor or a system builder. In the sample output, we have 2 NOTE sections: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 0 0 4 [ 3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 0 0 4 Examine 2nd section with the command: $ readelf -x 2 hello we have: Hex dump of section '.note.ABI-tag': 0x00400254 04000000 10000000 01000000 474e5500 ............GNU. 0x00400264 00000000 02000000 06000000 20000000 ............ ... PROGBITS indicates a section holding the main content of a program, either code or data. There are many PROGBITS sections: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 0 0 1 ... [11] .init PROGBITS 0000000000400390 00000390 000000000000001a 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 00000000004003b0 000003b0 0000000000000020 0000000000000010 AX 0 0 16 [13] .plt.got PROGBITS 00000000004003d0 000003d0 0000000000000008 0000000000000000 AX 0 0 8 [14] .text PROGBITS 00000000004003e0 000003e0 0000000000000192 0000000000000000 AX 0 0 16 [15] .fini PROGBITS 0000000000400574 00000574 0000000000000009 0000000000000000 AX 0 0 4 [16] .rodata PROGBITS 0000000000400580 00000580 0000000000000004 0000000000000004 AM 0 0 4 [17] .eh_frame_hdr PROGBITS 0000000000400584 00000584 000000000000003c 0000000000000000 A 0 0 4 [18] .eh_frame PROGBITS 00000000004005c0 000005c0 0000000000000114 0000000000000000 A 0 0 8 ... [23] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 0 0 8 [24] .got.plt PROGBITS 0000000000601000 00001000 0000000000000020 0000000000000008 WA 0 0 8 [25] .data PROGBITS 0000000000601020 00001020 0000000000000010 0000000000000000 WA 0 0 8 [27] .comment PROGBITS 0000000000000000 00001030 0000000000000034 0000000000000001 MS 0 0 1 For our operating system, we only need the following section: .text This section holds all the compiled code of a program. .data This section holds the initialized data of a program. Since the data are initialized with actual values, gcc allocates the section with actual byte in the executable binary. .rodata This section holds read-only data, such as fixed-size strings in a program, e.g. “Hello World”, and others. .bss This section, shorts for Block Started by Symbol, holds uninitialized data of a program. Unlike other sections, no space is allocated for this section in the image of the executable binary on disk. The section is allocated only when the program is loaded into main memory. Other sections are mainly needed for dynamic linking, that is code linking at runtime for sharing between many programs. To enable such feature, an OS as a runtime environment must be presented. Since we run our OS on bare metal, we are effectively creating such environment. For simplicity, we won't add dynamic linking to our OS. SYMTAB and DYNSYM These sections hold symbol table. A symbol table is an array of entries that describe symbols in a program. A symbol is a name assigned to an entity in a program. The types of these entities are also the types of symbols, and these are the possible types of an entity: In the sample output, section 5 and 29 are symbol tables: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 5] .dynsym DYNSYM 00000000004002b8 000002b8 0000000000000048 0000000000000018 A 6 1 8 ... [29] .symtab SYMTAB 0000000000000000 00001068 0000000000000648 0000000000000018 30 47 8 To show the symbol table: $ readelf -s hello Output consists of 2 symbol tables, corresponding to the two sections above, .dynsym and .symtab: Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2) 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ Symbol table '.symtab' contains 67 entries: Num: Value Size Type Bind Vis Ndx Name .......................................... 59: 0000000000601040 0 NOTYPE GLOBAL DEFAULT 26 _end 60: 0000000000400430 42 FUNC GLOBAL DEFAULT 14 _start 61: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 62: 0000000000400526 32 FUNC GLOBAL DEFAULT 14 main 63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 64: 0000000000601038 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ 65: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 66: 00000000004003c8 0 FUNC GLOBAL DEFAULT 11 _init TLS The symbol is associated with a Thread-Local Storage entity. Num is the index of an entry in a table. Value is the virtual memory address where the symbol is located. Size is the size of the entity associated with a symbol. Type is a symbol type according to table. NOTYPE The type of a symbol is not specified. OBJECT The symbol is associated with a data object. In C, any variable definition is of OBJECT type. FUNC The symbol is associated with a function or other executable code. SECTION The symbol is associated with a section, and exists primarily for relocation. FILE The symbol is the name of a source file associated with an executable binary. COMMON The symbol labels an uninitialized variable. That is, when a variable in C is defined as global variable without an initial value, or as an external variable using the extern keyword. In other words, these variables stay in .bss section. Bind is the scope of a symbol. LOCAL are symbols that are only visible in the object files that defined them. In C, the static modifier marks a symbol (e.g. a variable/function) as local to only the file that defines it. If we define variables and functions with static modifer: static int global_static_var = 0; static void local_func() { } int main(int argc, char *argv[]) { static int local_static_var = 0; return 0; } Then we get the static variables listed as local symbols after compiling: $ gcc -m32 hello.c -o hello $ readelf -s hello Symbol table '.dynsym' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.0 (2) 2: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) 4: 080484bc 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used Symbol table '.symtab' contains 72 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND ......... output omitted ......... 38: 0804a020 4 OBJECT LOCAL DEFAULT 26 global_static_var 39: 0804840b 6 FUNC LOCAL DEFAULT 14 local_func 40: 0804a024 4 OBJECT LOCAL DEFAULT 26 local_static_var.1938 ......... output omitted ......... GLOBAL are symbols that are accessible by other object files when linking together. These symbols are primarily non-static functions and non-static global data. The extern modifier marks a symbol as externally defined elsewhere but is accessible in the final executable binary, so an extern variable is also considered GLOBAL. Similar to the LOCAL example above, the output lists many GLOBAL symbols such as main: Num: Value Size Type Bind Vis Ndx Name ......... output omitted ......... 66: 080483e1 10 FUNC GLOBAL DEFAULT 14 main ......... output omitted ......... WEAK are symbols whose definitions can be redefined. Normally, a symbol with multiple definitions are reported as an error by a compiler. However, this constraint is lax when a definition is explicitly marked as weak, which means the default implementation can be replaced by a different definition at link time. Suppose we have a default implementation of the function add: #include __attribute__((weak)) int add(int a, int b) { printf("warning: function is not implemented.\n"); return 0; } int main(int argc, char *argv[]) { printf("add(1,2) is %d\n", add(1,2)); return 0; } __attribute__((weak)) is a [margin: function attribute ]function attribute. A function attributefunction attribute is extra information for a compiler to handle a function differently from a normal function. In this example, weak attribute makes the function add a weak function,which means the default implementation can be replaced by a different definition at link time. Function attribute is a feature of a compiler, not standard C. If we do not supply a different function definition in a different file (must be in a different file, otherwise gcc reports as an error), then the default implementation is applied. When the function add is called, it only prints the message: "warning: function not implemented"and returns 0: $ ./hello warning: function is not implemented. add(1,2) is 0 However, if we supply a different definition in another file e.g. math.c: int add(int a, int b) { return a + b; } and compile the two files together: $ gcc math.c hello.c -o hello Then, when running hello, no warning message is printed and the correct value is returned. Weak symbol is a mechanism to provide a default implementation, but replaceable when a better implementation is available (e.g. more specialized and optimized) at link-time. Vis is the visibility of a symbol. The following values are available: [Table 6: Symbol Visibility ] +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Value | Description | +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | DEFAULT | The visibility is specified by the binding type of asymbol. • Global and weak symbols are visible outside of their defining component (executable file or shared object). • Local symbols are hidden. See HIDDEN below. | +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | HIDDEN | A symbol is hidden when the name is not visible to any other program outside of its running program. | +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | PROTECTED | A symbol is protected when it is shared outside of its running program or shared libary and cannot be overridden. That is, there can only be one definition for this symbol across running programs that use it. No program can define its own definition of the same symbol. | +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | INTERNAL | Visibility is processor-specific and is defined by processor-specific ABI. | +------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Ndx is the index of a section that the symbol is in. Aside from fixed index numbers that represent section indexes, index has these special values: [Table 7: Symbol Index ] +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Value | Description | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ABS | The index will not be changed by any symbol relocation. | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | COM | The index refers to an unallocated common block. | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | UND | The symbol is undefined in the current object file, which means the symbol depends on the actual definition in another file. Undefined symbols appears when the object file refers to symbols that are available at runtime, from shared library. | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | LORESERVE HIRESERVE | LORESERVE is the lower boundary of the reserve indexes. Its value is 0xff00. HIREVERSE is the upper boundary of the reserve indexes. Its value is 0xffff. The operating system reserves exclusive indexes between LORESERVE and HIRESERVE, which do not map to any actual section header. | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | XINDEX | The index is larger than LORESERVE. The actual value will be contained in the section SYMTAB_SHNDX, where each entry is a mapping between a symbol, whose Ndx field is a XINDEX value, and the actual index value. | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Others | Sometimes, values such as ANSI_COM, LARGE_COM, SCOM, SUND appear. This means that the index is processor-specific. | +-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Name is the symbol name. A C application program always starts from symbol main. The entry for main in the symbol table in .symtab section is: Num: Value Size Type Bind Vis Ndx Name 62: 0000000000400526 32 FUNC GLOBAL DEFAULT 14 main The entry shows that: • main is the 62[superscript:th] entry in the table. • main starts at address 0x0000000000400526. • main consumes 32 bytes. • main is a function. • main is in global scope. • main is visible to other object files that use it. • main is inside the 14[superscript:th] section, which is .text. This is logical, since .text holds all program code. STRTAB hold a table of null-terminated strings, called string table. The first and last byte of this section is always a NULL character. A string table section exists because a string can be reused by more than one section to represent symbol and section names, so a program like readelf or objdump can display various objects in a program, e.g. variable, functions, section names, in a human-readable text instead of its raw hex address. In the sample output, section 28 and 30 are of STRTAB type: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [28] .shstrtab STRTAB 0000000000000000 000018b6 000000000000010c 0000000000000000 0 0 1 [30] .strtab STRTAB 0000000000000000 000016b0 0000000000000206 0000000000000000 0 0 1 .shstrtab holds all the section names. .strtab holds the symbols e.g. variable names, function names, struct names, etc., in a C program, but not fixed-size null-terminated C strings; the C strings are kept in .rodata section. Strings in those section can be inspected with the command: $ readelf -p 29 hello The output shows all the section names, with the offset (also the string index) into .shstrtab the table to the left: String dump of section '.shstrtab': [ 1] .symtab [ 9] .strtab [ 11] .shstrtab [ 1b] .interp [ 23] .note.ABI-tag [ 31] .note.gnu.build-id [ 44] .gnu.hash [ 4e] .dynsym [ 56] .dynstr [ 5e] .gnu.version [ 6b] .gnu.version_r [ 7a] .rela.dyn [ 84] .rela.plt [ 8e] .init [ 94] .plt.got [ 9d] .text [ a3] .fini [ a9] .rodata [ b1] .eh_frame_hdr [ bf] .eh_frame [ c9] .init_array [ d5] .fini_array [ e1] .jcr [ e6] .dynamic [ ef] .got.plt [ f8] .data [ fe] .bss [ 103] .comment The actual implementation of a string table is a contiguous array of null-terminated strings. The index of a string is the position of its first character in the array. For example, in the above string table, .symtab is at index 1 in the array (NULL character is at index 0). The length of .symtab is 7, plus the NULL character, which occurs 8 bytes in total. So, .strtab starts at index 9, and so on. +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f | +-----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ | 00000000 | \0 | . | s | y | m | t | a | b | \0 | . | s | t | r | t | a | b | +-----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f | +-----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ | 00000010 | \0 | . | s | h | s | t | r | t | a | b | \0 | . | i | n | t | e | +-----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----+ .... and so on .... Similarly, the output of .strtab: String dump of section '.strtab': [ 1] crtstuff.c [ c] __JCR_LIST__ [ 19] deregister_tm_clones [ 2e] __do_global_dtors_aux [ 44] completed.7585 [ 53] __do_global_dtors_aux_fini_array_entry [ 7a] frame_dummy [ 86] __frame_dummy_init_array_entry [ a5] hello.c [ ad] __FRAME_END__ [ bb] __JCR_END__ [ c7] __init_array_end [ d8] _DYNAMIC [ e1] __init_array_start [ f4] __GNU_EH_FRAME_HDR [ 107] _GLOBAL_OFFSET_TABLE_ [ 11d] __libc_csu_fini [ 12d] _ITM_deregisterTMCloneTable [ 149] j [ 14b] _edata [ 152] __libc_start_main@@GLIBC_2.2.5 [ 171] __data_start [ 17e] __gmon_start__ [ 18d] __dso_handle [ 19a] _IO_stdin_used [ 1a9] __libc_csu_init [ 1b9] __bss_start [ 1c5] main [ 1ca] _Jv_RegisterClasses [ 1de] __TMC_END__ [ 1ea] _ITM_registerTMCloneTable HASH holds a symbol hash table, which supports symbol table access. DYNAMIC holds information for dynamic linking. NOBITS is similar to PROGBITS but occupies no space. .bss section holds uninitialized data, which means the bytes in the section can have any value. Until a operating system actually loads the section into main memory, there is no need to allocate space for the binary image on disk to reduce the size of a binary file. Here is the details of .bss from the example output: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [26] .bss NOBITS 0000000000601038 00001038 0000000000000008 0000000000000000 WA 0 0 1 [27] .comment PROGBITS 0000000000000000 00001038 0000000000000034 0000000000000001 MS 0 0 1 In the above output, the size of the section is only 8 bytes, while the offsets of both sections are the same, which means .bss consumes no byte of the executable binary on disk. Notice that the .comment section has no starting address. This means that this section is discarded when the executable binary is loaded into memory. REL holds relocation entries without explicit addends. This type will be explained in details in [sec:Understand-relocations-with-readelf] RELA holds relocation entries with explicit addends. This type will be explained in details in [sec:Understand-relocations-with-readelf] INIT_ARRAY is an array of function pointers for program initialization. When an application program runs, before getting to main(), initialization code in .init and this section are executed first. The first element in this array is an ignored function pointer. It might not make sense when we can include initialization code in the main() function. However, for shared object files where there are no main(), this section ensures that the initialization code from an object file executes before any other code to ensure a proper environment for main code to run properly. It also makes an object file more modularity, as the main application code needs not to be responsible for initializing a proper environment for using a particular object file, but the object file itself. Such a clear division makes code cleaner. However, we will not use any .init and INIT_ARRAY sections in our operating system, for simplicity, as initializing an environment is part of the operating-system domain. To use the INIT_ARRAY, we simply mark a function with the attribute constructor: #include __attribute__((constructor)) static void init1(){ printf("%s\n", __FUNCTION__); } __attribute__((constructor)) static void init2(){ printf("%s\n", __FUNCTION__); } int main(int argc, char *argv[]) { printf("hello world\n"); return 0; } The program automatically calls the constructor without explicitly invoking it: $ gcc -m32 hello.c -o hello $ ./hello init1 init2 hello world Optionally, a constructor can be assigned with a priority from 101 onward. The priorities from 0 to 100 are reserved for gcc. If we want init2 to run before init1, we give it a higher priority: #include __attribute__((constructor(102))) static void init1(){ printf("%s\n", __FUNCTION__); } __attribute__((constructor(101))) static void init2(){ printf("%s\n", __FUNCTION__); } int main(int argc, char *argv[]) { printf("hello world\n"); return 0; } The call order should be exactly as specified: $ gcc -m32 hello.c -o hello $ ./hello init2 init1 hello world We can add initialization functions using another method: #include void init1() { printf("%s\n", __FUNCTION__); } void init2() { printf("%s\n", __FUNCTION__); } /* Without typedef, init is a definition of a function pointer. With typedef, init is a declaration of a type.*/ typedef void (*init)(); __attribute__((section(".init_array"))) init init_arr[2] = {init1, init2}; int main(int argc, char *argv[]) { printf("hello world!\n"); return 0; } The attribute section(“...”) put a function into a particular section rather then the default .text. In this example, it is .init_arary. Again, the program automatically calls the constructors without explicitly invoking it: $ gcc -m32 hello.c -o hello $ ./hello init1 init2 hello world! FINI_ARRAY is an array of function pointers for program termination, called after exiting main(). If the application terminate abnormally, such as through abort() call or a crash, the .finit_array is ignored. A destructor is automatically called after exiting main(), if one or more available: #include __attribute__((destructor)) static void destructor(){ printf("%s\n", __FUNCTION__); } int main(int argc, char *argv[]) { printf("hello world\n"); return 0; } $ gcc -m32 hello.c -o hello $ ./hello hello world destructor PREINIT_ARRAY is an array of function pointers that are invoked before all other initialization functions in INIT_ARRAY. To use the .preinit_array, the only way to put functions into this section is to use the attribute section(): #include void preinit1() { printf("%s\n", __FUNCTION__); } void preinit2() { printf("%s\n", __FUNCTION__); } void init1() { printf("%s\n", __FUNCTION__); } void init2() { printf("%s\n", __FUNCTION__); } typedef void (*preinit)(); typedef void (*init)(); __attribute__((section(".preinit_array"))) preinit preinit_arr[2] = {preinit1, preinit2}; __attribute__((section(".init_array"))) init init_arr[2] = {init1, init2}; int main(int argc, char *argv[]) { printf("hello world!\n"); return 0; } $ gcc -m32 hello2.c -o hello2 $ ./hello2 preinit1 preinit2 init1 init2 hello world! GROUP defines a section group, which is the same section that appears in different object files but when merged into the final executable binary file, only one copy is kept and the rest in other object files are discarded. This section is only relevant in C++ object files, so we will not examine further. SYMTAB_SHNDX is a section containing extended section indexes, that are associated with a symbol table. This section only appears when the Ndx value of an entry in the symbol table exceeds the LORESERVE value. This section then maps between a symbol and an actual index value of a section header. Upon understanding section types, we can understand the number in Link and Info fields: +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | Type | Link | Info | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | DYNAMIC | Entries in this section uses the section index of the dynamic string table. | 0 | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | HASH GNU_HASH | The section index of the symbol table to which the hash table applies. | 0 | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | REL RELA | The section index of the associated symbol table. | The section index to which the relocation applies. | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | SYMTAB DYNSYM | The section index of the associated string table. | One greater than the symbol table index of the last local symbol. | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | GROUP | The section index of the associated symbol table. | The symbol index of an entry in the associated symbol table. The name of the specified symbol table entry provides a signature for the section group. | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | SYMTAB_SHNDX | The section header index of the associated symbol table. | | +-----------------+--------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ Verify that the value of the Link field of a SYMTAB section is the index of a STRTAB section. Verify that the value of the Info field of a SYMTAB section is the index of last local symbol + 1. It means, in the symbol table, from the index listed by Info field onward, no local symbol appears. Verify that the value of the Info field of a REL section is the index of the SYMTAB section. Verify that the value of the Link field of a REL section is the index of the section where relocation is applied. For example. if the section is .rel.text, then the relocating section should be .text. Program header table A program header tableprogram header table is an array of program headers that defines the memory layout of a program at runtime. A program headerprogram header is a description of a program segment. A program segmentprogram segment is a collection of related sections. A segment contains zero or more sections. An operating system when loading a program, only use segments, not sections. To see the information of a program header table, we use the -l option with readelf: $ readelf -l Similar to a section, a program header also has types: PHDR specifies the location and size of the program header table itself, both in the file and in the memory image of the program INTERP specifies the location and size of a null-terminated path name to invoke as an interpreter for linking runtime libraries. LOAD specifies a loadable segment. That is, this segment is loaded into main memory. DYNAMIC specifies dynamic linking information. NOTE specifies the location and size of auxiliary information. TLS specifies the Thread-Local Storage template, which is formed from the combination of all sections with the flag TLS. GNU_STACK indicates whether the program's stack should be made executable or not. Linux kernel uses this type. A segment also has permission, which is a combination of these 3 values:[float MarginTable: [MarginTable 3: Segment Permission ] +-------------+-------------+ | Permission | Description | +-------------+-------------+ +-------------+-------------+ | R | Readable | +-------------+-------------+ | W | Writable | +-------------+-------------+ | E | Executable | +-------------+-------------+ ] • Read (R) • Write (W) • Execute (E) ------------------------------------------- The command to get the program header table: $ readelf -l hello Output: Elf file type is EXEC (Executable file) Entry point 0x400430 There are 9 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001f8 0x00000000000001f8 R E 8 INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x000000000000070c 0x000000000000070c R E 200000 LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x0000000000000228 0x0000000000000230 RW 200000 DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28 0x00000000000001d0 0x00000000000001d0 RW 8 NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254 0x0000000000000044 0x0000000000000044 R 4 GNU_EH_FRAME 0x00000000000005e4 0x00000000004005e4 0x00000000004005e4 0x0000000000000034 0x0000000000000034 R 4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10 GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x00000000000001f0 0x00000000000001f0 R 1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got In the sample output, LOAD segment appears twice: LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x000000000000070c 0x000000000000070c R E 200000 LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10 0x0000000000000228 0x0000000000000230 RW 200000 Why? Notice the permission: • the upper LOAD has Read and Execute permission. This is a text segment. A text segment contains read-only instructions and read-only data. • the lower LOAD has Read and Write permission. This is a data segment. It means that this segment can be read and written to, but is not allowed to be used as executable code, for security reason. Then, LOAD contains the following sections: 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss The first number is the index of a program header in program header table, and the remaining text is the list of all sections within a segment. Unfortunately, readelf does not print the index, so a user needs to keep track manually which segment is of which index. First segment starts at index 0, second at index 1 and so on. LOAD are segments at index 2 and 3. As can be seen from the two lists of sections, most sections are loadable and is available at runtime. ------------------------------------------- Segments vs sections As mentioned earlier, an operating system loads program segments, not sections. However, a question arises: Why doesn't the operating system use sections instead? After all, a section also contains similar information to a program segment, such as the type, the virtual memory address to be loaded, the size, the attributes, the flags and align. As explained before, a segment is the perspective of an operating system, while a section is the perspective of a linker. To understand why, looking into the structure of a segment, we can easily see: • A segment is a collection of sections. It means that sections are logically grouped together by their attributes. For example, all sections in a LOAD segment are always loaded by the operating system; all sections have the same permission, either a RE (Read + Execute) for executable sections, or RW (Read + Write) for data sections. • By grouping sections into a segment, it is easier for an operating system to batch load sections just once by loading the start and end of a segment, instead of loading section by section. • Since a segment is for loading a program and a section is for linking a program, all the sections in a segment is within its start and end virtual memory addresses of a segment. To see the last point clearer, consider an example of linking two object files. Suppose we have two source files: #include int main(int argc, char *argv[]) { printf("Hello World\n"); return 0; } and: int add(int a, int b) { return a + b; } Now, compile the two source files as object files: $ gcc -m32 -c math.c $ gcc -m32 -c hello.c Then, we check the sections of math.o: $ readelf -S math.o There are 11 section headers, starting at offset 0x1a8: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 000034 00000d 00 AX 0 0 1 [ 2] .data PROGBITS 00000000 000041 000000 00 WA 0 0 1 [ 3] .bss NOBITS 00000000 000041 000000 00 WA 0 0 1 [ 4] .comment PROGBITS 00000000 000041 000035 01 MS 0 0 1 [ 5] .note.GNU-stack PROGBITS 00000000 000076 000000 00 0 0 1 [ 6] .eh_frame PROGBITS 00000000 000078 000038 00 A 0 0 4 [ 7] .rel.eh_frame REL 00000000 00014c 000008 08 I 9 6 4 [ 8] .shstrtab STRTAB 00000000 000154 000053 00 0 0 1 [ 9] .symtab SYMTAB 00000000 0000b0 000090 10 10 8 4 [10] .strtab STRTAB 00000000 000140 00000c 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) As shown in the output, all the section virtual memory addresses of every section are set to 0. At this stage, each object file is simply a block of binary that contains code and data. Its existence is to serve as a material container for the final product, which is the executable binary. As such, the virtual addresses in hello.o are all zeroes. No segment exists at this stage: $ readelf -l math.o There are no program headers in this file. The same happens to other object file: There are 13 section headers, starting at offset 0x224: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 000034 00002e 00 AX 0 0 1 [ 2] .rel.text REL 00000000 0001ac 000010 08 I 11 1 4 [ 3] .data PROGBITS 00000000 000062 000000 00 WA 0 0 1 [ 4] .bss NOBITS 00000000 000062 000000 00 WA 0 0 1 [ 5] .rodata PROGBITS 00000000 000062 00000c 00 A 0 0 1 [ 6] .comment PROGBITS 00000000 00006e 000035 01 MS 0 0 1 [ 7] .note.GNU-stack PROGBITS 00000000 0000a3 000000 00 0 0 1 [ 8] .eh_frame PROGBITS 00000000 0000a4 000044 00 A 0 0 4 [ 9] .rel.eh_frame REL 00000000 0001bc 000008 08 I 11 8 4 [10] .shstrtab STRTAB 00000000 0001c4 00005f 00 0 0 1 [11] .symtab SYMTAB 00000000 0000e8 0000b0 10 12 9 4 [12] .strtab STRTAB 00000000 000198 000013 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) $ readelf -l hello.o There are no program headers in this file. Only when object files are combined into a final executable binary, sections are fully realized: $ gcc -m32 math.o hello.o -o hello $ readelf -S hello. There are 31 section headers, starting at offset 0x1804: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481cc 0001cc 000050 10 A 6 1 4 [ 6] .dynstr STRTAB 0804821c 00021c 00004a 00 A 0 0 1 [ 7] .gnu.version VERSYM 08048266 000266 00000a 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 08048270 000270 000020 00 A 6 1 4 [ 9] .rel.dyn REL 08048290 000290 000008 08 A 5 0 4 [10] .rel.plt REL 08048298 000298 000010 08 AI 5 24 4 [11] .init PROGBITS 080482a8 0002a8 000023 00 AX 0 0 4 [12] .plt PROGBITS 080482d0 0002d0 000030 04 AX 0 0 16 [13] .plt.got PROGBITS 08048300 000300 000008 00 AX 0 0 8 [14] .text PROGBITS 08048310 000310 0001a2 00 AX 0 0 16 [15] .fini PROGBITS 080484b4 0004b4 000014 00 AX 0 0 4 [16] .rodata PROGBITS 080484c8 0004c8 000014 00 A 0 0 4 [17] .eh_frame_hdr PROGBITS 080484dc 0004dc 000034 00 A 0 0 4 [18] .eh_frame PROGBITS 08048510 000510 0000ec 00 A 0 0 4 [19] .init_array INIT_ARRAY 08049f08 000f08 000004 00 WA 0 0 4 [20] .fini_array FINI_ARRAY 08049f0c 000f0c 000004 00 WA 0 0 4 [21] .jcr PROGBITS 08049f10 000f10 000004 00 WA 0 0 4 [22] .dynamic DYNAMIC 08049f14 000f14 0000e8 08 WA 6 0 4 [23] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4 [24] .got.plt PROGBITS 0804a000 001000 000014 04 WA 0 0 4 [25] .data PROGBITS 0804a014 001014 000008 00 WA 0 0 4 [26] .bss NOBITS 0804a01c 00101c 000004 00 WA 0 0 1 [27] .comment PROGBITS 00000000 00101c 000034 01 MS 0 0 1 [28] .shstrtab STRTAB 00000000 0016f8 00010a 00 0 0 1 [29] .symtab SYMTAB 00000000 001050 000470 10 30 48 4 [30] .strtab STRTAB 00000000 0014c0 000238 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) Every loadable section is assigned an address, highlighted in green. The reason each section got its own address is that in reality, gcc does not combine an object by itself, but invokes the linker ld. The linker ld uses the default script that it can find in the system to build the executable binary. In the default script, a segment is assigned a starting address 0x8048000 and sections belong to it. Then: • \mathtt{1^{st}\,section\,address=starting\,segment\,address+section\,offset=0x8048000+0x154=0x08048154} • \mathtt{2^{nd}\,section\,address=starting\,segment\,address+section\,offset=0x8048000+0x168=0x08048168} • .... and so on until the last loadable section... Indeed, the end address of a segment is also the end address of the final section. We can see this by listing all the segments: $ readelf -l hello And check, for example, LOAD segment which starts at 0x08048000 and end at \mathtt{0x08048000+0x005fc=0x080485fc} : Elf file type is EXEC (Executable file) Entry point 0x8048310 There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x005fc 0x005fc R E 0x1000 LOAD 0x000f08 0x08049f08 0x08049f08 0x00114 0x00118 RW 0x1000 DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4 NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4 GNU_EH_FRAME 0x0004dc 0x080484dc 0x080484dc 0x00034 0x00034 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 GNU_RELRO 0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got The last section in the first LOAD segment is .eh_frame. The section starts at 0x08048510, with the offset 0x510 and its size is 0xec. The end address of .eh_frame should be: \mathtt{0x08048510+0x510+0xec=0x080485fc} , exactly the same as the end address of the first LOAD segment. Chapter [chap:Linking-and-loading] will explore this whole process in detail. Runtime inspection and debug A [margin: debugger ]debuggerdebugger is a program that allows inspection of a running program. A debugger can start and run a program then stop at a specific line for examining the state of the program at that point. The point where the debugger stop (but not halt) is called a breakpoint. We will be using the GDB - GNU Debugger for debugging our kernel. gdb is the program name. gdb can do four main kinds of things: • Start your program, specifying anything that might affect its behavior. • Make your program stop on specified conditions. • Examine what has happened, when your program has stopped • Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another A sample program There must be an existing program for debugging. The good old “ Hello World” program suffices for the educational purpose in this chapter: #include int main(int argc, char *argv[]) { printf("Hello World!\n"); return 0; } We compile it with debugging information with the option -g: $ gcc -m32 -g hello.c -o hello Finally, we start gdb with the program as argument: $ gdb hello Static inspection of a program Before inspecting a program at runtime, gdb loads it first. Upon loading into memory (but without running), a lot of useful information can be retrieve for inspection. The commands in this section can be used before the program runs. However, they are also usable when the program runs and can display even more information. Command: info target/info file/info files This command prints the information of the target being debugged. A target is the debugging program. The output of the command from hello program, a local target in detail: (gdb) info target Symbols from "/tmp/hello". Local exec file: `/tmp/hello', file type elf32-i386. Entry point: 0x8048310 0x08048154 - 0x08048167 is .interp 0x08048168 - 0x08048188 is .note.ABI-tag 0x08048188 - 0x080481ac is .note.gnu.build-id 0x080481ac - 0x080481cc is .gnu.hash 0x080481cc - 0x0804821c is .dynsym 0x0804821c - 0x08048266 is .dynstr 0x08048266 - 0x08048270 is .gnu.version 0x08048270 - 0x08048290 is .gnu.version_r 0x08048290 - 0x08048298 is .rel.dyn 0x08048298 - 0x080482a8 is .rel.plt 0x080482a8 - 0x080482cb is .init 0x080482d0 - 0x08048300 is .plt 0x08048300 - 0x08048308 is .plt.got 0x08048310 - 0x080484a2 is .text 0x080484a4 - 0x080484b8 is .fini 0x080484b8 - 0x080484cd is .rodata 0x080484d0 - 0x080484fc is .eh_frame_hdr 0x080484fc - 0x080485c8 is .eh_frame 0x08049f08 - 0x08049f0c is .init_array 0x08049f0c - 0x08049f10 is .fini_array 0x08049f10 - 0x08049f14 is .jcr 0x08049f14 - 0x08049ffc is .dynamic 0x08049ffc - 0x0804a000 is .got 0x0804a000 - 0x0804a014 is .got.plt 0x0804a014 - 0x0804a01c is .data 0x0804a01c - 0x0804a020 is .bss The output displayed reports: • Path of a symbol file. A symbol file is the file that contains the debugging information. Usually, this is the same file as the binary, but it is common to separate between an executable binary and its debugging information into 2 files, especially for remote debugging. In the example, it is this line: Symbols from "/tmp/hello". • The path of the debugging program and its file type. In the example, it is this line: Local exec file: `/tmp/hello', file type elf32-i386. • The entry point to the debugging program. That is, the very first code the program runs. In the example, it is this line: Entry point: 0x8048310 • A list of sections with its starting and ending addresses. In the example, it is the remaining output. If the debugging program runs in a different machine, it is a remote target and gdb only prints a brief information: (gdb) info target Remote serial target in gdb-specific protocol: Debugging a target over a serial line. Command: maint info sections This command is similar to info target but give extra information about program sections, specifically the file offset and the flags of each section. Here is the output when running against hello program: (gdb) maint info sections Exec file: `/tmp/hello', file type elf64-x86-64. [0] 0x00400238->0x00400254 at 0x00000238: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS [1] 0x00400254->0x00400274 at 0x00000254: .note.ABI-tag ALLOC LOAD READONLY DATA HAS_CONTENTS [2] 0x00400274->0x00400298 at 0x00000274: .note.gnu.build-id ALLOC LOAD READONLY DATA HAS_CONTENTS [3] 0x00400298->0x004002b4 at 0x00000298: .gnu.hash ALLOC LOAD READONLY DATA HAS_CONTENTS [4] 0x004002b8->0x00400318 at 0x000002b8: .dynsym ALLOC LOAD READONLY DATA HAS_CONTENTS [5] 0x00400318->0x00400355 at 0x00000318: .dynstr ALLOC LOAD READONLY DATA HAS_CONTENTS [6] 0x00400356->0x0040035e at 0x00000356: .gnu.version ALLOC LOAD READONLY DATA HAS_CONTENTS [7] 0x00400360->0x00400380 at 0x00000360: .gnu.version_r ALLOC LOAD READONLY DATA HAS_CONTENTS ....remaining output omitted.... The output is similar to info target, but with more details. Next to the section names are the section flags, which are attributes of a section. Here, we can see that the sections with LOAD flag are from LOAD segment. The command can be combined with the section flags for filtered outputs: ALLOBJ displays sections for all loaded object files, including shared libraries. Shared libraries are only displayed when the program is already running. section names displays only named sections. The command: (gdb) maint info sections .text .data .bss only displays .text, .data and .bss sections: Exec file: `/tmp/hello', file type elf64-x86-64. [13] 0x00400430->0x004005c2 at 0x00000430: .text ALLOC LOAD READONLY CODE HAS_CONTENTS [24] 0x00601028->0x00601038 at 0x00001028: .data ALLOC LOAD DATA HAS_CONTENTS [25] 0x00601038->0x00601040 at 0x00001038: .bss ALLOC section-flags displays only sections with specified section flags. Note that these section flags are specific to gdb, though it is based on the section attributes defined previously. Currently, gdb understands the following flags: ALLOC Section will have space allocated in the process when loaded. Set for all sections except those containing debug information. LOAD Section will be loaded from the file into the child process memory. Set for pre-initialized code and data, clear for .bss sections. RELOC Section needs to be relocated before loading. READONLY Section cannot be modified by the child process. CODE Section contains executable code only. DATA Section contains data only (no executable code). ROM Section will reside in ROM. CONSTRUCTOR Section contains data for constructor/destructor lists. HAS_CONTENTS Section is not empty. NEVER_LOAD An instruction to the linker to not output the section. COFF_SHARED_LIBRARY A notification to the linker that the section contains COFF shared library information. COFF is an object file format, similar to ELF. While ELF is the file format for an executable binary, COFF is the file format for an object file. IS_COMMON Section contains common symbols. We can restrict the output to only display sections that contain code with the command: (gdb) maint info sections CODE The output: Exec file: `/tmp/hello', file type elf64-x86-64. [10] 0x004003c8->0x004003e2 at 0x000003c8: .init ALLOC LOAD READONLY CODE HAS_CONTENTS [11] 0x004003f0->0x00400420 at 0x000003f0: .plt ALLOC LOAD READONLY CODE HAS_CONTENTS [12] 0x00400420->0x00400428 at 0x00000420: .plt.got ALLOC LOAD READONLY CODE HAS_CONTENTS [13] 0x00400430->0x004005c2 at 0x00000430: .text ALLOC LOAD READONLY CODE HAS_CONTENTS [14] 0x004005c4->0x004005cd at 0x000005c4: .fini ALLOC LOAD READONLY CODE HAS_CONTENTS Command: info functions This command lists all function names and their loaded addresses. The names can be filtered with a regular expression. Run the command, we get the following output: (gdb) info functions All defined functions: File hello.c: int main(int, char **); Non-debugging symbols: 0x00000000004003c8 _init 0x0000000000400400 puts@plt 0x0000000000400410 __libc_start_main@plt 0x0000000000400430 _start 0x0000000000400460 deregister_tm_clones 0x00000000004004a0 register_tm_clones 0x00000000004004e0 __do_global_dtors_aux 0x0000000000400500 frame_dummy 0x0000000000400550 __libc_csu_init 0x00000000004005c0 __libc_csu_fini 0x00000000004005c4 _fini Command: info variables This command lists all global and static variable names, or filtered with a regular expression. If we add a global variable int i into the sample source program and recompile then run the command, we get the following output: (gdb) info variables All defined variables: File hello.c: int i; Non-debugging symbols: 0x00000000004005d0 _IO_stdin_used 0x00000000004005e4 __GNU_EH_FRAME_HDR 0x0000000000400708 __FRAME_END__ 0x0000000000600e10 __frame_dummy_init_array_entry 0x0000000000600e10 __init_array_start 0x0000000000600e18 __do_global_dtors_aux_fini_array_entry 0x0000000000600e18 __init_array_end 0x0000000000600e20 __JCR_END__ 0x0000000000600e20 __JCR_LIST__ 0x0000000000600e28 _DYNAMIC 0x0000000000601000 _GLOBAL_OFFSET_TABLE_ 0x0000000000601028 __data_start 0x0000000000601028 data_start 0x0000000000601030 __dso_handle 0x000000000060103c __bss_start 0x000000000060103c _edata 0x000000000060103c completed 0x0000000000601040 __TMC_END__ 0x0000000000601040 _end Command: disassemble/disas This command displays the assembly code of the executable file. gdb can display the assembly code of a function: (gdb) disassemble main Dump of assembler code for function main: 0x0804840b <+0>: lea ecx,[esp+0x4] 0x0804840f <+4>: and esp,0xfffffff0 0x08048412 <+7>: push DWORD PTR [ecx-0x4] 0x08048415 <+10>: push ebp 0x08048416 <+11>: mov ebp,esp 0x08048418 <+13>: push ecx 0x08048419 <+14>: sub esp,0x4 0x0804841c <+17>: sub esp,0xc 0x0804841f <+20>: push 0x80484c0 0x08048424 <+25>: call 0x80482e0 0x08048429 <+30>: add esp,0x10 0x0804842c <+33>: mov eax,0x0 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] 0x08048434 <+41>: leave 0x08048435 <+42>: lea esp,[ecx-0x4] 0x08048438 <+45>: ret End of assembler dump. It would be more useful if source is included: (gdb) disassemble /s main Dump of assembler code for function main: hello.c: 4 { 0x0804840b <+0>: lea ecx,[esp+0x4] 0x0804840f <+4>: and esp,0xfffffff0 0x08048412 <+7>: push DWORD PTR [ecx-0x4] 0x08048415 <+10>: push ebp 0x08048416 <+11>: mov ebp,esp 0x08048418 <+13>: push ecx 0x08048419 <+14>: sub esp,0x4 5 printf("Hello World!\n"); 0x0804841c <+17>: sub esp,0xc 0x0804841f <+20>: push 0x80484c0 0x08048424 <+25>: call 0x80482e0 0x08048429 <+30>: add esp,0x10 6 return 0; 0x0804842c <+33>: mov eax,0x0 7 } 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] 0x08048434 <+41>: leave 0x08048435 <+42>: lea esp,[ecx-0x4] 0x08048438 <+45>: ret End of assembler dump. Now the high level source (in green text) is included as part of the assembly dump. Each line is backed by the corresponding assembly code below it. If the option /r is added, raw instructions in hex are included, just like how objdump displays assembly code by default: (gdb) disassemble /rs main Dump of assembler code for function main: hello.c: 4 { 0x0804840b <+0>: 8d 4c 24 04 lea ecx,[esp+0x4] 0x0804840f <+4>: 83 e4 f0 and esp,0xfffffff0 0x08048412 <+7>: ff 71 fc push DWORD PTR [ecx-0x4] 0x08048415 <+10>: 55 push ebp 0x08048416 <+11>: 89 e5 mov ebp,esp 0x08048418 <+13>: 51 push ecx 0x08048419 <+14>: 83 ec 04 sub esp,0x4 5 printf("Hello World!\n"); 0x0804841c <+17>: 83 ec 0c sub esp,0xc 0x0804841f <+20>: 68 c0 84 04 08 push 0x80484c0 0x08048424 <+25>: e8 b7 fe ff ff call 0x80482e0 0x08048429 <+30>: 83 c4 10 add esp,0x10 6 return 0; 0x0804842c <+33>: b8 00 00 00 00 mov eax,0x0 7 } 0x08048431 <+38>: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4] 0x08048434 <+41>: c9 leave 0x08048435 <+42>: 8d 61 fc lea esp,[ecx-0x4] 0x08048438 <+45>: c3 ret End of assembler dump. A function in a specific file can also be specified: (gdb) disassemble /sr 'hello.c'::main Dump of assembler code for function main: hello.c: 4 { 0x0804840b <+0>: 8d 4c 24 04 lea ecx,[esp+0x4] 0x0804840f <+4>: 83 e4 f0 and esp,0xfffffff0 0x08048412 <+7>: ff 71 fc push DWORD PTR [ecx-0x4] 0x08048415 <+10>: 55 push ebp 0x08048416 <+11>: 89 e5 mov ebp,esp 0x08048418 <+13>: 51 push ecx 0x08048419 <+14>: 83 ec 04 sub esp,0x4 5 printf("Hello World!\n"); 0x0804841c <+17>: 83 ec 0c sub esp,0xc 0x0804841f <+20>: 68 c0 84 04 08 push 0x80484c0 0x08048424 <+25>: e8 b7 fe ff ff call 0x80482e0 0x08048429 <+30>: 83 c4 10 add esp,0x10 6 return 0; 0x0804842c <+33>: b8 00 00 00 00 mov eax,0x0 7 } 0x08048431 <+38>: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4] 0x08048434 <+41>: c9 leave 0x08048435 <+42>: 8d 61 fc lea esp,[ecx-0x4] 0x08048438 <+45>: c3 ret End of assembler dump. The filename must be included in a single quote, and the function must be prefixed by double colons e.g. 'hello.c'::main to specify disassembling of the function main in the file hello.c. Command: x This command examines the content of a given memory range. We can examine the raw content of main: (gdb) x main 0x804840b
: 0x04244c8d By default, without any argument, the command only prints the content of a single memory address. In this case, that is the starting memory address of main. With format arguments, the command can print a range of memory in a specific format. (gdb) x/20b main 0x804840b
: 0x8d 0x4c 0x24 0x04 0x83 0xe40xf0 0xff 0x8048413 : 0x71 0xfc 0x55 0x89 0xe5 0x510x83 0xec 0x804841b : 0x04 0x83 0xec 0x0c /20b main argument means that the command prints 20 bytes, where main starts in memory. The general form for format argument is: / If the repeated count is not supplied, by default gdb supplies the count as 1. The format letter is one of the following values: +---------+-------------------------------------------------------------------------------------------------+ | Letter | Description | +---------+-------------------------------------------------------------------------------------------------+ +---------+-------------------------------------------------------------------------------------------------+ | o | Print the memory content in octal format. | +---------+-------------------------------------------------------------------------------------------------+ | x | Print the memory content in hex format. | +---------+-------------------------------------------------------------------------------------------------+ | d | Print the memory content in decimal format. | +---------+-------------------------------------------------------------------------------------------------+ | u | Print the memory content in unsigned decimal format. | +---------+-------------------------------------------------------------------------------------------------+ | t | Print the memory content in binary format. | +---------+-------------------------------------------------------------------------------------------------+ | f | Print the memory content in float format. | +---------+-------------------------------------------------------------------------------------------------+ | a | Print the memory content as memory addresses. | +---------+-------------------------------------------------------------------------------------------------+ | i | Print the memory content as a series of assembly instructions, similar to disassemble command. | +---------+-------------------------------------------------------------------------------------------------+ | c | Print the memory content as an array of ASCII characters. | +---------+-------------------------------------------------------------------------------------------------+ | s | Print the memory content as a string | +---------+-------------------------------------------------------------------------------------------------+ Depends on the circumstance, certain format is advantageous than the others. For example, if a memory region contains floating-point numbers, then it is better to use the format f than viewing the number as separated 1-byte hex numbers. Command: print/p Examining raw memory is useful but usually it is better to have a more human-readable output. This command does precisely the task: it pretty-prints an expression. An expression can be a global variable, a local variable in current stack frame, a function, a register, a number... Runtime inspection of a program The main use of a debugger is to examine the state of a program, when it is running. gdb provides a set of useful commands for retrieving useful runtime information. Command: run This command starts running the program. Run the hello program: (gdb) r Starting program: /tmp/hello Hello World! [Inferior 1 (process 1002) exited normally] The program runs successfully and printed the message “Hello World”. However, it would not be useful if all gdb can do is run a program. Command: break/b This command sets a breakpoint at a location in the high-level source code. When gdb runs to a specific location marked by a breakpoint, it stops executing for a programmer to inspect the current state of a program. A breakpoint can be set on a line as displayed by an editor. Suppose we want to set a breakpoint at line 3 of the program, which is the start of main function: #include @|\color{red}\bfseries int main(int argc, char *argv[])|@ { printf("Hello World!\n"); return 0; } When running a program, instead of running from start to finish, gdb stopped at line 3: (gdb) b 3 Breakpoint 1 at 0x400535: file hello.c, line 3. (gdb) r Starting program: /tmp/hello Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at hello.c:5 5 printf("Hello World!\n"); The breakpoint is at line 3, but gdb stopped line 5. The reason is that line 3 does not contain code, but a function signature; gdb only stops where it can execute code. The code in the function starts at line 5, the call to printf, so gdb stops there. Line of code is not always the reliable way to specify a breakpoint, as the source code can be changed. What if gdb should always stop at main function? In this case, a better method is to use the function name directly: b main Then, regardless of how the source code changes, gdb always stops at the main function. Sometimes, the debugging program does not contain debug info, or gdb is debugging assembly code. In that case, a memory address can be specified as a stop point. To get the function address, print command can be used: (gdb) print main $3 = {int (int, char **)} 0x400526
Knowing the address of main, we can easily set a breakpoint with a memory address: b *0x400526 gdb can also set breakpoint in any source file. Suppose that hello program is composed not just one file but many files e.g. hello1.c, hello2.c, hello3.c... In that case, simply add the filename before either a line number: b hello.c:3 A function name in a specific file can also be set: b hello.c:main Command: next/n This command executes the current line and stops at the next line. When the current line is a function call, steps over it. After setting a breakpoint at main, run a program and stop at the first printf: (gdb) r Starting program: /tmp/hello Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at hello.c:5 5 printf("Hello World!\n"); Then, to proceed to the next statement, we use the next command: (gdb) n Hello World! 6 return 0; In the output, the first line shows the output produced after executing line 5; then, the next line shows where gdb stops currently, which is line 6. Command: step/s This command executes the current line and stops at the next line. When the current line is a function call, steps into it to the first next line in the called function. Suppose we have a new function add[footnote: Why should we add a new function and function call instead of using the existing printf call? Stepping into shared library functions is tricky because to make debugging works, the debug info must be installed and loaded. It is not worth the trouble for demonstrating this simple command. ]: #include int add(int a, int b) { return a + b; } int main(int argc, char *argv[]) { add(1, 2); printf("Hello World!\n"); return 0; } If step command is used instead of next on the function call printf, gdb steps inside the function: (gdb) r Starting program: /tmp/hello Breakpoint 1, main (argc=1, argv=0xffffd154) at hello.c:11 11 add(1, 2); (gdb) s add (a=1, b=2) at hello.c:6 6 return a + b; After executing the command s, gdb stepped into the add function where the first statement is a return. Command: ni At the core, gdb operates on assembly instruction. Source line by line debugging is simply an enhancement to make it friendlier for programmers. Each statement in C translates to one or more assembly instruction, as shown with objdump and disassemble command. With the debug info available, gdb knows how many instructions belong to one line of high-level code; line by line debugging is just a execution of assembly instructions of a line when moving from the current line to the next. This command executes the one assembly instruction belongs to the current line. Until all assembly instructions of the current line are executed, gdb will not move to the next line. If the current instruction is a call, step over it to the next instruction. When breakpoint is on the printf call and ni is used, it steps through each assembly instruction: (gdb) disassemble /s main Dump of assembler code for function main: hello.c: 4 { 0x0804840b <+0>: lea ecx,[esp+0x4] 0x0804840f <+4>: and esp,0xfffffff0 0x08048412 <+7>: push DWORD PTR [ecx-0x4] 0x08048415 <+10>: push ebp 0x08048416 <+11>: mov ebp,esp 0x08048418 <+13>: push ecx 0x08048419 <+14>: sub esp,0x4 5 printf("Hello World!\n"); 0x0804841c <+17>: sub esp,0xc 0x0804841f <+20>: push 0x80484c0 0x08048424 <+25>: call 0x80482e0 0x08048429 <+30>: add esp,0x10 6 return 0; => 0x0804842c <+33>: mov eax,0x0 7 } 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] 0x08048434 <+41>: leave 0x08048435 <+42>: lea esp,[ecx-0x4] 0x08048438 <+45>: ret End of assembler dump. (gdb) r Starting program: /tmp/hello Breakpoint 1, main (argc=1, argv=0xffffd154) at hello.c:5 5 printf("Hello World!\n"); (gdb) ni 0x0804841f 5 printf("Hello World!\n"); (gdb) ni 0x08048424 5 printf("Hello World!\n"); (gdb) ni Hello World! 0x08048429 5 printf("Hello World!\n"); (gdb) 6 return 0; Upon entering ni, gdb executes current instruction and display the next instruction. That's why from the output, gdb only displays 3 addresses: 0x0804841f, 0x08048424 and 0x08048429. The instruction at 0x0804841c, which is the first instruction of printf, is not displayed because it is the first instruction that gdb stopped at. Assume that gdb stopped at the first instruction of printf at 0x0804841c, the current instruction can be displayed using x command: (gdb) x/i $eip => 0x804841c : sub esp,0xc Command: si Similar to ni, this command executes the current assembly instruction belongs to the current line. But if the current instruction is a call, step into it to the first next instruction in the called function. Recall that the assembly code generated from printf contains a call instruction: (gdb) disassemble /s main Dump of assembler code for function main: hello.c: 4 { 0x0804840b <+0>: lea ecx,[esp+0x4] 0x0804840f <+4>: and esp,0xfffffff0 0x08048412 <+7>: push DWORD PTR [ecx-0x4] 0x08048415 <+10>: push ebp 0x08048416 <+11>: mov ebp,esp 0x08048418 <+13>: push ecx 0x08048419 <+14>: sub esp,0x4 5 printf("Hello World!\n"); 0x0804841c <+17>: sub esp,0xc 0x0804841f <+20>: push 0x80484c0 0x08048424 <+25>: call 0x80482e0 0x08048429 <+30>: add esp,0x10 6 return 0; => 0x0804842c <+33>: mov eax,0x0 7 } 0x08048431 <+38>: mov ecx,DWORD PTR [ebp-0x4] 0x08048434 <+41>: leave 0x08048435 <+42>: lea esp,[ecx-0x4] 0x08048438 <+45>: ret End of assembler dump. We try instruction by instruction stepping again, but this time by running si at 0x08048424, where call resides: (gdb) si 0x0804841f 5 printf("Hello World!\n"); (gdb) si 0x08048424 5 printf("Hello World!\n"); (gdb) x/i $eip => 0x8048424 : call 0x80482e0 (gdb) si 0x080482e0 in puts@plt () The next instruction right after 0x8048424 is the first instruction at 0x080482e0 in puts function. In other words, gdb stepped into puts instead of stepping over it. Command: until This command executes until the next line is greater than the current line. Suppose we have a function that execute a long loop: #include int add1000() { int total = 0; for (int i = 0; i < 1000; ++i){ total += i; } printf("Done adding!\n"); return total; } int main(int argc, char *argv[]) { add1000(1, 2); printf("Hello World!\n"); return 0; } Using next command, we need to press 1000 times for finishing the loop. Instead, a faster way is to use until: (gdb) b add1000 Breakpoint 1 at 0x8048411: file hello.c, line 4. (gdb) r Starting program: /tmp/hello Breakpoint 1, add1000 () at hello.c:4 4 int total = 0; (gdb) until 5 for (int i = 0; i < 1000; ++i){ (gdb) until 6 total += i; (gdb) until 5 for (int i = 0; i < 1000; ++i){ (gdb) until 8 printf("Done adding!\n"); Executing the first until, gdb stopped at line 5 since line 5 is greater than line 4. Executing the second until, gdb stopped at line 6 since line 6 is greater than line 5. Executing the third until, gdb stopped at line 5 since the loop still continues. Because line 5 is less than line 6, with the fourth until, gdb kept executing until it does not go back to line 5 anymore and stopped at line 8. This is a great way to skip over loop in the middle, instead of setting unneeded breakpoint. until can be supplied with an argument to explicitly execute to a specific line: (gdb) r Starting program: /tmp/hello Breakpoint 1, add1000 () at hello.c:4 4 int total = 0; (gdb) until 8 add1000 () at hello.c:8 8 printf("Done adding!\n"); Command: finish This command executes until the end of a function and displays the return value. finish is actually just a more convenient version of until. Using the add1000 function from the previous example and use finish instead of until: (gdb) r Starting program: /tmp/hello Breakpoint 1, add1000 () at hello.c:4 4 int total = 0; (gdb) finish Run till exit from #0 add1000 () at hello.c:4 Done adding! 0x08048466 in main (argc=1, argv=0xffffd154) at hello.c:15 15 add1000(1, 2); Value returned is $1 = 499500 Command: bt This command prints the backtrace of all stack frames. A [margin: backtrace ]backtracebacktrace is a list of currently active functions: Suppose we have a chain of function calls: void d(int d) { }; void c(int c) { d(0); } void b(int b) { c(1); } void a(int a) { b(2); } int main(int argc, char *argv[]) { a(3); return 0; } bt can visualize such a chain in action: (gdb) b a Breakpoint 1 at 0x8048404: file hello.c, line 9. (gdb) r Starting program: /tmp/hello Breakpoint 1, a (a=3) at hello.c:9 9 void a(int a) { b(2); } (gdb) s b (b=2) at hello.c:7 7 void b(int b) { c(1); } (gdb) s c (c=1) at hello.c:5 5 void c(int c) { d(0); } (gdb) s d (d=0) at hello.c:3 3 void d(int d) { }; (gdb) bt #0 d (d=0) at hello.c:3 #1 0x080483eb in c (c=1) at hello.c:5 #2 0x080483fb in b (b=2) at hello.c:7 #3 0x0804840b in a (a=3) at hello.c:9 #4 0x0804841b in main (argc=1, argv=0xffffd154) at hello.c:13 Most-recent calls are placed on top and least-recent calls are near the bottom. In this case, d is the most current active function, so it has the index 0. Next is c, the 2[superscript:nd] active function, has the index 1 and so on with function b, function a, and finally function main at the bottom, the least-recent function. That is how we read a backtrace. Command: up This command goes up one frame earlier the current frame. Instead of staying in d function, we can go up to c function and look at its state: (gdb) bt #0 d (d=0) at hello.c:3 #1 0x080483eb in c (c=1) at hello.c:5 #2 0x080483fb in b (b=2) at hello.c:7 #3 0x0804840b in a (a=3) at hello.c:9 #4 0x0804841b in main (argc=1, argv=0xffffd154) at hello.c:13 (gdb) up #1 0x080483eb in c (c=1) at hello.c:3 3 void b(int b) { c(1); } The output displays the current frame is moved to c and where the call to c is made, which is in function b at line 3. Command: down Similar to up, this command goes down one frame later then the current frame. After inspecting c function, we can go back to d: (gdb) bt #0 d (d=0) at hello.c:3 #1 0x080483eb in c (c=1) at hello.c:5 #2 0x080483fb in b (b=2) at hello.c:7 #3 0x0804840b in a (a=3) at hello.c:9 #4 0x0804841b in main (argc=1, argv=0xffffd154) at hello.c:13 (gdb) up #1 0x080483eb in c (c=1) at hello.c:3 3 void b(int b) { c(1); } (gdb) down #0 d (d=0) at hello.c:1 1 void d(int d) { }; Command: info registers This command lists the current values in commonly used registers. This command is useful when debugging assembly and operating system code, as we can inspect the current state of the machine. Executing the command, we can see the commonly used registers: (gdb) info registers eax 0xf7faddbc -134554180 ecx 0xffffd0c0 -12096 edx 0xffffd0e4 -12060 ebx 0x0 0 esp 0xffffd0a0 0xffffd0a0 ebp 0xffffd0a8 0xffffd0a8 esi 0xf7fac000 -134561792 edi 0xf7fac000 -134561792 eip 0x804841c 0x804841c eflags 0x286 [ PF SF IF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99 The above registers suffice for writing our operating system in later part. How debuggers work: A brief introduction How breakpoints work When a programmer places a breakpoint somewhere in his code, what actually happens is that the first opcode of the first instruction of a statement is replaced with another instruction, int 3 with opcode CCh: [float Figure: [Figure 0.17: Opcode replacement, with int 3 ] +-----+-----+---------+ +-----+-----+----+ | 83 | ec | 0c | \rightarrow | cc | ec | 0c | +-----+-----+---------+ +-----+-----+----+ +---------------------+ +----------------+ | sub esp,0x4 | | int 3 | +---------------------+ +----------------+ ] int 3 only costs a single byte, making it efficient for debugging. When int 3 instruction is executed, the operating system calls its breakpoint interrupt handler. The handler then checks what process reaches a breakpoint, pauses it and notifies the debugger it has paused a debugged process. The debugged process is only paused and that means a debugger is free to inspect its internal state, like a surgeon operates on an anesthetic patient. Then, the debugger replaces the int 3 opcode with the original opcode and executes the original instruction normally. [float Figure: [Figure 0.18: Restore the original opcode, after int 3 was executed ] +-----+-----+----+ +-----+-----+---------+ | cc | ec | 0c | \rightarrow | 83 | ec | 0c | +-----+-----+----+ +-----+-----+---------+ +----------------+ +---------------------+ | int 3 | | sub esp,0x4 | +----------------+ +---------------------+ ] It is simple to see int 3 in action. First, we add an int 3 instruction where we need gdb to stop: #include int main(int argc, char *argv[]) { asm("int 3"); printf("Hello World\n"); return 0; } int 3 precedes printf, so gdb is expected to stop at printf. Next, we compile with debug enable and with Intel syntax: $ gcc -masm=intel -m32 -g hello.c -o hello Finally, start gdb: $ gdb hello Running without setting any breakpoint, gdb stops at printf call, as expected: (gdb) r Starting program: /tmp/hello Program received signal SIGTRAP, Trace/breakpoint trap. main (argc=1, argv=0xffffd154) at hello.c:6 6 printf("Hello World\n"); The blue text indicates that gdb encountered a breakpoint, and indeed it stopped at the right place: the printf call, where int 3 preceded it. Single stepping When breakpoint is implemented, it is easy to implement single stepping: a debugger simply places another int 3 opcode in the next instruction. So, when a programmer sets a breakpoint at an instruction, the next instruction is automatically set by the debugger, thus enable instruction by instruction debugging. Similarly, source line by line debugging is just the placements of the very first opcodes in the two statements with two int 3 opcodes. How a debugger understands high level source code DWARF is a debugging file format used by many compilers and debuggers to support source level debugging. DWARF contains information that maps between entities in the executable binary with the source files. A program entity can either be data or code. A DIE, or [margin: Debugging Information Entry ]Debugging Information EntryDebugging Information Entry, is a description of a program entity. A DIE consists of a tag, which specifies the entity that the DIE describes, and a list of  attributes that describes the entity. Of all the attributes, these two attributes enables source-level debugging: • Where the entity appears in the source files: which file and which line the entity appears. • Where the entity appears in the executable binary: in which memory address the entity is loaded at runtime. With the precise address, gdb can retrieve correct value for a data entity, or place a correct breakpoint and stop accordingly for a code entity. Without the information of these addresses, gdb would not know where the entities are to inspect them. +---------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------+ | hello.c | | DIE | +---------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------+ +--------------------------------------------------------------+------------------------------------------------------------------------------------+ +------------------------------------------------------------------+ |   Line 1   Line 2 \Rightarrow Line 3   Line 5   Line 6 | #include   int main(int argc, char *argv[]) .......... ..........   |       \rightarrow    | .... .... main in hello.c is at 0x804840b in hello .... .... | +--------------------------------------------------------------+------------------------------------------------------------------------------------+ +------------------------------------------------------------------+                     \downarrow \uparrow +------------------------------------------------------------------+ | hello (at 0x804840b) | +------------------------------------------------------------------+ +------------------------------------------------------------------+ | ...8d 4c 24 04 83 e4 f0 ff 71 fc .... | +------------------------------------------------------------------+ In addition to DIEs, another binary-to-source mapping is the line number table. The line number table maps between a line in the source code and at which memory address is the start of the line in the executable binary. In sum, to successfully enable source-level debugging, a debugger needs to know the precise location of the source files and the load addresses at runtime. Address matching, between the image layout of the ELF binary and the address where it is loaded, is extremely important since debug information relies on correct loading address at runtime. That is, it assumes the addresses as recorded in the binary image at compile-time the same as at runtime e.g. if the load address for .text section is recorded in the executable binary at 0x800000, then when the binary actually runs, .text should really be loaded at 0x800000 for gdb to be able to correctly match running instructions with high-level code statement. Address mismatching makes debug information useless, as actual code at one address is displayed as code at another address. Without this knowledge, we will not be able to build an operating system that can be debugged with gdb. When an executable binary contains debug info, readelf can display such information in a readable format. Using the good old hello world program: #include int main(int argc, char *argv[]) { printf("Hello World\n"); return 0; } and compile with debug info: $ gcc -m32 -g hello.c -o hello With the binary ready, we can look at the line number table with the command: $ readlelf -wL hello -w option prints all the debug information. In combination with its sub-option, only specific information is displayed. For example, with -L, only the line number table is displayed: Decoded dump of debug contents of section .debug_line: CU: hello.c: File name Line number Starting address hello.c 6 0x804840b hello.c 7 0x804841c hello.c 9 0x804842c hello.c 10 0x8048431 From the above output: CU shorts for Compilation Unit, a separately compiled source file. In the example, we only have one file, hello.c. File name displays the filename of the current compilation unit. Line number is the line number in the source file of which the line is not an empty line. In the example, line 8 is an empty line, so it does not appear. Starting address is the memory address where the line actually starts in the executable binary. With such crystal clear information, this is how gdb is able to set a breakpoint on a line easily. For placing breakpoints on variables and functions, it is time to look at the DIEs. To get the DIEs information from an executable binary, run the command: $ readlelf -wi hello -wi option lists all the DIE entries. This is one typical DIE entry: <0>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_producer : (indirect string, offset: 0xe): GNU C11 5.4.0 20160609 -masm=intel -m32 -mtune=generic -march=i686 -g -fstack-protector-strong <10> DW_AT_language : 12 (ANSI C99) <11> DW_AT_name : (indirect string, offset: 0xbe): hello.c <15> DW_AT_comp_dir : (indirect string, offset: 0x97): /tmp <19> DW_AT_low_pc : 0x804840b <1d> DW_AT_high_pc : 0x2e <21> DW_AT_stmt_list : 0x0 Red This left-most number indicates the current nesting level of a DIE entry. 0 is the outer-most level DIE with its entity is the compilation unit. This means subsequent DIE entries with higher nesting level are all the children of this tag, the compilation unit. It makes sense, as all the entities must originate from a source file. Blue These numbers in hex format indicate the offsets into .debug_info section. Each meaningful information is displayed along with its offset. When an attribute references to another attribute, the offset is used to precisely identify the referenced attribute. Green These names with DW_AT_ prefix are the attributes attached to a DIE that describe an entity. Notable attributes: DW_AT_name DW_AT_comp_dir The filename of the compilation unit and the directory where compilation occurred. Without the filename and the path, gdb would not be able to display the high-level source, despite the availability of the debug info. Debug info only contains the mapping between source and binary, not the source code itself. DW_AT_low_pc DW_AT_high_pc The start and end of the current entity, which is the compilation unit, in the executable binary. The value in DW_AT_low_pc is the starting address. DW_AT_high_pc is the size of the compilation unit, when adding up to DW_AT_low_pc results in the end address of the entity. In this example, code compiled from hello.c starts at 0x804840b and end at \mathtt{0x804840b+0x2e=0x8048439} . To really make sure, we verify with objdump: int main(int argc, char *argv[]) { 804840b: 8d 4c 24 04 lea ecx,[esp+0x4] 804840f: 83 e4 f0 and esp,0xfffffff0 8048412: ff 71 fc push DWORD PTR [ecx-0x4] 8048415: 55 push ebp 8048416: 89 e5 mov ebp,esp 8048418: 51 push ecx 8048419: 83 ec 04 sub esp,0x4 printf("Hello World\n"); 804841c: 83 ec 0c sub esp,0xc 804841f: 68 c0 84 04 08 push 0x80484c0 8048424: e8 b7 fe ff ff call 80482e0 8048429: 83 c4 10 add esp,0x10 return 0; 804842c: b8 00 00 00 00 mov eax,0x0 } 8048431: 8b 4d fc mov ecx,DWORD PTR [ebp-0x4] 8048434: c9 leave 8048435: 8d 61 fc lea esp,[ecx-0x4] 8048438: c3 ret 8048439: 66 90 xchg ax,ax 804843b: 66 90 xchg ax,ax 804843d: 66 90 xchg ax,ax 804843f: 90 nop It is true: main starts at 804840b and end at 8048439, right after the ret instruction at 8048438. The instructions after 8048439 are just padding bytes inserted by gcc for alignment, which do not belong to main. Note that the output from objdump shows much more code past main. It is not counted, as the code is outside of hello.c, added by gcc for the operating system. hello.c contains only one function: main and this is why hello.c also starts and ends the same as main. Pink This number displays the abbreviation form of a tag. An abbreviation is the form of a DIE. When debug info is displayed with -wi, the DIEs are displayed with their values. -wa option shows abbreviations in the .debug_abbrev section: Contents of the .debug_abbrev section: Number TAG (0x0) 1 DW_TAG_compile_unit [has children] DW_AT_producer DW_FORM_strp DW_AT_language DW_FORM_data1 DW_AT_name DW_FORM_strp DW_AT_comp_dir DW_FORM_strp DW_AT_low_pc DW_FORM_addr DW_AT_high_pc DW_FORM_data4 DW_AT_stmt_list DW_FORM_sec_offset DW_AT value: 0 DW_FORM value: 0 .... more abbreviations .... The output is similar to a DIE output, with only attribute names and without any value. We can also say an abbreviation is a type of a DIE, as an abbreviation represents the structure of a particular DIE. Many DIEs share the same abbreviation, or structure, thus they are of the same type. An abbreviation number specifies which type a DIE is in the abbreviation table above. Abbreviations improve encoding efficiency (reduce binary size) because each DIE needs not to carry their structure information as pairs of attribute-value[footnote: For example, data format such as YAML or JSON encodes its attribute names along with its values. This simplifies encoding, but with overhead. ], but simply refers to an abbreviation for correct decoding. Here are all the DIEs of hello represented as a tree: In the figure [dwarf_tree], DW_TAG_subprogram represents a function such as main. Its children are the DIEs of argc and argv. With such precise information, matching source to binary is an easy job for gdb. If more than one compilation units exist in an executable binary, the DIE entries are sorted according to the compilation order from gcc. For example, suppose we have another test.c source file[footnote: It can contain anything. Just a sample file. ] and compile it together with hello: $ gcc -masm=intel -m32 -g test.c hello.c -o hello Then, the all DIE entries in test.c are displayed before the DIE entries in hello.c: <0>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_producer : (indirect string, offset: 0x0): GNU C11 5.4.0 20160609 -masm=intel -m32 -mtune=generic -march=i686 -g -fstack-protector-strong <10> DW_AT_language : 12 (ANSI C99) <11> DW_AT_name : (indirect string, offset: 0x64): test.c <15> DW_AT_comp_dir : (indirect string, offset: 0x5f): /tmp <19> DW_AT_low_pc : 0x804840b <1d> DW_AT_high_pc : 0x6 <21> DW_AT_stmt_list : 0x0 <1><25>: Abbrev Number: 2 (DW_TAG_subprogram) <26> DW_AT_external : 1 <26> DW_AT_name : bar <2a> DW_AT_decl_file : 1 <2b> DW_AT_decl_line : 1 <2c> DW_AT_low_pc : 0x804840b <30> DW_AT_high_pc : 0x6 <34> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <36> DW_AT_GNU_all_call_sites: 1 ....after all DIEs in test.c listed.... <0><42>: Abbrev Number: 1 (DW_TAG_compile_unit) <43> DW_AT_producer : (indirect string, offset: 0x0): GNU C11 5.4.0 20160609 -masm=intel -m32 -mtune=generic -march=i686 -g -fstack-protector-strong <47> DW_AT_language : 12 (ANSI C99) <48> DW_AT_name : (indirect string, offset: 0xc5): hello.c <4c> DW_AT_comp_dir : (indirect string, offset: 0x5f): /tmp <50> DW_AT_low_pc : 0x8048411 <54> DW_AT_high_pc : 0x2e <58> DW_AT_stmt_list : 0x35 ....then all DIEs in hello.c are listed.... Groundwork Bootloader A bootloader loads an OS, or an application [footnote: Many embedded devices don't use an OS. In embedded systems, the bootloader is simply included in boot firmware and no bootloader is needed. ] that runs and communicate directly with hardware. To run an OS, the first thing to write is a bootloader. In this chapter, we are going to write a rudimentary bootloader, as our main focus is writing an operating system, not a bootloader. More interestingly, this chapter will present related tools and techniques that are applicable for writing a bootloader as well as an operating system. x86 Boot Process After the POST process finished, the CPU's program counter is set to the address FFFF:0000h for executing BIOS code. BIOS - Basic Input/Output System is a firmware that performs hardware initialization and provides a set of generic subroutines to control input/output devices. The BIOS checks all available storage devices (floppy disks and hard disks) if any device is bootable, by examining the last two bytes of the first sector whether it has the boot record signature of 0x55, 0xAA. If so, the BIOS loads the first sector to the address 7C00h, set the program counter to that address and let the CPU executing code from there. The first sector is called Master Boot Record, or MBR. The program in the first sector is called MBR Bootloader. Using BIOS services BIOS provides many basic services for controlling the hardware at the boot stage. A service is a group of routines that controls a particular hardware device, or returns information of current system. Each service is given an interrupt number. To call a BIOS routine, an int instruction must be used with an interrupt number. Each BIOS service defines its own numbers for its routines; to call a routine, a specific number must be written to a register required by each service. The list of all BIOS interrupts is available with Ralf Brown's Interrupt List at: http://www.cs.cmu.edu/~ralf/files.html . [float Figure: [Figure 0.19: The boot process. ] ] Example: Interrupt call 13h (diskette service) requires number of sectors to read, track number, sector number, head number and drive number to read from a storage device. The content of the sector is stored in memory at the address defined by the pair of registers ES:BX. The parameters are stored in registers like this: ; Store sector content in the buffer 10FF:0000 mov dx, 10FFh mov es, dx xor bx, bx mov al, 2 ; read 2 sector mov ch, 0 ; read track 0 mov cl, 2 ; 2nd sector is read mov dh, 0 ; head number mov dl, 0 ; drive number. Drive 0 is floppy drive. mov ah, 0x02 ; read floppy sector function int 0x13 ; call BIOS - Read the sector The BIOS is only available in real mode. However, when switching to protected mode, then BIOS will not be usable anymore and the operating system code is responsible for controlling hardware devices. This is when the operating system stands on its own: it must provide its own kernel drivers for talking to hardware. Boot process 1. BIOS transfers control to MBR bootloader by jumping to 0000:7c00h, where bootloader is assumed to exist already. 2. Setup machine environment for booting by properly initialize segment registers to enable flat memory model. 3. Load the kernel: (a) Read kernel from disk. (b) Save it somewhere in the main memory. (c) Jump to the starting code address of the kernel and execute. 4. If error occurs, print a message to notify users something went wrong and halt. Example Bootloader Here is a simple bootloader that does nothing, except not crashing the machine but halt it gracefully. If the virtual machine does not halt but text repeatedly flashing, it means the bootloader does not load properly and the machine crashed. The machine crashed because it keeps executing until the near end of physical memory (1 MB in real mode), which is FFFF:0000h, which starts the whole BIOS boot process all over again. This is effectively a reset, but not fully, since machine environment from previous run is still reserved. For that reason, it is called a warm reboot. The opposite of warm reboot is cold reboot, in which the machine environment is reset to initial settings when the computer starts from a powerless state. ;****************************************** ; bootloader.asm ; A Simple Bootloader ;****************************************** org 0x7c00 bits 16 start: jmp boot ;; constant and variable definitions msg db "Welcome to My Operating System!", 0ah, 0dh, 0h boot: cli ; no interrupts cld ; all that we need to init hlt ; halt the system ; We have to be 512 bytes. Clear the rest of the bytes with 0 times 510 - ($-$$) db 0 dw 0xAA55 ; Boot Signiture Compile and load We compile the code with nasm and write it to a disk image: $ nasm -f bin bootloader.asm -o bootloader Then, we create a 1.4 MB floppy disk and: $ dd if=/dev/zero of=disk.img bs=512 count=2880 2880+0 records in 2880+0 records out 1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.00625622 s, 236 MB/s Then, we write the bootloader to the 1[superscript:st]sector: $ dd conv=notrunc if=bootloader of=disk.img bs=512 count=1 seek=0 1+0 records in 1+0 records out 512 bytes copied, 0.000102708 s, 5.0 MB/s The option conv=notrunc preserves the original size of the floppy disk. Without this option, the 1.4 MB disk image will be completely replaced by the new disk.img with only 512 bytes, and we do not want that happens. In the past, developing an operating system is complicated because a programmer needs to understand specific hardware he is using. Even though x86 was ubiquitous, the minute differences between models made some code written for a machine not run on another. Further, if you use the same physical computer you write your operating system take very long between runs, and also difficult to debug. Fortunately, today we can uniformly produce a virtual machine with a particular specification and avoid the incompatibility issue altogether, thus making an OS easier to write and test since everyone can reproduce the same machine environment. We will be using QEMU, a generic and open source machine emulator and virtualizer. QEMU can emulate various types of machine, not limited to x86_64 only. Debug is easy since you can connect GDB to a virtual machine to debug code that runs on it, through QEMU's built-in GDB server. QEMU can use disk.img as a boot device e.g. a floppy disk: $ qemu-system-i386 -machine q35 -fda disk.img -gdb tcp::26000 -S • With option -machine q35, QEMU emulates a q35 machine model from Intel.[footnote: The following command lists all supported emulated machines from QEMU: qemu-system-i386 -machine help ]. • With option -fda disk.img, QEMU uses disk.img as a floppy disk image. • With option -gdb tcp::26000, QEMU allows gdb to connect to the virtual machine for remote debugging through a tcp socket with port 26000. • With option -S, QEMU waits for gdb to connect before it starts running. After the command is executed, a new console window that displays the screen output of the virtual machine. Open another terminal, run gdb and set the current architecture to i8086, since we are running in 16-bit mode: (gdb) set architecture i8086 warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration of GDB. Attempting to continue with the default i8086 settings. The target architecture is assumed to be i8086 Then, connect gdb to the waiting virtual machine with this command: (gdb) target remote localhost:26000 Remote debugging using localhost:26000 0x0000fff0 in ?? () Then, place a breakpoint at 0x7c00: (gdb) b *0x7c00 Breakpoint 1 at 0x7c00 Note the asterisk before the memory address. Without the asterisk, gdb treats the address as a symbol in a program rather than an address. Then, for convenience, we use a split layout for viewing the assembly code and registers together: (gdb) layout asm (gdb) layout reg Finally, run the program: (gdb) c If the virtual machine successfully runs the bootloader, this is what the QEMU screen should look like: [float Figure: [Figure 0.20: Boot succeeded. ] ] Debugging If, for some reason, the sample bootloader cannot get to such screen and gdb does not stop at 0x7c00, then the following scenarios are likely: • The bootloader is invalid: the message “Boot failed: not a bootable disk” appears for floppy disk booting. Make sure the boot signature is at the last 2 bytes of the 512-byte first sector. • The machine cannot find a boot disk: the message “Boot failed: not a bootable disk” appears for floppy disk booting. Make sure the bootloader is correctly written to the first sector. It can be verify by check the disk with hd: $ hd disk.img | less If the first 512 bytes are all zeroes, then it is likely that the bootloader is incorrectly written to another sector. • The machine crashes: When such scenario happens, it reset back to the beginning at FFFF:0000h. If the QEMU machine starts without waiting for gdb, then the console output window keeps flashing as the machine is repeatedly reset. It is likely some instruction in the bootloader code causing the fault. ------------------------------------------- Print a welcome message We loaded the bootloader successfully. But, it needs to do something useful other than halting our machine. The easiest thing to do is printing something on screen, like how an introduction to all programming language starts with “Hello World”. Our bootloader prints “Welcome to my operating system”[footnote: Or whatever message you want. ]. In this part, we will build a simple I/O library that allows us to set a cursor anywhere on the screen and print text there. First, create a file io.asm for I/O related routines. Then, write the following routines: 1. MovCursor Purpose: Move a cursor to a specific location on screen and remember this location. Parameters: • bh = Y coordinate • bl = X coordinate. Return: None 2. PutChar Purpose: Print a character on screen, at the cursor position previously set by MovCursor . Parameters: • al = Character to print • bl = text color • cx = number of times the character is repeated Return: None 3. Print Purpose: Print a string. Parameters: • ds:si = Zero terminated string Return: None Test the routines by putting each in the bootloader source, compile and run. To debug, run GDB and set a breakpoint at a specific routine. The end result is that Print should display a welcome message on screen. ------------------------------------------- Loading a program from bootloader Now that we get the feel of how to use the BIOS services, it is time for something more complicated. We will place our kernel on 2[superscript:nd] sector onward, and our bootloader reads 30 sectors starting from 2[superscript:nd] sector. Why 30 sectors? Our kernel will grow gradually, so we will preserve 30 sectors and save us time for modifying the bootloader each time the kernel size expands another sector. The primary responsibility of a bootloader is to read an operating system from some storage device e.g. hard disk, then loads it into main memory and transfer the control to the loaded operating system, similar to how the BIOS reads and loads a bootloader. At the moment, our bootloader does nothing more than just an assembly program loaded by the BIOS. To make our bootloader a real one, it must perform well the above two tasks: read and load an operating system. Floppy Disk Anatomy To read from a storage device, we must understand how the device works, and the provided interface for controlling it. First of all, a floppy disk is a storage device, similar to RAM, but can store information even when a computer is turned off, thus is called persistent storage device[margin: persistent storage device ]persistent storage device. A floppy disk also a persistent storage device, thus it provides a storage space up to 1.4 MB, or 1,474,560 bytes. When reading from a floppy disk, the smallest unit that can be read is a sectorsector, a group of 512 contiguous bytes. A group of 18 sectors is a tracktrack. Each side of a floppy disk consists of 80 tracks. A floppy drive is required to read a floppy disk. Inside a floppy drive contains an arm with 2 heads, each head reads a side of a floppy drive; head 0 writes the upper side and head 1 writes the lower side of a floppy disk. [float MarginFigure: [MarginFigure 8: Sector and Track. ] ] When a floppy drive writes data to a brand new floppy disk, track 0 on the upper side is written first, by head 0. When the upper track 0 is full, the lower track 0 is used by head 1. When both the upper and lower side of a track 0 are full, it goes back to head 0 for writing data again, but this time the upper side of track 1 and so on, until no space left on the device. The same procedure is also applied for reading data from floppy disk.[float MarginFigure: [MarginFigure 9: Floppy disk platter with 2 sides. ] ] Read and load sectors from a floppy disk First, we need to a sample program for writing into the 2[superscript:nd] sector, so we can experiment with floppy disk reading: ;****************************************** ; sample.asm ; A Sample Program ;****************************************** mov eax, 1 add eax, 1 Such a program is good enough. To simplify and for the purpose of demonstration, we will use the same floppy disk that holds the bootloader to hold our operating system. The operating system image starts from the 2[superscript:nd] sector, as the 1[superscript:st] sector is already in use by the bootloader. We compile and write it to the 2[superscript:nd] sector with dd: $ nasm -f bin sample.asm -o sample $ dd if=sample of=disk.img bs=512 count=1 seek=0 [float Figure: [Figure 0.21: The bootloader and the sample program on floppy disk. ] +---------------------------+---------------------------+------------+---------------------------+ | 1[superscript:st] sector | 2[superscript:nd] sector | ..... | 30[superscript:th] sector | +---------------------------+---------------------------+------------+---------------------------+ | bootloader | sample | .... | (empty) | +---------------------------+---------------------------+------------+---------------------------+ ] Next, we need to fix the bootloader for reading from the floppy disk and load a number of arbitrary sectors. Before doing so, a basic understanding of floppy disk is required. To read data from disk, interrupt 13 with AH = 02 is a routine for reading sectors from disk into memory: AH = 02 AL = number of sectors to read (1-128 dec.) CH = track/cylinder number (0-1023 dec., see below) CL = sector number (1-17 dec.) DH = head number (0-15 dec.) DL = drive number (0=A:, 1=2nd floppy, 80h=drive 0, 81h=drive 1) ES:BX = pointer to buffer Return: AH = status (see INT 13,STATUS) AL = number of sectors read CF = 0 if successful = 1 if error Apply the above routine, the bootloader can read the 2[superscript:nd] sector: ;****************************************** ; Bootloader.asm ; A Simple Bootloader ;****************************************** org 0x7c00 bits 16 start: jmp boot ;; constant and variable definitions msg db "Welcome to My Operating System!", 0ah, 0dh, 0h boot: cli ; no interrupts cld ; all that we need to init mov ax, 0x50 ;; set the buffer mov es, ax xor bx, bx mov al, 2 ; read 2 sector mov ch, 0 ; track 0 mov cl, 2 ; sector to read (The second sector) mov dh, 0 ; head number mov dl, 0 ; drive number mov ah, 0x02 ; read sectors from disk int 0x13 ; call the BIOS routine jmp 0x50:0x0 ; jump and execute the sector! hlt ; halt the system ; We have to be 512 bytes. Clear the rest of the bytes with 0 times 510 - ($-$$) db 0 dw 0xAA55 ; Boot Signiture The above code jumps to the address 0x50:00 (which is 0x500). To test the code, load it on a QEMU virtual machine and connect through gdb, then place a breakpoint at 0x500. If gdb stops at the address, with the assembly listing is the same code as in sample.asm, then the bootloader successfully loaded the program. This is an important milestone, as we ensure that our operating system are loaded and ran properly. Improve productivity with scripts Automate build with GNU Make Up to this point, the whole development process felt repetitive: whenever a change is made, the same commands are entered again. The commands are also complex. Ctrl+r helps, but it still feels tedious. GNU Make is a program that controls and automates the process of building a complex software. For a small program, like a single C source file, invoking gcc is quick and easy. However, soon your software will be more complex, with multiples spanning multiple directories, it is a chore to manually build and link files. To solve such problem, a tool was created to automate away this problem and is called a build system. GNU Make is one such of tools. There are various build systems out there, but GNU Make is the most popular in Linux world, as it is used for building the Linux kernel. For a comprehensive introduction to make, please refer to the official Introduction to Make: https://www.gnu.org/software/make/manual/html_node/Introduction.html#Introduction . And that's enough for our project. You can also download the manual in different formats e.g. PDF from the official manual page: https://www.gnu.org/software/make/manual/ . With Makefile, we can build simpler commands and save time: all: bootloader bootdisk bootloader: nasm -f bin bootloader.asm -o bootloader.o kernel: nasm -f bin sample.asm -o bootloader.o bootdisk: bootloader.o kernel.o dd if=/dev/zero of=disk.img bs=512 count=2880 dd conv=notrunc if=bootloader.o of=disk.img bs=512 count=1 seek=0 dd conv=notrunc if=sample.o of=disk.img bs=512 count=1 seek=1 Now, with a single command, we can build from start to finish a disk image with a bootloader at 1[superscript:st]sector and the sample program at 2[superscript:nd]sector: $ make bootdisk nasm -f bin bootloader.asm -o bootloader.o nasm -f bin sample.asm -o bootloader.o dd if=/dev/zero of=disk.img bs=512 count=2880 2880+0 records in 2880+0 records out 1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.00482188 s, 306 MB/s dd conv=notrunc if=bootloader.o of=disk.img bs=512 count=1 seek=0 0+1 records in 0+1 records out 10 bytes copied, 7.0316e-05 s, 142 kB/s dd conv=notrunc if=sample.o of=disk.img bs=512 count=1 seek=1 0+1 records in 0+1 records out 10 bytes copied, 0.000208375 s, 48.0 kB/s Looking at the Makefile, we can see a few problems: First, the name disk.img are all over the place. When we want to change the disk image name e.g. floppy_disk.img, all the places with the name disk.img must be changed manually. To solve this problem, we use a variable, and every appearance of disk.img is replaced with the reference to the variable. This way, only one place that is changed - the variable definition - all other places are updated automatically. The following variables are added: BOOTLOADER=bootloader.o OS=sample.o DISK_IMG=disk.img.o The second problem is, the name bootloader and sample appears as part of the filenames of the source files e.g. bootloader.asm and sample.asm, as well as the filenames of the binary files e.g. bootloader and sample. Similar to disk.img, when a name changed, every reference of that name must also be changed manually for both the names of the source files and the names of the binary files e.g. if we change bootloader.asm to loader.asm, then the object file bootloader.o needs changing to loader.o. To solve this problem, instead of changing filenames manually, we create a rule that automatically generate the filenames of one extension to another. In this case, we want any source file that starts with .asm to have its equivalent binary files, without any extension e.g. bootloader.asm \rightarrow bootloader.o. Such transformation is common, so GNU Make provides built-in functions: wildcard and patsubst for solving such problems: BOOTLOADER_SRCS := $(wildcard *.asm) BOOTLOADER_OBJS := $(patsubst %.asm, %.o, $(BOOTLOADER_SRCS)) wildcard matches any .asm file in the current directory, then assigned the list of matched files into the variable BOOTLOADER_SRCS. In this case, BOOTLOADER_SRCS is assigned the value: bootloader.asm sample.asm patsubst substitutes any filename starts with .asm into a filename .o e.g. bootloader.asm \rightarrow bootloader.o. After patsubsts runs, we get a list of object files in BOOTLOADER_OBJS: bootloader.o sample.o Finally, a recipe for building from .asm to .o are needed: %.o: %.asm nasm -f bin $< -o $@ • $< is a special variable that refers to the input of the recipe: %.asm. • $@ is a special variable that refers to the output of the recipe: %.o. When the recipe is executed, the variables are replaced with the actual values. For example, if a transformation is bootloader.asm \rightarrow bootloader.o, then the actual command executed when replace the placeholders in the recipe is: nasm -f bin bootloader.asm -o bootloader.o With the recipe, all the .asm files are built automatically with the nasm command into .o files and we no longer need a separate recipe for each object files. Putting it all together with the new variables, we get a better Makefile: BOOTLOADER=bootloader.o OS=sample.o DISK_IMG=disk.img BOOTLOADER_SRCS := $(wildcard *.asm) BOOTLOADER_OBJS := $(patsubst %.asm, %.o, $(BOOTLOADER_SRCS)) all: bootdisk %.o: %.asm nasm -f bin $< -o $@ bootdisk: $(BOOTLOADER_OBJS) dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=1 seek=1 From here on, any .asm file is compiled automatically, without an explicit recipe for each file. The object files are in the same directory as the source files, making it more difficult when working with the source tree. Ideally, object files and source files should live in different directories. We want a better organized directory layout like Figure [project-layout].[float MarginFigure: [MarginFigure 10: A better project layout ] . ├── bootloader │   └── bootloader.asm │   └── Makefile ├── build │   ├── bootloader │   │   └── bootloader.o │   ├── disk.img │   └── os │   └── sample.o ├── Makefile └── os ├── Makefile └── sample.asm The layout can be displayed with tree command: $ tree ] bootloader/ directory holds bootloader source files; os/ holds operating system source files that we are going to write later; build/ holds the object files for both the bootloader, the os and the final disk image disk.img. Notice that bootloader/ directory also has its own Makefile. This Makefile will be responsible for building everything in bootloader/ directory, while the top-level Makefile is released from the burden of building the bootloader, but only the disk image. The content of the Makefile in bootloader/ directory should be: BUILD_DIR=@|\color{blue}\bfseries ../build/|@bootloader BOOTLOADER_SRCS := $(wildcard *.asm) BOOTLOADER_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(BOOTLOADER_SRCS)) all: $(BOOTLOADER_OBJS) $(BUILD_DIR)/%.o: %.asm nasm -f bin $< -o $@[float MarginFigure: [MarginFigure 11: Makefile in bootloader/ ] . ├── bootloader │   └── bootloader.asm │   └── Makefile ├── build │   ├── bootloader │   │   └── bootloader.o │   ├── disk.img │   └── os │   └── sample.o ├── Makefile └── os ├── Makefile └── sample.asm ] Basically everything related to the bootloader in the top-level Makefile are extracted into this Makefile. When make runs this Makefile, bootloader.o should be built and put into ../build/ directory. As a good practice, all references to ../build/ go through BUILD_DIR variable. The recipe for transforming from .asm \rightarrow .o is also updated with proper paths, else it will not work. • %.asm refers to the assembly source files in the current directory. • $(BUILD_DIR)/%.o refers to the output object files in the build directory in the path ../build/. The entire recipe implements the transformation from \rightarrow ../build/. Note that all paths must be correct. If we try to build object files in a different directory e.g. current directory, it will not work since there is no such recipe exists to build objects at such a path. We also create a similar Makefile for os/ directory:[float MarginFigure: [MarginFigure 12: Makefile in os/ ] . ├── bootloader │   └── bootloader.asm │   └── Makefile ├── build │   ├── bootloader │   │   └── bootloader.o │   ├── disk.img │   └── os │   └── sample.o ├── Makefile └── os ├── Makefile └── sample.asm ] BUILD_DIR=../build/os OS_SRCS := $(wildcard *.asm) OS_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(OS_SRCS)) all: $(OS_OBJS) $(BUILD_DIR)/%.o: %.asm nasm -f bin $< -o $@ For now, it looks almost identical to the Makefile for bootloader. In the next chapter, we will update it for C code. Then, we update the top-level Makefile:[float MarginFigure: [MarginFigure 13: Top-level Makefile ] . ├── bootloader │   └── bootloader.asm │   └── Makefile ├── build │   ├── bootloader │   │   └── bootloader.o │   ├── disk.img │   └── os │   └── sample.o ├── Makefile └── os ├── Makefile └── sample.asm ] BUILD_DIR=build BOOTLOADER=$(BUILD_DIR)/bootloader/bootloader.o OS=$(BUILD_DIR)/os/sample.o DISK_IMG=disk.img all: bootdisk .PHONY: bootdisk bootloader os bootloader: make -C bootloader os: make -C os bootdisk: bootloader os dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=1 seek=1 The build process is now truly modularized: • bootloader and os builds are now delegated to child Makefile of respective components. -C option tells make to execute with a Makefile in a supplied directory. In this case, the directories are bootloader/ and os/. • The target all of the top-level Makefile is only responsible for bootdisk target, which is the primary target of this Makefile. In many cases, a target is not always a filename, but is just a name for a recipe to be always executed when requested. If a filename is of the same name as a target and the file is up-to-date, make does not execute the target. To solve this problem, .PHONY specifies that some targets are not files. All phony targets will then run when requested, regardless of files of the same names. To save time entering the command for starting up a QEMU virtual machine, we also add a target to the top-level Makefile: qemu: qemu-system-i386 -machine q35 -fda $(DISK_IMG) -gdb tcp::26000 -S One last problem is project cleaning. At the moment, object files need removing manually and this is a repetitive process. Instead, let the Makefile of each component takes care of cleaning its object files, then top-level Makefile performs project cleaning by calling the component Makefile to do the jobs. Each Makefile is added with a clean target at the end: • Bootloader Makefile: clean: rm $(BUILD_DIR)/* • OS Makefile: clean: rm $(BUILD_DIR)/* • Top-level Makefile: clean: make -C bootloader clean make -C os clean Simply invoking make clean at the project root, all object files the are removed. GNU Make Syntax summary GNU Make, at its core, is a domain-specific language for build automation. As any programming language, it needs a way to define data and code. In a Makefile, variables carry data. A variable value is either hard coded or evaluated from invoking a shell such as Bash. All variable values in Make has the same type: a string of text. Number 3 is not a number, but textual representation of the symbol 3. Here are common ways how to define data in a Makefile: +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Syntax | Description | +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | A = 1 B = 2 C = $$(expr $(A) + $(B)) ⇒ A is 1, B is 2, C is 3. | Declare a variable and assign a textual value to it. the double dollar sign $$ means the enclosing expression evaluating by a shell, defined by /bin/sh. In this case, the enclosing expression is (expr $(A) + $(B)) and is evaluated by Bash. | +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | PATH = /bin PATH := $PATH:/usr/bin ⇒ PATH is /bin/:/usr/bin | Declare a variable and assign to it. However, the difference is that the = syntax does not allow refer to a variable to use itself as a value in the right hand side, while this syntax does. | +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | PATH = /bin PATH += /usr/bin ⇒ PATH is /bin/:/usr/bin | Append a new value at the end of a variable. Equivalent to: PATH := $PATH:/usr/bin | +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CFLAGS ?= -o ⇒ CFLAGS is assigned the value -o if it was not defined. | This syntax is called conditional reference. Set a variable to a value if it is undefined. This is useful if a user wants to supply different value for a variable from the command line e.g. add debugging option to CFLAGS. Otherwise, Make uses the default defined by ?=. | +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | SRCS = lib1.c lib2.c main.c OBJS := $(SRC:.o=.c) ⇒ OBJS has the value lib1.o lib2.o main.o | This syntax is called substitution reference. A part of referenced variable is replaced with something else. In this case, all the .c extension is replaced by .o extension, thus creating a list of object files for OBJS variable from the list of source files from SRCS variable. | +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Code in GNU Make is a collection of recipes that it can run. Each recipe is analogous to a function in a programming language, and can be called like a regular function. Each recipe carries a series of shell commands to be executed by a shell e.g. Bash. A recipe has the following format: target: prerequisites command Each target is analogous to a function name. Each prerequisite is a call another target. Each command is one of Make's built-in commands or a command that is executable by a shell. All prerequisites must be satisfied before entering main body of target ; that is, each prerequisite must not return any error. If any error is returned, Make terminates the whole build process and prints an error on the command line. Each time make runs, by default if no target is supplied, it starts with all target, go through every prerequisites and finally the body of all. all is analogous to main in other programming languages. However, if make is given a target, it will start from that target instead of main. This feature is useful to automate multiple aspects in a project. For example, one target is for building the project, one target is for generating the documents e.g. test reports, another target for running the whole test suite and all runs every main targets. Automate debugging steps with GDB script For the convenience, we save GDB configuration to .gdbinit file at the project root directory. This configuration is just a collection of GDB commands and a few extra commands. When gdb runs, it first loads the .gdbinit file at home directory, then the .gdbinit file at the current directory. Why shouldn't we put commands in ~/.gdbinit? Because these commands are specific to only this projec e.g. not all programs are required a remote connection. Our first configuration: define hook-stop # Translate the segment:offset into a physical address printf "[%4x:%4x] ", $cs, $eip x/i $cs*16+$eip end The above script displays the memory address in [segment:offset] format, which is necessary for debugging our bootloader and operating system code. It is better to use Intel syntax: set disassembly-flavor intel The following commands set a more convenient layout for debugging assembly code: layout asm layout reg We are currently debugging bootloader code, so it is a good idea to first set it to 16-bit: set architecture i8086 Every time the QEMU virtual machine starts, gdb must always connect to port 26000. To avoid the trouble of manually connecting to the virtual machine, add the command: target remote localhost:26000 Debugging the bootloader needs a breakpoint at 0x7c00, where our bootloader code starts: b *0x7c00 Now, whenever gdb starts, it automatically set correct architecture based on code, automatically connects to the virtual machine[footnote: The QEMU virtual machine should have already been started before starting gdb. ], displays output in a convenient layout and set a necessary breakpoint. All that need to do is run the program. Linking and loading on bare metal [margin: Relocation ]RelocationRelocation is the process of replacing symbol references with its actual symbolic definitions in an object file. A symbol reference is the memory address of a symbol. If the definition is hard to understand, consider a similar analogy: house relocation. Suppose that a programmer bought a new house and the new house is empty. He must buy furnitures and appliances to fulfill daily needs and thus, he made a list of items to buy, and where to place them. To visualize the placements of new items, he draws a blueprint of the house and the respective places of all items. He then travels to the shops to buy goods. Whenever he visit a shop and sees matched items, he tells the shop owner to note them down. After done selecting, he tells the shop owner to pick up a brand new item instead of the objects on display, then give the address for delivering the goods to his new house. Finally, when the goods arrive, he places the items where he planned at the beginning. Now that house relocation is clear, object relocation is similar: • The list of items represents the relocation table, where the memory location for each symbol (item) is predetermined. • Each item represents a pair of symbol definition and its symbol address. • Each shop represents a compiled object file. • Each item on display represents a symbol definition and references in the object file. • The new address, where all the goods are delivered, represents the final executable binary or the final object file. Since the items on display are not for sale, the shop owner delivers brand new goods instead. Similarly, the object files are not merged together, but copied all over a new file, the object/executable file. • Finally, the goods are placed in the positions according to the shopping list made from the beginning. Similarly, the symbol definitions are placed appropriately in its respective section and the symbol references of the final object/executable file are replaced with the actual memory addresses of the symbol definitions. Understand relocations with readelf Earlier, when we explore object sections, there exists sections that begins with .rel. These sections are relocation tables that maps between a symbol and its location in the final object file or the final executable binary[footnote: A .rel section is equivalent to a list of items in the house analogy. ]. Suppose that a function foo is defined in another object file, so main.c declares it as extern: int i; void foo(); int main(int argc, char *argv[]) { i = 5; foo(); return 0; } void foo() {} When we compile main.c as object file with this command: $ gcc -m32 -masm=intel -c main.c Then, we can inspect the relocation tables with this command: $ readelf -r main.o The output: Relocation section '.rel.text' at offset 0x1cc contains 2 entries: Offset Info Type Sym.Value Sym. Name 00000013 00000801 R_386_32 00000004 i 0000001c 00000a02 R_386_PC32 0000002e foo Relocation section '.rel.eh_frame' at offset 0x1dc contains 2 entries: Offset Info Type Sym.Value Sym. Name 00000020 00000202 R_386_PC32 00000000 .text 0000004c 00000202 R_386_PC32 00000000 .text Offset An [margin: offset ]offsetoffset is the location into a section of a binary file, where the actual memory address of a symbol definition is replaced. The section with .rel prefix determines which section to offset into. For example, .rel.text is the relocation table of symbols whose address needs correcting in .text section, at a specific offset into .text section. In the example output: 0000001c 00000a02 R_386_PC32 0000002e foo The blue number indicates there exists a reference of symbol foo that is 1c bytes into .text section. To see it clearer, we recompile main.c with option -g into the file main_debug.o, then run objdump on it and got: Disassembly of section .text: 00000000
: int i; void foo(); int main(int argc, char *argv[]) { 0: 8d 4c 24 04 lea ecx,[esp+0x4] 4: 83 e4 f0 and esp,0xfffffff0 7: ff 71 fc push DWORD PTR [ecx-0x4] a: 55 push ebp b: 89 e5 mov ebp,esp d: 51 push ecx e: 83 ec 04 sub esp,0x4 i = 5; 11: c7 05 00 00 00 00 05 mov DWORD PTR ds:0x0,0x5 18: 00 00 00 foo(); 1b: e8 fc ff ff ff call 1c return 0; 20: b8 00 00 00 00 mov eax,0x0 } 25: 83 c4 04 add esp,0x4 28: 59 pop ecx 29: 5d pop ebp 2a: 8d 61 fc lea esp,[ecx-0x4] 2d: c3 ret ....irrelevant content omitted.... The byte at 1b[superscript:] is the opcode e8, the call instruction; byte at 1c is the value fc. Why is the operand value for e8 is 0xfffffffc, which is equivalent to -4, but the translated instruction call 1c? Info Info specifies index of a symbol in the symbol table and the type of relocation to perform. 0000001c 00000a02 R_386_PC32 0000002e foo The pink number is the index of symbol foo in the symbol table, and the green number is the relocation type. The numbers are written in hex format. In the example, 0a means 10 in decimal, and symbol foo is indeed at index 10: 10: 0000002e 6 FUNC GLOBAL DEFAULT 1 foo Type Type represents the type value in textual form. Looking at the type of foo: 0000001c 00000a02 R_386_PC32 0000002e foo The green number is type in its numeric form, and R_386_PC32 is the name assigned to that value. Each value represents a relocation method of calculation. For example, with the type R_386_PC32, the following formula is applied for relocation (Inteli386 psABI): Relocated\,Offset=S+A-P To understand the formula, it is necessary to understand symbol values. Sym.Value This field shows the symbol value. A symbol value is a value assigned to a symbol, whose meaning depends on the Ndx field: A symbol whose section index is COMMON, its symbol value holds alignment constraints. In the symbol table, the variable i is identified as COM (uninitialized variable):[footnote: The command for listing symbol table is (assume the object file is hello.o): readelf -s hello.o ] Symbol table '.symtab' contains 16 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS hello2.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 5 6: 00000000 0 SECTION LOCAL DEFAULT 7 7: 00000000 0 SECTION LOCAL DEFAULT 8 8: 00000000 0 SECTION LOCAL DEFAULT 10 9: 00000000 0 SECTION LOCAL DEFAULT 12 10: 00000000 0 SECTION LOCAL DEFAULT 14 11: 00000000 0 SECTION LOCAL DEFAULT 15 12: 00000000 0 SECTION LOCAL DEFAULT 13 13: 00000004 4 OBJECT GLOBAL DEFAULT COM i 14: 00000000 46 FUNC GLOBAL DEFAULT 1 main 15: 0000002e 6 FUNC GLOBAL DEFAULT 1 foo so its symbol value is a memory alignment for assigning a proper memory address that conforms to the alignment in the final memory address. In the case of i, the value is 4, so the starting memory address of i in the final binary file will be a multiple of 4. A symbol whose Ndx identifies a specific section, its symbol value holds a section offset. In the symbol table, main and foo belong to section 1: 14: 00000000 46 FUNC GLOBAL DEFAULT 1 main 15: 0000002e 6 FUNC GLOBAL DEFAULT 1 foo which is .text[footnote: .text holds program code and read-only data. ] section[footnote: The command for listing sections is (assume the object file is hello.o): readelf -S hello.o ]: There are 20 section headers, starting at offset 0x558: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000 000034 000034 00 AX 0 0 1 [ 2] .rel.text REL 00000000 000414 000010 08 I 18 1 4 [ 3] .data PROGBITS 00000000 000068 000000 00 WA 0 0 1 [ 4] .bss NOBITS 00000000 000068 000000 00 WA 0 0 1 [ 5] .debug_info PROGBITS 00000000 000068 000096 00 0 0 1 ..... remaining output omitted for clarity.... In the final executable and shared object files, instead of the above values, a symbol value holds a memory address. After compiling hello.o into the final executable hello, the symbol table now contains the memory address for each symbol[footnote: The command to compile the object file hello.o into the executable hello: gcc -g -m32 -masm=intel hello.o -o hello ]: Symbol table '.symtab' contains 75 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 08048154 0 SECTION LOCAL DEFAULT 1 2: 08048168 0 SECTION LOCAL DEFAULT 2 3: 08048188 0 SECTION LOCAL DEFAULT 3 ....output omitted... 64: 08048409 6 FUNC GLOBAL DEFAULT 14 foo 65: 0804a020 0 NOTYPE GLOBAL DEFAULT 26 _end 66: 080482e0 0 FUNC GLOBAL DEFAULT 14 _start 67: 08048488 4 OBJECT GLOBAL DEFAULT 16 _fp_hw 68: 0804a01c 4 OBJECT GLOBAL DEFAULT 26 i 69: 0804a018 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 70: 080483db 46 FUNC GLOBAL DEFAULT 14 main ...ouput omitted... Unlike the values of the symbols foo, i and main as in the hello.o object file, the complete memory addresses are in place. Now it suffices to understand relocation types. Previously, we mentioned the type R_386_PC32. The following formula is applied for relocation (Inteli386 psABI): Relocated\,Offset=S+A-P where S represents the value of the symbol. In the final executable binary, it is the address of the symbol. A represents the addend, an extra value added to the value of a symbol. P Represents the memory address to be fixed. Relocate Offset is the distance between a relocating location[footnote: where the referenced memory address is to be fixed. ] and the actual memory location of a symbol definition, or a memory address. But why do we waste time in calculating a distance instead of replacing with a direct memory address? The reason is that x86 architecture does not use employ any addressing mode that uses an absolute memory address, as listed in table [mod-rm-32]. All addressing modes in x86 are relative. In some assembly language, an absolute address can be used simply because it is a syntactic sugar that is later transformed into one of the relative addressing mode provided by the x86 hardware by the assembler. ------------------------------------------- For the foo symbol: 0000001c 00000a02 R_386_PC32 0000002e foo The distance between the usage of foo in main.o and its definition, applying the formula S+A-P is: \mathtt{2e+0-1c=12} . That is, the place where memory fixing starts is 0x12 or 18 bytes away from the definition of the symbol foo. However, to make an instruction works properly, we must also subtract 4 from 0x12 and results in 0xe. Why the extra -4? Because the relative address starts at the end of an instruction, not the address where memory fixing starts. For that reason, we must also exclude the 4 bytes of the overwritten address. Indeed, looking at the objdump output of the object file hello.o: Disassembly of section .text: 00000000
: 0: 8d 4c 24 04 lea ecx,[esp+0x4] 4: 83 e4 f0 and esp,0xfffffff0 7: ff 71 fc push DWORD PTR [ecx-0x4] a: 55 push ebp b: 89 e5 mov ebp,esp d: 51 push ecx e: 83 ec 04 sub esp,0x4 11: c7 05 00 00 00 00 05 mov DWORD PTR ds:0x0,0x5 18: 00 00 00 1b: e8 fc ff ff ff call 1c 20: b8 00 00 00 00 mov eax,0x0 25: 83 c4 04 add esp,0x4 28: 59 pop ecx 29: 5d pop ebp 2a: 8d 61 fc lea esp,[ecx-0x4] 2d: c3 ret 0000002e : 2e: 55 push ebp 2f: 89 e5 mov ebp,esp 31: 90 nop 32: 5d pop ebp 33: c3 ret The place where memory fixing starts is after the opcode e8, with the mock value fc ff ff ff, which is -4 in decimal. However, the assembly code, the value is displayed as 1c. the memory address right after e8. The reason is that the instruction e8 starts at 1b and ends at 20[footnote: The end of an instruction is the memory address right after its last operand. The whole instruction e8 spans from the address 1b to the address 1f. ]. -4 means 4 bytes backward from the end of instruction, that is: \mathtt{20-4=1c} . After linking, the output of the final executable file is displayed with the actual memory fixing: 080483db
: 80483db: 8d 4c 24 04 lea ecx,[esp+0x4] 80483df: 83 e4 f0 and esp,0xfffffff0 80483e2: ff 71 fc push DWORD PTR [ecx-0x4] 80483e5: 55 push ebp 80483e6: 89 e5 mov ebp,esp 80483e8: 51 push ecx 80483e9: 83 ec 04 sub esp,0x4 80483ec: c7 05 1c a0 04 08 05 mov DWORD PTR ds:0x804a01c,0x5 80483f3: 00 00 00 80483f6: e8 0e 00 00 00 call 8048409 80483fb: b8 00 00 00 00 mov eax,0x0 8048400: 83 c4 04 add esp,0x4 8048403: 59 pop ecx 8048404: 5d pop ebp 8048405: 8d 61 fc lea esp,[ecx-0x4] 8048408: c3 ret 08048409 : 8048409: 55 push ebp 804840a: 89 e5 mov ebp,esp 804840c: 90 nop 804840d: 5d pop ebp 804840e: c3 ret 804840f: 90 nop In the final output, the opcode e8 previously at 1b now starts at the address 80483f6. The mock value fc ff ff ff is replaced with the actual value 0e 00 00 00 using the same calculating method from its object file: opcode e8 is at 80483f6. The definition of foo is at 8048409. The offset from the next address after e8 is \mathtt{8048409+0-80483f7-4=0e} . However, for readability, the assembly is displayed as call 8048409 , since GNU as[footnote: Or any current assembler in use today. ] assembler allows specifying the actual memory address of a symbol definition. Such address is later translated into relative addressing mode, saving the programmer the trouble of calculating offset manually. ------------------------------------------- Sym. Name This field displays the name of a symbol to be relocated. The named symbol is the same as written in a high level language such as C. Crafting ELF binary with linker scripts A [margin: linker ]linkerlinker is a program that combines separated object files into a final binary file. When gcc is invoked, it runs ld underneath to turn object files into the final executable file.. A linker script[margin: linker script ]linker script is a text file that instructs how a linker should combine object files. When gcc runs, it uses its default linker script to build the memory layout of a compiled binary file. Standardized memory layout is called object file format e.g. ELF includes program headers, section headers and their attributes. The default linker script is made for running in the current operating system environment[footnote: To view the default script, use --verbose option: ld --verbose ]. Running on bare metal, the default script cannot be used as it is not designed for such environment. For that reason, a programmer needs to supply his own linker script for such environments. Every linker script consists of a series of commands with the following format: COMMAND { sub-command 1 sub-command 2 .... more sub-command.... } Each sub-command is specific to only the top-level command. The simplest linker script needs only one command: SECTION, that consumes input sections from object files and produces output sections of the final binary file[footnote: Recall that sections are chunks of code or data, or both. ]. Example linker script Here is a minimal example of a linker script: SECTIONS /* Command */ { . = 0x10000; /* sub-command 1 */ .text : { *(.text) } /* sub-command 2 */ . = 0x8000000; /* sub-command 3 */ .data : { *(.data) } /* sub-command 4 */ .bss : { *(.bss) } /* sub-command 5 */ } Code Dissection: +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Code | Description | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | SECTION | Top-level command that declares a list of custom program sections. ld provides a set of such commands. | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | . = 0x10000; | Set location counter to the address 0x10000. Location counter specifies the base address for subsequent commands. In this example, subsequent commands will use 0x10000 onward. | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | .text : { *(.text) } | Since location counter is set to 0x10000, the output .text in the final binary file will starts at the address 0x10000. This command combines all .text sections from all object files with *(.text) syntax into a final .text section. The * is the wildcard which matches any file name. | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | . = 0x8000000; | Again, the location counter is set to 0x8000000. Subsequent commands will use this address for working with sections. | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | .data : { *(.data) } | All .data section are combined into one .data section in the final binary file. | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | .bss : { *(.bss) } | All .bss section are combined into one .bss section in the final binary file. | +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ The addresses 0x10000 and 0x8000000 are called Virtual Memory Address. A virtual memory address[margin: virtual memory address ]virtual memory address is the address where a section is loaded in memory when a program runs. To use the linker script, we save it as a file e.g. main.lds[footnote: .lds is the extension for linker script. ]; then, we need a sample program in a file, e.g. main.c: void test() {} int main(int argc, char *argv[]) { return 0; } Then, we compile the file and explicitly invoke ld with the linker script: $ gcc -m32 -g -c main.c $ ld -m elf_i386 -o main -T main.lds main.o In the ld command, the options are similar to gcc: +---------+--------------------------------------------------------------------------------------------------------------+ | Option | Description | +---------+--------------------------------------------------------------------------------------------------------------+ +---------+--------------------------------------------------------------------------------------------------------------+ | -m | Specify object file format that ld produces. In the example, elf_i386 means a 32-bit ELF is to be produced. | +---------+--------------------------------------------------------------------------------------------------------------+ | -o | Specify the name of the final executable binary. | +---------+--------------------------------------------------------------------------------------------------------------+ | -T | Specify the linker script to use. In the example, it is main.lds. | +---------+--------------------------------------------------------------------------------------------------------------+ The remaining input is a list of object files for linking. After the command ld is executed, the final executable binary - main - is produced. If we try running it: $ ./main Segmentation fault The reason is that when linking manually, the entry address must be explicitly set, or else ld sets it to the start of .text section by default. We can verify from the readelf output: $ readelf -h main ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x10000 Start of program headers: 64 (bytes into file) Start of section headers: 2098144 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 3 Size of section headers: 64 (bytes) Number of section headers: 14 Section header string table index: 11 The entry point address is set to 0x10000, which is the beginning of .text section. Using objdump to examine the address: $ objdump -z -M intel -S -D prog | less we see that the address 0x10000 does not start at main function when the program runs: Disassembly of section .text: 00010000 : int a = 5; int i; void test(){} 10000: 55 push ebp 10001: 89 e5 mov ebp,esp 10003: 90 nop 10004: 5d pop ebp 10005: c3 ret 00010006
: int main(int argc, char *argv[]) { 10006: 55 push ebp 10007: 89 e5 mov ebp,esp return 0; 10009: b8 00 00 00 00 mov eax,0x0 } 1000e: 5d pop ebp 1000f: c3 ret The start of .text section at 0x10000 is the function test, not main! To enable the program to run at main properly, we need to set the entry point in the linker script with the following line at the beginning of the file: ENTRY(main) Recompile the executable binary file main again. This time, the output from readelf is different: ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x10006 Start of program headers: 52 (bytes into file) Start of section headers: 9168 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 3 Size of section headers: 40 (bytes) Number of section headers: 14 Section header string table index: 11 The program now executes code at the address 0x10006 when it starts. 0x10006 is where main starts! To make sure we really starts at main, we run the program with gdb, set two breakpoints at main and test functions: $ gdb ./main .... output omitted .... Reading symbols from ./main...done. (gdb) b test Breakpoint 1 at 0x10003: file main.c, line 1. (gdb) b main Breakpoint 2 at 0x10009: file main.c, line 5. (gdb) r Starting program: /tmp/main Breakpoint 2, main (argc=-11493, argv=0x0) at main.c:5 5 return 0; As displayed in the output, gdb stopped at the 2[superscript:nd] breakpoint first. Now, we run the program normally, without gdb: $ ./main Segmentation fault We still get a segmentation fault. It is to be expected, as we ran a custom binary without C runtime support from the operating system. The last statement in the main function: return 0, simply returns to a random place[footnote: Return address is above the current ebp. However, when we enter main, no return value is pushed on the stack. So, when return is executed, it simply retrieves any value above ebp and use as a return address. ]. The C runtime ensures that the program exit properly. In Linux, the _exit() function is implicitly called when main returns. To fix this problem, we simply change the program to exit properly: void test() {} int main(int argc, char *argv[]) { asm("mov eax, 0x1\n" "mov ebx, 0x0\n" "int 0x80"); } Inline assembly is required because interrupt 0x80 is defined for system calls in Linux. Since the program uses no library, there is no other way to call system functions, aside from using assembly. However, when writing our operating system, we will not need such code, as there is no environment for exiting properly yet. Now that we can precisely control where the program runs initially, it is easy to bootstrap the kernel from the bootloader. Before we move on to the next section, note how readelf and objdump can be applied to debug a program even before it runs. Understand the custom ELF structure In the example, we manage to create a runnable ELF executable binary from a custom linker script, as opposed to the default one provided by gcc. To make it convenient to look into its structure: $ readelf -e main -e option is the combination of 3 options -h -l -S: ....... ELF header output omitted ....... Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00010000 001000 000010 00 AX 0 0 1 [ 2] .eh_frame PROGBITS 00010010 001010 000058 00 A 0 0 4 [ 3] .debug_info PROGBITS 00000000 001068 000087 00 0 0 1 [ 4] .debug_abbrev PROGBITS 00000000 0010ef 000074 00 0 0 1 [ 5] .debug_aranges PROGBITS 00000000 001163 000020 00 0 0 1 [ 6] .debug_line PROGBITS 00000000 001183 000038 00 0 0 1 [ 7] .debug_str PROGBITS 00000000 0011bb 000078 01 MS 0 0 1 [ 8] .comment PROGBITS 00000000 001233 000034 01 MS 0 0 1 [ 9] .shstrtab STRTAB 00000000 00133a 000074 00 0 0 1 [10] .symtab SYMTAB 00000000 001268 0000c0 10 11 10 4 [11] .strtab STRTAB 00000000 001328 000012 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x001000 0x00010000 0x00010000 0x00068 0x00068 R E 0x1000 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 Section to Segment mapping: Segment Sections... 00 .text .eh_frame 01 The structure is incredibly simple. Both the segment and section listings can be contained within one screen. This is not the case with default ELF executable binary. From the output, there are only 11 sections, and only two are loaded at runtime: .text and .eh_frame because both section are assigned with an actual memroy addresses, 0x10000 and 0x10010 respectively. The remaining sections are assigned with 0 in the final executable binary[footnote: As opposed to the object files, where memory addresses are always 0 and only assigned with actual values in the linking process. ], which mean they are not loaded at runtime. It makes sense, as those sections are related to versioning[footnote: It is the .comment section. It can be viewed with the comment readelf -p .comment main. ], debugging[footnote: The ones starts with .debug prefix. ] and linking[footnote: The symbol tables and string table. ]. The program segment header table is even simpler. It only contains 2 segments: LOAD and GNU_STACK. By default, if the linker script does not supply the instructions for building program segments, ld provides reasonable default segments. As in this case, .text should be in the LOAD segment. GNU_STACK segment is a GNU extension used by the Linux kernel to control the state of the program stack. We will not need this segment, along with .eh_frame, which is for exception handling, as we write our own operating system from scratch. To achieve these goals, we will need to create our own program headers instead of letting ld handles the task, and instruct ld to remove .eh_frame. Manipulate the program segments First, we need to craft our own program header table by using the following syntax: PHDRS { [ FILEHDR ] [ PHDRS ] [ AT ( address ) ] [ FLAGS ( flags ) ] ; } PHDRS command, similar to SECTION command, but for declaring a list of custom program segments with a predefined syntax. name is the header name for later referenced by a section declared in SECTION command. type is the ELF segment type, as described in section [sec:Program-header-table] , with added prefix PT_. For example, instead of NULL or LOAD as displayed by readelf, it is PT_NULL or PT_LOAD. ------------------------------------------- With only name and type, we can create any number of program segments. For example, we can add the NULL program segment and remove the GNU_STACK segment: PHDRS { null PT_NULL; code PT_LOAD; } SECTIONS { . = 0x10000; .text : { *(.text) } :code . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } } The content of PHDRS command tells that the final executable binary contains 2 program segments: NULL and LOAD. The NULL segment is given the name null and LOAD segment given the name code to signify this LOAD segment contains program code. Then, to put a section into a segment, we use the syntax :, where phdr is the name given to a segment earlier. In this example, .text section is put into code segment. We compile and see the result (assuming main.o compiled earlier remains): $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x10000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 LOAD 0x001000 0x00010000 0x00010000 0x00010 0x00010 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text .eh_frame Those 2 segments are now NULL and LOAD instead of LOAD and GNU_STACK. We can add as many segments of the same type, as long as they are given different names: PHDRS { null1 PT_NULL; null2 PT_NULL; code1 PT_LOAD; code2 PT_LOAD; } SECTIONS { . = 0x10000; .text : { *(.text) } :code1 .eh_frame : { *(.eh_frame) } :code2 . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } } After amending the PHDRS content earlier with this new segment listing, we put .text into code1 segment and .eh_frame into code2 segment, we compile and see the new segments: $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x10000 There are 4 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 LOAD 0x001000 0x00010000 0x00010000 0x00010 0x00010 R E 0x1000 LOAD 0x001010 0x00010010 0x00010010 0x00058 0x00058 R 0x1000 Section to Segment mapping: Segment Sections... 00 01 02 .text 03 .eh_frame Now .text and .eh_frame are in different segments. ------------------------------------------- FILEHDR is an optional keyword, when added specifies that a program segment includes the ELF file header of the executable binary. However, this attribute should only added for the first program segment, as it drastically alters the size and starting address of a segment because the ELF header is always at the beginning of a binary file, recall that a segment starts at the address of its first content, which is in most of the cases (except for this case, which is the file header), the first section. ------------------------------------------- Adding the FILEHDR keyword changes the size of NULL segment: PHDRS { null PT_NULL FILEHDR; code PT_LOAD; } ..... content is the same ..... We link it again and see the result: $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x10000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align NULL 0x000000 0x00000000 0x00000000 0x00034 0x00034 R 0x4 LOAD 0x001000 0x00010000 0x00010000 0x00068 0x00068 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text .eh_frame In previous examples, the file size and memory size of the NULL section are always 0, now they are both 34 bytes, which is the size of an ELF header. If we assign FILEHDR to a non-starting segment, its size and starting address changes significantly: PHDRS { null PT_NULL; code PT_LOAD FILEHDR; } ..... content is the same ..... $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x10000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4 LOAD 0x000000 0x0000f000 0x0000f000 0x01068 0x01068 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text .eh_frame The size of the LOAD segment in the previous example is only 0x68, the same size as the total sizes of .text and .eh_frame sections in it. But now, it is 0x01068, got 0x1000 bytes larger. What is the reason for these extra bytes? A simple answer: segment alignment. From the output, the alignment of this segment is 0x1000; it means that regardless of which address is the start of this segment, it must be divisible by 0x1000. For that reason, the starting address of LOAD is 0xf000 because it is divisible by 0x1000. Another question arises: why is the starting address 0xf000 instead of 0x10000? .text is the first section, which starts at 0x10000, so the segment should start at 0x10000. The reason is that we include FILEHDR as part of the segment, it must expand to include the ELF file header, which is at the very start of an ELF executable binary. To satisfy this constraint and the alignment constraint, 0xf000 is the closest address. Note that the virtual and physical memory addresses are the addresses at runtime, not the locations of the segment in the file on disk. As the FileSiz field shows, the segment only consumes 0x1068 bytes on disk. Figure [LOAD_segment] illustrates the difference between the memory layouts with and without FILEHDR keyword. [float Figure: [Figure 0.22: LOAD segment on disk and in memory. ] [float Figure: [Sub-Figure a: Without FILEHDR. ] ] [float Figure: [Sub-Figure b: With FILEHDR. ] ] ] ------------------------------------------- PHDRS is an optional keyword, when added specifies that a program segment is a program segment header table. ------------------------------------------- The first segment of the default executable binary generated by gcc is a PHDR since the program segment header table appears right after the ELF header. It is also a convenient segment to put the ELF header into using the FILEHDR keyword. We replace the unused NULL segment earlier with a PHDR segment: PHDRS { headers PT_PHDR FILEHDR PHDRS; code PT_LOAD FILEHDR; } ..... content is the same ..... $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x10000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x001000 0x00010000 0x00010000 0x00068 0x00068 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text .eh_frame As shown in the output, the first segment is of type PHDR. Its size is 0x74, which includes: • 0x34 bytes for ELF header. • 0x40 bytes for the program segment header table, with 2 entries, each is 0x20 bytes (32 bytes) in length. The above number is consistent with ELF header output: ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 ....... output omitted ...... Size of this header: 52 (bytes) --> 0x34 bytes Size of program headers: 32 (bytes) --> 0x20 bytes each program header Number of program headers: 2 --> 0x40 bytes in total Size of section headers: 40 (bytes) Number of section headers: 12 Section header string table index: 9 ------------------------------------------- AT ( address ) specifies the load memory address where the segment is placed. Every segment or section has a virtual memory address and a load memory address: • A [margin: virtual memory address ]virtual memory addressvirtual memory address is a starting address of a segment or a section when a program is in memory and running. The memory address is called virtual because it does not map to the actual memory cell that corresponds to the address number, but any random memory cell, which depends on how the underlying operating system translates the address. For example, the virtual memory address 0x1 might map to the memory cell with the physical address 0x1000. • A load memory address[margin: load memory address ]load memory address is the physical memory address, where a program is loaded but not yet running. The load memory address is specified by AT syntax. Normally both types of addresses are the same, and the physical address can be ignored. They differ when loading and running are purposely divided into two distinct phases that require different address regions. For example, a program can be designed to load into a ROM[footnote: Read-Only Memory ] at a fixed address. But when loading into RAM for a bare-metal application or an operating system to use, the program needs a load address that accommodates the addressing scheme of the target application or operating system. ------------------------------------------- We can specify a load memory address for the segment LOAD with AT syntax: PHDRS { headers PT_PHDR FILEHDR PHDRS AT(0x500); code PT_LOAD; } ..... content is the same ..... $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x4000 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000500 0x00074 0x00074 R 0x4 LOAD 0x001000 0x00004000 0x00002000 0x00068 0x00068 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text .eh_frame It depends on an operating system whether to use the address or not. For our operating system, the virtual memory address and load are the same, so an explicit load address is none of our concern. ------------------------------------------- FLAGS (flags) assigns permissions to a segment. Each flag is an integer that represents a permission and can be combined with OR operations. Possible values: +-------------+--------+-------------+ | Permission | Value | Description | +-------------+--------+-------------+ +-------------+--------+-------------+ | R | 1 | Readable | +-------------+--------+-------------+ | W | 2 | Writable | +-------------+--------+-------------+ | E | 4 | Executable | +-------------+--------+-------------+ ------------------------------------------- We can create a LOAD segment with Read, Write and Execute permissions enabled: PHDRS { headers PT_PHDR FILEHDR PHDRS AT(0x500); code PT_LOAD FILEHDR FLAGS(0x1 | 0x2 | 0x4); } ..... content is the same ..... $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x0 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000500 0x00074 0x00074 R 0x4 LOAD 0x001000 0x00000000 0x00000000 0x00010 0x00010 RWE 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text .eh_frame LOAD segment now gets all the RWE permissions, as shown above. ------------------------------------------- Finally, we want to remove the .eh_frame or any unwanted section, we add a special section called /DISCARD/: ... program segment header table remains the same ... SECTIONS { /* . = 0x10000; */ .text : { *(.text) } :code . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } /DISCARD/ : { *(.eh_frame) } } Any section putting in /DISCARD/ disappears in the final executable binary: $ ld -m elf_i386 -o main -T main.lds main.o $ readelf -l main Elf file type is EXEC (Executable file) Entry point 0x0 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000500 0x00074 0x00074 R 0x4 LOAD 0x001000 0x00000000 0x00000000 0x00010 0x00010 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text As can be seen, .eh_frame is nowhere to be found. C Runtime: Hosted vs Freestanding The purpose of .init, .init_array, .fini_array and .preinit_array section is to initialize a C Runtime environment that supports the C standard libraries. Why does C need a runtime environment, when it is supposed to be a compiled language? The reason is that many of the standard functions depend on the underlying operating system, which is of itself a big runtime environment. For example, I/O related functions such as reading from keyboard with gets(), reading from file with open(), printing on screen with printf(), managing system memory with malloc(), free(), etc. A C implementation cannot provide such routines without a running operating system, which is a hosted environment. A hosted environment hosted environment is a runtime environment that: • provides a default implementation of C libraries that includes system-dependent data and routines. • perform resource allocations to prepare an environment for a program to run. This process is similar to the hardware initialization process: • When first powered up, a desktop computer loads its basic system routines from a read-only memory stored on the motherboard. • Then, it starts initializing an environment, such as setting default values for various registers in CPU and devices, before executing the any code. In contrast, a freestanding environmentfreestanding environment is an environment that does not provide system-dependent data and routines. As a consequence, almost no C library exists and the environment can run code compiled written from pure C syntax. For a free standing environment to become a host environment, it must implement standard C system routines. But for a conforming freestanding environment, it only needs these header files available: , , and (according to GCC manual). For a typical desktop x86 program, C runtime environment is initialized by a compiler so a program runs normal. However, for an embedded platform where a program runs directly on it, this is not the case. The typical C runtime environment used in desktop operating systems cannot be used on the embedded platforms, because architectural differences and resource constraints. As such, the software writer must implement a custom C runtime environment suitable for the targeted platform. For the embedded platform, In writing our operating system, the first step is to create a freestanding environment before creating a hosted one. Debuggable bootloader on bare metal Currently, the bootloader is compiled as a flat binary file. Although gdb can display the assembly code, it is not always the same as the source code. In the assembly source code, there exists variable names and labels. These symbols are lost when compiled as a flat binary file, making debugging more difficult. Another issue is the mismatch between the written assembly source code and the displayed assembly source code. The written code might contain higher level syntax that is assembler-specific and is generated into lower-level assembly code as displayed by gdb. Finally, with debug information available, the command next/n and prev/p can be used instead of ni and si. To enable debug information, we modify the bootloader Makefile: 1. The bootloader must be compiled as a ELF binary. Open the Makefile in bootloader/ directory and change this line under $(BUILD_DIR)/%.o: %.asm recipe: nasm -f bin $< -o $@ to this line: nasm -f elf $< -F dwarf -g -o $@ In the updated recipe, bin format is replaced with elf format to enable debugging information to be properly produced.-F option specifies the debug information format, which is dwarf in this case. Finally, -g option causes nasm to actually generate debug information in selected format. 2. Then, ld consumes the ELF bootloader binary and produces another ELF bootloader binary, with proper starting memory address of .text section that match the actual address of the bootloader at runtime, when QEMU virtual machine loads it at 0x7c00. We need ld because when compiled by nasm, the starting address is assumed to be 0, not 0x7c00. 3. Finally, we use objcopy to separate extract only the flat binary content as the original bootloader by adding this line to $(BUILD_DIR)/%.o: %.asm: objcopy -O binary $(BUILD_DIR)/bootloader.o.elf $@ objcopy, as its name implies, is a program that copies and translates object files. Here, we copy the original ELF bootloader and translate it into a flat binary file. The updated recipe should look like: $(BUILD_DIR)/%.o: %.asm nasm -f elf $< -F dwarf -g -o $@ ld -m elf_i386 -T bootloader.lds $@ -o $@.elf objcopy -O binary $(BUILD_DIR)/bootloader.o.elf $@ Now we test the bootloader with debug information available: 1. Start the QEMU machine: $ make qemu 2. Start gdb with the debug information stored in bootloader.o.elf: $ gdb build/bootloader/bootloader.o.elf After getting into gdb, press the Enter key and if the sample .gdbinit section [sub:Automate-debugging-steps] is used, the output should look like: ---Type to continue, or q to quit--- [f000:fff0] 0x0000fff0 in ?? () Breakpoint 1 at 0x7c00: file bootloader.asm, line 6. (gdb) gdb now understand where the instruction at address 0x7c00 is in the assembly source file, thanks to the debug information. Debuggable program on bare metal The process of building a debug-ready executable binary is similar to that of a bootloader, except more involved. Recall that for a debugger to work properly, its debugging information must contain correct address mappings between memory addresses and the source code. gcc stores such mapping information in DIE entries, in which it tells gdb at which code address corresponds to a line in a source file, so that breakpoints work properly. But first, we need a sample C source file, a very simple one: void main() {} Because this is a free standing environment, standard libraries that involve system functions such as printf() would not work, because a C runtime does not exist. At this stage, the goal is to correctly jump to main with source code displayed properly in gdb, so no fancy C code is needed yet. The next step is updating os/Makefile: BUILD_DIR=../build_os OS=$(BUILD_DIR)/os @|\color{red}\bfseries CFLAGS+=-ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3|@ OS_SRCS := $(wildcard *.c) OS_OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(OS_SRCS)) all: $(OS) $(BUILD_DIR)/%.o: %.c gcc $(CFLAGS) -m32 -c $< -o $@ $(OS): $(OS_OBJS) ld -m elf_i386 -T@|\color{blue}\bfseries os.lds|@ $(OS_OBJS) -o $@ clean: rm $(OS_OBJS) We updated the Makefile with the following changes: • Add a CFLAGS variable for passing options to gcc. • Instead of the rule to build assembly source code earlier, it is replaced with a C version with a recipe to build C source files. The CFLAGS variable makes the gcc command in the recipe looks cleaner regardless how many options are added. • Add a linking command for building the final executable binary of the operating system with a custom linker script os.lds. Everything looks good, except for the linker script part. Why is it needed? The linker script is required for controlling at which physical memory address the operating system binary appears in the memory, so the linker can jump to the operating system code and execute it. To complete this requirement, the default linker script used by gcc would not work as it assumes the compiled executable runs inside an existing operating system, while we are writing an operating system itself. The next question is, what will be the content in the linker script? To answer this question, we must understand what goals to achieve with the linker script: • For the bootloader to correctly jump to and execute the operating system code. • For gdb to debug correctly with the operating system source code. To achieve the goals, we must devise a design of a suitable memory layout for the operating system. Recall that the bootloader developed in chapter [chap:Bootloader] can already load a simple binary compiled from the sample Assembly program sample.asm. To load the operating system, we can simply throw binary compiled from sample.asm with the binary compiled from os.c above. If only it is that simple. The idea is correctly, but not enough. The goals implies the following constraints: 1. The operating system code is written in C and compiled as an ELF executable binary. It means, the bootloader needs to retrieve correct entry address from the ELF header. 2. To debug properly with gdb, the debug info must contain correct mappings between instruction addresses and source code. Thanks to the understanding of ELF and DWARF acquire in the earlier chapters, we can certainly modify the bootloader and create an executable binary that satisfy the above constraint. We will solve these problems one by one. Loading an ELF binary from a bootloader Earlier we examined that an ELF header contains a entry address of a program. That information is 0x18 bytes away from the beginning of an ELF header, according to man elf : typedef struct { unsigned char e_ident[EI_NIDENT]; uint16_t e_type; uint16_t e_machine; uint32_t e_version; ElfN_Addr e_entry; ElfN_Off e_phoff; ElfN_Off e_shoff; uint32_t e_flags; uint16_t e_ehsize; uint16_t e_phentsize; uint16_t e_phnum; uint16_t e_shentsize; uint16_t e_shnum; uint16_t e_shstrndx; } ElfN_Ehdr; The offset from the start of the struct to the start of e_entry is: • 16 bytes of e_ident[EI_NIDENT]: #define EI_NIDENT 16 • 2 bytes of e_type • 2 bytes of e_machine • 4 bytes of e_version \mathtt{Offset=16+2+2+4=24=0x18} e_entry is of type ElfN_Addr, in which N is either 32 or 64. We are writing 32-bit operating system, in this case N=32 and so ElfN_Addr is Elf32_Addr, which is 4 bytes long. With any program, such as this simple one: #include int main(int argc, char *argv[]) { printf("hello world!\n"); return 0; } We can retrieve the entry address with a human-readable presentation using readelf: $ gcc hello.c -o hello $ readelf -h hello ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 .... output omitted .... Entry point address: 0x400430 .... output omitted .... Or in raw binary with hd: $ hd hello | less 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 3e 00 01 00 00 00 30 04 40 00 00 00 00 00 |..>.....0.@.....| ......... The offset 0x18 is the start of the least-significant byte of e_entry, which is 0x30, followed by 04 40 00, together in reverse makes the address 0x00400430. Now that we know where the position of the entry address in the ELF header, it is easy to modify the bootloader made in section [sub:Read-and-load] to retrieve and jump to the address: ;****************************************** ; Bootloader.asm ; A Simple Bootloader ;****************************************** bits 16 start: jmp boot ;; constant and variable definitions msg db "Welcome to My Operating System!", 0ah, 0dh, 0h boot: cli ; no interrupts cld ; all that we need to init mov ax, 50h ;; set the buffer mov es, ax xor bx, bx mov al, 2 ; read 2 sector mov ch, 0 ; we are reading the second sector past us, ; so its still on track 0 mov cl, 2 ; sector to read (The second sector) mov dh, 0 ; head number mov dl, 0 ; drive number. Remember Drive 0 is floppy drive. mov ah, 0x02 ; read floppy sector function int 0x13 ; call BIOS - Read the sector jmp @|\color{blue}\bfseries [500h + 18h]|@ ; jump and execute the sector! hlt ; halt the system ; We have to be 512 bytes. Clear the rest of the bytes with 0 times 510 - ($-$$) db 0 dw 0xAA55 ; Boot Signiture It is as simple as that! First, we load the operating system binary at 0x500, then we retrieve the entry address at the offset 0x18 from 0x500, by first calculating the expression 500h+18h=518h to get the actual in-memory address, then retrieve the content by dereference it. The first part is done. For the next part, we need to build an ELF operating system image for the bootloader to load. The first step is to create a linker script: @|\color{blue}\bfseries ENTRY(main);|@ PHDRS { headers PT_PHDR FILEHDR PHDRS; code PT_LOAD; } SECTIONS { .text @|\color{blue}\bfseries 0x500|@: { *(.text) } :code .data : { *(.data) } .bss : { *(.bss) } /DISCARD/ : { *(.eh_frame) } } The script is straight-forward and remains almost the same as before. The only differences are: • main are explicitly specified as the entry point by specifying ENTRY(main). • .text is explicitly specified with 0x500 as its virtual memory address since we load the operating system image at 0x500. After putting the script, we compile with make and it should work smoothly: $ make clean; make $ readelf -l build/os/os Elf file type is EXEC (Executable file) Entry point 0x500 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x000500 0x00000500 0x00000500 0x00040 0x00040 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text All looks good, until we run it. We begin by starting the QEMU virtual machine: $ make qemu Then, start gdb and load the debug info (which is also in the same binary file) and set a breakpoint at main: (gdb) symbol-file build/os/os Reading symbols from build/os/os...done. (gdb) b main Breakpoint 2 at 0x500 Then we start the program: (gdb) symbol-file build/os/os Reading symbols from build/os/os...done. (gdb) b main Breakpoint 2 at 0x500 Keep the programming running until it stops at main: (gdb) c Continuing. [ 0:7c00] Breakpoint 1, 0x00007c00 in ?? () (gdb) c Continuing. [ 0: 500] Breakpoint 2, main () at main.c:1 At this point, we switch the layout to the C source code instead of the registers: (gdb) layout split layout split creates a layout that consists of 3 smaller windows: • Source window at the top. • Assembly window in the middle. • Command window at the bottom. After the command, the layout should look like this: ┌──main.c───────────────────────────────────────────────────────┐ B+>│1 void main(){} │ │2 │ │3 │ │4 │ │5 │ │6 │ │7 │ │8 │ │9 │ │10 │ │11 │ │12 │ │13 │ │14 │ │15 │ │16 │ └───────────────────────────────────────────────────────────────┘ B+>│0x500
jg 0x547 │ │0x502 dec sp │ │0x503 inc si │ │0x504 add WORD PTR [bx+di],ax │ │0x506 add WORD PTR [bx+si],ax │ │0x508 add BYTE PTR [bx+si],al │ │0x50a add BYTE PTR [bx+si],al │ │0x50c add BYTE PTR [bx+si],al │ │0x50e add BYTE PTR [bx+si],al │ │0x510 add al,BYTE PTR [bx+si] │ │0x512 add ax,WORD PTR [bx+si] │ │0x514 add WORD PTR [bx+si],ax │ │0x516 add BYTE PTR [bx+si],al │ │0x518 add BYTE PTR [di],al │ │0x51a add BYTE PTR [bx+si],al │ │0x51c xor al,0x0 │ │0x51e add BYTE PTR [bx+si],al │ └───────────────────────────────────────────────────────────────┘ remote Thread 1 In: main L1 PC: 0x500 [f000:fff0] 0x0000fff0 in ?? () Breakpoint 1 at 0x7c00 (gdb) symbol-file build/os/os Reading symbols from build/os/os...done. (gdb) b main Breakpoint 2 at 0x500: file main.c, line 1. (gdb) c Continuing. [ 0:7c00] Breakpoint 1, 0x00007c00 in ?? () (gdb) c Continuing. [ 0: 500] Breakpoint 2, main () at main.c:1 (gdb) layout split (gdb) Something wrong is going on here. It is not the generated assembly code for function call as it is known in section [sub:Function-Call-and] . It is definitely wrong, verified with objdump: $ objdump -D build/os/os | less /home/tuhdo/workspace/os/build/os/os: file format elf32-i386 Disassembly of section .text: 00000500
: 500: 55 push %ebp 501: 89 e5 mov %esp,%ebp 503: 90 nop 504: 5d pop %ebp 505: c3 ret .... remaining output omitted .... The assembly code of main is completely different. This is why understanding assembly code and its relation to high-level languages are important. Without the knowledge, we would have used gdb as a simple source-level debugger without bother looking at the assembly code from the split layout. As a consequence, the true cause of the non-working code could never been discovered. Debugging the memory layout What is the reason for the incorrect Assembly code in main displayed by gdb? There can only be one cause: the bootloader jumped to the wrong addresses. But why was the address wrong? We made the .text section at address 0x500, in which main code is in the first byte for executing, and instructed the bootloader to retrieve the address at the offset 0x18, then jump to the entry address.[float MarginFigure: [MarginFigure 14: Memory state after loading 2[superscript:nd] sector. ] ] Then, it might be possible for the bootloader to load the operating system address at the wrong address. But then, we explicitly set the load address to 50h:00, which is 0x500, and so the correct address was used. After the bootloader loas the 2[superscript:nd] sector, the in-memory state should look like the figure [mem-state-bootloader] : What is the reason for the incorrect Assembly code in main displayed by gdb? There can only be one cause: the bootloader jumped to the wrong addresses. But why was the address wrong? We made the .text section at address 0x500, in which main code is in the first byte for executing, and instructed the bootloader to retrieve the address at the offset 0x18, then jump to the entry address. Then, it might be possible for the bootloader to load the operating system address at the wrong address. But then, we explicitly set the load address to 50h:00, which is 0x500, and so the correct address was used. After the bootloader loads the 2[superscript:nd] sector, the in-memory state should look like the figure [mem-state-bootloader] . Here is the problem: 0x500 is the start of the ELF header. The bootloader actually loads the 2[superscript:nd] sector, which stores the executable as a whole, to 0x500. Clearly, .text section, where main resides, is far from 0x500. Since the in-memory entry address of the executable binary is 0x500, .text should be at \mathtt{0x500+0x500=0xa00} . However, the entry address recorded in the ELF header remains 0x500 and as a result, the bootloader jumped there instead of 0xa00. This is one of the issues that must be fixed. The other issue is the mapping between debug info and the memory address. Because the debug info is compiled with the assumed offset 0x500 that is the start of .text section, but due to actual loading, the offset is pushed another 0x500 bytes, making the address actually is at 0xa00. This memory mismatch renders the debug info useless. [float Figure: [Figure 0.23: Wrong symbol-memory mappings in debug info. ] ] In summary, we have 2 problems to overcome: • Fix the entry address to account for the extra offset when loading into memory. • Fix the debug info to account for the extra offset when loading into memory. First, we need to know the actual layout of the compiled executable binary:l $ readelf -l build/os/os Elf file type is EXEC (Executable file) Entry point 0x500 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x000500 0x00000500 0x00000500 0x00040 0x00040 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text Notice the Offset and the VirtAddress fields: both have the same value. This is problematic, as the entry address and the memory addresses in the debug info depend on VirtAddr field, but the Offset having the same value destroys the validity of VirtAddr[footnote: The offset is the distance in bytes between the beginning of the file, the address 0, to the beginning address of a segment or a section. ] because it means that the real in-memory address will always be greater than the VirtAddr. If we try to adjust the virtual memory address of the .text section in the linker script os.lds, whatever value we set also sets the Offset to the same value, until we set it to some value equal or greater than 0x1074: Elf file type is EXEC (Executable file) Entry point 0x1074 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x000074 0x00001074 0x00001074 0x00006 0x00006 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text If we adjust the virtual address to 0x1073, both the Offset and VirtAddr still share the same value: Elf file type is EXEC (Executable file) Entry point 0x1073 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x001073 0x00001073 0x00001073 0x00006 0x00006 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text The key to answer such phenonemon is in the Align field. The value 0x1000 indicates that the offset address of the segment should be divisible by 0x1000, or if the distance between segment is divisible by 0x1000, the linker removes such distance to save the binary size. We can do some experiments to verify this claim[footnote: All the outputs are produced by the command: $ readelf -l build/os/os ]: • By setting the virtual address of .text to 0x0 to 0x73 (in os.lds), the offset starts from 0x1000 to 0x1073, accordingly. For example, by setting it to 0x0: Elf file type is EXEC (Executable file) Entry point 0x0 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x001000 0x00000000 0x00000000 0x00006 0x00006 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text By default, if we do not specify any virtual address, the offset stays at 0x1000 because 0x1000 is the perfect offset to satisfy the alignment constraint. Any addition from 0x1 to 0x73 makes the segment misaligned, but the linker keeps it anyway because it is told so. • By setting the virtual address of .text to 0x74 (in os.lds): Elf file type is EXEC (Executable file) Entry point 0x74 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x000074 0x00000074 0x00000074 0x00006 0x00006 R E 0x1000 Section to Segment mapping: Segment Sections... 00 01 .text PHDR is 0x74 bytes in size, so if LOAD starts at 0x1074, the distance between the PHDR segment and LOAD segment is \mathtt{0x1074-0x74=0x1000} bytes. To save space, it removes that extra 0x1000 bytes. • By setting the virtual address of .text to any value between 0x75 and 0x1073 (in os.lds), the offset takes the exact values specified, as can be seen in the case of setting to 0x1073 above. • By setting the virtual address of .text to any value equal or greater than 0x1074: it starts all over again at 0x74, where the distance is equal to 0x1000 bytes. Now we get a hint how to control the values of Offset and VirtAddr to produce a desired binary layout. What we need is to change the Align field to a value with smaller value for finer grain control. It might work out with a binary layout like this: Elf file type is EXEC (Executable file) Entry point 0x600 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x000100 0x00000600 0x00000600 0x00006 0x00006 R E 0x100 Section to Segment mapping: Segment Sections... 00 01 .text The binary will look like figure [fig-good-bin-layout] in memory: [float Figure: [Figure 0.24: A good binary layout. ] ] If we set the Offset field to 0x100 from the beginning of the file and the VirtAddr to 0x600, when loading in memory, the actual memory of .text is \mathtt{0x500+0x100=0x600} ; 0x500 is the memory location where the bootloader loads into the physical memory and 0x100 is the offset from the end of ELF header to .text. The entry address and the debug info will then take the value 0x600 from the VirtAddr field above, which totally matches the actual physical layout. We can do it by changing os.lds as follow: @|\color{blue}\bfseries ENTRY(main);|@ PHDRS { headers PT_PHDR FILEHDR PHDRS; code PT_LOAD; } SECTIONS { .text @|\color{blue}\bfseries 0x600|@: @|\color{magenta} ALIGN(0x100)|@ { *(.text) } :code .data : { *(.data) } .bss : { *(.bss) } /DISCARD/ : { *(.eh_frame) } } The ALIGN keyword, as it implies, tells the linker to align a section, thus the segment containing it. However, to make the ALIGN keyword has any effect, automatic alignment must be disabled. According to man ld: -n --nmagic Turn off page alignment of sections, and disable linking against shared libraries. If the output format supports Unix style magic numbers, mark the output as "NMAGIC" That is, by default, each section is aligned by an operating system page, which is 4096, or 0x1000 bytes in size. The -n or -nmagic option disables this behavior, which is needed. We amend the ld command used in os/Makefile: ..... above content omitted .... $(OS): $(OS_OBJS) ld -m elf_i386 @|\color{red}\bfseries -nmagic|@ -Tos.lds $(OS_OBJS) -o $@ Finally, we also need to update the top-level Makefile to write more than one sector into the disk image for the operating system binary, as its size exceeds one sector: $ ls -l build/os/os -rwxrwxr-x 1 tuhdo tuhdo 9060 Feb 13 21:37 build/os/os We update the rule so that the sectors are automatically calculated: ..... above content omitted .... bootdisk: bootloader os dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=$$(($(shell stat --printf="%s" $(OS))/512)) seek=1 After updating the everything, recompiling the executable binary and we get the desired offset and virtual memory at 0x100 and 0x600, respectively: Elf file type is EXEC (Executable file) Entry point 0x600 There are 2 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000000 0x00000000 0x00000000 0x00074 0x00074 R 0x4 LOAD 0x000100 0x00000600 0x00000600 0x00006 0x00006 R E 0x100 Section to Segment mapping: Segment Sections... 00 01 .text Testing the new binary First, we start the QEMU machine: $ make qemu In another terminal, we start gdb, loading the debug info and set a breakpoint at main: $ gdb The following output should be produced: ---Type to continue, or q to quit--- [f000:fff0] 0x0000fff0 in ?? () Breakpoint 1 at 0x7c00 Breakpoint 2 at 0x600: file main.c, line 1. Then, let gdb runs until it hits the main function, then we change to the split layout between source and assembly: (gdb) layout split The final terminal output should look like this: ┌──main.c───────────────────────────────────────────────────────┐ B+>│1 void main(){} │ │2 │ │3 │ │4 │ │5 │ │6 │ │7 │ │8 │ │9 │ │10 │ │11 │ │12 │ │13 │ │14 │ │15 │ │16 │ └───────────────────────────────────────────────────────────────┘ B+>│0x600
push bp │ │0x601 mov bp,sp │ │0x603 nop │ │0x604 pop bp │ │0x605 ret │ │0x606 aaa │ │0x607 add BYTE PTR [bx+si],al │ │0x609 add BYTE PTR [si],al │ │0x60b add BYTE PTR [bx+si],al │ │0x60d add BYTE PTR [bx+si],al │ │0x60f add BYTE PTR [si],al │ │0x611 add ax,bp │ │0x613 push ss │ │0x614 add BYTE PTR [bx+si],al │ │0x616 or al,0x67 │ │0x618 adc al,BYTE PTR [bx+si] │ │0x61a add BYTE PTR [bx+si+0x2],al │ └───────────────────────────────────────────────────────────────┘ remote Thread 1 In: main L1 PC: 0x600 (gdb) c Continuing. [ 0:7c00] Breakpoint 1, 0x00007c00 in ?? () (gdb) c Continuing. [ 0: 600] Breakpoint 2, main () at main.c:1 (gdb) layout split Now, the displayed assembly is the same as in objdump, except the registers are 16-bit ones. This is normal, as gdb is operating in 16-bit mode, while objdump displays code in 32-bit mode. To make sure, we verify the raw opcode by using x command: (gdb) x/16xb 0x600 0x600
: 0x55 0x89 0xe5 0x90 0x5d 0xc3 0x37 0x00 0x608: 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00 From the assembly window, main stops at the address 0x605. As such, the corresponding bytes from 0x600 to 0x605 are highlighted in red from the output of the command x/16xb 0x600. Then, the raw opcode from the objdump output: $ objdump -z -M intel -S -D build/os/os | less build/os/os: file format elf32-i386 Disassembly of section .text: 00000600
: void main(){} 600: 55 push ebp 601: 89 e5 mov ebp,esp 603: 90 nop 604: 5d pop ebp 605: c3 ret Disassembly of section .debug_info: ...... output omitted ...... Both raw opcode displayed by the two programs are the same. In this case, it proved that gdb correctly jumped to the address of main for a proper debugging. This is an extremely important milestone. Being able to debug in bare metal will help tremendously in writing an operating system, as a debugger allows a programmer to inspect the internal state of a running machine at each step to verify his code, step by step, to gradually build up a solid understanding. Some professional programmers do not like debuggers, but it is because they understand their domain deep enough to not need to rely on a debugger to verify their code. When encountering new domains, a debugger is indispensable learning tool because of its verifiability. However, even with the aid of debugger, writing an operating system is still not a walk in the park. The debugger may give the access to the machine at one point in time, but it does not give the cause. To find out the root cause, is up to the ability of a programmer. Later in the book, we will learn how to use other debugging techniques, such as using QEMU logging facility to debug CPU exceptions. Kernel Programming x86 Descriptors Basic operating system concepts The first and foremost, OS manages hardware resources. It's easy to see the core features of an OS based on Von Neumann diagram: CPU management: allows programs to share CPU for multitasking. Memory management: allocates enough storage for programs to run. Devices management: detects and communicates with different devices Any OS should be good at the above fundamentals tasks. Another important feature of an OS is to provide an software interface layer, that hides away hardware interfaces, to interface with applications that run on top of that OS. The benefits of such a layer: • reusability: that is, the same software API can be reused across programs, thus simplifying software development process • separation of concerns: bugs appear either in application programs, or in the OS; a programmer needs to isolate where the bugs are. • simplify software development process: provides an easier to use software interface layer with a uniform access to hardware resources across devices, instead of directly using the hardware interface of a particular device. Hardware Abstraction Layer There are so many hardware devices out there, so it's best to leave the hardware engineers how the devices talk to an OS. To achieve this goal, the OS only provides a set of agreed software interfaces between itself and the device driver writers and is called Hardware Abstraction Layer. In C, this software interface is implemented through a structure function pointers. [illustrate with Linux example] System programming interface System programming interfaces are standard interfaces that an OS provides application programs to use its services. For example, if a program wishes to read a file on disk, then it must call a function like open() and let the OS handle the details of talking to the hard disk for retrieving the file. The need for an Operating System In a way, OS is an overhead, but a necessary one, for a user to tell a computer what to do. When resources in a computer system (CPU, GPU, memory, hard drive...) became big and more complicated, it's tedious to manually manage all the resources. Imagine we have to manually load programs on a computer with 3 GB of RAM. We would have to load programs at various fix addresses, and for each program a size must be manually calculated to avoid wasting memory resource, and enough for programs to not overriding each other. Or, when we want to give computer input through the keyboard, without an OS, an application also has to carry code to facilitate the communication with keyboard hardware; each application then handles such keyboard communication on its own. Why should there be such duplications across applications for such standard feature? If you write an accounting software, why should a programmer concern writing a keyboard driver, totally irrelevant to the problem domain? That's why a crucial job of an OS is to hide the complexity of hardware devices, so a program is freed from the burden of maintaining its own code for hardware communication by having a standardized set of interfaces and thus, reduce potential bugs along with faster development time. To write an OS effectively, a programmer need to understand well the underlying computer architecture that programmer are writing an OS for. The first reason is, many OS concepts are supported by the architecture e.g. the concepts of virtual memory are well supported by x86 architecture. If the underlying computer architecture is not well-understood, OS developers are doomed to reinvent it in your OS, and such software-implemented solutions run slower than the hardware version. Drivers Drivers are programs that enable an OS to communicate and use features of hardware devices. For example, a keyboard driver enables an OS to get input from keyboard; or a network driver allows a network card to send and receive data packets to and from the Internet. If you only write application programs, you may wonder how can software control hardware devices? As mentioned in Chapter 2, through the hardware-software interface: by writing to a device's registers or to write to ports of a device, through the use of CPU's instructions. Userspace and kernel space Kernel space refers to the working environment of an OS that only the kernel can access. Kernel space includes the direct communication with hardware, or manipulate privileged memory regions (such as kernel code and data). In contrast, userspace refers to less privileged processes that run above the OS, and is supervised by the OS. To access the kernel facility, user program must go through the standardized system programming interfaces provided by the OS. Memory Segment Segment Descriptor Types of Segment Descriptors Code and Data descriptors Task Descriptor Interrupt Descriptor Descriptor Scope Global Descriptor Local Descriptor Segment Selector Enhancement: Bootloader with descriptors Process Concepts Process Task A task is a unit of work that an OS needs to do, similar to how human have tasks to do daily. From a user point of view, a task for a computer to do can be web browsing, document editing, gaming, sending and receiving emails... Since a CPU can only execute sequentially, one instruction after another (fetching from main memory), there must be some way to do many meaningful tasks at once. For that reason, the computer must share the resources e.g. registers, stack, memory... between tasks, since we have many tasks but single and limited resources. Process Process is a data structure that keeps track of the execution state of a task. Task is a general concept, and process is the implementation of a task. In a general-purpose OS, a task is usually a program. For example, when you run Firefox, a process structure is created to keep track of where the stack and the heap allocated for firefox are, where Firefox's code area is and which instruction EIP is holding to execute next... The typical process structure looks like this: [insert process image] Process is a virtual computer, but much more primitive than the virtual machine in virtualization software like Virtual Box, and that's a good thing. Imagine having to run a full-fledged virtual machine for every task; how wasteful of machine resources that would be.. In the view of a running process, its code executes as if it runs directly on hardware. Each process has its own set of register values, which are kept tracked by the OS, and its own contiguous virtual memory space (which is discontiguous in actual physical memory). The code in a process is given virtual memory addresses to read and write from. [ illustrate: - a process looks like a mini Von Neumann - with contiguous memory, each with a color; each cell of a process mapped to distant memory cell in physical memory ] A process can run so much until the OS tells it to temporary stop for other tasks to use the hardware resources. The suspended process can then wait until further notice from the OS. This whole switching process is so fast that a computer user think his computer actually runs tasks in parallel. The program that does the switching between tasks is called a *scheduler*. Scheduler An OS needs to perform a wide range of different functionalities, e.g. web browsing, document editing, gaming... A scheduler decides which tasks got to run before the others and, for how long, in an efficient manner. Scheduler enables your computer to become a time sharing system, because tasks share CPU execution time and no one process can monopolize the CPU (in practice, it still happens regularly). Without a scheduler, only a single task can be performed at a time. Context switch When a process is prepared to be switched out for another process to take its place, certain hardware resources i.e. current open files, current register values... must be backed up to later resume that process's execution. Priority Priority is an important metric for OS to decide which task is scheduled to run before the others to allocate appropriate CPU execution time for each task. Preemptive vs Non-preemptive A preemptive OS can interrupt an executing process and switch to another process. A non-preemtive OS, a task runs until its completion. Process states State is a particular condition of a process, triggered by an action from the scheduler. A process goes through various states during its life cycle. A process typically has these states: Run indicating CPU is executing code in this process. Sleep (or Suspended): indicating CPU is executing some process else. Destroyed: process is done and waiting to be destroyed completely. procfs Threads Threads are units of work inside a process that shares the execution environment. A process creates a whole new execution environment with code of its own: [illustration between process and thread, with each process is a big rectangle box and threads nested boxes point to different code region] Instead of creating a completely new process structure in memory, OS simply let the thread uses some of the resources of the parent process that created it. A thread has its own registers, program counter, stack pointer, and its own call stack. Everything else is shared between the threads, such as an address space, heap, static data, and code segments, and file descriptors. Because thread simply reuses existing resources and involve no context switching, it is much faster to create and switch between processes. However, note that the above scheme is just an implementation of thread concept. You can completely treat thread the same as process (hence you can call all processes threads and vice versa). Or you can just back up some resources, whlie leaving some resources shared. It's up to the OS designer to distinguish between threads and processes. Threads are usually implemented as a component of a process. On Linux, a thread is simply a process that shares resources with its parent process; for that reason, a Linux thread is also called *light-weight process*. Or put it another way, a thread in Linux is merely an implementation of a single-threaded process that execute its main program code. A multi-threaded program in Linux is just a process with shared with its single-threaded children processes, each points to different code region of its parent process. [TODO: turn the above table into a diagram] On Windows, threads and processes are two separated entities, so the above description for Linux does not apply. However, the general idea: a thread shares the execution environment, holds. Task: x86 concept of a process Task Data Structure Task State Segment Task Descriptor Process Implementation Requirements Major Plan Stage 1: Switch to a task from bootloader Stage 2: Switch to a task with one function from kernel Stage 3: Switch to a task with many functions from kernel To implement the concept of a process, a kernel needs to be able to save and restore its machine states for different tasks. Description [Describe task switching mechanism involving LDT and GDT] qasdfasdf asd Constraints Design Implementation plan Milestone: Code Refactor Interrupt Memory management Address Space Address space is the set of all addressable memory locations. There are 2 types of address spaces in physical memory address: • One for memory: • One for I/O: Each process has its own address space to do whatever it wants, as long as the physical memory is not exhausted. This address space is called virtual memory. Virtual Memory Physical memory is a contagious memory locations that has a simple mapping between a physical memory address and its corresponding location in memory, decoded by memory controller. On the other hand, *virtual memory* does not have direct mapping between a memory address and the corresponding physical memory location, even though it appears contagious from the view of an userspace program. Instead, virtual memory address is translated by OS into an actual physical memory address. For that reason, even addresses appear next to each other in virtual memory space, they are scattered through out the physical memory. Why virtual memory is needed? Because virtual memory reduces the complexity of programming, by giving each program an illusion that it has its own separate "physical" memory to work with. Without virtual memory, programs must know and agree with each other their own memory regions to not accidentally destroy each other. [illustration a world without virtual memory] Virtual memory also enables a more secured OS, as application programs cannot manipulate main memory directly, so malicious programs won't cause havocs by destroying main memory and possibly hardware devices, by gaining access to hardware I/O ports. Another benefit is that virtual memory can extend beyond physical memory, by storing its data to hard disk. By swapping some of unused memory (i.e. inactive memory of a sleeping process), the system gains some free memory to continue running, so no data is destroyed. Otherwise, the OS is forced to kill a random user process to free up some memory, and you may lose unsaved work that belongs to the killed process. However, this process can significantly slow down the whole system because of Von Neumann bottleneck. In the old days, when memory was scarce, it was useful. File System File system is a mechanism on how raw bytes in a storage device can be meaningfully managed. That is, a group of bytes at specific locations in a storage device can be allocated for a purpose e.g. storing raw ASCII document, and later the exact chunks of bytes can be retrieved correctly. File system manages many such groups of bytes. It's helpful to think a file system as a database that maps between high level information and specific locations in a hard disk, similar to how business information is mapped to a specific row in a table. The high level information that is relevant to a file system is organized as *files* and *directories*. [illustration between a file system and a database table to see how they are similar] File is an entity that includes two components: metadata and the actual raw data. Metadata is the information describes the properties of the raw data associated with the file; raw data are real content of a file. Directory is a file that holds a group of files and also child directories. Together, they create a file hierarchy system as commonly seen in Windows or Linux. Example: Ex2 filesystem [LaTeX Command: printindex] Bibliography References [Hardy 2005] G. H. Hardy, "A Mathematician's Apology", University of Alberta Mathematical Sciences Society (2005), 13. [Intel 2016] Intel, Intel® 64 and IA-32 Architectures Optimization Reference Manual (Intel, 2016). [Kovitz 1999] Benjamin L. Kovitz, "Practical Software Requirements", Manning (1999), 53. [Peirce 1933] Charles Sanders Peirce, "Collected Papers v. 4" (1933). [Wakerly 1999] John F. Wakerly, "Digital Design: Principles and Practices", Prentice Hall (1999), 86. ================================================ FILE: book_src/images/.rid ================================================ 58f78e5b0bedbe9328c87d501e6feda8 ================================================ FILE: book_src/images/02/layer_translation.graphml ================================================ Assembly Language Logic Gates Circuit Mathematics Problem Domain Programming Language ================================================ FILE: book_src/images/03/.rid ================================================ f5ac4f7ffcf0c9cdf703fb078663fd4e ================================================ FILE: book_src/images/04/.rid ================================================ 49527604b893e9c9a27465cd47b4ab70 ================================================ FILE: book_src/images/04/modrm32.tex ================================================ \begin{tabular}{|>{\raggedright}p{4cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|>{\raggedright}p{1cm}|} \hline \multicolumn{3}{|l|}{\textsf{\footnotesize{}r8(/r)}} & \textsf{\footnotesize{}AL} & \textsf{\footnotesize{}CL} & \textsf{\footnotesize{}DL} & \textsf{\footnotesize{}BL} & \textsf{\footnotesize{}AH} & \textsf{\footnotesize{}CH} & \textsf{\footnotesize{}DH} & \textsf{\footnotesize{}BH }\tabularnewline \multicolumn{3}{|l|}{\textsf{\footnotesize{}r16(/r)}} & \textsf{\footnotesize{}AX} & \textsf{\footnotesize{}CX } & \textsf{\footnotesize{}DX } & \textsf{\footnotesize{}BX} & \textsf{\footnotesize{}SP } & \textsf{\footnotesize{}BP} & \textsf{\footnotesize{}SI} & \textsf{\footnotesize{}DI }\tabularnewline \multicolumn{3}{|l|}{\textsf{\footnotesize{}r32(/r)}} & \textsf{\footnotesize{}EAX} & \textsf{\footnotesize{}ECX} & \textsf{\footnotesize{}EDX } & \textsf{\footnotesize{}EBX } & \textsf{\footnotesize{}ESP} & \textsf{\footnotesize{}EBP} & \textsf{\footnotesize{}ESI} & \textsf{\footnotesize{}EDI}\tabularnewline \multicolumn{3}{|l|}{\textsf{\footnotesize{}mm(/r)}} & \textsf{\footnotesize{}MM0} & \textsf{\footnotesize{}MM1} & \textsf{\footnotesize{}MM2} & \textsf{\footnotesize{}MM3} & \textsf{\footnotesize{}MM4} & \textsf{\footnotesize{}MM5} & \textsf{\footnotesize{}MM6} & \textsf{\footnotesize{}MM7}\tabularnewline \multicolumn{3}{|l|}{\textsf{\footnotesize{}xmm(/r) }} & \textsf{\footnotesize{}XMM0} & \textsf{\footnotesize{}XMM1} & \textsf{\footnotesize{}XMM2} & \textsf{\footnotesize{}XMM3} & \textsf{\footnotesize{}XMM4} & \textsf{\footnotesize{}XMM5} & \textsf{\footnotesize{}XMM6} & \textsf{\footnotesize{}XMM7}\tabularnewline \multicolumn{3}{|l|}{\textsf{\footnotesize{}(In decimal) /digit (Opcode)}} & \textsf{\footnotesize{}0} & \textsf{\footnotesize{}1 } & \textsf{\footnotesize{}2} & \textsf{\footnotesize{}3} & \textsf{\footnotesize{}4} & \textsf{\footnotesize{}5} & \textsf{\footnotesize{}6} & \textsf{\footnotesize{}7 }\tabularnewline \multicolumn{3}{|l|}{\textsf{\footnotesize{}(In binary) REG =}} & \textsf{\footnotesize{}000} & \textsf{\footnotesize{}001} & \textsf{\footnotesize{}010} & \textsf{\footnotesize{}011} & \textsf{\footnotesize{}100} & \textsf{\footnotesize{}101} & \textsf{\footnotesize{}110} & \textsf{\footnotesize{}111}\tabularnewline \hline \textsf{\textbf{\footnotesize{}~~~~~~~Effective Address}} & \textsf{\textbf{\footnotesize{}~~Mod}} & \textsf{\textbf{\footnotesize{}~~R/M}} & \multicolumn{8}{c|}{\textsf{\textbf{\footnotesize{}Values of ModR/M Byte (In Hexadecimal)}}}\tabularnewline \hline \texttt{\footnotesize{}{[}EAX{]}} & \texttt{\footnotesize{}00} & \texttt{\footnotesize{}000} & \texttt{\footnotesize{}00} & \texttt{\footnotesize{}08} & \texttt{\footnotesize{}10} & \texttt{\footnotesize{}18} & \texttt{\footnotesize{}20} & \texttt{\footnotesize{}28} & \texttt{\footnotesize{}30} & \texttt{\footnotesize{}38}\tabularnewline \texttt{\footnotesize{}{[}ECX{]}} & & \texttt{\footnotesize{}001} & \texttt{\footnotesize{}01} & \texttt{\footnotesize{}09} & \texttt{\footnotesize{}11} & \texttt{\footnotesize{}19} & \texttt{\footnotesize{}21} & \texttt{\footnotesize{}29} & \texttt{\footnotesize{}31} & \texttt{\footnotesize{}39}\tabularnewline \texttt{\footnotesize{}{[}EDX{]}} & & \texttt{\footnotesize{}010} & \texttt{\footnotesize{}02} & \texttt{\footnotesize{}0A} & \texttt{\footnotesize{}12} & \texttt{\footnotesize{}1A} & \texttt{\footnotesize{}22} & \texttt{\footnotesize{}2A} & \texttt{\footnotesize{}32} & \texttt{\footnotesize{}3A}\tabularnewline \texttt{\footnotesize{}{[}EBX{]}} & & \texttt{\footnotesize{}011} & \texttt{\footnotesize{}03} & \texttt{\footnotesize{}0B} & \texttt{\footnotesize{}13} & \texttt{\footnotesize{}1B} & \texttt{\footnotesize{}23} & \texttt{\footnotesize{}2B} & \texttt{\footnotesize{}33} & \texttt{\footnotesize{}3B}\tabularnewline \texttt{\footnotesize{}{[}-\--{]}{[}-\--{]}\textsuperscript{1}} & & \texttt{\footnotesize{}100} & \texttt{\footnotesize{}04} & \texttt{\footnotesize{}0C} & \texttt{\footnotesize{}14} & \texttt{\footnotesize{}1C} & \texttt{\footnotesize{}24} & \texttt{\footnotesize{}2C} & \texttt{\footnotesize{}34} & \texttt{\footnotesize{}3C}\tabularnewline \texttt{\footnotesize{}disp32\textsuperscript{2}} & & \texttt{\footnotesize{}101} & \texttt{\footnotesize{}05} & \texttt{\footnotesize{}0D} & \texttt{\footnotesize{}15} & \texttt{\footnotesize{}1D} & \texttt{\footnotesize{}25} & \texttt{\footnotesize{}2D} & \texttt{\footnotesize{}35} & \texttt{\footnotesize{}3D}\tabularnewline \texttt{\footnotesize{}{[}ESI{]}} & & \texttt{\footnotesize{}110} & \texttt{\footnotesize{}06} & \texttt{\footnotesize{}0E} & \texttt{\footnotesize{}16} & \texttt{\footnotesize{}1E} & \texttt{\footnotesize{}26} & \texttt{\footnotesize{}2E} & \texttt{\footnotesize{}36} & \texttt{\footnotesize{}3E}\tabularnewline \texttt{\footnotesize{}{[}EDI{]}} & & \texttt{\footnotesize{}111} & \texttt{\footnotesize{}07} & \texttt{\footnotesize{}0F} & \texttt{\footnotesize{}17} & \texttt{\footnotesize{}1F} & \texttt{\footnotesize{}27} & \texttt{\footnotesize{}2F} & \texttt{\footnotesize{}37} & \texttt{\footnotesize{}3F}\tabularnewline \hline \texttt{\footnotesize{}{[}EAX{]} + disp8\textsuperscript{\textsf{\footnotesize{}3}}} & \texttt{\footnotesize{}01} & \texttt{\footnotesize{}000} & \texttt{\footnotesize{}40} & \texttt{\footnotesize{}48} & \texttt{\footnotesize{}50} & \texttt{\footnotesize{}58} & \texttt{\footnotesize{}60} & \texttt{\footnotesize{}68} & \texttt{\footnotesize{}70} & \texttt{\footnotesize{}78}\tabularnewline \texttt{\footnotesize{}{[}ECX{]} + disp8} & & \texttt{\footnotesize{}001} & \texttt{\footnotesize{}41} & \texttt{\footnotesize{}49} & \texttt{\footnotesize{}51} & \texttt{\footnotesize{}59} & \texttt{\footnotesize{}61} & \texttt{\footnotesize{}69} & \texttt{\footnotesize{}71} & \texttt{\footnotesize{}79}\tabularnewline \texttt{\footnotesize{}{[}EDX{]} + disp8} & & \texttt{\footnotesize{}010} & \texttt{\footnotesize{}42} & \texttt{\footnotesize{}4A} & \texttt{\footnotesize{}52} & \texttt{\footnotesize{}5A} & \texttt{\footnotesize{}62} & \texttt{\footnotesize{}6A} & \texttt{\footnotesize{}72} & \texttt{\footnotesize{}7A}\tabularnewline \texttt{\footnotesize{}{[}EBX{]} + disp8} & & \texttt{\footnotesize{}011} & \texttt{\footnotesize{}43} & \texttt{\footnotesize{}4B} & \texttt{\footnotesize{}53} & \texttt{\footnotesize{}5B} & \texttt{\footnotesize{}63} & \texttt{\footnotesize{}6B} & \texttt{\footnotesize{}73} & \texttt{\footnotesize{}7B}\tabularnewline \texttt{\footnotesize{}{[}-\--{]}{[}-\--{]} + disp8} & & \texttt{\footnotesize{}100} & \texttt{\footnotesize{}44} & \texttt{\footnotesize{}4C} & \texttt{\footnotesize{}54} & \texttt{\footnotesize{}5C} & \texttt{\footnotesize{}64} & \texttt{\footnotesize{}6C} & \texttt{\footnotesize{}74} & \texttt{\footnotesize{}7C}\tabularnewline \texttt{\footnotesize{}{[}EBP{]} + disp8} & & \texttt{\footnotesize{}101} & \texttt{\footnotesize{}45} & \texttt{\footnotesize{}4D} & \texttt{\footnotesize{}55} & \texttt{\footnotesize{}5D} & \texttt{\footnotesize{}65} & \texttt{\footnotesize{}6D} & \texttt{\footnotesize{}75} & \texttt{\footnotesize{}7D}\tabularnewline \texttt{\footnotesize{}{[}ESI{]} + disp8} & & \texttt{\footnotesize{}110} & \texttt{\footnotesize{}46} & \texttt{\footnotesize{}4E} & \texttt{\footnotesize{}56} & \texttt{\footnotesize{}5E} & \texttt{\footnotesize{}66} & \texttt{\footnotesize{}6E} & \texttt{\footnotesize{}76} & \texttt{\footnotesize{}7E}\tabularnewline \texttt{\footnotesize{}{[}EDI{]} + disp8} & & \texttt{\footnotesize{}111} & \texttt{\footnotesize{}47} & \texttt{\footnotesize{}4F} & \texttt{\footnotesize{}57} & \texttt{\footnotesize{}5F} & \texttt{\footnotesize{}67} & \texttt{\footnotesize{}6F} & \texttt{\footnotesize{}77} & \texttt{\footnotesize{}7F}\tabularnewline \hline \texttt{\footnotesize{}{[}EAX{]} + disp32} & \texttt{\footnotesize{}10} & \texttt{\footnotesize{}000} & \texttt{\footnotesize{}80} & \texttt{\footnotesize{}88} & \texttt{\footnotesize{}90} & \texttt{\footnotesize{}98} & \texttt{\footnotesize{}A0} & \texttt{\footnotesize{}A8} & \texttt{\footnotesize{}B0} & \texttt{\footnotesize{}B8}\tabularnewline \texttt{\footnotesize{}{[}ECX{]} + disp32} & & \texttt{\footnotesize{}001} & \texttt{\footnotesize{}81} & \texttt{\footnotesize{}89} & \texttt{\footnotesize{}91} & \texttt{\footnotesize{}99} & \texttt{\footnotesize{}A1} & \texttt{\footnotesize{}A9} & \texttt{\footnotesize{}B1} & \texttt{\footnotesize{}B9}\tabularnewline \texttt{\footnotesize{}{[}EDX{]} + disp32} & & \texttt{\footnotesize{}010} & \texttt{\footnotesize{}82} & \texttt{\footnotesize{}8A} & \texttt{\footnotesize{}92} & \texttt{\footnotesize{}9A} & \texttt{\footnotesize{}A2} & \texttt{\footnotesize{}AA} & \texttt{\footnotesize{}B2} & \texttt{\footnotesize{}BA}\tabularnewline \texttt{\footnotesize{}{[}EBX{]} + disp32} & & \texttt{\footnotesize{}011} & \texttt{\footnotesize{}83} & \texttt{\footnotesize{}8B} & \texttt{\footnotesize{}93} & \texttt{\footnotesize{}9B} & \texttt{\footnotesize{}A3} & \texttt{\footnotesize{}AB} & \texttt{\footnotesize{}B3} & \texttt{\footnotesize{}BB}\tabularnewline \texttt{\footnotesize{}{[}-\--{]}{[}-\--{]} + disp32} & & \texttt{\footnotesize{}100} & \texttt{\footnotesize{}84} & \texttt{\footnotesize{}8C} & \texttt{\footnotesize{}94} & \texttt{\footnotesize{}9C} & \texttt{\footnotesize{}A4} & \texttt{\footnotesize{}AC} & \texttt{\footnotesize{}B4} & \texttt{\footnotesize{}BC}\tabularnewline \texttt{\footnotesize{}{[}EBP{]} + disp32} & & \texttt{\footnotesize{}101} & \texttt{\footnotesize{}85} & \texttt{\footnotesize{}8D} & \texttt{\footnotesize{}95} & \texttt{\footnotesize{}9D} & \texttt{\footnotesize{}A5} & \texttt{\footnotesize{}AD} & \texttt{\footnotesize{}B5} & \texttt{\footnotesize{}BD}\tabularnewline \texttt{\footnotesize{}{[}ESI{]} + disp32} & & \texttt{\footnotesize{}110} & \texttt{\footnotesize{}86} & \texttt{\footnotesize{}8E} & \texttt{\footnotesize{}96} & \texttt{\footnotesize{}9E} & \texttt{\footnotesize{}A6} & \texttt{\footnotesize{}AE} & \texttt{\footnotesize{}B6} & \texttt{\footnotesize{}BE}\tabularnewline \texttt{\footnotesize{}{[}EDI{]} + disp32} & & \texttt{\footnotesize{}111} & \texttt{\footnotesize{}87} & \texttt{\footnotesize{}8F} & \texttt{\footnotesize{}97} & \texttt{\footnotesize{}9F} & \texttt{\footnotesize{}A7} & \texttt{\footnotesize{}AF} & \texttt{\footnotesize{}B7} & \texttt{\footnotesize{}BF}\tabularnewline \hline \texttt{\footnotesize{}EAX/AX/AL/MM0/XMM0} & \texttt{\footnotesize{}11} & \texttt{\footnotesize{}000} & \texttt{\footnotesize{}C0} & \texttt{\footnotesize{}C8} & \texttt{\footnotesize{}D0} & \texttt{\footnotesize{}D8} & \texttt{\footnotesize{}E0} & \texttt{\footnotesize{}E8} & \texttt{\footnotesize{}F0} & \texttt{\footnotesize{}F8}\tabularnewline \texttt{\footnotesize{}ECX/CX/CL/MM/XMM1} & & \texttt{\footnotesize{}001} & \texttt{\footnotesize{}C1} & \texttt{\footnotesize{}C9} & \texttt{\footnotesize{}D1} & \texttt{\footnotesize{}D9} & \texttt{\footnotesize{}E1} & \texttt{\footnotesize{}E9} & \texttt{\footnotesize{}F1} & \texttt{\footnotesize{}F9}\tabularnewline \texttt{\footnotesize{}EDX/DX/DL/MM2/XMM2} & & \texttt{\footnotesize{}010} & \texttt{\footnotesize{}C2} & \texttt{\footnotesize{}CA} & \texttt{\footnotesize{}D2} & \texttt{\footnotesize{}DA} & \texttt{\footnotesize{}E2} & \texttt{\footnotesize{}EA} & \texttt{\footnotesize{}F2} & \texttt{\footnotesize{}FA}\tabularnewline \texttt{\footnotesize{}EBX/BX/BL/MM3/XMM3} & & \texttt{\footnotesize{}011} & \texttt{\footnotesize{}C3} & \texttt{\footnotesize{}CB} & \texttt{\footnotesize{}D3} & \texttt{\footnotesize{}DB} & \texttt{\footnotesize{}E3} & \texttt{\footnotesize{}EB} & \texttt{\footnotesize{}F3} & \texttt{\footnotesize{}FB}\tabularnewline \texttt{\footnotesize{}ESP/SP/AH/MM4/XMM4} & & \texttt{\footnotesize{}100} & \texttt{\footnotesize{}C4} & \texttt{\footnotesize{}CC} & \texttt{\footnotesize{}D4} & \texttt{\footnotesize{}DC} & \texttt{\footnotesize{}E4} & \texttt{\footnotesize{}EC} & \texttt{\footnotesize{}F4} & \texttt{\footnotesize{}FC}\tabularnewline \texttt{\footnotesize{}EBP/BP/CH/MM5/XMM5} & & \texttt{\footnotesize{}101} & \texttt{\footnotesize{}C5} & \texttt{\footnotesize{}CD} & \texttt{\footnotesize{}D5} & \texttt{\footnotesize{}DD} & \texttt{\footnotesize{}E5} & \texttt{\footnotesize{}ED} & \texttt{\footnotesize{}F5} & \texttt{\footnotesize{}FD}\tabularnewline \texttt{\footnotesize{}ESI/SI/DH/MM6/XMM6} & & \texttt{\footnotesize{}110} & \texttt{\footnotesize{}C6} & \texttt{\footnotesize{}CE} & \texttt{\footnotesize{}D6} & \texttt{\footnotesize{}DE} & \texttt{\footnotesize{}E6} & \texttt{\footnotesize{}EE} & \texttt{\footnotesize{}F6} & \texttt{\footnotesize{}FE}\tabularnewline \texttt{\footnotesize{}EDI/DI/BH/MM7/XMM7} & & \texttt{\footnotesize{}111} & \texttt{\footnotesize{}C7} & \texttt{\footnotesize{}CF} & \texttt{\footnotesize{}D7} & \texttt{\footnotesize{}DF} & \texttt{\footnotesize{}E7} & \texttt{\footnotesize{}EF} & \texttt{\footnotesize{}F7} & \texttt{\footnotesize{}FF}\tabularnewline \hline \multicolumn{11}{>{\raggedright}p{14.5cm}}{\begin{enumerate} \item \textsf{\footnotesize{}The {[}-\--{]}{[}-\--{]} nomenclature means a SIB follows the ModR/M byte.}{\footnotesize \par} \item \textsf{\footnotesize{}The disp32 nomenclature denotes a 32-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is added to the index.}{\footnotesize \par} \item \textsf{\footnotesize{}The disp8 nomenclature denotes an 8-bit displacement that follows the ModR/M byte (or the SIB byte if one is present) and that is sign-extended and added to the index.}\end{enumerate} }\tabularnewline \end{tabular} ================================================ FILE: book_src/images/05/.rid ================================================ a9ba32dde86cd02374a576cbb347870e ================================================ FILE: book_src/images/06/.rid ================================================ 978a2a6b43366794c5decbda95bf1e08 ================================================ FILE: book_src/images/07/.rid ================================================ 58310471881fcc80a0b152521c5de8ae ================================================ FILE: book_src/images/08/.rid ================================================ 1ba7fe42ddc5a44d1184e22d6c2fa796 ================================================ FILE: book_src/references.bib ================================================ % This file was created with JabRef 2.10. % Encoding: UTF8 @InBook{Hardy, Title = {A Mathematician's Apology}, Author = {G. H. Hardy}, Chapter = {10}, Pages = {13}, Publisher = {University of Alberta Mathematical Sciences Society}, Year = {2005}, Owner = {Tu Do}, Timestamp = {2016.10.05} } @Book{intel_opt_manual, Title = {Intel® 64 and IA-32 Architectures Optimization Reference Manual}, Author = {Intel}, Pages = {672}, Publisher = {Intel}, Year = {2016}, Owner = {Tu Do}, Timestamp = {2016.12.12} } @Book{Intel_volume1, Title = {Intel 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture}, Author = {Intel}, Pages = {482}, Publisher = {Intel}, Year = {2016}, Owner = {Tu Do}, Timestamp = {2016.12.15} } @InBook{Kovitz_psr, Title = {Practical Software Requirements}, Author = {Benjamin L. Kovitz}, Chapter = {3}, Pages = {53}, Publisher = {Manning}, Year = {1999}, __markedentry = {[Tu Do:]}, Owner = {Tu Do}, Timestamp = {2016.09.20} } @InBook{Peirce, Title = {Collected Papers v. 4}, Author = {Charles Sanders Peirce}, Chapter = {A Boolean Algebra with One Constant}, Year = {1933}, Owner = {Tu Do}, Timestamp = {2016.09.28} } @Manual{74hc00_data_sheet, Title = {74HC00; 74HCT00 Quad 2-input NAND gate}, Author = {NXP Semiconductors}, Edition = {7}, Month = {November}, Organization = {NXP Semiconductors}, Year = {2015}, Owner = {Tu Do}, Timestamp = {2017.01.16} } @InBook{John_digital, Title = {Digital Design: Principles and Practices}, Author = {John F. Wakerly}, Chapter = {3}, Pages = {86}, Publisher = {Prentice Hall}, Year = {1999}, Owner = {Tu Do}, Timestamp = {2016.09.27} } ================================================ FILE: code/chapter7/os/.gdbinit ================================================ define hook-stop # Translate the segment:offset into a physical address printf "[%4x:%4x] ", $cs, $eip end set architecture i8086 layout asm layout reg set disassembly-flavor intel target remote localhost:26000 symbol-file build/os/os b *0x7c00 b main ================================================ FILE: code/chapter7/os/Makefile ================================================ BUILD_DIR=build BOOTLOADER=$(BUILD_DIR)/bootloader/bootloader.o OS=$(BUILD_DIR)/os/sample.o DISK_IMG=disk.img all: bootdisk .PHONY: bootdisk bootloader os bootloader: make -C bootloader os: make -C os bootdisk: bootloader os dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=1 seek=1 qemu: qemu-system-i386 -machine q35 -fda $(DISK_IMG) -gdb tcp::26000 -S clean: make -C bootloader clean make -C os clean ================================================ FILE: code/chapter7/os/bootloader/Makefile ================================================ BUILD_DIR=../build/bootloader BOOTLOADER_SRCS := $(wildcard *.asm) BOOTLOADER_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(BOOTLOADER_SRCS)) all: $(BOOTLOADER_OBJS) $(BUILD_DIR)/%.o: %.asm nasm -f bin $< -o $@ clean: rm $(BUILD_DIR)/* ================================================ FILE: code/chapter7/os/bootloader/bootloader.asm ================================================ ;****************************************** ; Bootloader.asm ; A Simple Bootloader ;****************************************** bits 16 start: jmp boot ;; constant and variable definitions msg db "Welcome to My Operating System!", 0ah, 0dh, 0h boot: cli ; no interrupts cld ; all that we need to init mov ax, 50h ; ;; set the buffer mov es, ax xor bx, bx mov al, 2 ; read 2 sector mov ch, 0 ; we are reading the second sector past us, so its still on track 0 mov cl, 2 ; sector to read (The second sector) mov dh, 0 ; head number mov dl, 0 ; drive number. Remember Drive 0 is floppy drive. mov ah, 0x02 ; read floppy sector function int 0x13 ; call BIOS - Read the sector jmp 0x50:0x0 ; jump and execute the sector! hlt ; halt the system ; We have to be 512 bytes. Clear the rest of the bytes with 0 times 510 - ($-$$) db 0 dw 0xAA55 ; Boot Signiture ================================================ FILE: code/chapter7/os/os/Makefile ================================================ BUILD_DIR=../build/os OS_SRCS := $(wildcard *.asm) OS_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(OS_SRCS)) all: $(OS_OBJS) $(BUILD_DIR)/%.o: %.asm nasm -f bin $< -o $@ clean: rm $(BUILD_DIR)/* ================================================ FILE: code/chapter7/os/os/sample.asm ================================================ ;****************************************** ; sample.asm ; A Sample Program ;****************************************** mov eax, 1 add eax, 1 ================================================ FILE: code/chapter8/os/.gdbinit ================================================ define hook-stop # Translate the segment:offset into a physical address printf "[%4x:%4x] ", $cs, $eip end set architecture i8086 layout asm layout reg set disassembly-flavor intel target remote localhost:26000 symbol-file build/os/os b *0x7c00 b main ================================================ FILE: code/chapter8/os/Makefile ================================================ BUILD_DIR=build BOOTLOADER=$(BUILD_DIR)/bootloader/bootloader.o OS=$(BUILD_DIR)/os/os DISK_IMG=disk.img all: bootdisk .PHONY: bootloader os bootloader: make -C bootloader os: make -C os bootdisk: bootloader os # @echo "size is $(size)" # @echo "count is $(count)" dd if=/dev/zero of=$(DISK_IMG) bs=512 count=2880 dd conv=notrunc if=$(BOOTLOADER) of=$(DISK_IMG) bs=512 count=1 seek=0 # dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=1 seek=1 dd conv=notrunc if=$(OS) of=$(DISK_IMG) bs=512 count=$$(($(shell stat --printf="%s" $(OS))/512)) seek=1 qemu: qemu-system-i386 -machine q35 -fda $(DISK_IMG) -gdb tcp::26000 -S clean: make -C bootloader clean make -C os clean ================================================ FILE: code/chapter8/os/bootloader/Makefile ================================================ BUILD_DIR=../build/bootloader BOOTLOADER_SRCS := $(wildcard *.asm) BOOTLOADER_OBJS := $(patsubst %.asm, $(BUILD_DIR)/%.o, $(BOOTLOADER_SRCS)) all: $(BOOTLOADER_OBJS) $(BUILD_DIR)/%.o: %.asm nasm -f elf $< -F dwarf -g -o $@ ld -m elf_i386 -T bootloader.lds $@ -o $@.elf objcopy -O binary $(BUILD_DIR)/bootloader.o.elf $@ clean: rm $(BUILD_DIR)/* ================================================ FILE: code/chapter8/os/bootloader/bootloader.asm ================================================ ;****************************************** ; Bootloader.asm ; A Simple Bootloader ;****************************************** bits 16 start: jmp boot ;; constant and variable definitions msg db "Welcome to My Operating System!", 0ah, 0dh, 0h boot: cli ; no interrupts cld ; all that we need to init mov ax, 50h ; ;; set the buffer mov es, ax xor bx, bx mov al, 17 ; read 2 sector mov ch, 0 ; we are reading the second sector past us, so its still on track 0 mov cl, 2 ; sector to read (The second sector) mov dh, 0 ; head number mov dl, 0 ; drive number. Remember Drive 0 is floppy drive. mov ah, 0x02 ; read floppy sector function int 0x13 ; call BIOS - Read the sector jmp [500h + 0x18] ; jump and execute the sector! hlt ; halt the system ; We have to be 512 bytes. Clear the rest of the bytes with 0 times 510 - ($-$$) db 0 dw 0xAA55 ; Boot Signiture ================================================ FILE: code/chapter8/os/bootloader/bootloader.lds ================================================ OUTPUT(bootloader); PHDRS { headers PT_NULL; text PT_LOAD FILEHDR PHDRS ; data PT_LOAD ; } SECTIONS { . = SIZEOF_HEADERS; .text 0x7c00: { *(.text) } :text .data : { *(.data) } :data } ================================================ FILE: code/chapter8/os/os/Makefile ================================================ BUILD_DIR=../build/os OS=$(BUILD_DIR)/os CFLAGS+=-ffreestanding -nostdlib -m32 -gdwarf-4 -ggdb3 OS_SRCS := $(wildcard *.c) OS_OBJS := $(patsubst %.c, $(BUILD_DIR)/%.o, $(OS_SRCS)) all: $(OS) $(BUILD_DIR)/%.o: %.c gcc $(CFLAGS) -m32 -c $< -o $@ $(OS): $(OS_OBJS) ld -m elf_i386 -nmagic -Tos.lds $(OS_OBJS) -o $@ # objcopy --only-keep-debug $(OS) $(OS).dbg # strip -g $(OS) clean: rm $(BUILD_DIR)/* ================================================ FILE: code/chapter8/os/os/main.c ================================================ void main(){} ================================================ FILE: code/chapter8/os/os/os.lds ================================================ ENTRY(main); PHDRS { headers PT_PHDR FILEHDR PHDRS; code PT_LOAD; } SECTIONS { .text 0x600: ALIGN(0x100) { *(.text) } :code .data : { *(.data) } .bss : { *(.bss) } /DISCARD/ : { *(.eh_frame) } } ================================================ FILE: code/chapter8/os/os/sample.asm ================================================ ;****************************************** ; sample.asm ; A Sample Program ;****************************************** mov eax, 1 add eax, 1