100% found this document useful (1 vote)
18 views

Foundations of ARM64 Linux Debugging, Disassembling, and Reversing: Analyze Code, Understand Stack Memory Usage, and Reconstruct Original C/C++ Code with ARM64 1st Edition Dmitry Vostokov instant download

The document provides information about various ebooks and textbooks available for download, focusing on topics such as ARM64 Linux debugging, disassembling, and reversing. It includes links to specific titles authored by Dmitry Vostokov, along with details about the content and structure of the books. Additionally, it mentions the copyright and publication details for the works listed.

Uploaded by

shirezahrau
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
18 views

Foundations of ARM64 Linux Debugging, Disassembling, and Reversing: Analyze Code, Understand Stack Memory Usage, and Reconstruct Original C/C++ Code with ARM64 1st Edition Dmitry Vostokov instant download

The document provides information about various ebooks and textbooks available for download, focusing on topics such as ARM64 Linux debugging, disassembling, and reversing. It includes links to specific titles authored by Dmitry Vostokov, along with details about the content and structure of the books. Additionally, it mentions the copyright and publication details for the works listed.

Uploaded by

shirezahrau
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 74

Download the full version and explore a variety of ebooks

or textbooks at https://ebookmass.com

Foundations of ARM64 Linux Debugging,


Disassembling, and Reversing: Analyze Code,
Understand Stack Memory Usage, and Reconstruct
Original C/C++ Code with ARM64 1st Edition Dmitry
Vostokov
_____ Tap the link below to start your download _____

https://ebookmass.com/product/foundations-of-arm64-linux-
debugging-disassembling-and-reversing-analyze-code-
understand-stack-memory-usage-and-reconstruct-original-c-c-
code-with-arm64-1st-edition-dmitry-vostokov/

Find ebooks or textbooks at ebookmass.com today!


We believe these products will be a great fit for you. Click
the link to download now, or visit ebookmass.com
to discover even more!

Foundations of Linux Debugging, Disassembling, and


Reversing: Analyze Binary Code, Understand Stack Memory
Usage, and Reconstruct C/C++ Code with Intel x64 1st
Edition Dmitry Vostokov
https://ebookmass.com/product/foundations-of-linux-debugging-
disassembling-and-reversing-analyze-binary-code-understand-stack-
memory-usage-and-reconstruct-c-c-code-with-intel-x64-1st-edition-
dmitry-vostokov/

Foundations of ARM64 Linux Debugging, Disassembling, and


Reversing Dmitry Vostokov

https://ebookmass.com/product/foundations-of-arm64-linux-debugging-
disassembling-and-reversing-dmitry-vostokov/

Fundamentals of Trace and Log Analysis: A Pattern-Oriented


Approach to Monitoring, Diagnostics, and Debugging 1st
Edition Dmitry Vostokov
https://ebookmass.com/product/fundamentals-of-trace-and-log-analysis-
a-pattern-oriented-approach-to-monitoring-diagnostics-and-
debugging-1st-edition-dmitry-vostokov-2/

Fundamentals of Trace and Log Analysis A Pattern-Oriented


Approach to Monitoring, Diagnostics, and Debugging 1st
Edition Dmitry Vostokov
https://ebookmass.com/product/fundamentals-of-trace-and-log-analysis-
a-pattern-oriented-approach-to-monitoring-diagnostics-and-
debugging-1st-edition-dmitry-vostokov/
Python Debugging for AI, Machine Learning, and Cloud
Computing: A Pattern-Oriented Approach 1st Edition Dmitry
Vostokov
https://ebookmass.com/product/python-debugging-for-ai-machine-
learning-and-cloud-computing-a-pattern-oriented-approach-1st-edition-
dmitry-vostokov/

Visual Studio Code Distilled: Evolved Code Editing for


Windows, macOS, and Linux - Third Edition Alessandro Del
Sole
https://ebookmass.com/product/visual-studio-code-distilled-evolved-
code-editing-for-windows-macos-and-linux-third-edition-alessandro-del-
sole/

Visual Studio Code Distilled: Evolved Code Editing for


Windows, macOS, and Linux 3 / converted Edition Alessandro
Del Sole
https://ebookmass.com/product/visual-studio-code-distilled-evolved-
code-editing-for-windows-macos-and-linux-3-converted-edition-
alessandro-del-sole/

International Swimming Pool and Spa Code 2021 1st Edition


International Code Council

https://ebookmass.com/product/international-swimming-pool-and-spa-
code-2021-1st-edition-international-code-council/

International Fire Code (International Code Council


Series) 2021 1st Edition International Code Council

https://ebookmass.com/product/international-fire-code-international-
code-council-series-2021-1st-edition-international-code-council/
Foundations of ARM64
Linux Debugging,
Disassembling, and
Reversing
Analyze Code, Understand Stack
Memory Usage, and Reconstruct
Original C/C++ Code with ARM64

Dmitry Vostokov
Foundations of
ARM64 Linux
Debugging,
Disassembling, and
Reversing
Analyze Code, Understand
Stack Memory Usage,
and Reconstruct Original C/C++
Code with ARM64

Dmitry Vostokov
Foundations of ARM64 Linux Debugging, Disassembling, and Reversing:
Analyze Code, Understand Stack Memory Usage, and Reconstruct Original
C/C++ Code with ARM64

Dmitry Vostokov
Dublin, Ireland

ISBN-13 (pbk): 978-1-4842-9081-1 ISBN-13 (electronic): 978-1-4842-9082-8


