-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathFirstProgsCh.xml
More file actions
1314 lines (1143 loc) · 60.3 KB
/
FirstProgsCh.xml
File metadata and controls
1314 lines (1143 loc) · 60.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<chapter id="firstprogs">
<title>Your First Programs</title>
<!--
Copyright 2002 Jonathan Bartlett
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.1 or any later version published by the Free Software
Foundation; with no Invariant Sections, with no Front-Cover Texts,
and with no Back-Cover Texts. A copy of the license is included in fdl.xml
-->
<para>
In this chapter you will learn the process for writing and building
Linux assembly-language programs. In addition, you will learn the
structure of assembly-language programs, and a few assembly-language
commands. As you go through this chapter, you may want to refer also
to <xref linkend="instructionsappendix" /> and
<xref linkend="gdbappendix" />.
</para>
<para>
These programs may overwhelm you at first. However, go through
them with diligence, read them and their explanations as many times
as necessary, and you will have a solid foundation of knowledge to
build on. Please tinker around with the programs as much as you can.
Even if your tinkering does not work, every failure will help you learn.
</para>
<sect1>
<title>Entering in the Program</title>
<para>
Okay, this first program is simple. In fact, it's not
going to do anything but exit! It's short, but it shows
some basics about assembly language and Linux programming.
You need to enter the program in an editor exactly as written,
with the filename <filename>exit.s</filename>. The program follows.
Don't worry about not understanding it. This section only deals with
typing it in and running it. In <xref linkend="assemblyoutline" /> we
will describe how it works.
</para>
<programlisting>
&exit-s;
</programlisting>
<para>
What you have typed in is called the <emphasis>source code<indexterm><primary>source code</primary></indexterm></emphasis>.
Source code is the human-readable form of a program. In order to
transform it into a program that a computer can run, we need to
<emphasis>assemble<indexterm><primary>assemble</primary></indexterm></emphasis> and <emphasis>link<indexterm><primary>link</primary></indexterm></emphasis> it.
</para>
<para>
The first step is to <emphasis>assemble</emphasis> it. Assembling is the
process that transforms what you typed into instructions for the machine.
The machine itself only reads sets of numbers, but humans prefer words.
An <emphasis>assembly language<indexterm><primary>assembly language</primary></indexterm></emphasis> is a more human-readable
form of the instructions a computer understands. Assembling transforms
the human-readable file into a machine-readable one.
To assembly the program type in the command
<programlisting>
as exit.s -o exit.o
</programlisting>
<literal>as</literal><indexterm><primary><literal>as</literal></primary></indexterm> is the command which runs the assembler,
<filename>exit.s</filename> is the source file<indexterm><primary>source file</primary></indexterm>, and
<literal>-o exit.o</literal> tells the assemble to put its output
in the file <filename>exit.o</filename>.
<filename>exit.o</filename> is an <emphasis>object file<indexterm><primary>object file</primary></indexterm></emphasis>. An
object file is code that is in the machine's language, but has not
been completely put together. In most large programs, you will have
several source files, and you will convert
each one into an object file. The <emphasis>linker</emphasis><indexterm><primary>linker</primary></indexterm> is the program that is
responsible for putting the object files together and adding
information to it so that the kernel knows how to load and run it.
In our case, we only have one object file, so the linker is only adding
the information to enable it to run. To <emphasis>link<indexterm><primary>link</primary></indexterm></emphasis> the
file, enter the command
<programlisting>
ld exit.o -o exit
</programlisting>
<literal>ld</literal><indexterm><primary>ld</primary></indexterm> is the command to run the linker,
<filename>exit.o</filename> is the object file we want to link,
and <literal>-o exit</literal> instructs the linker to output
the new program into a file called <filename>exit</filename>.<footnote><para>
If you are new to Linux and <trademark class="registered">UNIX</trademark>, you may not be aware that files don't
have to have extensions. In fact, while <trademark class="registered">Windows</trademark> uses the
<literal>.exe</literal> extension to signify an executable program,
UNIX executables usually have no extension.</para></footnote> If any
of these commands reported errors, you have either mistyped your program
or the command. After
correcting the program, you have to re-run all the commands.
<emphasis>You must always re-assemble and re-link
programs after you modify the source file for the changes to occur in the
program</emphasis>. You can run <filename>exit</filename> by typing in
the command
<programlisting>
./exit
</programlisting>
The <filename>./</filename><indexterm><primary><filename>./</filename></primary></indexterm> is used to tell the computer that the program
isn't in one of the normal program directories, but is the current
directory instead<footnote><para><filename>.</filename> refers
to the current directory in Linux and UNIX systems.</para></footnote>.
You'll notice
when you type this command, the only thing that happens is that you'll go
to the next line. That's because this program does nothing but exit.
However, immediately after you run the program, if you type in
<indexterm><primary>echo</primary></indexterm>
<indexterm><primary>$?</primary></indexterm>
<programlisting>
echo $?
</programlisting>
It will say <literal>0</literal>. What is happening is that every program
when it exits gives Linux an <emphasis>exit status code<indexterm><primary>exit status code</primary></indexterm></emphasis>,
which tells it if everything went all right. If everything was okay, it
returns 0. UNIX programs return numbers other than zero to indicate
failure or other errors, warnings, or statuses. The programmer determines what each number means. You can view this code by typing in
<literal>echo $?</literal>.
In the following section we will look at what each part of the code
does.
</para>
</sect1>
<sect1 id="assemblyoutline">
<title>Outline of an Assembly Language Program</title>
<para>
Take a look at the program we just entered. At the beginning there are
lots of lines that begin with
hashes (<literal>#</literal>). These are <emphasis>comments<indexterm><primary>comments</primary></indexterm></emphasis>.
Comments are not translated by the assembler. They are used only for
the programmer to talk to anyone who looks at the
code in the future. Most programs you write will be modified by others. Get
into the habit of writing comments in your code that will
help them understand both why the program exists and how it works.
Always include the following in your comments:
</para>
<itemizedlist>
<listitem><para>The purpose of the code</para></listitem>
<listitem><para>An overview of the processing involved</para></listitem>
<!-- FIXME - Dominique suggests an extended example of this -->
<listitem><para>Anything strange your program does and why it does
it<footnote><para>You'll find that many programs end up doing things strange
ways. Usually there is a reason for that, but, unfortunately, programmers
never document such things in their comments. So, future programmers either
have to learn the reason the hard way by modifying the code and watching it
break, or just leaving it alone whether it is still needed or not. You
should <emphasis>always</emphasis> document any strange behavior your program
performs. Unfortunately, figuring out what is strange and what is straightforward comes mostly with experience.</para></footnote></para></listitem>
</itemizedlist>
<para>
After the comments, the next line says
<programlisting>
.section .data
</programlisting>
Anything starting with a period isn't directly translated into a machine
instruction. Instead, it's an instruction to the assembler itself. These
are called <emphasis>assembler directives<indexterm><primary>assembler directives</primary></indexterm></emphasis> or <emphasis>pseudo-operations<indexterm><primary>pseudo-operations</primary></indexterm></emphasis> because they are handled by the assembler and are not actually run by the computer.
The <literal>.section</literal><indexterm><primary><literal>.section</literal></primary></indexterm>
command breaks your program up into sections. This command starts the
data section<indexterm><primary>data section</primary></indexterm>,
where you list any memory storage you will need for data.
Our program doesn't use any, so we don't need the section. It's just here
for completeness. Almost every program you write in the future will have data.
</para>
<para>
Right after this you have
<programlisting>
.section .text
</programlisting>
<indexterm><primary><literal>.text</literal></primary></indexterm>
which starts the text section. The text
section<indexterm><primary>text section</primary></indexterm> of a program
is where the program instructions live.
</para>
<para>
The next instruction is
<programlisting>
.globl _start
</programlisting>
This instructs the assembler that <literal>_start</literal><indexterm><primary><literal>_start</literal></primary></indexterm> is important
to remember. <literal>_start</literal> is a <emphasis>symbol<indexterm><primary>symbol</primary></indexterm></emphasis>,
which means that it is going to be replaced by something else either
during assembly or linking. Symbols are generally used to mark locations
of programs or data, so you can refer to them by name instead of by their
location number. Imagine if you had to refer to every memory location
by its address. First of all, it would be very confusing because you would
have to memorize or look up the numeric memory address of every piece of code
or data. In addition, every time you had to insert a piece of data or
code you would have to change all the addresses in your program!
Symbols are used so that the assembler and linker can take care of
keeping track of addresses, and you can concentrate on writing your
program.
</para>
<para>
<literal>.globl</literal><indexterm><primary><literal>.globl</literal></primary></indexterm> means that the assembler shouldn't
discard this symbol after assembly, because the linker will need it.
<literal>_start</literal><indexterm><primary><literal>_start</literal></primary></indexterm> is a special symbol that always needs to be
marked with <literal>.globl</literal> because it marks the location of the
start of the program. <emphasis>Without marking this
location in this way, when the computer loads your program it won't know
where to begin running your program</emphasis>.
</para>
<para>
The next line
<programlisting>
_start:
</programlisting>
<emphasis>defines</emphasis> the value of the <literal>_start</literal><indexterm><primary>_start</primary></indexterm> label. A <emphasis>label<indexterm><primary>labels</primary></indexterm></emphasis>
is a symbol<indexterm><primary>symbol</primary></indexterm> followed by
a colon. Labels define a symbol's value. When the
assembler<indexterm><primary>assembler</primary></indexterm> is assembling
the program, it has to assign each data value and instruction an address.
Labels tell the assembler to make the symbol's value be wherever the
next instruction or data element will be. This way, if the actual
physical location of the data or instruction changes, you don't have to
rewrite any references to it - the symbol automatically gets the new value.
</para>
<para>
Now we get into actual computer instructions. The first such instruction is this:
</para>
<programlisting>
movl $1, %eax
</programlisting>
<para>
When the program runs, this instruction transfers
the number <literal>1</literal> into the &eax; register. In assembly language,
many instructions have <emphasis>operands</emphasis><indexterm><primary>operands</primary></indexterm>. <literal>movl</literal><indexterm><primary>movl</primary></indexterm> has two operands -
the <emphasis>source</emphasis> and the <emphasis>destination</emphasis>. In
this case, the source is the literal number 1, and the destination is the
&eax; register. Operands can be numbers, memory location references, or
registers. Different instructions allow different types of operands. See
<xref linkend="instructionsappendix" /> for more information on which
instructions take which kinds of operands.
</para>
<para>
On most instructions which
have two operands, the first one is the source operand and the second one
is the destination. Note that in these cases, the source operand is not
modified at all. Other instructions of this type are, for example,
<literal>addl</literal><indexterm><primary>addl</primary></indexterm>,
<literal>subl</literal><indexterm><primary>subl</primary></indexterm>, and
<literal>imull</literal><indexterm><primary>imull</primary></indexterm>.
These add/subtract/multiply
the source operand from/to/by the destination operand and and save the result
in the destination operand. Other instructions may have an operand hardcoded
in. <literal>idivl</literal><indexterm><primary>idivl</primary></indexterm>,
for example, requires that the dividend be
in &eax;, and &edx; be zero, and the quotient is then transferred to &eax;
and the remainder to &edx;. However, the divisor can be any register or
memory location.
</para>
<para>
On x86 processors, there are several general-purpose registers<indexterm><primary>general-purpose registers</primary></indexterm><footnote><para>Note that on x86 processors, even the general-purpose registers have some special purposes, or used to before it went 32-bit. However, these are general-purpose registers for most instructions. Each of them has at least one instruction where it is used in a special way. However, for most of them, those instructions aren't covered in this book.</para></footnote>
(all of which can be used with <literal>movl</literal>):
</para>
<itemizedlist>
<listitem><para>&eax-indexed;</para></listitem>
<listitem><para>&ebx-indexed;</para></listitem>
<listitem><para>&ecx-indexed;</para></listitem>
<listitem><para>&edx-indexed;</para></listitem>
<listitem><para>&edi-indexed;</para></listitem>
<listitem><para>&esi-indexed;</para></listitem>
</itemizedlist>
<para>
In addition to these general-purpose registers,
there are also several special-purpose registers<indexterm><primary>special-purpose registers</primary></indexterm>, including:
</para>
<itemizedlist>
<listitem><para>&ebp-indexed;</para></listitem>
<listitem><para>&esp-indexed;</para></listitem>
<listitem><para>&eip-indexed;</para></listitem>
<listitem><para>&eflags-indexed;</para></listitem>
</itemizedlist>
<para>
We'll discuss these later, just be aware that they
exist.<footnote><para>You may be wondering, <emphasis>why do all of these
registers begin with the letter <literal>e</literal>?</emphasis> The
reason is that early generations of x86 processors were 16 bits
rather than 32 bits.
Therefore, the registers were only half the length
they are now. In later generations of x86 processors, the size of the
registers doubled. They kept
the old names to refer to the first half of the register, and added an
<literal>e</literal> to refer to the extended versions of the register.
Usually you will only use the extended versions. Newer models also
offer a 64-bit mode, which doubles the size of these registers yet again
and uses an <literal>r</literal> prefix to indicate the larger registers (i.e.
&rax; is the 64-bit version of &eax;). However, these processors are not
widely used, and are not covered in this book.
</para></footnote> Some of these registers, like &eip-indexed; and &eflags-indexed; can
only be accessed through special instructions. The others can be accessed
using the same instructions as general-purpose registers, but they have
special meanings, special uses, or are simply faster when used in a specific
way.
</para>
<para>
So, the <literal>movl</literal><indexterm><primary><literal>movl</literal></primary></indexterm> instruction moves the number
<literal>1</literal> into <literal>%eax</literal>. The
dollar-sign in front of the one indicates that we want to use
immediate mode addressing<indexterm><primary>immediate mode addressing</primary></indexterm> (refer back to <xref linkend="dataaccessingmethods" />). Without the dollar-sign it would do direct addressing<indexterm><primary>direct addressing mode</primary></indexterm>,
loading whatever number is at address <literal>1</literal>. We want the
actual number <literal>1</literal> loaded in, so we have to use immediate
mode.
</para>
<para>
The reason we are moving the number 1 into &eax; is because we are
preparing to call the Linux Kernel. The
number <literal>1</literal> is the number of the <literal>exit</literal><indexterm><primary><literal>exit</literal></primary></indexterm>
<emphasis>system call</emphasis>
<indexterm><primary>system call</primary></indexterm>.
We will discuss system calls in more depth soon, but basically they are
requests for the operating system's help. Normal programs can't do
everything. Many operations such as calling other programs, dealing with
files, and exiting have to be handled
by the operating system through system calls<indexterm><primary>system calls</primary></indexterm>.
When you make a system call, which we will do shortly, the system
call number has to be loaded into &eax-indexed;
(for a complete listing of system calls and their numbers,
see <xref linkend="syscallap" />).
Depending on the system call, other registers may have
to have values in them as well. Note that system calls is not the only use or
even the main use of registers. It is just the one we are dealing with in
this first program. Later programs will use registers for regular
computation.
</para>
<para>
The operating system, however, usually needs more information than just which
call to make. For example, when dealing with files, the operating system
needs to know which file you are dealing with, what data you want to write,
and other
details. The extra details, called <emphasis>parameters<indexterm><primary>parameters</primary></indexterm></emphasis>
are stored in other registers. In the case of the <literal>exit</literal> system call,
the operating system requires a status code be loaded in &ebx-indexed;. This
value is then returned to the system. This is the value you retrieved
when you typed <literal>echo $?</literal>. So, we load &ebx; with
<literal>0</literal> by typing the following:
</para>
<programlisting>
movl $0, %ebx
</programlisting>
<para>
Now, loading
registers<indexterm><primary>registers</primary></indexterm> with these
numbers doesn't do anything itself.
Registers are used for all sorts of things besides system calls. They
are where all program logic such as addition, subtraction, and comparisons
take place. Linux simply requires that certain registers be loaded with
certain parameter values before making a system call. &eax-indexed; is
always required to be loaded with the system call number.
For the other registers, however, each system call has different requirements.
In the <literal>exit<indexterm><primary>exit</primary></indexterm></literal>
system call, &ebx-indexed; is required to be loaded with the exit status<indexterm><primary>exit status code</primary></indexterm>.
We will discuss different system calls as they are needed. For a list of
common system calls and what is required to be in each register, see <xref linkend="syscallap" />
</para>
<para>
The next instruction is the "magic" one. It looks like this:
</para>
<programlisting>
int $0x80
</programlisting>
<para>
The <literal>int<indexterm><primary>int</primary></indexterm></literal> stands for
<emphasis>interrupt<indexterm><primary>interrupts</primary></indexterm></emphasis>. The
<literal>0x80<indexterm><primary>0x80</primary></indexterm></literal> is the interrupt
number to use.<footnote>
<para>You
may be wondering why it's <literal>0x80</literal> instead of just
<literal>80</literal>. The reason is that the number is written in
hexadecimal<indexterm><primary>hexadecimal</primary></indexterm>. In hexadecimal, a single digit can hold 16 values instead
of the normal 10. This is done by utilizing the letters
<literal>a</literal> through <literal>f</literal>
in addition to the regular digits. <literal>a</literal> represents 10,
<literal>b</literal> represents 11, and so on. 0x10 represents the number
16, and so on. This will be discussed more in depth later, but just be
aware that numbers starting with <literal>0x</literal> are in hexadecimal.
Tacking on an <literal>H</literal> at the end is also sometimes used instead, but
we won't do that in this book. For more information about this, see <xref linkend="countingchapter" />
</para></footnote>
An <emphasis>interrupt<indexterm><primary>interrupts</primary></indexterm></emphasis> interrupts the normal program flow, and
transfers control from our program to Linux<indexterm><primary>Linux</primary></indexterm> so that it will do a system
call.<footnote><para>Actually, the
interrupt transfers control to whoever set up an <emphasis>interrupt
handler</emphasis> for the interrupt number. In the case of Linux,
all of them are set to be handled by the Linux kernel.</para></footnote>.
You can think of it as like signaling Batman(or
Larry-Boy<indexterm><primary>Larry-Boy</primary></indexterm><footnote><para>If you don't watch Veggie Tales, you should. Start with Dave and the Giant Pickle.</para></footnote>, if you prefer).
You need something done,
you send the signal, and then he comes to the rescue. You don't care how
he does his work - it's more or less magic - and when he's done you're
back in control. In this case, all we're doing is asking Linux to
terminate the program, in which case we won't be back in control.
If we didn't signal the interrupt, then no system call would have been
performed.
</para>
<note>
<title>Quick System Call Review</title>
<para>
To recap - Operating System features are accessed through
system calls<indexterm><primary>system calls</primary></indexterm>. These are invoked by setting up the registers
in a special way and issuing the instruction <literal>int $0x80</literal>.
Linux knows which system call we want to access by what we stored
in the &eax-indexed; register. Each system call has other requirements
as to what needs to be stored in the other registers. System call
number 1 is the <literal>exit</literal> system call, which requires
the status code<indexterm><primary>status code</primary></indexterm>
to be placed in &ebx-indexed;.
</para>
</note>
<para>
Now that you've assembled, linked, run, and examined the program, you
should make some basic edits. Do things like change the number
that is loaded into <literal>%ebx</literal>, and watch it come out
at the end with <literal>echo $?<indexterm><primary>echo</primary></indexterm><indexterm><primary>$?</primary></indexterm></literal>. Don't forget
to assemble and link it again before running it.
Add some comments. Don't worry, the worse thing that would happen is that the
program won't assemble or link, or will freeze your screen. That's just
part of learning!
</para>
</sect1>
<sect1>
<title>Planning the Program</title>
<para>
In our next program we will try to find the maximum of a list of numbers.
Computers are very detail-oriented, so in order to write the program we
will have to have planned out a number of details. These details include:
</para>
<itemizedlist>
<listitem><para>Where will the original list of numbers be stored?</para></listitem>
<listitem><para>What procedure will we need to follow to find the maximum number?</para></listitem>
<listitem><para>How much storage do we need to carry out that procedure?</para></listitem>
<listitem><para>Will all of the storage fit into registers, or do we need to use some memory as well?</para></listitem>
</itemizedlist>
<para>
You might not think that something as simple as finding the maximum number from
a list would take much planning. You can usually tell people to find the
maximum number, and they can do so with little trouble. However, our minds
are used to putting together complex tasks automatically. Computers need
to be instructed through the process. In addition, we can usually hold any
number of things in our mind without much trouble. We usually don't even
realize we are doing it. For example, if you scan a list of numbers for the
maximum, you will probably keep in mind both the highest number you've seen
so far, and where you are in the list. While your mind does this
automatically, with computers you have to explicitly set up storage for holding
the current position on the list and the current maximum number. You also
have other problems such as how to know when to stop. When reading a piece
of paper, you can stop when you run out of numbers. However, the computer
only contains numbers, so it has no idea when it has reached the last of
<emphasis>your</emphasis> numbers.
</para>
<para>
In computers, you have to plan every step of the way. So, let's do
a little planning. First of all, just for reference, let's name the
address where the list of numbers starts as <literal>data_items</literal>.
Let's say that the last number in the list will be a zero, so we know where
to stop. We also need a value to hold the current position in the list,
a value to hold the current list element being examined, and the current
highest value on the list. Let's assign each of these a register:
</para>
<itemizedlist>
<listitem><para>&edi; will hold the current position in the list.</para></listitem>
<listitem><para>&ebx; will hold the current highest value in the list.</para></listitem>
<listitem><para>&eax; will hold the current element being examined.</para></listitem>
</itemizedlist>
<para>
When we begin the program and look at the first item in the list, since we
haven't seen any other items, that item will automatically be the current
largest element in the list. Also, we will set the current position in the
list to be zero - the first element. From then, we will follow the following
steps:
</para>
<orderedlist>
<listitem><para>Check the current list element (&eax;) to see if it's zero (the terminating element).</para></listitem>
<listitem><para>If it is zero, exit.</para></listitem>
<listitem><para>Increase the current position (&edi;).</para></listitem>
<listitem><para>Load the next value in the list into the current value register (&eax;). What addressing mode might we use here? Why?</para></listitem>
<listitem><para>Compare the current value (&eax;) with the current highest value (&ebx;).</para></listitem>
<listitem><para>If the current value is greater than the current highest value, replace the current highest value with the current value.</para></listitem>
<listitem><para>Repeat.</para></listitem>
</orderedlist>
<para>
That is the procedure. Many times in that procedure I made use of the word
"if". These places are where decisions are to be made. You see, the computer
doesn't follow the exact same sequence of instructions every time. Depending
on which "if"s are correct, the computer may follow a different set of
instructions. The second time through, it might not have the highest value.
In that case, it will skip step 6, but come back to step 7. In every
case except the last one, it will skip step 2. In more complicated programs,
the skipping around increases dramatically.
</para>
<para>
These "if"s are a class of instructions called <emphasis>flow control<indexterm><primary>flow control</primary></indexterm></emphasis> instructions, because they tell the computer which steps
to follow and which paths to take. In the previous program, we did not
have any flow control instructions, as there was only one possible path to
take - exit. This program is much more dynamic in that it is directed by
data. Depending on what data it receives, it will follow different instruction
paths.
</para>
<para>
In this program, this will be accomplished by two different
instructions, the conditional
jump<indexterm><primary>conditional jump</primary></indexterm> and the
unconditional jump<indexterm><primary>unconditional jump</primary></indexterm>.
The conditional
jump changes paths based on the results of a previous comparison or
calculation. The unconditional jump just goes directly to a different path
no matter what. The unconditional jump may seem useless, but it is very
necessary since all of the instructions will be laid out on a line. If a
path needs to converge back to the main path, it will have to do this by
an unconditional jump. We will see more of both of these jumps in the
next section.
</para>
<para>
Another use of flow control<indexterm><primary>flow control</primary></indexterm> is in implementing loops<indexterm><primary>loops</primary></indexterm>. A loop is a piece
of program code that is meant to be repeated. In our example, the first
part of the program (setting the current position to 0 and loading the
current highest value with the current value) was only done once, so it
wasn't a loop. However, the next part is repeated over and over again
for every number in the list. It is only left when we have come to the
last element, indicated by a zero. This is called a <emphasis>loop</emphasis>
because it occurs over and over again. It is implemented by doing
unconditional jumps to the beginning of the loop at the end of the loop, which
causes it to start over. However, you have to always remember to have a
conditional jump to exit the loop somewhere, or the loop will continue
forever! This condition is called an <emphasis>infinite loop<indexterm><primary>infinite loop</primary></indexterm></emphasis>.
If we accidentally left out step 1, 2, or 3, the loop (and our program)
would never end.
</para>
<para>
In the next section, we will implement this program that we have planned.
Program planning sounds complicated - and it is, to some degree. When you
first start programming, it's often hard to convert our normal thought
process into a procedure that the computer can understand. We often forget
the number of "temporary storage locations" that our minds are using to
process problems. As you read and write programs, however, this will
eventually become very natural to you. Just have patience.
</para>
</sect1>
<sect1 id="maximum">
<title>Finding a Maximum Value</title>
<para>
Enter the following program as <filename>maximum.s</filename>:
</para>
<programlisting>
&maximum-s;
</programlisting>
<para>
Now, assemble and link it with these commands:
</para>
<programlisting>
as maximum.s -o maximum.o
ld maximum.o -o maximum
</programlisting>
<para>
Now run it, and check its status.
</para>
<programlisting>
./maximum
echo $?
</programlisting>
<para>
You'll notice it returns the value <literal>222</literal>. Let's take
a look at the program and what it does. If you look in the comments, you'll
see that the program finds the maximum of a set of numbers (aren't comments
wonderful!). You may also notice that in this program we actually have
something in the data section<indexterm><primary>data section</primary></indexterm>.
These lines are the data section:
</para>
<programlisting>
data_items: #These are the data items
.long 3,67,34,222,45,75,54,34,44,33,22,11,66,0
</programlisting>
<para>
Lets look at this. <literal>data_items</literal> is a
label<indexterm><primary>labels</primary></indexterm> that
refers to the location that follows it. Then, there is a directive
that starts with <literal>.long<indexterm><primary>.long</primary></indexterm></literal>. That causes the assembler
to reserve memory for the list of numbers that follow it.
<literal>data_items</literal> refers to the location of the first one.
Because <literal>data_items</literal> is a label, any time in our program
where we need to refer to this address we can use the
<literal>data_items</literal> symbol, and the assembler will substitute
it with the address where the numbers start during assembly. For example,
the instruction <literal>movl data_items, %eax</literal> would move the
value 3 into &eax;.
There are several different types of memory locations other than <literal>.long<indexterm><primary>.long</primary></indexterm></literal>
that can be reserved. The main ones are as follows:
</para>
<variablelist>
<varlistentry>
<term><literal>.byte<indexterm><primary>.byte</primary></indexterm></literal></term>
<listitem><para>
Bytes take up one storage location for each number. They are limited
to numbers between 0 and 255.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>.int<indexterm><primary>.int</primary></indexterm></literal></term>
<listitem><para>
Ints (which differ from the <literal>int</literal> instruction) take up
two storage locations for each number. These are limitted to numbers
between 0 and 65535.<footnote><para>Note that no numbers in assembly language
(or any other computer language I've seen) have commas embedded in them. So,
always write numbers like <literal>65535</literal>, and never like
<literal>65,535</literal>.</para></footnote>
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>.long<indexterm><primary>.long</primary></indexterm></literal></term>
<listitem><para>
Longs take up four storage locations. This is the same amount of
space the registers use, which is why they are used in this program.
They can hold numbers between 0 and 4294967295.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>.ascii<indexterm><primary>.ascii</primary></indexterm></literal></term>
<listitem><para>
The <literal>.ascii</literal> directive is to enter in characters
into memory. Characters each take up one storage location (they are
converted into bytes internally). So, if you gave the directive
<literal>.ascii "Hello there\0"</literal>, the assembler would reserve 12 storage
locations (bytes). The first byte contains the numeric code for
<literal>H</literal>, the second byte contains the numeric code for
<literal>e</literal>, and so forth. The last character is represented
by <literal>\0</literal><indexterm><primary>\0</primary></indexterm>,
and it is the terminating character (it will
never display, it just tells other parts of the program that that's the
end of the characters). Letters and numbers that start with a backslash
represent characters that are not typeable on the keyboard or easily viewable
on the screen.
For example, <literal>\n</literal><indexterm><primary>\n</primary></indexterm> refers to the "newline"<indexterm><primary>newline</primary></indexterm> character which causes the computer to start output on the next line and <literal>\t</literal>
<indexterm><primary>\t</primary></indexterm> refers to the "tab"<indexterm><primary>tab</primary></indexterm> character. All of the letters in an <literal>.ascii</literal> directive should be in quotes.
</para></listitem>
</varlistentry>
</variablelist>
<para>
In our example, the assembler reserves 14 <literal>.long</literal>s,
one right after another. Since each long takes up 4 bytes, that means
that the whole list takes up 56 bytes. These are the numbers we will
be searching through to find the maximum. <literal>data_items</literal>
is used by the assembler to refer to the address of the first of these values.
</para>
<para>
Take note that the last data item in the list is a zero. I decided
to use a zero to tell my program that
it has hit the end of the list. I could have done this other ways. I
could have had the size of the list hard-coded into the program. Also,
I could have put the length of the list as the first item, or in a separate
location. I also could have made a symbol which marked the last location
of the list items. No matter how I do it, I must have some method of
determining the end of the list. The computer knows nothing -
it can only do what it is told. It's not going to stop processing unless I give
it some sort of signal. Otherwise it would continue processing past the end
of the list into the data that follows it, and even to locations where
we haven't put any data.
</para>
<para>
Notice that we don't have a
<literal>.globl<indexterm><primary>.globl</primary></indexterm></literal> declaration for <literal>data_items</literal>.
This is because we only refer to these locations within the program. No
other file or program needs to know where they are located. This is
in contrast to the <literal>_start<indexterm><primary>_start</primary></indexterm></literal> symbol, which Linux
needs to know where it is so that it knows where to begin
the program's execution. It's not an error to write
<literal>.globl data_items</literal>, it's just not necessary.
Anyway, play around with this line and add your own numbers. Even
though they are <literal>.long</literal>, the program will produce
strange results if any number is greater than 255, because that's the
largest allowed
exit status<indexterm><primary>exit status code</primary></indexterm>.
Also notice that if you move the 0 to
earlier in the list, the rest get ignored.
<emphasis>Remember that any time
you change the source file, you have to re-assemble and re-link
your program. Do this now and see the results</emphasis>.
</para>
<para>
All right, we've played with the data a little bit. Now let's look
at the code. In the comments you will notice that we've marked
some <emphasis>variables<indexterm><primary>variables</primary></indexterm></emphasis>
that we plan to use. A variable
is a dedicated storage location used for a specific purpose, usually
given a distinct name by the programmer. We talked about these in the
previous section, but didn't give them a name. In this program, we have
several variables:
</para>
<itemizedlist>
<listitem><para>a variable for the current maximum number found</para></listitem>
<listitem><para>a variable for which number of the list we are currently examining, called the index</para></listitem>
<listitem><para>a variable holding the current number being examined</para></listitem>
</itemizedlist>
<para>
In this case,we have few enough variables that we can hold them all in
registers. In larger programs, you have to put them in memory, and then move
them to registers<indexterm><primary>registers</primary></indexterm> when you are ready to use them. We will discuss how
to do that later. When people start out programming, they usually
underestimate the number of variables they will need. People are not used
to having to think through every detail of a process, and therefore leave out
needed variables in their first programming attempts.
</para>
<para>
In this program, we are using &ebx; as the location
of the largest item we've found. &edi; is used as the
<emphasis>index<indexterm><primary>index</primary></indexterm></emphasis> to the current data item we're looking at.
Now, let's talk about what an index is. When we read the information
from <literal>data_items</literal>,
we will start with the first one (data item number 0), then go to the second
one (data item number 1), then the third (data item number 2), and so on.
The data item number is the <emphasis>index<indexterm><primary>index</primary></indexterm></emphasis> of
<literal>data_items</literal>. You'll notice that the first instruction
we give to the computer is:
</para>
<programlisting>
movl $0, %edi
</programlisting>
<para>
Since we are using <literal>%edi</literal> as our index, and we want to start
looking at the first item, we load <literal>%edi</literal> with 0. Now,
the next instruction is tricky, but crucial to what we're doing. It says:
</para>
<programlisting>
movl data_items(,%edi,4), %eax
</programlisting>
<indexterm><primary>movl</primary></indexterm>
<para>
Now to understand this line, you need to keep several things in mind:
</para>
<itemizedlist>
<listitem><para><literal>data_items</literal> is the location number of the start of our number list.</para></listitem>
<listitem><para>Each number is stored across 4 storage locations (because we declared it using <literal>.long</literal>)</para></listitem>
<listitem><para><literal>%edi</literal> is holding 0 at this point</para></listitem>
</itemizedlist>
<para>
So, basically what this line does is say, "start at the beginning of
data_items, and take the first item number (because <literal>%edi</literal>
is 0), and remember that each number takes up four storage locations."
Then it stores that number in <literal>%eax</literal>. This is how you write
indexed addressing mode<indexterm><primary>indexed addressing mode</primary></indexterm>
instructions in assembly language. The instruction in a general form
is this:
</para>
<programlisting>
movl BEGINNINGADDRESS(,%INDEXREGISTER,WORDSIZE)
</programlisting>
<para>
In our case <literal>data_items</literal> was our beginning address, &edi; was our
index register<indexterm><primary>index register</primary></indexterm>, and 4 was our word size. This topic is discussed further in <xref linkend="movaddrmodes" />.
</para>
<para>
If you look at the numbers in <literal>data_items</literal>, you will see that the number
3 is now in &eax;. If &edi; was set
to 1, the number 67 would be in &eax;, and if it
was set to 2, the number 34 would be in &eax;, and so
forth. Very strange things would happen if we used a number other than
4 as the size of our storage locations.<footnote><para>The instruction
doesn't really use 4 for the size of the storage locations, although
looking at it that way works for our purposes now. It's actually what's
called a <emphasis>multiplier<indexterm><primary>multiplier</primary></indexterm></emphasis>. basically, the way it works is that
you start at the location specified by <literal>data_items</literal>, then
you add <literal>%edi</literal>*4 storage locations, and retrieve the number
there. Usually, you use the size of the numbers as your multiplier, but in
some circumstances you'll want to do other things.</para></footnote>
The way you write this is very awkward, but if you know what each piece does,
it's not too difficult. For more information about this, see
<xref linkend="movaddrmodes" />
</para>
<para>
Let's look at the next line:
</para>
<programlisting>
movl %eax, %ebx
</programlisting>
<para>
We have the first item to look at stored in <literal>%eax</literal>. Since
it is the first item, we know it's the biggest one we've looked at.
We store it in <literal>%ebx</literal>, since that's where we are
keeping the largest number found. Also, even though <literal>movl<indexterm><primary>movl</primary></indexterm></literal>
stands for <emphasis>move</emphasis>, it actually copies the value, so
<literal>%eax</literal> and <literal>%ebx</literal> both contain the
starting value.<footnote><para>Also, the <literal>l</literal> in
<literal>movl<indexterm><primary>movl</primary></indexterm></literal> stands for <emphasis>move long</emphasis> since
we are moving a value that takes up four storage locations.</para></footnote>
</para>
<para>
Now we move into a <emphasis>loop<indexterm><primary>loop</primary></indexterm></emphasis>.
A loop is a segment of your program that might run more than once. We have marked the starting
location of the loop in the symbol <literal>start_loop</literal>. The
reason we are doing a loop is because we don't know how many
data items we have to process, but the procedure will be the same no
matter how many there are. We don't want to have to rewrite our program for
every list length possible. In fact, we don't even want to have to write out
code for a comparison for every list item. Therefore, we have a single
section of code (a loop) that we execute over and over again for every
element in <literal>data_items</literal>.
</para>
<para>
In the previous section, we outlined what this loop needed to do. Let's
review:
</para>
<itemizedlist>
<listitem><para>Check to see if the current value being looked at is zero. If so, that means we are at the end of our data and should exit the loop.</para></listitem>
<listitem><para>We have to load the next value of our list.</para></listitem>
<listitem><para>We have to see if the next value is bigger than our current biggest value.</para></listitem>
<listitem><para>If it is, we have to copy it to the location we are holding the largest value in.</para></listitem>
<listitem><para>Now we need to go back to the beginning of the loop.</para></listitem>
</itemizedlist>
<para>
Okay, so now lets go to the code. We have the beginning of the loop
marked with <literal>start_loop</literal>. That is so we know where to go back
to at the end of our loop. Then we have these instructions:
</para>
<programlisting>
cmpl $0, %eax
je loop_exit
</programlisting>
<para>
The <literal>cmpl<indexterm><primary>cmpl</primary></indexterm></literal> instruction compares the two values. Here,
we are comparing the number 0 to the number stored in &eax;
This compare instruction also affects a register not mentioned here, the
&eflags-indexed; register. This is also known as the status register<indexterm><primary>status register</primary></indexterm>,
and has many uses which we will discuss later. Just be aware that the
result of the comparison is stored in the status register. The next line
is a flow control<indexterm><primary>flow control</primary></indexterm> instruction which says to
<emphasis>jump</emphasis> to the <literal>loop_exit</literal> location
if the values that were just compared are equal (that's what the
<literal>e</literal>
of <literal>je</literal> means). It uses the status register to hold the
value of
the last comparison. We used <literal>je</literal>, but there are many jump
statements that you can use:
</para>
<variablelist>
<varlistentry>
<term><literal>je</literal></term>
<listitem><para>
Jump if the values were equal
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>jg</literal></term>
<listitem><para>
Jump if the second value was greater than the first
value<footnote><para>notice that the comparison is to see if the
<emphasis>second</emphasis> value is greater than the first. I
would have thought it the other way around. You will find a lot of
things like this when learning programming. It occurs because different
things make sense to different people. Anyway, you'll just have to
memorize such things and go on.</para></footnote>
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>jge</literal></term>
<listitem><para>
Jump if the second value was greater than or equal to the first value
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>jl</literal></term>
<listitem><para>
Jump if the second value was less than the first value
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>jle</literal></term>
<listitem><para>
Jump if the second value was less than or equal to the first value
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>jmp</literal></term>
<listitem><para>
Jump no matter what. This does not need to be preceeded by a
comparison.
</para></listitem>
</varlistentry>
</variablelist>
<para>
The complete list is documented in <xref linkend="instructionsappendix" />.
In this case, we are jumping if &eax; holds the value
of zero. If so, we are done and we go to
<literal>loop_exit</literal>.<footnote><para>The names of these symbols
can be anything you want them to be, as long as they only contain letters
and the underscore character(<literal>_</literal>). The only one that
is forced is <literal>_start<indexterm><primary>_start</primary></indexterm></literal>, and possibly others that you
declare with <literal>.globl<indexterm><primary>.globl</primary></indexterm></literal>. However, if it is a symbol you