https://doi.org/10.1007/978-1-4842-9082-8
Copyright © 2023 by Dmitry Vostokov
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or
part of the material is concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way,
and transmission or information storage and retrieval, electronic adaptation, computer software,
or by similar or dissimilar methodology now known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark
symbol with every occurrence of a trademarked name, logo, or image we use the names, logos,
and images only in an editorial fashion and to the benefit of the trademark owner, with no
intention of infringement of the trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if
they are not identified as such, is not to be taken as an expression of opinion as to whether or not
they are subject to proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of
publication, neither the authors nor the editors nor the publisher can accept any legal
responsibility for any errors or omissions that may be made. The publisher makes no warranty,
express or implied, with respect to the material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Celestin Suresh John
Development Editor: James Markham
Coordinating Editor: Mark Powers
Cover designed by eStudioCalamar
Cover image by Susan Wilkinson on Unsplash (www.unsplash.com)
Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY
10004, U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected],
or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member
(owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance
Inc is a Delaware corporation.
For information on translations, please e-mail [email protected]; for
reprint, paperback, or audio rights, please e-mail [email protected].
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook
versions and licenses are also available for most titles. For more information, reference our Print
and eBook Bulk Sales web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is
available to readers on GitHub (https://github.com/Apress). For more detailed information,
please visit http://www.apress.com/source-code.
Printed on acid-free paper
Table of Contents
About the Author���������������������������������������������������������������������������������ix

About the Technical Reviewer�������������������������������������������������������������xi

Preface����������������������������������������������������������������������������������������������xiii

Chapter 1: Memory, Registers, and Simple Arithmetic�������������������������1


Memory and Registers Inside an Idealized Computer������������������������������������������1
Memory and Registers Inside ARM 64-Bit Computer��������������������������������������������2
“Arithmetic” Project: Memory Layout and Registers��������������������������������������������3
“Arithmetic” Project: A Computer Program�����������������������������������������������������������5
“Arithmetic” Project: Assigning Numbers to Memory Locations���������������������������5
Assigning Numbers to Registers���������������������������������������������������������������������������8
“Arithmetic” Project: Adding Numbers to Memory Cells���������������������������������������9
Incrementing/Decrementing Numbers in Memory and Registers�����������������������12
Multiplying Numbers�������������������������������������������������������������������������������������������15
Summary������������������������������������������������������������������������������������������������������������18

Chapter 2: Code Optimization�������������������������������������������������������������19


“Arithmetic” Project: C/C++ Program�����������������������������������������������������������������19
Downloading GDB�����������������������������������������������������������������������������������������������20
GDB Disassembly Output – No Optimization�������������������������������������������������������21
GDB Disassembly Output – Optimization������������������������������������������������������������27
Summary������������������������������������������������������������������������������������������������������������28

iii
Table of Contents

Chapter 3: Number Representations��������������������������������������������������29


Numbers and Their Representations�������������������������������������������������������������������29
Decimal Representation (Base Ten)��������������������������������������������������������������������30
Ternary Representation (Base Three)������������������������������������������������������������������30
Binary Representation (Base Two)����������������������������������������������������������������������31
Hexadecimal Representation (Base Sixteen)������������������������������������������������������32
Why Are Hexadecimals Used?�����������������������������������������������������������������������������32
Summary������������������������������������������������������������������������������������������������������������34

Chapter 4: Pointers�����������������������������������������������������������������������������35
A Definition���������������������������������������������������������������������������������������������������������35
“Pointers” Project: Memory Layout and Registers����������������������������������������������36
“Pointers” Project: Calculations��������������������������������������������������������������������������38
Using Pointers to Assign Numbers to Memory Cells�������������������������������������������39
Adding Numbers Using Pointers�������������������������������������������������������������������������46
Incrementing Numbers Using Pointers���������������������������������������������������������������51
Multiplying Numbers Using Pointers�������������������������������������������������������������������54
Summary������������������������������������������������������������������������������������������������������������58

Chapter 5: Bytes, Halfwords, Words, and Doublewords����������������������59


Using Hexadecimal Numbers������������������������������������������������������������������������������59
Byte Granularity��������������������������������������������������������������������������������������������������60
Bit Granularity�����������������������������������������������������������������������������������������������������60
Memory Layout���������������������������������������������������������������������������������������������������61
Summary������������������������������������������������������������������������������������������������������������64

iv
Table of Contents

Chapter 6: Pointers to Memory�����������������������������������������������������������65


Pointers Revisited�����������������������������������������������������������������������������������������������65
Addressing Types������������������������������������������������������������������������������������������������65
Registers Revisited���������������������������������������������������������������������������������������������70
NULL Pointers�����������������������������������������������������������������������������������������������������70
Invalid Pointers���������������������������������������������������������������������������������������������������70
Variables As Pointers������������������������������������������������������������������������������������������71
Pointer Initialization��������������������������������������������������������������������������������������������71
Initialized and Uninitialized Data�������������������������������������������������������������������������72
More Pseudo Notation�����������������������������������������������������������������������������������������72
“MemoryPointers” Project: Memory Layout�������������������������������������������������������73
Summary������������������������������������������������������������������������������������������������������������87

Chapter 7: Logical Instructions and PC����������������������������������������������89


Instruction Format����������������������������������������������������������������������������������������������89
Logical Shift Instructions������������������������������������������������������������������������������������90
Logical Operations����������������������������������������������������������������������������������������������90
Zeroing Memory or Registers�����������������������������������������������������������������������������91
Program Counter�������������������������������������������������������������������������������������������������92
Code Section�������������������������������������������������������������������������������������������������������93
Summary������������������������������������������������������������������������������������������������������������94

Chapter 8: Reconstructing a Program with Pointers��������������������������95


Example of Disassembly Output: No Optimization����������������������������������������������95
Reconstructing C/C++ Code: Part 1��������������������������������������������������������������������98
Reconstructing C/C++ Code: Part 2������������������������������������������������������������������100
Reconstructing C/C++ Code: Part 3������������������������������������������������������������������102

v
Table of Contents

Reconstructing C/C++ Code: C/C++ Program��������������������������������������������������103


Example of Disassembly Output: Optimized Program���������������������������������������104
Summary����������������������������������������������������������������������������������������������������������106

Chapter 9: Memory and Stacks��������������������������������������������������������107


Stack: A Definition���������������������������������������������������������������������������������������������107
Stack Implementation in Memory���������������������������������������������������������������������108
Things to Remember�����������������������������������������������������������������������������������������110
Stack Push Implementation������������������������������������������������������������������������������111
Stack Pop Implementation��������������������������������������������������������������������������������111
Register Review������������������������������������������������������������������������������������������������111
Application Memory Simplified�������������������������������������������������������������������������112
Stack Overflow��������������������������������������������������������������������������������������������������113
Jumps���������������������������������������������������������������������������������������������������������������114
Calls������������������������������������������������������������������������������������������������������������������115
Call Stack����������������������������������������������������������������������������������������������������������116
Exploring Stack in GDB�������������������������������������������������������������������������������������118
Summary����������������������������������������������������������������������������������������������������������121

Chapter 10: Frame Pointer and Local Variables�������������������������������123


Stack Usage������������������������������������������������������������������������������������������������������123
Register Review������������������������������������������������������������������������������������������������124
Addressing Array Elements�������������������������������������������������������������������������������124
Stack Structure (No Function Parameters)�������������������������������������������������������126
Function Prolog�������������������������������������������������������������������������������������������������127
Raw Stack (No Local Variables and Function Parameters)�������������������������������127
Function Epilog�������������������������������������������������������������������������������������������������129

vi
Table of Contents

“Local Variables” Project����������������������������������������������������������������������������������130


Disassembly of Optimized Executable��������������������������������������������������������������133
Summary����������������������������������������������������������������������������������������������������������134

Chapter 11: Function Parameters�����������������������������������������������������135


“FunctionParameters” Project��������������������������������������������������������������������������135
Stack Structure�������������������������������������������������������������������������������������������������136
Function Prolog and Epilog�������������������������������������������������������������������������������138
Project Disassembled Code with Comments����������������������������������������������������139
Parameter Mismatch Problem��������������������������������������������������������������������������144
Summary����������������������������������������������������������������������������������������������������������145

Chapter 12: More Instructions����������������������������������������������������������147


PSTATE Flags�����������������������������������������������������������������������������������������������������147
Testing for 0������������������������������������������������������������������������������������������������������147
TST – Logical Compare�������������������������������������������������������������������������������������148
CMP – Compare Two Operands�������������������������������������������������������������������������149
TST or CMP?�����������������������������������������������������������������������������������������������������150
Conditional Jumps��������������������������������������������������������������������������������������������150
Function Return Value���������������������������������������������������������������������������������������151
Summary����������������������������������������������������������������������������������������������������������152

Chapter 13: Function Pointer Parameters����������������������������������������153


“FunctionPointerParameters” Project���������������������������������������������������������������153
Commented Disassembly���������������������������������������������������������������������������������154
Summary����������������������������������������������������������������������������������������������������������161

vii
Table of Contents

Chapter 14: Summary of Code Disassembly Patterns����������������������163


Function Prolog/Epilog��������������������������������������������������������������������������������������163
ADR (Address)���������������������������������������������������������������������������������������������������164
Passing Parameters������������������������������������������������������������������������������������������164
Accessing Saved Parameters and Local Variables��������������������������������������������165
Summary����������������������������������������������������������������������������������������������������������166

Index�������������������������������������������������������������������������������������������������167

viii
About the Author
Dmitry Vostokov is an internationally
recognized expert, speaker, educator, scientist,
and author. He is the founder of the pattern-
oriented software diagnostics, forensics,
and prognostics discipline and Software
Diagnostics Institute (DA+TA: DumpAnalysis.
org + TraceAnalysis.org). Vostokov has also
authored more than 50 books on software
diagnostics, anomaly detection and analysis,
software and memory forensics, root cause analysis and problem solving,
memory dump analysis, debugging, software trace and log analysis,
reverse engineering, and malware analysis. He has more than 25 years
of experience in software architecture, design, development, and
maintenance in various industries, including leadership, technical, and
people management roles. Dmitry also founded Syndromatix, Anolog.
io, BriteTrace, DiaThings, Logtellect, OpenTask Iterative and Incremental
Publishing (OpenTask.com), Software Diagnostics Technology and
Services (former Memory Dump Analysis Services; PatternDiagnostics.
com), and Software Prognostics. In his spare time, he presents various
topics on Debugging TV and explores Software Narratology, its further
development as Narratology of Things and Diagnostics of Things (DoT),
Software Pathology, and Quantum Software Diagnostics. His current
areas of interest are theoretical software diagnostics and its mathematical
and computer science foundations, application of formal logic, artificial
intelligence, machine learning and data mining to diagnostics and anomaly
detection, software diagnostics engineering and diagnostics-driven

ix
About the Author

development, and diagnostics workflow and interaction. Recent areas


of interest also include cloud native computing, security, automation,
functional programming, and applications of category theory to software
development and big data.

x
About the Technical Reviewer
Sundar Pandian has more than three
years of experience in embedded software
development, including development of device
drivers, middleware software, and application
services for the infotainment system on the
Android platform. He’s also developed CAN
protocol drivers for the automotive braking
system on the Autosar platform.
He’s developed software with C, C++,
and Java and worked in the automotive,
semiconductor, and telecom industries. He has
a bachelor’s in electronics and communication engineering. Currently, he
serves as a firmware/middleware engineer for audio DSPs.

xi
Preface
The book covers topics ranging from ARM64 assembly language
instructions and writing programs in assembly language to pointers, live
debugging, and static binary analysis of compiled C and C++ code.
Diagnostics of core memory dumps, live and postmortem debugging
of Linux applications, services, and systems, memory forensics, malware,
and vulnerability analysis require an understanding of ARM64 assembly
language and how C and C++ compilers generate code, including
memory layout and pointers. This book is about background knowledge
and practical foundations that are needed to understand internal Linux
program structure and behavior, start working with the GDB debugger, and
use it for disassembly and reversing. It consists of practical step-by-step
exercises of increasing complexity with explanations and many diagrams,
including some necessary background topics.
By the end of the book, you will have a solid understanding of how
Linux C and C++ compilers generate binary code. In addition, you will be
able to analyze such code confidently, understand stack memory usage,
and reconstruct original C/C++ code.
The book will be useful for

• Software support and escalation engineers, cloud


security engineers, SRE, and DevSecOps

• Software engineers coming from JVM background

• Software testers

• Engineers coming from non-Linux environments, for


example, Windows or Mac OS X

xiii
Preface

• Engineers coming from non-ARM environments, for


example, x86/x64

• Linux C/C++ software engineers without assembly


language background

• Security researchers without assembly language


background

• Beginners learning Linux software reverse engineering


techniques

This book can also be used as an ARM64 assembly language and Linux
debugging supplement for relevant undergraduate-level courses.

Source Code
All source code used in this book can be downloaded from ­github.com/
apress/arm64-linux-debugging-disassembling-reversing.

xiv
CHAPTER 1

Memory, Registers,
and Simple Arithmetic
 emory and Registers Inside an
M
Idealized Computer
Computer memory consists of a sequence of memory cells, and each cell
has a unique address (location). Every cell contains a “number.” We refer
to these “numbers” as contents at addresses (locations). Because memory
access is slower than arithmetic instructions, there are so-called registers
to speed up complex operations that require memory to store temporary
results. We can also think about them as stand-alone memory cells. The
name of a register is its address. Figure 1-1 illustrates this.

© Dmitry Vostokov 2023 1


D. Vostokov, Foundations of ARM64 Linux Debugging, Disassembling, and Reversing,
https://doi.org/10.1007/978-1-4842-9082-8_1
Chapter 1 Memory, Registers, and Simple Arithmetic

Figure 1-1. Computer memory represented as a sequence of memory


cells and locations

 emory and Registers Inside ARM


M
64-Bit Computer
Here, addresses for memory locations containing integer values usually
differ by four or eight, and we also show two registers called X0 and X1.
The first halves of them are called W0 and W1 as shown in Figure 1-2.

2
Chapter 1 Memory, Registers, and Simple Arithmetic

Figure 1-2. Typical ARM 64-bit memory and register layout

Because memory cells contain “numbers,” we start with simple


arithmetic and ask a processor to compute the sum of two numbers to see
how memory and registers change their values.

“ Arithmetic” Project: Memory Layout


and Registers
For our project, we have two memory addresses (locations) that we call
“a” and “b.” We can think about “a” and “b” as names of their respective
addresses (locations). Now we introduce a special notation where (a)

3
Chapter 1 Memory, Registers, and Simple Arithmetic

means contents at the memory address (location) “a.” If we use the C


or C++ language to write our project, we declare and define memory
locations “a” and “b” as

static int a, b;

By default, when we load a program, static memory locations are filled


with zeroes, and we can depict our initial memory layout after loading the
program, as shown in Figure 1-3.

Figure 1-3. Initial memory layout after loading the program

4
Chapter 1 Memory, Registers, and Simple Arithmetic

“Arithmetic” Project: A Computer Program


We can think of a computer program as a sequence of instructions for
the manipulation of contents of memory cells and registers. For example,
addition operation: add the contents of memory cell №12 to the contents
of memory cell №14. In our pseudo-code, we can write

[14] <- [14] + [12]

Our first program in pseudo-code is shown on the left of the table:

[a] <- 1 Here, we put assembly instructions corresponding to


[b] <- 1 pseudo-code.
[b] <- [b] + [a]
[a] <- [a] + 1
[b] <- [b] * [a]

“<-” means moving (assigning) the new value to the contents of a


memory location (address). “//” is a comment sign, and the rest of the line
is a comment. “=” shows the current value at a memory location (address).
To remind, a code written in a high-level programming language is
translated to a machine language by a compiler. However, the machine
language can be readable if its digital codes are represented in some
mnemonic system called assembly language. For example, ADD X1, X1, #1
is increment by one of what is stored in the register memory cell X1.

“ Arithmetic” Project: Assigning Numbers


to Memory Locations
We remind that “a” means the location (address) of the memory cell,
and it is also the name of the location (address) 00000000004b2b00 (see
Figure 1-3). [a] means the contents (number) stored at the address “a.”

5
Chapter 1 Memory, Registers, and Simple Arithmetic

If we use the C or C++ language, “a” is called “the variable a,” and we
write the assignment as

a = 1;

In ARM64 assembly language, we write several instructions for that:

adr x0, a
mov w1, #1
str w1, [x0]

In the GDB disassembly output, we may see the following code:

adrp    x0, 0x4b2000
add     x0, x0, #0xb00
mov     w1, #0x1
str     w1, [x0]

We show the translation of our pseudo-code into assembly language in


the right column:

[a] <- 1          // x0 = a adr  x0, a


// w1 = 1 mov  w1, #1
// [a] = 1 str  w1, [x0]
[b] <- 1          // x0 = b adr  x0, b
// w1 = 1 mov  w1, #1
// [b] = 1 str  w1, [x0]
[b] <- [b] + [a]
[a] <- [a] + 1
[b] <- [b] * [a]

adrp x0, 0x4b2000, and subsequent add x0, x0, #0xb00 is how the
compiler generates code to calculate the address “a” instead of specifying it
directly. Such code is required for addressing large regions of memory, and

6
Chapter 1 Memory, Registers, and Simple Arithmetic

the compiler uses it even for smaller regions where just one adr instruction
is sufficient.
Literal constants have the # prefix, for example, #0x1. The 0x prefix
means the following number is hexadecimal. We explain such numbers
in Chapter 3. Please also notice that the movement direction is the same
in both the disassembly output and the pseudo-code: from right to left
(except for the str instruction).
After executing the first three assembly language instructions, we have
the memory layout shown in Figure 1-4A.

Figure 1-4A. Memory layout after executing the first three assembly
language instructions

7
Chapter 1 Memory, Registers, and Simple Arithmetic

After executing the next three assembly language instructions, we have


the memory layout shown in Figure 1-4B.

Figure 1-4B. Memory layout after executing the next three assembly
language instructions

Assigning Numbers to Registers


In the previous section, we saw that assigning numbers was a part of
memory assignments. We can write in pseudo-code:

register <- 1
register <- [a]

8
Chapter 1 Memory, Registers, and Simple Arithmetic

Note that we do not use brackets when we refer to register contents.


The latter instruction means assigning (copying) the number at the
location (address) “a” to a register.
In assembly language, we write

mov  w1, #1              // 1 is copied to the first half of X1


register
mov  x1, #1              // full contents of X1 register are
replaced with 1
adr  x0, a               // copy the location (address) "a" to
X0 register
ldr  w1, [x0]            // copy the number at the location
stored in X0 to
                         // the first half of X1 register
Ldr  x1, [x0]            // copy the number at the location
stored in X0 to X1

In the GDB disassembly output, we may see the output where one
adr instruction is replaced by adrp/add instructions with parts of the
address value:

adrp x0, 0x4b2000        // 0x4b2000 + 0xb00 = 0x4b2b00


("a" address)
add  x0, x0, #0xb00
ldr  w1, [x0]

“ Arithmetic” Project: Adding Numbers


to Memory Cells
Now let's look at the following pseudo-code statement in more detail:

[b] <- [b] + [a]

9
Chapter 1 Memory, Registers, and Simple Arithmetic

To recall, “a” and “b” mean the names of locations (addresses)


00000000004b2b00 and 00000000004b2b04, respectively (see Figures 1-4A
and 1-4B). [a] and [b] mean contents at addresses “a” and “b,” respectively,
simply some numbers stored there.
In the C or C++ language, we write the following statement:

b = b + a;
b += a;

In assembly language, we use the instruction ADD. Because of ARM


architecture limitations, we cannot use memory addresses in one step
(instruction), for example, add b, b, a. We can only use the add register1,
register1, register0 instruction to add the value stored in the register0 to
the value stored in the register1 and move the result to the register1. So,
first, we need to load (ldr) contents at addresses “a” and “b” to registers
and store (str) the result back to the memory location “b” after addition.
Recall that a register is like a temporary memory cell itself here:

Register2 <- [b]


Register1 <- [a]
Register2 <- register2 + register1
[b] <- register2

In assembly language, we write

adr  x0, b
ldr  w1, [x0]
adr  x0, a
ldr  w0, [x0]
add  w1, w1, w0
adr  x0, b
str  w1, [x0]

In the GDB disassembly output, we may see the following code:

10
Chapter 1 Memory, Registers, and Simple Arithmetic

adrp x0, 0x4b2000


add  x0, x0, #0xb00
ldr  w1, [x0]
adrp x0, 0x4b2000
add  x0, x0, #0xb04
ldr  w0, [x0]
add  w1, w1, w0
adrp x0, 0x4b2000
add  x0, x0, #0xb04
str  w1, [x0]

Now we can translate our pseudo-code into assembly language:

[a] <- 1          // x0 = a adr  x0, a


// w1 = 1 mov  w1, #1
// [a] = 1 str  w1, [x0]
[b] <- 1          // x0 = b adr  x0, b
// w1 = 1 mov  w1, #1
// [b] = 1 str  w1, [x0]
[b] <- [b] + [a]  // x0 = b adr  x0, b
// w1 = 1 ldr  w1, [x0]
// x0 = a adr  x0, a
// w0 = 1 ldr  w0, [x0]
// w1 = 2 add  w1, w1, w0
// x0 = b adr  x0, b
// [b] = 2 str  w1, [x0]
[a] <- [a] + 1
[b] <- [b] * [a]

After executing ADR, LDR, ADD, and STR instructions, we have the
memory layout illustrated in Figure 1-5.

11
Chapter 1 Memory, Registers, and Simple Arithmetic

Figure 1-5. Memory layout after executing ADR, LDR, ADD, and STR
instructions

Incrementing/Decrementing Numbers
in Memory and Registers
In pseudo-code, it looks simple and means increment (decrement) a
number stored at the location (address) “a”:

[a] <- [a] + 1


[a] <- [a] – 1

In the C or C++ language, we can write this using three possible ways:

12
Chapter 1 Memory, Registers, and Simple Arithmetic

a = a + 1;
++a;
a++;
b = b – 1;
--b;
b--;

In assembly language, we use instructions ADD and SUB and write

add  x0, x0, #1
sub  x0, x0, #1

adr  x0, a
ldr  w1, [x0]
add  w1, w1, #1
str  w1, [x0]

adr  x0, b
ldr  w1, [x0]
sub  w1, w1, #1
str  w1, [x0]

In the GDB disassembly output, we may see the similar instructions:

adrp x0, 0x4b2000


add  x0, x0, #0xb00
ldr  w0, [x0]
add  w1, w0, #0x1
adrp x0, 0x4b2000
add  x0, x0, #0xb00
str  w1, [x0]

13
Chapter 1 Memory, Registers, and Simple Arithmetic

Now we add the assembly language translation of increment:

[a] <- 1          // x0 = a adr  x0, a


                  // w1 = 1 mov  w1, #1
                  // [a] = 1 str  w1, [x0]
[b] <- 1          // x0 = b adr  x0, b
                  // w1 = 1 mov  w1, #1
                  // [b] = 1 str  w1, [x0]
[b] <- [b] + [a]  // x0 = b adr  x0, b
                  // w1 = 1 ldr  w1, [x0]
                  // x0 = a adr  x0, a
                  // w0 = 1 ldr  w0, [x0]
                  // w1 = 2 add  w1, w1, w0
                  // x0 = b adr  x0, b
                  // [b] = 2 str  w1, [x0]
[a] <- [a] + 1    // x0 = a adr  x0, a
                  // w1 = 1 ldr  w1, [x0]
                  // w1 = 2 add  w1, w1, #1
                  // [a] = 2 str  w1, [x0]
[b] <- [b] * [a]

After the execution of the ADD instruction, we have the memory layout
illustrated in Figure 1-6.

14
Chapter 1 Memory, Registers, and Simple Arithmetic

Figure 1-6. Memory layout after the execution of the ADD instruction

Multiplying Numbers
In pseudo-code, we write

[b] <- [b] * [a]

It means that we multiply the number at the location (address) “b” by


the number at the location (address) “a.”
In the C or C++ language, we can write that using two ways:

b =  b * a;
b *= a;

15
Chapter 1 Memory, Registers, and Simple Arithmetic

In assembly language, we use instruction MUL and write

adr  x0, b
ldr  w1, [x0]
adr  x0, a
ldr  w0, [x0]
mul  w1, w1, w0
adr  x0, b
str  w1, [x0]

In the GDB disassembly output, we may see the following code:

adrp x0, 0x4b2000


add  x0, x0, #0xb04
ldr  w1, [x0]
adrp x0, 0x4b2000
add  x0, x0, #0xb00
ldr  w0, [x0]
mul  w1, w1, w0
adrp x0, 0x4b2000
add  x0, x0, #0xb04
str  w1, [x0]

Now we add additional assembly instructions to our pseudo-code


assembly language translation:

16
Chapter 1 Memory, Registers, and Simple Arithmetic

[a] <- 1          // x0 = a adr  x0, a


                  // w1 = 1 mov  w1, #1
                  // [a] = 1 str  w1, [x0]
[b] <- 1          // x0 = b adr  x0, b
                  // w1 = 1 mov  w1, #1
                  // [b] = 1 str  w1, [x0]
[b] <- [b] + [a]  // x0 = b adr  x0, b
                  // w1 = 1 ldr  w1, [x0]
                  // x0 = a adr  x0, a
                  // w0 = 1 ldr  w0, [x0]
                  // w1 = 2 add  w1, w1, w0
                  // x0 = b adr  x0, b
                  // [b] = 2 str  w1, [x0]
[a] <- [a] + 1    // x0 = a adr  x0, a
                  // w1 = 1 ldr  w1, [x0]
                  // w1 = 2 add  w1, w1, #1
                  // [a] = 2 str  w1, [x0]
[b] <- [b] * [a]  // x0 = b adr  x0, b
                  // w1 = 2 ldr  w1, [x0]
                  // x0 = a adr  x0, a
                  // w0 = 2 ldr  w0, [x0]
                  // w1 = 4 mul  w1, w1, w0
                  // x0 = b adr  x0, b
                  // [b] = 4 str  w1, [x0]

After the execution of the STR instruction, we have the memory layout
illustrated in Figure 1-7.

17
Chapter 1 Memory, Registers, and Simple Arithmetic

Figure 1-7. Memory layout after the execution of the STR instruction

Summary
This chapter introduced CPU registers and explained the memory layout
of a simple arithmetic program. We learned basic ARM64 commands,
including loading values from and storing values in memory. We also
manually translated C and C++ code to assembly language.
The next chapter looks at assembly language code produced by a
debugger via disassembling binary code. Then, we reverse it to C and C++
code. We also compare the disassembly output of nonoptimized code to
optimized code.

18
CHAPTER 2

Code Optimization
“Arithmetic” Project: C/C++ Program
Let's rewrite our “Arithmetic” program in C/C++. Corresponding assembly
language instructions are put in comments:

int a, b;

int main(int argc, char* argv[])


{
      a = 1;              // adr  x0, a
                          // mov  w1, #1
                          // str  w1, [x0]

      b = 1;              // adr  x0, b


                          // mov  w1, #1
                          // str  w1, [x0]

      b = b + a;          // adr  x0, b


                          // ldr  w1, [x0]
                          // adr  x0, a
                          // ldr  w0, [x0]
                          // add  w1, w1, w0
                          // adr  x0, b
                          // str  w1, [x0]

© Dmitry Vostokov 2023 19


D. Vostokov, Foundations of ARM64 Linux Debugging, Disassembling, and Reversing,
https://doi.org/10.1007/978-1-4842-9082-8_2
Chapter 2 Code Optimization

      ++a;                // adr  x0, a
                          // ldr  w1, [x0]
                          // add  w1, w1, #1
                          // str  w1, [x0]

      b = b * a;          // adr  x0, b


                          // ldr  w1, [x0]
                          // adr  x0, a
                          // ldr  w0, [x0]
                          // mul  w1, w1, w0
                          // adr  x0, b
                          // str  w1, [x0]

                          // results: [a] = 2 and [b] = 4


      return 0;
}

Downloading GDB
We used one of the free ARM64 Linux compute instances available from
cloud providers. In our case, GDB was already available after provisioning.
If, in your case, GDB is not available, you need to install it together with
basic build tools. For example, in Debian:

$ sudo apt install build-essential


$ sudo apt install gdb

You may also need to download git to clone source code:

$ sudo apt install git


$ cd ~
$ git clone github.com/apress/arm64-linux-debugging-­
disassembling-reversing .

20
Chapter 2 Code Optimization

On our RHEL-type system, we updated the tools (git included)


and GDB via

$ sudo yum group install "Development Tools"


$ sudo yum install gdb

GDB Disassembly Output – No Optimization


The source code can be downloaded from the following location:

github.com/apress/arm64-linux-debugging-disassembling-
reversing/Chapter2/

If we compile and link the program in no optimization mode (default):

$ gcc ArithmeticProjectC.cpp -o ArithmeticProjectC

we get the binary executable module we can load in GDB and inspect
assembly code.
First, we run GDB with the program as a parameter:

$ gdb ./ArithmeticProjectC
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.0.2.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/
licenses/gpl.html>
This is free software: you are free to change and
redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type
"show copying"
and "show warranty" for details.
This GDB was configured as "aarch64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...

21
Chapter 2 Code Optimization

Reading symbols from /home/coredump/pflddr/A64/Chapter2/


ArithmeticProjectC...(no debugging symbols found)...done.
(gdb)

Next, we put a breakpoint at our main C/C++ function to allow the


program execution to stop at that point and give us a chance to inspect
memory and registers. Symbolic names/function names like "main" can be
used instead of code memory locations:

(gdb) break main


Breakpoint 1 at 0x4005bc

Then we start the execution of the program (let it run). The program
then stops at the previously set breakpoint:

Starting program: /home/coredump/pflddr/A64/Chapter2/./


ArithmeticProjectC

Breakpoint 1, 0x00000000004005bc in main ()


Missing separate debuginfos, use: debuginfo-install
glibc-2.17-325.0.2.el7_9.aarch64

Now we disassemble the main function:

(gdb) disass main


Dump of assembler code for function main:
   0x00000000004005b8 <+0>:     sub     sp, sp, #0x10
=> 0x00000000004005bc <+4>:     str     w0, [sp,#12]
   0x00000000004005c0 <+8>:     str     x1, [sp]
   0x00000000004005c4 <+12>:    adrp    x0, 0x420000
   0x00000000004005c8 <+16>:    add     x0, x0, #0x20
   0x00000000004005cc <+20>:    mov     w1, #0x1          // #1
   0x00000000004005d0 <+24>:    str     w1, [x0]
   0x00000000004005d4 <+28>:    adrp    x0, 0x420000
   0x00000000004005d8 <+32>:    add     x0, x0, #0x24

22
Chapter 2 Code Optimization

   0x00000000004005dc <+36>:    mov     w1, #0x1          // #1


   0x00000000004005e0 <+40>:    str     w1, [x0]
   0x00000000004005e4 <+44>:    adrp    x0, 0x420000
   0x00000000004005e8 <+48>:    add     x0, x0, #0x24
   0x00000000004005ec <+52>:    ldr     w1, [x0]
   0x00000000004005f0 <+56>:    adrp    x0, 0x420000
   0x00000000004005f4 <+60>:    add     x0, x0, #0x20
   0x00000000004005f8 <+64>:    ldr     w0, [x0]
   0x00000000004005fc <+68>:    add     w1, w1, w0
   0x0000000000400600 <+72>:    adrp    x0, 0x420000
   0x0000000000400604 <+76>:    add     x0, x0, #0x24
   0x0000000000400608 <+80>:    str     w1, [x0]
   0x000000000040060c <+84>:    adrp    x0, 0x420000
   0x0000000000400610 <+88>:    add     x0, x0, #0x20
   0x0000000000400614 <+92>:    ldr     w0, [x0]
   0x0000000000400618 <+96>:    add     w1, w0, #0x1
   0x000000000040061c <+100>:   adrp    x0, 0x420000
   0x0000000000400620 <+104>:   add     x0, x0, #0x20
   0x0000000000400624 <+108>:   str     w1, [x0]
---Type <return> to continue, or q <return> to quit---
   0x0000000000400628 <+112>:   adrp    x0, 0x420000
   0x000000000040062c <+116>:   add     x0, x0, #0x24
   0x0000000000400630 <+120>:   ldr     w1, [x0]
   0x0000000000400634 <+124>:   adrp    x0, 0x420000
   0x0000000000400638 <+128>:   add     x0, x0, #0x20
   0x000000000040063c <+132>:   ldr     w0, [x0]
   0x0000000000400640 <+136>:   mul     w1, w1, w0
   0x0000000000400644 <+140>:   adrp    x0, 0x420000
   0x0000000000400648 <+144>:   add     x0, x0, #0x24
   0x000000000040064c <+148>:   str     w1, [x0]

23
Chapter 2 Code Optimization

   0x0000000000400650 <+152>:   mov     w0, #0x0          // #0


   0x0000000000400654 <+156>:   add     sp, sp, #0x10
   0x0000000000400658 <+160>:   ret
End of assembler dump.

We repeat the part of the formatted disassembly output here that


corresponds to our C/C++ code:

   0x00000000004005c4 <+12>:    adrp    x0, 0x420000


   0x00000000004005c8 <+16>:    add     x0, x0, #0x20
   0x00000000004005cc <+20>:    mov     w1, #0x1
   0x00000000004005d0 <+24>:    str     w1, [x0]
   0x00000000004005d4 <+28>:    adrp    x0, 0x420000
   0x00000000004005d8 <+32>:    add     x0, x0, #0x24
   0x00000000004005dc <+36>:    mov     w1, #0x1
   0x00000000004005e0 <+40>:    str     w1, [x0]
   0x00000000004005e4 <+44>:    adrp    x0, 0x420000
   0x00000000004005e8 <+48>:    add     x0, x0, #0x24
   0x00000000004005ec <+52>:    ldr     w1, [x0]
   0x00000000004005f0 <+56>:    adrp    x0, 0x420000
   0x00000000004005f4 <+60>:    add     x0, x0, #0x20
   0x00000000004005f8 <+64>:    ldr     w0, [x0]
   0x00000000004005fc <+68>:    add     w1, w1, w0
   0x0000000000400600 <+72>:    adrp    x0, 0x420000
   0x0000000000400604 <+76>:    add     x0, x0, #0x24
   0x0000000000400608 <+80>:    str     w1, [x0]
   0x000000000040060c <+84>:    adrp    x0, 0x420000
   0x0000000000400610 <+88>:    add     x0, x0, #0x20
   0x0000000000400614 <+92>:    ldr     w0, [x0]
   0x0000000000400618 <+96>:    add     w1, w0, #0x1
   0x000000000040061c <+100>:   adrp    x0, 0x420000
   0x0000000000400620 <+104>:   add     x0, x0, #0x20

24
Chapter 2 Code Optimization

   0x0000000000400624 <+108>:   str     w1, [x0]


   0x0000000000400628 <+112>:   adrp    x0, 0x420000
   0x000000000040062c <+116>:   add     x0, x0, #0x24
   0x0000000000400630 <+120>:   ldr     w1, [x0]
   0x0000000000400634 <+124>:   adrp    x0, 0x420000
   0x0000000000400638 <+128>:   add     x0, x0, #0x20
   0x000000000040063c <+132>:   ldr     w0, [x0]
   0x0000000000400640 <+136>:   mul     w1, w1, w0
   0x0000000000400644 <+140>:   adrp    x0, 0x420000
   0x0000000000400648 <+144>:   add     x0, x0, #0x24
   0x000000000040064c <+148>:   str     w1, [x0]

We can directly translate it to bare assembly code we used in the


previous chapter and put corresponding pseudo-code in comments
(memory addresses may be different on your system):

   0x00000000004005c4 <+12>:    adrp    x0, 0x420000      


// [a] <- 1
   0x00000000004005c8 <+16>:    add     x0, x0, #0x20
   0x00000000004005cc <+20>:    mov     w1, #0x1
   0x00000000004005d0 <+24>:    str     w1, [x0]
   0x00000000004005d4 <+28>:    adrp    x0, 0x420000      
// [b] <- 1
   0x00000000004005d8 <+32>:    add     x0, x0, #0x24
   0x00000000004005dc <+36>:    mov     w1, #0x1
   0x00000000004005e0 <+40>:    str     w1, [x0]
   0x00000000004005e4 <+44>:    adrp    x0, 0x420000      
// [b] <- [b] + [a]
   0x00000000004005e8 <+48>:    add     x0, x0, #0x24
   0x00000000004005ec <+52>:    ldr     w1, [x0]
   0x00000000004005f0 <+56>:    adrp    x0, 0x420000
   0x00000000004005f4 <+60>:    add     x0, x0, #0x20

25
Chapter 2 Code Optimization

   0x00000000004005f8 <+64>:    ldr     w0, [x0]


   0x00000000004005fc <+68>:    add     w1, w1, w0
   0x0000000000400600 <+72>:    adrp    x0, 0x420000
   0x0000000000400604 <+76>:    add     x0, x0, #0x24
   0x0000000000400608 <+80>:    str     w1, [x0]
   0x000000000040060c <+84>:    adrp    x0, 0x420000      
// [a] <- [a] + 1
   0x0000000000400610 <+88>:    add     x0, x0, #0x20
   0x0000000000400614 <+92>:    ldr     w0, [x0]
   0x0000000000400618 <+96>:    add     w1, w0, #0x1
   0x000000000040061c <+100>:   adrp    x0, 0x420000
   0x0000000000400620 <+104>:   add     x0, x0, #0x20
   0x0000000000400624 <+108>:   str     w1, [x0]
   0x0000000000400628 <+112>:   adrp    x0, 0x420000      
// [b] <- [b] * [a]
   0x000000000040062c <+116>:   add     x0, x0, #0x24
   0x0000000000400630 <+120>:   ldr     w1, [x0]
   0x0000000000400634 <+124>:   adrp    x0, 0x420000
   0x0000000000400638 <+128>:   add     x0, x0, #0x20
   0x000000000040063c <+132>:   ldr     w0, [x0]
   0x0000000000400640 <+136>:   mul     w1, w1, w0
   0x0000000000400644 <+140>:   adrp    x0, 0x420000
   0x0000000000400648 <+144>:   add     x0, x0, #0x24
   0x000000000040064c <+148>:   str     w1, [x0]

Now we can exit GDB:

(gdb) q
A debugging session is active.

        Inferior 1 [process 11103] will be killed.

Quit anyway? (y or n) y
$

26
Chapter 2 Code Optimization

GDB Disassembly Output – Optimization


If we compile and link the program in optimization mode:

$ gcc ArithmeticProjectC.cpp -O1 -o ArithmeticProjectC

and after repeating the same steps in GDB, we get the following output:

(gdb) disass main


Dump of assembler code for function main:
   0x00000000004005b8 <+0>:     adrp    x0, 0x420000
   0x00000000004005bc <+4>:     add     x1, x0, #0x20
   0x00000000004005c0 <+8>:     mov     w2, #0x2          // #2
=> 0x00000000004005c4 <+12>:    str     w2, [x0,#32]
   0x00000000004005c8 <+16>:    mov     w0, #0x4          // #4
   0x00000000004005cc <+20>:    str     w0, [x1,#4]
   0x00000000004005d0 <+24>:    mov     w0, #0x0          // #0
   0x00000000004005d4 <+28>:    ret

This corresponds to the following pseudo-code:

[a] <- 2
[b] <- 4

The calculation of memory addresses is a bit more complex:

   0x00000000004005b8 <+0>:   adrp  x0, 0x420000


   0x00000000004005bc <+4>:   add   x1, x0, #0x20     
// x1 = x0 +
0x20 = a
   0x00000000004005c0 <+8>:   mov   w2, #0x2          // w2 = 2
=> 0x00000000004005c4 <+12>:  str   w2, [x0,#32]      // #32 in 0x20
                                                      // [a] = [x0
+ 0x20] = 2
   0x00000000004005c8 <+16>:  mov   w0, #0x4          // w0 = 4
   0x00000000004005cc <+20>:  str   w0, [x1,#4]       // [b] = [a
+ 4] = 4

27
Chapter 2 Code Optimization

What happened to all our assembly code in this executable? This


code seems to be directly placing the end result into “a” and “b” memory
cells if we observe. Why is this happening? The answer lies in compiler
optimization. When the code is compiled in optimization mode, the
compiler can calculate the final result from the simple C/C++ source
code itself and generate only the necessary code to update corresponding
memory locations.

Summary
In this chapter, we looked at assembly language code produced by a
debugger via disassembling binary code. Then, we reversed it to C and C++
code. We also compared the disassembly output of nonoptimized code to
optimized code and understood why.
The next chapter refreshes number representations, especially the
hexadecimal one.

28
CHAPTER 3

Number
Representations
Numbers and Their Representations
Imagine a herder in ancient times trying to count his sheep. He has a
certain number of stones (twelve):

However, he can only count up to three and arranges the total into
groups of three:

© Dmitry Vostokov 2023 29


D. Vostokov, Foundations of ARM64 Linux Debugging, Disassembling, and Reversing,
https://doi.org/10.1007/978-1-4842-9082-8_3
Chapter 3 Number Representations

The last picture is a representation (a kind of notation) of the number


of stones. We have one group of three groups of three stones plus a
separate group of three stones. If he could count up to ten, we would see a
different representation of the same number of stones. We would have one
group of ten stones and another group of two stones.

Decimal Representation (Base Ten)


Let’s now see how twelve stones are represented in arithmetic notation if
we can count up to ten. We have one group of ten numbers plus two:

12dec = 1 * 10 + 2 or 1 * 101 + 2 * 100

Here is another exercise with 123 stones. We have 1 group of ten by


ten stones, another group of 2 groups of ten stones, and the last group of
3 stones:

123dec = 1 * 10*10 + 2 * 10 + 3 or 1 * 102 + 2 * 101 + 3 * 100

We can formalize it in the following summation notation:

Ndec = an*10n + an-1*10n-1 + … + a2*102 + a1*101 + a0*100


0 <= ai <= 9
Using the summation symbol, we have this formula:

n
Ndec = ∑ ai*10i
i=0

Ternary Representation (Base Three)


Now we come back to our herder’s example of twelve stones. We have
1 group of three by three stones, 1 group of three stones, and an empty
(0) group (which is not empty if we have one stone only or have thirteen

30
Chapter 3 Number Representations

stones instead of twelve). We can write down the number of groups


sequentially: 110. Therefore, 110 is a ternary representation (notation) of
twelve stones, and it is equivalent to 12 written in decimal notation:

12dec = 1*32 + 1*31 + 0*30

Ndec = an*3n + an-1*3n-1 + … + a2*32 + a1*31 + a0*30


ai = 0 or 1 or 2

n
Ndec = ∑ ai*3i
i=0

Binary Representation (Base Two)


In the case of counting up to two, we have more groups for twelve stones:
1100. Therefore, 1100 is a binary representation (notation) for 12 in
decimal notation:

12dec = 1*23 + 1*22 + 0*21 + 0*20

123dec = 1*26 + 1*25 + 1*24 + 1*23 + 0*22 + 1*21 + 1*20 or


11110112
Ndec = an*2n + an-1*2n-1 + … + a2*22 + a1*21 + a0*20
ai = 0 or 1

n
Ndec = ∑ ai*2i
i=0

31
Other documents randomly have
different content
niinkuin seisomaan keskelle virtaa? Meitä ympäröi vesi, tyttäreni, ja
sen lisäksi sangen likaista vettä; pidetään varamme, ettemme
kastu."

Nuori tyttö veti päänsä takaisin vaunujen sisään.

"Tältä puolelta ei voi nähdä mitään, isä", sanoi hän; "jos


hevosemme saattaisivat tehdä puolikäännöksen, voisimme nähdä
vaunujen ikkunasta, ja silloin meillä olisi melkein yhtä hyvä paikka
kuin kuvernöörin talossa".

"Käännä, ajaja", huusi parooni de Taverney.

"Se on mahdotonta, herra parooni", vastasi mies; "silloin minä


tulisin heti rusentaneeksi kymmenen ihmistä".

"No, lempo, rusenna!"

"Oh, monsieur", virkkoi Andrée isälleen.

"Oh, isä" huudahti Filip.

"Mikä parooni se siellä tahtoo murjoa köyhää kansaa?" huusi


samassa monta uhkaavaa ääntä.

"Parbleu, se olen minä", sanoi parooni de Taverney kumartuen


ikkunasta ulos ja näyttäen kumartuessaan kaulassaan riippuvaa
punaista ritarinauhaa suurristeineen.

Siihen aikaan kunnioitettiin vielä ritarinauhoja, jopa punaistakin


suurristeineen; väki nurisi edelleen, mutta alenevassa asteikossa.

"Odottakaahan, isä, minä laskeudun maahan", sanoi Filip, "ja


katson, onko mahdollista päästä eteenpäin".
"Ole varovainen, veljeni, henkesi voi olla vaarassa; etkö kuule,
miten hevoset hirnuvat ja tömistelevät."

"Sanoisit paremminkin ärjyvät", oikaisi parooni. "Kas niin,


laskeudutaan maahan; sano heille, Filip, että väistyvät tieltä ja että
me tahdomme päästä eteenpäin."

"Ah, te ette tunne enää Pariisia, isä", vastasi Filip; "sellainen


komentelu saattoi ehkä ennen käydä päinsä, mutta nyt voisi se
epäonnistua, ja tehän ette toivoisi arvollenne moista nolausta, eikö
niin?"

"Mutta kun ne lurjukset saavat kuulla, kuka minä olen…"

"Isä", vastasi Filip hymyillen, "vaikka olisitte itse dauphin, ei teidän


tieltänne mentäisi, varsinkaan juuri tällä hetkellä, sillä katsokaa, nyt
alkaa ilotulitus".

"Me emme siis saa nähdä mitään", virkkoi Andrée harmissaan.

"Se on sinun vikasi, hitossa!" vastasi parooni; "sinä hukkasit yli


kaksi tuntia aikaa pukeutumiseen".

"Filip", sanoi Andrée, "enkö voisi turvautua käsivarteesi ja asettua


keskelle joukkoa?"

"Kyllä, hyvä neiti", vastasi monta miestä, jotka Andréen kauneus


sai heltymään; "tulkaa, te ette vie paljon tilaa, ja teille avataan
paikka".

"Tahdotko, Andrée?" kysyi Filip.

"Mielelläni", vastasi Andrée.


Ja hän hypähti alas vaunuista koskematta astuinlautaan.

"No mene sitten", sanoi parooni; "mutta minä, joka välitän viis
ilotulituksista, jään tänne".

Kansa kunnioittaa, ellei sitä jokin intohimo ärsytä, ja palvelee aina


sitä kuningatarta, jota kutsutaan kauneudeksi. Ja niinpä aukesikin se
nyt Andréen ja hänen veljensä edessä, ja muuan siivo porvari, joka
oli perheineen saanut haltuunsa erään kivipenkin, antoi vaimonsa ja
tyttärensä asettua hiukan ahtaammalle, niin että Andrée sai paikan
heidän välissään.

Filip asettui seisomaan sisarensa viereen, joka nojasi nyt toisella


kädellään hänen olkapäähänsä.

Gilbert oli tullut heidän perässään ja seisoi nyt neljän askelen


päässä sisaruksista ja katseli Andréeta kiihkein silmin.

"Onko siinä hyvä paikka?" kysyi Filip.

"Erinomainen", vastasi nuori tyttö.

"Niin käy, kun on kaunis", virkkoi kapteeni hymyillen.

— Ah niin, jumalallisen kaunis! mutisi Gilbert itsekseen.

Andrée kuuli kyllä nämä sanat; mutta kun ne oli kai lausunut joku
kansan mies, niin ei hän välittänyt niistä sen enempää kuin jokin
intialainen jumala uhrista, kun paaria-luokkaan kuuluva raukka
laskee sen hänen jalkainsa juureen.
KAHDESKYMMENESKUUDES LUKU

Pakokauhu

Andrée ja hänen veljensä olivat tuskin asettuneet paikalleen, kun


jo ensimmäiset raketit suhahtivat kiemurrellen kohti taivasta, ja
kaikuva huuto kuului kansa joukosta, joka kohdisti tästä lähtien
kaiken huomionsa ainoastaan torin keskustan tarjoamaan
näytelmään.

Ilotulituksen alku oli suurenmoinen ja vastasi joka suhteessa


Ruggierin loistavaa mainetta. Temppelin tulet syttyivät vähitellen ja
näyttivät pian tulesta luodun julkisivun. Kättentaputus remahti;
mutta se mieltymyksen osoitus muuttui hurjiksi hyvähuudoiksi, kun
delfiinien kidoista ja virtojen uurnista alkoi nousta tulisuihkuja, joiden
eriväriset liekkiputoukset suihkusivat ristiin.

Moinen vertaansa turhaan etsivä näky, nimittäin


seitsemänsataatuhatta ihmistä yhdessä laumassa karjumassa ilosta
katsellen tulista palatsia, oli saanut Andréen sellaisen kummastuksen
valtaan, ettei hän koettanut sitä salatakaan.
Kolmen askeleen päässä hänestä seisoi Gilbert, erään
jättiläismäisen kantajan hartiain takana, joka kohotti ylös lastaan;
Gilbert, joka katseli Andréeta hänen itsensä tähden, ja ilotulitusta
ainoastaan hänen katselemisensa vuoksi.

Gilbert näki Andréen sivulta; jokainen raketti valaisi noita kauniita


kasvoja ja sai nuorukaisen hätkähtämään; hänestä tuntui kuin olisi
yleisön ihailuun ollut syynä tuo hänen oma ihana näkynsä, tuo
taivaallinen olento, jota hän palveli epäjumalanaan.

Andrée ei ollut ennen nähnyt Pariisia eikä näin suurta


kansantulvaa tai juhlaloistoa; sellaisten uutuuksien runsaus sai hänet
aivan ymmälle.

Yhtäkkiä välähti ilmi kirkas valo, joka syöksyi vinosti jokea kohti.
Se oli pommi, joka räjähti kovalla paukkeella ja jonka monia
vaihtelevia värejä Andrée ihaili.

"Katso, Filip, kuinka kaunista", sanoi hän.

"Taivaan Isä, tuo viime raketti oli kovin huonosti suunnattu!"


huudahti nuori mies levottomana ja vastaamatta sisarelleen. "Se ei
varmaankaan mennyt minne sen piti, sillä se lensi vaakasuoraan eikä
piirtänyt kaarta niinkuin sen olisi tullut tehdä."

Tuskin oli Filip ehtinyt ilmaista tämän rauhattomuutensa, joka alkoi


heti ilmetä myös pelokkaana väristyksenä kansanjoukossa, kun
bastionista, johon kukkakimppu ja ilotulituksen varalaitteet oli
sijoitettu, alkoi suihkuta kokonainen liekkipyörre. Torilla kajahti nyt
jyminä, niinkuin sata ukkosta olisi rynnännyt yhtaikaa joka
suunnalta, ja kuten olisi tuo suihkuava tuli ampunut joukkoon
granaatteja, ajoi se pakoon lähimpänä seisovat katsojat, lyöden heitä
äkkiarvaamatta vasten silmiä.

"Nytkö jo kukkakimppu!" huusivat kauempana seisovat. "Ei vielä,


se on liian aikaista!"

"Ei", sanoi Filip sisarelleen, "se ei ole kukkakimppu; se on


varmaankin joku onnettomuus, joka panee pian kansan lainehtimaan
kuin meri. Tule, Andrée; mennään heti takaisin vaunujen luokse;
tule."

"Oi, anna minun vielä katsella, Filip; se on niin kaunista!"

"Andrée, nyt ei ole silmänräpäystäkään aikaa hukata; tule heti. On


sattunut se onnettomuus, jota pelkäsin. Huonosti ammuttu raketti on
sytyttänyt bastionin tuleen. Ihmiset survovat jo toisiaan. Kuuletko,
miten he jo huutavat? Nuo eivät ole ilohuutoja, vaan hätähuutoja.
Nopeasti vaunujen luokse… Hyvät herrat, päästäkää meitä
menemään!"

Filip kietoi käsivartensa sisarensa ympärille ja veti häntä


mukaansa, koettaen mennä isänsä luokse, joka myöskin oli tullut
levottomaksi ja aavisti kuulemistaan huudoista jotakin vaaraa, vaikka
ei ymmärtänyt mitä, joskin se selvästi läheni. Siksi hän kurkisteli ulos
vaunujen ikkunoista etsien katseillaan lapsiansa.

Oli jo liian myöhäistä, ja Filipin ennustus kävi toteen.


Kukkakimppu, joka oli laadittu viidestätoistatuhannesta raketista,
leimahti tuleen, sinkoili joka taholle ja ahdisti katsojia kuin
tulipeitset, joita arenalla heitetään härän niskaan sitä taisteluun
ärsytettäessä.
Katselijat ensin kummastuivat, sitten pelästyivät, ja ponnahtivat
vaiston pakosta takaisin; ja moinen sadantuhannen ihmisen
pusertava peräytyminen sai toiset satatuhatta, jotka olivat ahtaaseen
alaansa tukehtua, työntämään samanlaiseen liikkeeseen jälleen
heidän takanaan olevat laumat. Ilotulitustelineet syttyivät tuleen,
lapset kirkuivat, naiset huitoivat menehtymäisillään käsiään;
kaupunginvartioston sotilaat iskivät oikealle ja vasemmalle luullen
voivansa tukkia huutajain suun ja palauttaa järjestyksen. Ja kaikkien
näiden syiden yhteisenä seurauksena oli, että se aalto, josta Filip oli
puhunut, syöksyi kuin vesipyörre sille puolelle toria, missä hän seisoi.
Siten hän ei päässytkään, niinkuin oli luullut, paroonin vaunujen
luokse, vaan vastustamaton virta vei hänet aivan päinvastaiseen
suuntaan, tuo tulva, josta ei minkäänlainen kuvaus voi antaa
käsitystä, sillä yksilöitten voima, jota jo pelästys ja kipu oli lisännyt
kymmenkertaiseksi, kasvoi satakertaiseksi kaikkien ponnistaessa
yhtaikaa.

Filip oli vetänyt Andréen mukanaan, ja myöskin Gilbert oli antanut


saman virran kuljettaa itseään; mutta kun hän oli joutunut
parinkymmenen askeleen päähän, tempasi hänet ryöppyynsä joukko
pakenevia, joka kääntyi vasempaan Madeleine-kadulle päin, ja
välittämättä hänen hurjista huudoistaan, joita hän päästeli, kun tunsi
täten joutuvansa erilleen Andréesta, se kiskoi häntä omalle
taholleen.

Andrée koetti pysyä kaikin voimin kiinni Filipin käsivarressa, mutta


sekaantui kuitenkin erääseen ryhmään, joka koetti väistyä kahden
vimmastuneen hevosen ja vaunujen edestä. Filip näki niiden
vaunujen kiivaasti ja uhkaavina lähestyvän; hevosten silmät
säkenöivät hurjistuneina, ja vaahto kuohui niiden sieraimista. Hän
ponnisti raivoisasti päästäkseen pois niiden tieltä. Mutta kaikki oli
turhaa, hän huomasi tungoksen takanaan avautuvan, hän eroitti
pillastuneitten eläinten päät, hän näki hevosten ponnahtavan
jaloilleen aivan kuin marmoriratsut, jotka vartioivat Tuileriesin
pääporttia. Ja kuten orja, joka niitä koettaa hillitä, päästi hän silloin
Andréen käsivarren, sysäsi hänet koko voimallaan pois vaaralliselta
väylältä ja tarttui lähimpänä olevan hevosen suitsiin. Hevonen nousi
takajaloilleen, Andrée näki veljensä kaatuvan, erkanevan suitsista ja
katoavan; hän päästi huudon, ojensi kätensä, hänet sysättiin
takaisin, käännettiin ympäri, ja hän oli silmänräpäyksen jälkeen
erillään veljestä, voimattomana, hoippuen ja niinkuin höyhen tuulen
viemänä, jaksamatta tehdä enempää kuin sekään vastarintaa
väkivallalle, joka kiidätti häntä eteenpäin.

Pauhaavat huudot, kamalammat kuin mitkään sotahuudot,


hevosten hirnunta, kauhea pyöräin jyrinä, kun ne milloin räikkyivät
katukivillä ja milloin nousivat ihmisruumiille, palavain
ilotulitustelineitten mustansininen loimu, sapelien tuhoisa välähtely,
kun eräät raivostuneet sotamiehet elivät paljastaneet aseensa, ja yli
koko tämän verisen sekasorron vaaleanpunaisella hohteella loistava
pronssinen kuvapatsas, joka näytti ikäänkuin johtavan verilöylyä,
tämä kaikki riitti riistämään Andréelta kaiken järjen ja kaiken hänen
voimansa. Ja sitäpaitsi olisivat jonkun jumalia vastaan taistelevan
jättiläisenkin jänteet olleet voimattomia moisessa temmellyksessä,
yhden ainoan yksilön, kamppailussa kaikkia, niin, itse kuolemaa
vastaan.

Andrée huusi sydäntä vihlovasti. Muuan sotamies avasi tietä


tungokseen, iskien miekallaan väkijoukkoon. Se ase oli välkähtänyt
Andréen pään päällä. Hän painoi kätensä ristiin kuin hukkuva, kun
viimeinen laine hyrskähtää hänen päälleen, huusi: "Jumala!" ja
kaatui.
Ken siellä kaatui, oli kuoleman oma.

Mutta oli eräs, joka oli tuntenut tuon kauhean, toivottoman


huudon ja ymmärtänyt, mitä se merkitsi. Gilbert, joka oli viety kauas
Andréesta, oli sitkeällä taistelulla kuitenkin päässyt lähestymään
häntä. Sama aalto, joka oli nielaissut Andréen, oli masentanut hänet
maahan, mutta hän oli noussut jälleen ylös; hän ryntäsi miekkaa
kohti, joka uhkasi Andréeta kuin säännöllisesti hakkaava kone, tarttui
sotamiehen kurkkuun, joka alkoi lyödä, ja kaatoi hänet takaperin.
Sotamiehen vieressä virui valkeaan pukuun puettu nuori nainen.
Gilbert tempaisi hänet syliinsä ja kantoi hänet pois niinkuin olisi ollut
jättiläinen.

Kun hän tunsi sydäntään vasten tuon naisen hennon muodon,


moisen kauneuden, ehkä tosin jo ruumiina, välähtivät hänen
silmänsä ylpeydestä; hän se nyt vallitsi asemaa, hän! Vallitsi
voimallaan ja rohkeudellaan! Kantamuksineen ryntäsi hän erääseen
miesvirtaan, joka oli kyllin voimakas kuohuillaan murtamaan vaikka
kivimuurit paetessaan. Se tungos piti häntä yllä ja kantoi häntä ja
nuorta tyttöä; hän kulki tai paremminkin pyöri toisten päällä
muutaman minuutin. Yhtäkkiä virta pysähtyi kuin murtuen johonkin
esteeseen. Gilbertin jalat koskettivat maahan; silloin vasta tunsi hän
Andréen painon, kohotti päätänsä nähdäkseen, mikä se este oli, ja
huomasi silloin olevansa kolmen askeleen päässä Kalustohuoneen
seinästä. Se kivimöhkäle oli murskannut tuon lihasrykelmän.

Tämän muutamia silmänräpäyksiä kestävän tuskallisen pysäyksen


aikana ennätti hän katsella Andréeta, joka nukkui aivan kuin
kuoleman unta; hänen sydämensä ei sykkinyt enää, hänen silmänsä
olivat ummessa ja kasvot sinertävänväriset niinkuin valkean ruusun,
kun se kuihtuu.
Gilbert luuli hänen kuolleen. Nyt pääsi häneltä vuorostaan huuto,
hän painoi huulensa Andréen vaatteihin, sitten hänen käteensä; ja
viimein, moisen liikkumattomuuden rohkaisemana, peitti hän
suudelmilla nuo kasvot ja paisuneet ja suljetut silmäluomet. Gilbert
punastui, itki, karjui ja koetti valaa sieluaan Andréen rintaan,
kummastellen, etteivät hänen suudelmansa, jotka olisivat saattaneet
kivenkin lämmittää, vaikuttaneet mitään tuohon ruumiiseen.

Yhtäkkiä tunsi Gilbert Andréen sydämen sykkivän kätensä


kohdalla.

"Hän on pelastettu!" huudahti Gilbert, nähden samalla mustan ja


verisen kansanlauman pakenevan ja kuullen onnettomuuden uhrien
sadatukset, huudot, korahdukset ja kuolemanvoihkaisut. — Hän on
pelastettu! Ja minä hänet olen pelastanut!

Gilbert-poloinen seisoi selin kiviseinään ja kasvot siltaan päin eikä


tullut katselleeksi oikealle puolelleen. Sillä puolella, monien vaunujen
edessä, joita ihmislauma kauan oli estänyt liikkumasta, mutta jotka
nyt alkoivat päästä kulkemaan joukon hiukan harvetessa, vaunujen
ja hevosten edessä, jotka pillastuivat ja hurjistuivat pian täyteen
laukkaan, aivan kuin ne ja kuskit olisivat joutuneet päästään
sekaisin, siellä pakeni nyt kaksikymmentätuhatta onnetonta,
ruhjottuina, toisiaan vasten ankarasti puserrettuina, kolhittuina.

Vaiston vetäminä väistyivät hevosten uhkaamat pitkin muurin


viertä, jota vastaan ensimmäiset heistä murskaantuivat.

Tuo väkivyöry veti nyt mukaansa tai murskasi kaikki ne, jotka
luulivat jo pelastuneensa haaksirikosta Kalustohuoneen luo turvaan
päästyään. Uusi putous törmäyksiä, eläviä ja kuolleita ruumiita
tulvahti Gilbertin yli; hän pääsi syvennykseen rautaisen säleportin
kulmaukseen ja mahtui siihen puolittain.

Pakenevien paino sai muurin rytisemään.

Gilbert oli tukehtumaisillaan jo hellittää; mutta hän ponnisti


kuitenkin viimeisetkin voimansa, kietoi Andréen käsivarsiinsa ja
painoi päänsä nuoren tytön rintaan. Olisi luullut, että hän aikoi
tukehuttaa suojeltavansa.

"Hyvästi, hyvästi!" mutisi hän ja paremminkin puri kuin suuteli


hänen vaatteitaan. "Hyvästi!"

Sitten loi hän silmänsä taivaalle ikäänkuin rukoillakseen vielä


viimeisen kerran sieltä apua.

Silloin osui hänen silmiinsä merkillinen näky.

Siellä seisoi mies muurin reunuskoristeen päällä, pitäen oikealla


kädellään kiinni muurissa olevasta renkaasta ja palauttaen vasemmat
käden viittauksilla järjestykseen kokonaista pakenevain armeijaa;
siellä seisoi mies, joka nähdessään tuon raivoisasti hyrskivän meren
jalkainsa juuressa lausui joskus jonkun sanan, teki joskus kädellään
jonkun liikkeen.

Kuullessaan nuo sanat ja huomatessaan hänen viittauksensa näkyi


joku yksilö laumasta pysähtyvän, ponnistavan voimansa,
kamppailevan ja takertuvan paikalleen päästäkseen tuon miehen
luokse. Toiset, jotka jo olivat tulleet hänen ympärilleen, näyttivät
tuntevan uusissa tulijoissa veljiä ja auttoivat nyt näitä veljiään
ponnistautumaan pois joukosta, nostaen ja tukien pystyssä heitä ja
temmaten heitä luokseen. Niin oli jo tuo pieni miesjoukko, joka
taisteli yhdessä aivan kuin siltapilari, joka halkaisee vesivyöryn,
saanut jaetuksi kansanlauman kahtia ja pidetyksi pakenevien vyöryä
aisoissa.

Joka hetki ilmestyi uusia sankareita, joita näytti aivan kuin maasta
nousevan, yhtyäkseen tuohon mieheen nuo kummallisella tavalla
lausutut sanat kuullessaan ja omituiset viittaukset nähdessään.

Viimeisillä voimanponnistuksilla onnistui Gilbertin nousta ylös; hän


tunsi, että pelastus oli olemassa, sillä tuolla vallitsi tyyneys ja mahti.
Palavien ilotulitus-telineitten tuli, kun se leimahti viimeisen kerran
sammuakseen, valaisi tuon miehen kasvoja. Gilbert huudahti
väkisinkin kummastuksesta.

"Oh, minä saan kyllä kuolla", mutisi Gilbert, "kunhan vain hän
elää!
Tuo mies osaa hänet pelastaa."

Ja hänessä purkausi ilmi ylevä uhrautumishalu, ja hän kohotti


kaksin käsin ylös nuorta tyttöä ja huusi:

"Parooni de Balsamo, pelastakaa neiti de Taverney!" Balsamo kuuli


tuon äänen, joka kajahti ihmislauman syvyydestä kuin raamatun
epätoivoiset huudot Herran tykö; hän näki valkean hahmon
kohoavan kaikki nielevästä aallokosta ylös; hänen seurueensa kaatoi
kaikki esteet hänen tieltään, ja hän tarttui nyt Andréehen, jota
Gilbertin piankin auttamattomasti herpoutuvat kädet pitivät ylhäällä,
ja otti hänet syliinsä. Sitten tempasi hänet jälleen mukaansa
kansanlauman liike, jota hän oli nyt lakannut ohjaamasta, ja hän
kantoi Andréeta pois, ennättämättä katsella taakseen.
Gilbert halusi sammaltaa vielä viimeisen sanan, ja ehkäpä hän
tahtoi turvautua itsekin tuon omituisen miehen suojelukseen,
saatuaan häneltä apua Andréelle; mutta hänellä ei ollut enää voimaa
muuhun kuin ainoastaan painaa huulensa nuoren tytön
hervottomana riippuvaan käsivarteen, ja repäistä suonenvetoisesti
kouristuneella kädellään pala neidon vaatteista, tämän uuden
Eurydiken, jonka tuonela riisti jälleen häneltä. [Eurydike oli
kreikkalaisessa jumalaistarustossa nainen, jonka hänen puolisonsa
ihmesoittaja Orfeus sai soittonsa mahdilla pelastetuksi puolitiehen
manalasta, mutta menetti hänet jälleen sinne, kun ei voinut olla
matkalla rakastettuunsa katsomatta, vaikka manalan jumala oli
asettanut sen tuon ylösnousemuksen ehdoksi. Suom.]

Sen viimeisen suudelman, näiden viimeisten jäähyväisten jälkeen


ei nuorukaisella ollut enää muuta tarjolla kuin kuolema; eikä hän
koettanutkaan sitä vastustaa; hän sulki silmänsä ja kaatui
henkiheitoksi nääntyneenä ruumisröykkiölle.
KAHDESKYMMENESSEITSEMÄS
LUKU

Kuolonkenttä

Ankaria myrskyjä seuraa aina tyyni, hirveä, mutta kuitenkin


virvoittava tyyni.

Kello oli noin kaksi aamulla. Suuret, valkeat pilvet kiitivät yli
Pariisin, ja kalpeassa kuutamossa kuvastuivat terävin piirtein
maaperän epätasaisuudet tuolla onnettomuuden kentällä, jonka
kuoppiin pakeneva ihmisvyöry oli syöksynyt ja tuhoutunut.

Kuun valossa, joka välistä peittyi suurten pilvenhuippujen taakse,


näkyi siellä täällä ojain reunoilla ja syvennyksissä ihmisruumiita
vaatteet sekaisin, jäykistynein jäsenin, mustansinertävin kasvoin,
kauhun ilmein taikka rukoukseen ojentunein käsin.

Keskeltä toria nousi ilotulitus-telineitten raunioilta keltainen ja


käryävä savu ja teki sekin osaltaan Ludvig XV:n torin nyt
tappotantereen näköiseksi.
Verisellä ja aukealla kentällä puikkelehti hiljaisia ja nopeasti
liikkuvia haamuja, jotka pysähtyivät, vilkuivat ympärilleen ja
kumartuivat maata kohti: he olivat ruumiinryöstäjiä, jotka saalinhimo
oli houkutellut kuin korpit sinne; kun he eivät olleet voineet varastaa
eläviltä, tulivat he nyt rosvoamaan kuolleilta; mutta useinkin he
näkivät harmikseen kanssaveljiensä ehtineen jo ennen heitä.

Kun he huomasivat pistinmiesten viimeinkin saapuvan ja uhkaavan


itseään, niin he pakenivat pelästyneinä ja tyytymättöminä tiehensä.

Mutta noiden pitkien ruumisjonojen välissä eivät varkaat ja


yövartijat olleet ainoita liikkujoita. Siellä kulki myöskin lyhty kädessä
henkilöitä, joita joku olisi ensi näkemältä saattanut pitää uteliaina
katsojina.

Mutta sangen surkuteltavia katselijoita he olivat; sillä he olivat


huolestuneita ystäviä ja sukulaisia, jotka olivat turhaan odottaneet
veljiään, ystäviään ja rakastajattariaan kotiin ja olivat nyt rientäneet
paikalle kaupungin kaukaisimmistakin kortteleista, sillä kamala
uutinen oli jo tuhoisan rajutuulen voimalla levinnyt yli Pariisin ja
muuttanut huolestuneiden tuskan etsimiseksi.

Tämä näytelmä oli ehkä vielä julmempi katsella kuin itse


onnettomuustapaus.

Kaikki mahdolliset ilmeet näki noilla kalpeilla kasvoilla, kaikki, sen


etsijän tuskasta, joka oli hellästi rakastetun ruumiin löytänyt, niiden
onnetonten kamalaan epäilykseen saakka, jotka eivät löytäneet
mitään, vaan katselivat nyt tutkivin silmin virtaa, joka juoksi
yksitoikkoisesti kohisten torin ohitse. Kerrottiin näet, että paljon
ruumiita oli jo heitetty alas virtaan, kaupungin hallituksen käskystä,
joka oli järjestänyt tulituksen huonosti ja tahtoi nyt salata
varomattomuutensa uhrien kauhistavaa määrää.

Kun he olivat katselleet tätä tuloksetonta näytelmää ja saaneet


tarpeekseen siitä, ja kun he olivat Seinen vedessä nilkkoihin seisten
saaneet sieluunsa yhä lisää öisen, kuohuvan virran tuottamaa
synkeää ahdistusta, niin läksivät he pois lyhty kädessä torilta ja
menivät tarkoin tutkimaan läheisiä katuja. Sinne kerrottiin nimittäin
monien haavoittuneiden laahautuneen saamaan apua tai ainakin
yrittäneen päästäkseen pois kärsimystensä näyttämöltä.

Jos he onnettomuudekseen siellä löysivät kaivatun henkilön,


kadotetun ystävän, ruumiiden joukosta, niin seurasivat sydäntä
särkevää tyrmistystä silloin valitushuudot, ja nyyhkytyksiin, joita
kuului verisellä kentällä joltain paikalta, vastasivat silloin vaikerrukset
toisaalta.

Joskus kajahti kentältä rämähdys, lyhty oli yhtäkkiä pudonnut


maahan ja murskaantunut; joku elävä oli suinpäin heittäytynyt
syleilemään viimeisen kerran vainajaa.

Mutta muitakin ääniä kuului tuolta laajalta kirkkomaalta.

Moni haavoittunut, joka oli kaatuessaan murskannut kätensä,


onneton, jonka rinnan oli miekka puhkaissut tai väkijoukon vyöry
pusertanut sisään, päästi korisevan vaikerruksen tai huokaavan
rukouksen. Ja silloin riensivät hänen luokseen kaikki, jotka toivoivat
löytävänsä sieltä ystävän, mutta he poistuivat sitten jälleen, kun
eivät häntä omakseen tunteneetkaan.

Torin päähän, puutarhan puolelle, oli kuitenkin yleisön


armeliaisuuden avulla saatu aikaan siirrettävä kenttäsairaala. Muuan
nuori lääkäri, jonka ammatin huomasi monista kirurgisista koneista,
joita hänellä oli ympärillään, antoi kuljettaa siellä luokseen miehiä ja
naisia. Mutta sitoessaan heidän haavojaan puhutteli hän heitä
sanoilla, jotka paremmin ilmaisivat vihaa onnettomuuden syytä kuin
sääliä sen uhreja kohtaan.

Hänellä oli kaksi lujaa kantajaa apuvoiminaan tässä verisessä


tarkastuksessaan, ja näille huusi hän lakkaamatta:

"Rahvaan naiset, rahvaan miehet ensin! Ne voi helposti tuntea,


sillä he ovat melkein aina pahemmin haavoittuneita ja varmasti
huonommissa vaatteissa!"

Kuullessaan nämä sanat, jotka lääkäri lausui karmivan


yksitoikkoisella äänellä joka kerta, kun uusi haavoittunut oli sidottu,
jo toisen kerran, kohotti nyt muuan kalpeakasvoinen nuori mies
päätänsä, haeskellessaan lyhty kädessä ruumiiden keskellä.

Hänen otsaansa oli viiltynyt leveä haava ja siitä tihkui


tuontuostakin punaisia veripisaroita. Hänen toinen kätensä oli
pistetty kahden suljetun takinnapin väliin, ja hänen hien peittämillä
kasvoillaan näki syvän ja kuvaamattoman mielenliikutuksen.

Kun hän nyt kuuli toisen kerran, kuten olemme sanoneet, lääkärin
kehoituksen, niin hän nosti päätänsä ja sanoi katsahtaen surullisena
irtileikattuja jäseniä, joita lääkäri näytti silmäilevän melkein
nautinnokseen:

"Mutta, monsieur, miksi te valikoitte tapaturman uhreja?"

"Siksi", vastasi tohtori kohottaen puhuttelun kuullessaan päätänsä,


"siksi, ettei kukaan hoitaisi köyhiä, ellen minä heitä muistaisi, ja siksi,
että rikkaat saavat aina hoitajansa! Laskekaahan hiukan lyhtyänne ja
katselkaa torin kivityksellä makaavia, niin näette itse sata köyhää
jokaista rikasta tai ylimystä vastaan. Tässäkin suuressa
onnettomuudessa on aatelisia ja rikkaita auttanut onni, joka viimein
kyllästyttää itse Jumalaakin, joten he ovat maksaneet ainoastaan
saman veron kuin tavallisestikin, nimittäin yhden tuhannelta."

Nuori mies kohotti lyhtyään, valaisten veristä otsaansa. "Silloin


olen minä tuo yksi", vastasi hän suuttumatta; "sillä minä olen ylimys,
ja olen niinkuin monet muut joutunut onnettomuuden uhriksi
tungoksessa, minä, jota hevonen potkaisi otsaan ja joka taitoin
vasemman käsivarteni pudotessani erääseen kuoppaan. Rikkaat ja
aateliset saavat aina hoitajansa, sanotte? Näette itse, että minua ei
vielä oli sidottu."

"Teillä on hotellinne… teillä on oma lääkärinne… menkää kotiinne,


koska voitte kävellä."

"Minä en pyydä teiltä itselleni apua, monsieur; minä etsin täältä


sisartani, nuorta, kaunista, kuudentoista ikäistä tyttöä, sillä hän on
varmaan tuhoutunut, vaikkei hän olekaan rahvaan nainen. Hänellä
oli yllään valkea puku ja kaulassa nauha, jossa oli risti; ja vaikka
hänellä on sekä koti että lääkäri, niin vastatkaa minulle, säälistä:
oletteko nähnyt häntä, jota etsin, monsieur?"

"Monsieur", vastasi nuori lääkäri kuumeellisen kaunopuheisesti,


mikä seikka osoitti, että nämä hänen nyt lausumansa ajatukset olivat
kauan hautuneet hänen aivoissaan, "monsieur, ihmisyys on minun
ojennusnuorani; sille minä uhraudun, ja jos minä nyt jätän aateliston
kuolinvuoteelleen auttaakseni köyhiä kärsiviä, niin noudatan
ainoastaan oikeaa ihmisyyden lakia, jonka minä olen valinnut
jumalakseni. Kaikki onnettomuudet, jotka ovat tänään tapahtuneet,
johtuvat teistä; ne johtuvat teidän väärinkäytöksistänne, teidän
epäoikeutetuista anastuksistanne, kestäkää nyt itse niiden
seuraukset. En, monsieur, en minä ole nähnyt teidän sisartanne."

Annettuaan puhuttelijalleen vastaukseksi tämän ankaran moitteen


ryhtyi tohtori jälleen leikkaustyöhönsä. Hänen luokseen oli tuotu
köyhä nainen, jolta molemmat jalat olivat murskaantuneet vaunujen
alle.

"Kuulkaa", lisäsi hän, singoten väistyvän Filipin jälkeen nämä


sanat, "kuulkaa: köyhätkö ne julkisissa juhlatilaisuuksissa ryntäävät
vaunuineen toisten päälle ja murskaavat rikkailta jalat?"

Filip oli tuota nuorta aatelia, joka on lahjoittanut meille sellaisetkin


miehet kuin Lafayetten ja Lamethin, ja hän oli montakin kertaa
julistanut aivan samoja periaatteita, jotka saivat hänet nyt tuon
nuoren lääkärin suusta tulleina kauhistumaan; niiden sovittaminen
käytäntöön osui häneen nyt rangaistuksena.

Melkeinpä murtunein sydämin läksi hän lääkärin lähistöltä


jatkaakseen surullista etsiskelyään. Ja tuskissaan kuultiin hänen
hetki sen jälkeen huutavan kyyneleiden murtamalla äänellä:

"Andrée! Andrée!"

Silloin kohtasi hänet ohi mennessään muuan vanha mies


harmaissa vaatteissa ja huopasäärykset jalassa; hän kulki hyvin
kiireesti, nojaten oikealla kädellään sauvaan ja pitäen vasemmassaan
öljytystä paperista tehtyä lyhtyä, jossa paloi talikynttilä.

Kun hän kuuli Filipin valittavan näin, käsitti hän, miten suuresti
nuori mies kärsi, ja mutisi itsekseen: "Voi onnetonta tuotakin!"
Mutta kun vanhus näytti tulleen torille samoissa aikeissa kuin
hänen surkuttelemansakin, jatkoi hän kulkuaan Filipin ohitse.

Mutta sitten virkkoi hän yhtäkkiä, ikäänkuin katuen sitä, että oli
mennyt kärsivän olennon ohitse tarjoamatta hänelle lohdutustaan:
"Monsieur, antakaa anteeksi, että otan osaa suruunne, mutta niiden,
joita on kohdannut sama onnettomuus, täytyy tukea toisiaan
pysyäkseen pystyssä. Sitäpaitsi voi teistä olla minulle hyötyä… te
olette etsinyt täältä kauan, sillä teidän kynttilänne on palanut
melkein loppuun, ja niinpä te tietänette pahimmat paikat torilla."

"Oi, niin, monsieur, minä ne kyllä tiedän."

"No niin, minäkin etsin erästä ihmistä."

"Katselkaa sitten ensin tuolta suurista haudoista. Siellä tapaatte yli


viisikymmentä ruumista."

"Viisikymmentä, hyvä Jumala! Niin paljon uhreja julkisessa


juhlassa!"

"Paljonko, sanotte, monsieur! Minä olen valaissut jo tuhansien


kasvoja löytämättä kuitenkaan sisartani."

"Sisartanne?"

"Niin, hän oli tuolla alhaalla päin. Minä hukkasin hänet, kun seisoin
erään penkin vieressä. Minä löysin kyllä paikan, jossa minut
temmattiin hänestä erilleni, mutta en hänestä itsestään
merkkiäkään. Minä lähden siis uudestaan etsimään häntä bastionin
luota."

"Minnekä päin väentungos pakeni, monsieur?"


"Uusille rakennuksille, Madeleine-kadulle päin."

"Silloin hän mahtaa olla sillä kulmalla?"

"Niin luulisi; ja minä olenkin jo hakenut sieltä; mutta sillä oli


hirvittävä pyörre. Suurin virta syöksyi tosin sille suunnalle, mutta
naisraukka, joka on joutunut suunniltaan, ei tiedä, minne menee,
vaan koettaa paeta milloin millekin taholle."

"Monsieur, tuskinpa on uskottavaa, että hän olisi voinut ponnistella


väen virtaa vastaan. Minä aion hakea noilta kaduilta päin. Tulkaa
kanssani, niin ehkä löydämme yhteisvoimin."

"Ja ketä te etsitte? Poikaanneko?" kysyi Filip varovaisesti. "En,


monsieur, vaan erästä lapsukaista, jonka minä otin melkein
omakseni."

"Ja te laskitte hänet ulos yksin?"

"Ah, se lapsukainen oli jo melkein mies: kahdeksan-,


yhdeksäntoista vuoden ikäinen. Hän oli oma herransa ja tahtoi
lähteä, enkä minä voinut häntä estää. Ja kuka sitäpaitsi olisi
saattanut aavistaa tällaista julmaa onnettomuutta!… Teidän
kynttilänne sammuu."

"Niin, monsieur."

"Tulkaa sitten kanssani, niin valaisen teillekin."

"Kiitoksia, te olette kovin ystävällinen; mutta ehkä olen teille


vaivaksi?"
"Oh, älkää sitä pelätkö, kun minun kerran on itsenikin etsittävä.
Tuo poika-raukka tuli kotiin aina niin säntillisesti", jatkoi vanhus
kulkien kaduille päin. "Mutta eilis-iltana minä aivan kuin aavistin
jotakin onnettomuutta. Minä odotin häntä, ja kello yksitoista sai
vaimoni kuulla juhlissa tapahtuneen onnettomuuden. Minä odotin
pari tuntia ja toivoin yhä, että hän palaisi. Mutta kun häntä ei
kuulunut, niin oli minusta halpamaista mennä makuulle hankkimatta
tietoja hänen kohtalostaan."

"Siis me menemme ensin tuonne talojen luokse?" kysyi


nuorukainen.

"Kyllä, sillä tehän sanoitte, että väkijoukko oli kai rynnännyt sinne
päin, ja varmaan se on sen tehnytkin. Epäilemättäkin on poloinen
nuorukainen hyökännyt sille suunnalle? Hän oli maalaispoika, joka ei
tuntenut edes tämän suuren kaupungin katuja, puhumattakaan
täkäläisten tavoista. Ehkäpä hän oli vasta ensi kerran Ludvig XV:n
torillakin."

"Ah, minunkin siskoni on maaseutulainen, monsieur."

"Voi, miten hirveä näky", sanoi ukko ja käänsi kasvonsa pois


rykelmästä päälletysten sulloutuneita ruumiita.

"Ja kuitenkin on etsittävä juuri tästä", vastasi nuori mies ja ojensi


päättävästi lyhtyään, valaisten tuota ruumiskasaa.

"Oi, minua pöyristää katsoa sinne, sillä kuinka vähäpätöinen


olento olenkin, kauhistaa kuoleman hävitys minua niin, etten voi
luontoani voittaa."
"Ennen tunsin minäkin samanlaista kauhua, mutta tänä yönä olen
käynyt oppini. Katsokaa nyt, tässä on eräs kuuden- tai
kahdeksantoista ikäinen poika, joka on nähtävästi tukehtunut, sillä
hänessä ei ole yhtään haavaa. Onko tämä se teidän etsimänne?"

Vanhus pakotti luontonsa taipumaan ja meni lyhtyineen


katsomaan.

"Ei, monsieur", vastasi hän; "se minun etsimäni on nuorempi,


hänellä on musta tukka ja kalpeat kasvot".

"Niin, valitettavasti ovat he nyt kaikki kalpeita", vastasi Filip.

"Ah, katsokaa", sanoi vanhus, "nyt me olemme Kalustohuoneen


seinämällä. Katsokaa, tuollaisia taistelujen jälkiä. Verta
muurinseinillä, vaaterepaleita aidan rautasäleissä, rikkirevittyjen
vaatteiden kappaleita, jotka liehuvat porttien rautakeihäissä. Ja eihän
edes ole paikkaa, mihin jalkansa astua."

"Täälläpäin, täälläpäin se on varmaan tapahtunut", mutisi Filip.

"Kuinka paljon kurjuutta!"

"Ah, taivaan Jumala!"

"Mikä siellä on?"

"Kappale valkeaa kangasta näkyy noiden ruumiiden alta. Siskollani


oli valkea puku. Antakaa, monsieur, Herran tähden minulle
lyhtyänne!"

Filip oli tosiaan huomannut valkean kangaskappaleen ja oli


tarttunut siihen; hänen täytyi kuitenkin päästää irti, sillä hänellä oli
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookmasss.com

You might also like