0% found this document useful (0 votes)
237 views257 pages

Cos2621 TL102 2023 PDF

This tutorial letter outlines the 12 study units that make up the Computer Organization and Architecture module, provides an overview of the theoretical and practical components, and notes that the prescribed textbook is Computer Organization & Architecture by Stallings. Key topics covered include computer components, number systems, Boolean algebra, instruction sets, and RISC computers. Students are advised to supplement the study guide with the textbook in order to fully understand the theoretical concepts.

Uploaded by

Ian Wallace
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
0% found this document useful (0 votes)
237 views257 pages

Cos2621 TL102 2023 PDF

This tutorial letter outlines the 12 study units that make up the Computer Organization and Architecture module, provides an overview of the theoretical and practical components, and notes that the prescribed textbook is Computer Organization & Architecture by Stallings. Key topics covered include computer components, number systems, Boolean algebra, instruction sets, and RISC computers. Students are advised to supplement the study guide with the textbook in order to fully understand the theoretical concepts.

Uploaded by

Ian Wallace
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/ 257

COS2621/102/3/2023

Tutorial Letter 102/3/2023

Computer Organisation and Architecture


COS2621

Year 2023

School of Computing

This tutorial letter contains important information


about your module.

BARCODE

Open Rubric
COS2621/102/3/2023

Dear Student

1 Study unit 0

It is important for any serious computer scientist/ICT professional to have a deep


knowledge of the way in which a computer program is executed. It does not matter
whether the program was written in a high-level language like C++, Visual Basic or
Java, or whether it was written in assembly language. Eventually, all program code
has to be translated into machine code before it can be executed. In this module, we
study the underlying organisation and operation of a modern digital computer. Our
aim is to explain what goes on at the lower levels inside a computer, and we do this
by examining some of the hardware and software components of a computer
system.

We would like to instill the following attitude: "Look, I don't know this particular
brand of computer, but since I know that almost all computers operate in basically
the same way, give me one or two weeks and the set of relevant manuals and I will
be quite at home with this computer".

Theoretical and practical components 

The theoretical part of the syllabus for COS2621 is covered in the prescribed book.
This tutorial letter (often referred to as the guide, or the study guide) contains all the
study material you will need for the practical component of this module.
COS2621/102/3/2023

The prescribed book for this module is:

Stallings, W. 2016. Computer Organization & Architecture: Designing for


performance. 10th edition. Prentice Hall.

Note that we are not going to study the chapters in Stallings in the order in which
they are presented. We have to introduce the assembly language concepts as
soon as possible in order for you to master the practical work. A short summary of
the concepts that we study in this module follows:

Study unit 1: Computer Organisation and Computer Architecture, Boolean


algebra and number systems (This study unit supplements chapters 1, 9 and 11
as well as appendix B of Stallings.)

Study unit 2: The evolution of computers has been characterized by increasing


processor speed, decreasing component size, increasing memory size, and
increasing I/O capacity and speed.

One factor responsible for the great increase in processor speed is the shrinking size
of microprocessor components; this reduces the distance between components and
hence increases speed. (This study unit supplements chapter 2 of Stallings.)

Study unit 3: An instruction cycle consists of an instruction fetch, followed by zero or

more operand fetches, followed by zero or more operand stores, followed by an


interrupt check (if interrupts are enabled).

The major computer system components (processor, main memory, I/O modules)
need to be interconnected in order to exchange data and control signals. The most
popular means of interconnection is the use of a shared system bus consisting of
multiple lines. In contemporary systems, there typically is a hierarchy of buses to
improve performance. (This study unit supplements chapter 3 of Stallings.)

Study unit 4: Processors make use of instruction pipelining to speed up execution.


In essence, pipelining involves breaking up the instruction cycle into a number of
separate stages that occur in sequence, such as fetch instruction, decode
3
COS2621/102/3/2023

instruction, determine operand addresses, fetch operands, execute instruction, and


write operand result. Instructions move through these stages, as on an assembly
line, so that in principle, each stage can be working on a different instruction at the
same time. The occurrence of branches and dependencies between instructions
complicates the design and use of pipelines. (This study unit supplements chapter
14 of Stallings).

Study unit 5: Computer Arithmetic (This study unit supplements Chapter 10 of

Stallings.)

Study unit 6: Instruction sets: Characteristics and Functions (This study unit
supplements chapter 12 and appendix B, as well as appendix O (online) of Stallings.)

Study unit 7: Instruction sets: Addressing mode and formats (This study
unit supplements chapter 13 of Stallings.)

Study unit 8: Cache memory (This study unit supplements Chapter 4 of Stallings.)

Study unit 9: Internal memory (This study unit supplements chapter 5 of Stallings).

Study unit 10: External memory (This study unit supplements chapter 6 of Stallings.)

Study unit 11: Input/ Output (This study unit supplements chapter 7 of Stallings.)

Study unit 12: RISC computers (This study unit supplements chapter 15 of Stallings.)

DEBUG: DEBUG, that is available as part of DOS within the Windows environment,
creates an environment in which relatively small assembly language programs can be
COS2621/102/3/2023

developed, run and debugged with ease. It can also be used to debug larger programs.
This is a very powerful debugging tool which you should learn to use effectively.

Important!

This study guide supplements the prescribed book. You cannot study this module
using only

this study guide. All the theoretical study material is contained in Stallings.

5
COS2621/102/3/2023

Study unit 1
Organisation and architecture

This study unit supplements the preface, chapters 1, 9 and 11, as well as Appendix B of

Stallings. The most important components of a computer are introduced. A short overview
f t hit t i i d d i i f fi t k

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

• identify the different components a computer system consists of

• describe the most important function of each component

• list the main components of the CPU

• describe the difference between computer organisation and computer architecture

• discuss the advantages of studying assembly language programming, computer


organisation and architecture

• be able to convert values between the binary, decimal and hexadecimal numbers
systems

• use Boolean algebra to simplify Boolean expressions


COS2621/102/3/2023

Stallings

Study chapter 1; chapter 9; chapter 11: section 11.1.

Read preface, chapter 11: sections 11.2 to 11.7; Appendix B.

7
COS2621/102/3/2023

Chapter 1
Introduction

Chapter 1 introduces the concept of the computer as a hierarchical system. A computer can
be viewed as a structure of components and its function described in terms of the collective
function of its cooperating components.

Each component, in turn, can be described in terms of its internal structure and function. The
major levels of this hierarchical view are introduced. The remainder of the book is organized,
top down, using these levels.

Stallings: Study section 1.2.

1.1 Basic building blocks 

Stallings: Study chapter 9. When working on the low level of computer systems, we
frequently use the binary and hexadecimal number systems. It is important that you
feel comfortable with both these number systems.

Stallings: Study chapter 11.1. The concepts discussed in chapter 11 form the basic
building blocks of computer components.

1.2 Boolean algebra 

Activity 1-1

Simplify the following expressions using Boolean algebra. Name the identity used in
every step.

a) [(CD)′ + A]′+ A + CD + AB
COS2621/102/3/2023

b) xyz + x′y + xyz′

c) ABC' + CB' + AC + AB'

Solution 

a) [(CD)′ + A]′ + A + CD + AB

= ((CD)′)′ A′ + A + CD + AB De Morgan

= CDA′ + A + CD + AB Double negative

= CD(A′+1) + A(1+B) Associative & distributive

= CD + A Null (Zero): A'+1=1

b) xyz + x′y + xyz′

= xy(z+z′) + x′y Distributive

= xy + x′y Complement

= y(x+x′) Distributive

=y Complement

c) ABC' + CB' + AC + AB'

= ABC' + CB' + AC(B+1) + AB' Null: B+1=1

= ABC' + (ABC + AC) + AB' + CB' Distributive & associative

= AB(C' + C) + AC + AB' + CB' Associative & distributive

= AB + AC + AB' + CB' Complement

= A(B + B') + AC + CB' Associative

= A + AC + CB' Complement
= A(C+1) + CB' Distributive

= A + CB' Null: C+1=1

9
COS2621/102/3/2023

Stallings: Read sections 11.2 to 11.7. This is not for examination purposes but you
will encounter the concepts explained here in other sections of the study material.

It is important that you understand the functions of multiplexers and decoders


respectively.

1.3 Summary 

The scope of the study material in the text book is discussed in the preface. It is
advisable to read this through to get an overview of the study material covered in this
module. Remember that we will not study all the chapters in Stallings and will not
work through the text book in the order in which the chapters are presented.

1.4 Key questions 

Make sure that you are able to answer the relevant review questions given at the end
of each of the chapters covered in this unit!

----oooOooo----
COS2621/102/3/2023

4 Study unit 2
5 Computer performance

This study unit supplements chapter 2 of Stallings. The history of the different computer

generations is discussed, with the emphasis on the technological advances that led to the
emergence of each new computer generation. Some of the factors that have to be taken
into account when designing a computer system are discussed, and we look at the

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

• discuss important issues that have to be resolved when designing computer


systems

• describe the evolution of the Intel x86 family of microprocessors

• describe what is meant by an embedded system

• discuss the impact of new approaches involving multicore machines, MICs and
GPUs

11
COS2621/102/3/2023

Stallings

Study sections 2.1 to 2.5.

(Study the sections from these chapters as indicated in this study unit. Read the rest of
COS2621/102/3/2023

2.1 Designing for performance 

The evolution of the different computer generations is discussed with a short explanation of
the technology that gave rise to the emergence of each new generation. We also look at
important factors that have to be taken into account in the design of a computer system.

The practical work for COS2621 should be done on an Intel x86 computer. Note that all
modern Intel CPUs are x64 but are x86 backwards compatible. Pay particular attention to
all the discussions in the prescribed book that deal with the Intel x86 family of
microprocessors. It is very important to note that there may be significant differences at a
low level between different families of microprocessors. For this reason, we do not restrict
our attention to the Intel x86, but also look at the organisation of the ARM processor.

2.2 Computer evolution 

Stallings: read section 2.1. Pay particular attention to the figures. If you understand these
diagrams it will be easier to understand the corresponding study material.

Stallings: study the following in section 2.1: 

 The general structure of the IAS computer that is based on the von Neuman design
 Moore’s law and the consequences thereof
 The set of characteristics that distinguish a particular family of computers

2.3 Design principles 

Stallings: study section 2.2.

13
COS2621/102/3/2023

Hardware and software are generally logically equivalent. This is a simple but very
important concept. Hardware and software are frequently capable of performing the same
function. Compare performing the same logical function in Boolean arithmetic (section
11.1), and using hardware (sections 11.2 and 11.3). In computer design, we often have to
decide which functions to implement in hardware and which in software.

Both methods have pros and cons that should be considered. Hardware offers speed but
not flexibility, whereas software offers flexibility but less speed. This phenomenon, known
as a "trade-off", is often relevant in this module. Remember that it is a design decision.
Except for the reasons mentioned here, there is no special reason why it is advisable to
implement a specific operation in hardware rather than in software or vice versa, but cost
often plays a role in the trade-off between the different approaches.

2.4 Multicore processors, MICs and  GPUs 

Stallings, study section 2.3

This section discusses the cutting-edge developments as far as computer architecture is


concerned.

2.5 The Intel x86 family and the ARM  processor 

Stallings: study section 2.4 and read section 2.5.

It is not necessary to memorise the differences between all the members of the Intel x86
family. However, take note of the main differences especially among the Pentium 1, 2, 3,
and 4 and the Pentium Multicore CPUs.

Read the section on embedded systems and the ARM CPU. Note that the ARM CPU is
also used in mobile phones and tablets! You need not memorise the differences between
the various members of the ARM family of microprocessors.

We study the design principles of RISC and CISC architectures respectively in study unit
12.

2.6 Summary 
Stallings, section 2.8 Make sure that you understand all the key terms, and that you
know what the acronyms listed there represent.
COS2621/102/3/2023

2.7 Key Questions 

Work through the review questions at the end of the chapter.

----oooOooo----

6 Notes

15
COS2621/102/3/2023

7 Study unit 3
8 Computer functions and interconnections

This study unit supplements chapter 3 of Stallings. The instruction cycle is described. We
also look at different ways in which computer components can be connected.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

• explain the instruction cycle

• explain what an interrupt is and what happens when an interrupt occurs

• describe the different classes of interrupt

• discuss different ways in which multiple interrupts can be handled

explain why interconnections between different computer components are


necessary

• explain what a computer bus is

• describe different bus structures and multiple-bus hierarchies

• distinguish different types of bus

• discuss bus arbitration and bus width


explain the difference between synchronous and asynchronous timing

• describe what PCI is
COS2621/102/3/2023

Stallings

Study sections 3.1 - 3.4.

Read sections 3.5 and 3.6.

You must study the sections indicated in this study unit.

17
COS2621/102/3/2023

3.1 Introduction 

Chapter 3 of Stallings gives a general introduction to the structures that are used to
connect different computer components. The instruction cycle is explained as well as the
handling of different types of interrupt. We look at ways in which buses are used for
interconnection.

3.2 Computer components 

Stallings: study section 3.1. Stallings discusses the components that a computer
system consists of and explains why connections between these components are
necessary.

3.3 Computer function 

Stallings: study section 3.2. The instruction cycle is explained. We look at interrupts
and how and why an interrupt cycle is introduced into the instruction cycle. In this way we
can test for an interrupt after the execution of every instruction. Stallings also discusses
ways in which multiple interrupts could be handled.

3.4 Interconnections 

Stallings: study section 3.3. The structure of the different interconnections in a


computer system is discussed in this section.

3.5 Bus interconnection, point‐to point interconnect and PCI  buses 


COS2621/102/3/2023

Stallings: study sections 3.4. The general structure of a bus, as well as the way in

which multiple buses can be used to optimise performance, are discussed. Different types
of bus are described and we look at bus arbitration and bus width. The concepts of
synchronous/asynchronous timing between communicating components are considered.

Stallings: read sections 3.5 and 3.6. PCI, as well as the newer PCI Express buses are
frequently used in microcomputers. It is not necessary to pay attention to detail.

3.6 Summary 

Make sure that you understand the key terms and that you know what the acronyms

listed in this section represent.

3.7 Key Questions. 

Work through the review questions at the end of the chapter.

----oooOooo----

9 Notes

19
COS2621/102/3/2023

10 Study unit 4
11 Processor Structure and Function

This study unit supplements chapter 14 of Stallings. The most important components of

the CPU are described and processor register organisation is discussed. We look in detail

at the register organisation of the Intel x86 and the ARM processors respectively. The

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

• describe the internal structure of the CPU in general

• describe the register organisation of the Intel x86

• describe what an interrupt is and what happens when an interrupt occurs

• describe different types of interrupt

• describe what an exception is and what happens when an exception occurs

• describe the instruction cycle for indirect addressing

• understand the principles of pipelining


COS2621/102/3/2023

Stallings

Study sections 14.1, 14.2, 14.3 and 14.5.

Read sections 14.4 and 14.6.

21
COS2621/102/3/2023

4.1 Introduction 

We look at CPU organisation using the instruction cycle to explain the need for the
different components comprising the CPU. The basic principles of instruction pipelining
are discussed without going into too much detail. The organisation of the Intel x86 family
is studied in detail since we need this knowledge to write assembly language programs
for this family of microprocessors. Finally, we look at the organization of the ARM
processor.

4.2 Processor organisation 

Stallings, study section 14.1. Once you understand the instruction cycle, the
organisation of the CPU will become clear.

Stallings, revise section 1.2.

4.3 Register organisation & the instruction cycle  revisited 

Stallings, study section 14.2. The purpose of a variety of sets of CPU registers is
explained. We study the register organisation of the Intel x86 family. We give more detail
regarding the register set of the Intel x86 relevant to our practical work in section 4.5 of
this study unit.

Stallings, study section 14.3. Indirect addressing on the Intel x86 is discussed in study
unit 7 of this study guide.

4.4 Instruction pipelining 
COS2621/102/3/2023

Stallings, read section 14.4.

4.5 The x86 processor 

Stallings, study section 14.5. Stallings does not give much detail regarding the
assembly language of the Intel x86 family. As you will be doing your practical work in x86
Assembly Language, we provide you with additional notes regarding the architecture and
assembly language of the Intel x86 family. It is important to realise that this particular
assembly language is but one of many different assembly languages. Each family of
machines has its own assembly language.

To avoid having to buy an expensive second text book for the practical work, we include a
description of the most important assembly language instructions in this section as well as
in the next two study units. It might take a while before you will be able to see how the
different concepts fit together, but working through some examples is always the easiest
way to learn a new programming language.

! Look at some examples in Appendix C

4.5.1 The register set of the x86  family 

Registers are special storage components inside the CPU (Central Processing Unit). The
registers common to all the Intel x86 processors are 16 bits in size and can be classified
as follows:

23
COS2621/102/3/2023

General-purpose registers: AX, BX, CX, DX

Segment registers: CS, DS, SS, ES

Index registers: SI, DI

Pointers: BP, IP, SP

Flags register: Nine of the bits (flags) in this register are of some
importance to us.

Most of the processors in the Intel family have extended general-purpose registers,
extended index registers and extended pointer registers that are 32 bits in size. These are
written as above with a prefix E. The extended versions of the general-purpose registers
are called EAX, EBX, ECX and EDX. Current Intel processors have 64-bit registers.

For your practical work, we are concerned only with the 16‐bit registers  of  the Integer 
Unit common to all the Intel chips. In this section, we therefore restrict our attention to 
these ones. 

4.5.1.1 General-purpose registers

The general-purpose registers are used for data movement and for arithmetic. Each of
these registers can be addressed as either one 16-bit (2 bytes) register or as two 8-bit (1
byte) registers. The leftmost byte is the high portion and the rightmost byte is the low
portion.

For example, AH and AL are the high and low portions of the AX register:
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

16-bit AX register

8-bit AH register 8-bit AL register

Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
COS2621/102/3/2023

Note that the bits are numbered from right to left on the Intel machines.

AX register: The AX register is known as the primary accumulator. Some text books
refer to the AX register as the accumulator. The AX register is mainly used for operations
involving data movement, input/output and arithmetic. Some instructions such as MUL
and DIV assume that AX contains the multiplicand and dividend respectively.

BX register: The BX register is the only general-purpose register that can be used as a
pointer to extend addressing. It is therefore referred to as the base register. It is also used
for arithmetic. We will have another look at extended addressing when we discuss
addressing modes.

CX register: The CX register is known as the count register since it is used, for example,
to control the number of times a loop is to be executed, or the number of shifts that should
be performed. It can also be used for arithmetic.

DX register: Some input/output operations such as IN and OUT use the DX register.
Multiply and divide operations involving 16-bit registers make use of the combination of
DX and AX. The DX register is thus known as the data register.

4.5.1.2 Segments and segment registers 

Memory consists of a collection of segments each of which is 64K bytes long. A segment
is an area in memory that begins on a paragraph boundary, in other words on an address
that is a multiple of 1610 (10h). This means that one segment could start at address
00000, another at address 00010h, another at address 00020h, et cetera. This also
means that segments can overlap. Note that the starting address of a segment always
ends with a 0 when written as a hexadecimal number. For this reason, the designers
decided that it would be unnecessary to store the last digit, which is always 0, in the
segment register, so the address of a segment is always stored without the rightmost 0.
For example, the address of the segment starting at 18A30h will be stored as 18A3h.
Some text books show the rightmost 0 in square brackets, for example 18A3[0]h.

25
COS2621/102/3/2023

A segment may be located anywhere in memory (as long as it starts on a paragraph


boundary) and may be as small as 1 paragraph (10h bytes) and as large as 64K bytes in
length. However, it requires only as much space as is required for execution by the
program that uses it.

A program written in x86 assembly language is divided into three primary segments,
namely:

- The code segment

- The data segment

- The stack segment.

The code segment (pointed to by the CS register) contains the machine instructions of
the program. All references to memory locations that contain instructions of a program are
relative to the start of a segment specified by the contents of the CS register. A byte of
memory is referenced by the segment that contains it, followed by an offset from the
beginning of that segment. The offset is indicated by the IP register (instruction pointer).

The notation used is segment:offset. The offset is between 0000h and FFFFh (FFFFh =
64K-1).

The IP register always contains the offset (relative to the start of the code segment) of the
next instruction to be executed, so CS:IP forms the actual 20-bit address of the next
instruction to be executed. The actual 20-bit address is also referred to as the effective
address.

Suppose CS contains BCEFh and IP contains 123h. The actual 20-bit hexadecimal
address referred to by BCEF:0123 is calculated as follows:

Segment address BCEF0 Remember the

(CS): rightmost 0
in
0123
address
Offset (IP):
Add the two addresses
t th
COS2621/102/3/2023

Activity 4.1

Calculate the actual 20-bit address referred to in the following examples:

(i) CS = 020A; IP = 1BCD

(ii) 74D6:0100

(iii) 3DA3:311

Solution 

(i) Segment address (CS): 020A0 Addresses in


hexadecimal
Offset (IP): 1BCD

Actual address (CS:IP): 03C6D

(ii) Segment address (CS): 74D60 Remember to add the


right-most 0
Offset (IP): 0100

Actual address (CS:IP): 74E60

(iii) Segment address (CS): 3DA30

Offset (IP): 311

Actual address (CS:IP): 3DD41

We do not always refer to addresses in the notation given above. When a memory
location in a specific segment is addressed from within that segment, we use only the
offset part.

Example: If a program is stored in some code segment, only the offset is used to refer to
other memory locations within this segment. Thus, JMP 123h will cause a jump to offset
123h within the memory segment where the program is loaded.
27
COS2621/102/3/2023

The IP register cannot be referenced directly in a program by a programmer. Its value can
be changed when using DEBUG during the debugging and testing phase of a program.
(Refer to Appendix A.3.2.) However, the value of IP can be changed indirectly by the
programmer by using JMP (jump) and conditional branch instructions.

You need not worry about the CS register. During normal execution of a program,
instructions are automatically fetched from memory. You do not need to concern yourself

with the values of CS and IP or any of the values of the segment registers.

The data segment (pointed to by the DS register) contains the variables, constants and
work areas of a program.

The actual address where data is fetched from memory when an instruction such as
MOV AL,[120h] is executed, is not the physical memory location 120h but the memory
location 120h relative to the contents of the DS register.

Suppose the DS register contains 0600h. The actual 20-bit location from which the byte of
data will be moved can be calculated as follows:

Data segment 06000 Remember the rightmost 0


address:
0120 Addresses in hexadecimal
Address given:
06120
Actual address:

You need not worry about the DS register either. The operating system sets the DS
register to a suitable value when a program is loaded. In actual fact, the operating system
decides where in memory both the program and the data should be located. One can set
the DS register to insist on using specific locations for data, but we will not use this
functionality in COS2621.

The stack segment (pointed to by the SS register) contains the program stack. The stack
is an area in memory that is used to save data and addresses that need to be temporarily
stored while the program is executing.
COS2621/102/3/2023

We demonstrate the use of the SS register in study unit 6 of this study guide.

The extra segment register (ES) is used during the manipulation of sequences of
characters by some string operations. The ES register is associated with the DI register
which is discussed in a later section. We will not work with the ES register in COS2621.

4.5.1.3 Index registers 

SI and DI: Index registers contain the offset of memory positions relative to the start of
the segment. SI (Source Index) and DI (Destination Index) are used to indicate source
and destination addresses when strings of characters are written to and read from
memory. SI usually contains an offset value from the DS register, but it can address any
memory position. The source string is pointed to by the SI register. The DI register is the
destination for string movement instructions. It usually contains an offset from the ES
register but can address any memory position.

The use of the SI and DI registers will be demonstrated in examples in study unit 6 of this
study guide.

4.5.1.4 Pointer and stack registers 

The stack is a special area in memory that is used for the temporary storage of
addresses and data. The stack is located in the stack segment. You may think of the
stack as a number of boxes stacked on top of each other. The last one to be added on top
(pushed onto the stack) is also the first one to be removed (popped) from the stack.

The Stack Pointer (SP) register holds the address (in the stack) of the last element to be
added to (pushed onto) the stack. In other words:

29
COS2621/102/3/2023

We can say that the SP register contains the offset from the beginning of the stack to the
top of the stack. So SS:SP contains the address of the top-of-the-stack.

The Base Pointer (BP) register contains an offset from the SS register. Normally, the
only word in the stack that is accessed is the one on top of the stack. However, the BP
register can also keep an offset in the stack segment and can be used in procedure calls,
especially when parameters are passed to subroutines. SS:BP contains the address of
the current word being processed in the stack. More information about the stack and the
BP and SP registers will be given in study unit 6 of this study guide.

4.5.1.5 The flags register 

Stallings: figure 14.22. The EFLAGS register is used as a flags register. Nine of the 32
bits of this register are common to all x86 processors. The other bits are not important for
COS2621 and we will not consider them in this section.

Each time an arithmetic instruction is executed, certain flags will be set either to 1 or 0 to
indicate the outcome of the operation. Not all instructions affect the flags and not all flags
are affected by instructions that do have an effect on flags. The way in which the
individual flags are affected by an instruction is shown in Appendix E where the
instructions comprising the x86 instruction set are listed.

The following bits in the flags register represent the individual flags we are interested in:
COS2621/102/3/2023

Bit Flag Contents or Description Set to 1

0 CF: Carry Flag 1) The carry from the high-order 1) If addition produced a
(leftmost) bit following an arithmetic carry or if a
operation subtraction produced a
borrow
2) The result of a
CoMPare instruction 2) When the data elements
compared are not equal
3)The bit which has been shifted or 3) If the bit which has been
rotated out of a register or memory shifted or rotated out of a
location register or memory location
is equal to 1

2 PF: Parity Flag Mainly used when transmitting data If the result of an operation
has an even number of 1-
bits
4 AF: Auxiliary Similar to CF, except that it indicates See CF
Flag the presence or absence of a carry
or overflow based on a 4-bit numeric
representation in bits 0, 1, 2, 3. It is
useful for operations on ‘packed
decimal’ (BCD) numbers
6 ZF: Zero Flag Indicates whether or not the result of Set to 1 for a zero result!
an arithmetic or compare operation
is equal to zero
7 SF: Sign Flag Contains the resulting sign after an Set to 1 if result is negative
arithmetic operation
8 TF: Trap Flag By setting TF to 1, the Intel
processors can be forced to operate
in single-step mode
9 IF: Interrupt Flag Allows interruption of normal
operations from peripherals and
other sources

31
COS2621/102/3/2023

10 DF: Direction If DF is set to 0, the special string


Flag manipulation instructions increment
the appropriate index registers and
proceed forward through memory. If
DF is set to 1 the index registers are
decremented and progress
is backward through
11 OF: Overflow 1) Overflow occurs if an arithmetic 1) Set to 1 if the carry into
flag operation on signed numbers gives and the carry out of the
a result that is out of range highest-order bit differ

2 ) Used during shift operations 2) Set to 1 if the sign bit of


an operand changes
during a shift operation,
otherwise set to 0
3) Used during division 3) Set to 1 if a division
operation produces a
quotient that is too big for
the register which has to
contain the result

The flags that concern us most are SF, ZF, CF and OF. Of these, the CF and OF are the
more complicated ones.

Carry flag: signed numbers (twos complement)]

For signed data, the range of signed numbers that can be stored in n bits is

-2 n-1  n  2 n-1 -1.

Thus, the ranges of signed numbers are as follows:

in an 8-bit register: ( -128)10  n  (127)10, and

in a 16-bit register: (-32 768)10  n  (32 767)10.

The following table summarises the conditions under which overflow occurs:
COS2621/102/3/2023

Carry into sign bit Carry out of sign Overflow


bit

No No No

No Yes Yes

Yes No Yes

Yes Yes No

Confusing as it may seem, the contents of a data field mean whatever you intend it to
mean. As long as the process writing the data and the one reading it interpret it the same
way, there is no problem. Apart from signed and unsigned integers we may also store
floating-point numbers or character data in ASCII, EBCDIC, UNICODE or any other
character code.

Let us look at a few examples to illustrate how the OF and CF are used to indicate
overflow for signed as well as unsigned numbers.

Note: The results in columns 2 and 3 are the equivalent of the binary numbers in column
1 interpreted as unsigned binary numbers and signed numbers in twos complement
representation, respectively. Look at the second addition for example:

(1000 0100)2 is the twos complement representation of (-124)10 in column 3 which differs
from (119 + 13 = 132)10 in column 2.

33
COS2621/102/3/2023

Examples: 

Signed and unsigned numbers in 8-bit registers

Binary Unsigned Signed Overflow flag Carry flag


numbers
numbers

1111 1001 249 -7 Carry into sign bit (0) is CF = 0


equal to the carry out
+0000 0011 +3 + 3 of sign bit (0).
1111 1100 252 -4 Thus OF = 0
Valid Valid

0111 0111 119 119 Carry into sign bit (1) is CF = 0


not equal to the carry
+0000 1101 + 13 + 13 out of sign bit (0).
1000 0100 132 -124 Thus OF = 1
Valid Invalid

1111 1100 252 -4 Carry into sign bit (1) is CF = 1


equal to the carry out
+ 0000 0101 + 5 + 5 of sign bit (1).
(1) 0000 0001 1 1 Thus OF = 0
Invalid Valid

1111 0110 246 - 10 Carry into sign bit (0) is CF = 1


- 119 not equal to the carry
+ 1000 1001 + 137 +127 out of sign bit (1).
(1) 0111 1111 127 Invalid Thus OF = 1
Invalid

Signed numbers in 16-bit registers


COS2621/102/3/2023

Binary number in twos Decimal Comments


complement representation (equivalent of
number in
column 1)

0100 1000 0011 1111 18 495 Overflow occurs since there


is a carry into the sign bit but
+ 0110 0100 0101 1010 + 25 690 no carry out.
1010 1100 1001 1001 - 21 351 Thus: OF = 1
Invalid

1110 1001 1111 1111 - 5 633 Overflow occurs since there


is a carry out of the sign bit
+ 1000 1100 1111 0000 -29 456 but no carry into the sign bit.
(1) 0111 0110 1110 1111 30 447 Thus: OF = 1
Invalid

1111 1111 1110 0111 -25 No overflow. The carry into


the sign bit (1) is equal to the
+ 1111 1111 1111 0110 -10 carry out (1) of the sign bit.
(1)1111 1111 1101 1101 -35 Thus: OF = 0
This is the twos complement Valid
representation of -35. Remember
that we discard the carry out of
the sign bit.

35
COS2621/102/3/2023

4.5.2 Reverse Byte Order in  Memory 

The x86 machines store bytes in reverse byte order in memory. Consider the number
0015h. Two bytes are required to store this number. The 16-bit number 0015h consists of
a high-order (most significant) byte 00h, and a low-order (least significant) byte 15h.
Suppose we want to store 0015h in memory from location 101h onwards. In memory the
low-order byte, 15h, will be stored in the low-order position 101h, and the high-order byte,
00h, will be stored in the high-order position 102h. Thus 0015h is stored in memory as
follows:

Memory position 101h 102h

Hexadecimal 15h 00h


number

The CPU expects numeric data in memory (not registers) to be stored in reverse byte
order and processes it accordingly. You must be aware of this peculiarity otherwise you
may get confused when you examine the contents of memory locations. The CPU
reverses the bytes again if data is loaded into registers from memory locations.

Activity 4.2

Execute the following two instructions and inspect the contents of memory locations 200h
and 201h:

mov ax,1234h

mov [200h],ax
COS2621/102/3/2023

Contents of memory location 200h: 34h

Contents of memory location 201h: 12h

We will learn more about byte-ordering conventions in the next study unit.

4.5.3 Interrupts 

An interrupt causes the interruption of normal program execution. In other words, the flow
of control is interrupted. Interrupts can be caused by hardware or software. Interrupts are
handled either by DOS or by BIOS. The DOS routines are part of the particular operating
system that is loaded, whereas most of the BIOS routines are hardwired onto the
motherboard.

Software interrupts: A software interrupt is generated by an INT instruction and is a call


to a specific interrupt routine (the address is found in the interrupt vector table) to request
a service from the operating system. Interrupts can be invoked by using the INT instruc-
tion. Software interrupts can also be referred to as system calls

Hardware interrupts: A hardware interrupt, sometimes called an external interrupt, is


generated by a special chip, called the Interrupt Controller. This chip requests the CPU
to suspend the current program temporarily and to process the interrupt. Example:
pressing a key on the keyboard causes the CPU to suspend the current program
temporarily and to execute the BIOS routine that reads the character from the keyboard
input port and stores it in a memory buffer.

The steps taken when a hardware interrupt occurs are similar to those when a software
interrupt occurs. The hardware interrupt is handled by the interrupt handler that

associates a specific vector in the interrupt vector table with that particular hardware
interrupt. Control is passed to the relevant interrupt service routine in the same way as
is done when a software interrupt occurs.

37
COS2621/102/3/2023

4.5.3.1 The interrupt vector table

Stallings, table 14.3. A part of memory is reserved for the interrupt vector table. Each
of the interrupts available on the Intel chips has a 4-byte (2-word) entry in the interrupt
vector table to accommodate an offset and a code segment address. For interrupt type 0,
the instruction offset is stored in the word at address 0, and the code segment address is
stored in the word at address 2. For interrupt type 1, the offset is stored in the word at
address 4, and the code segment address is stored in the word at address 6. In general,
for interrupt type n, the instruction offset is stored in the word at address 4*n, and the
code segment address is stored in the word at address (4 * n) + 2.

Interrupt Address Contents of address

number

Code segment
(4 * n)+2
address

n 4*n Offset address

. .

. .

. .

Code segment
6 address

1 4 Offset address

Code segment
2
address
0 0 Offset address

Each code segment and offset points to its own interrupt handler (also called interrupt
service routine). This is a block of code similar to a procedure, which must be executed
if that particular interrupt occurs.
COS2621/102/3/2023

4.5.3.2 The INT instruction ‐ software  interrupts 

The above description of how interrupts function might seem complicated but fortunately,
the operating system does most of the work. The programmer needs only to place one or
more values in registers and to invoke the relevant interrupt instruction. The instruction
used for interrupts by the Intel family is the INT instruction. Since (256)10 (i.e. 0 to FFh)
different types of interrupt are allowed, we must specify which one is required.

The format of the INT instruction is as follows: int number (number is an integer from
0 to FFh).

The interrupt instructions which we will use frequently are INT 20h and INT 21h. INT 20h
causes the program to terminate and control to be transferred back to DOS. INT 21h
allows operations such as reading a character from the keyboard, printing a character on
a printer, and displaying a character on the screen. We call the specific action to be
performed a function or service. The AH register is used to specify which function is
required. Example (refer to INT 21h in Appendix D):

mov ah,2 ; Select function 2, display character


mov dl,48h ; 48h is ASCII for 'H'
int 21h ; Display the character in DL on the screen
int 20h ; Return to DOS (terminate program)

More examples of the use of the INT instruction are included in Appendix C. The common
software interrupts, i.e. INT 10h, INT 17h and INT 21h, are listed in Appendix D.

4.5.4 The Assembly Process, Nasm and DEBUG 

There are a number of routes we can follow when creating an assembly language program
on the Intel x86. Two of the possibilities are shown in Figure 4.1. We can use NASM to
39
COS2621/102/3/2023

assemble the source code. We can then use DEBUG, which is available under DOS, to
trace through the program. DEBUG can also be used to assemble small programs but it
has limitations.

ALGORITHM

Source Program

DEBUG EDITOR

*.ASM file
DEBUG input

DEBUG NASM

*. COM file

(executable prog ram)

Test by using DEBUG Test by running the program

Figure 4.1: The assembly process 
COS2621/102/3/2023

4.6 The ARM processor

Stallings, read section 14.6. It should become clear why we need to study the register
organisation of the machine we are working with at a low level if we compare the register
organisation of the ARM processor to that of the Intel x86.

4.7 Summary 

Stallings, section 14.8. Make sure that you understand the processor organisation of the
Intel x86 and that you know the meaning of all the key words listed in this section.

4.8 Key Questions 

Work through the review questions at the end of the chapter.

----oooOooo----

12 Notes

41
COS2621/102/3/2023

13 Study unit 5
Computer arithmetic
14

This study unit supplements chapter 10 of Stallings. The way in which integer and floating-

point numbers are represented in a computer is explained. We look at instructions that can
be used on the Intel x86 to perform arithmetic and logical, as well as bit-manipulation

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

• explain how integers can be represented in a computer

• use assembly language to perform arithmetic and logical operations on integers on


the Intel x86

• use assembly language to perform bit manipulation operations on the Intel x86

• explain how floating-point numbers are stored in a computer

• show how a floating-point number is stored in a computer using a given floating-point


format

• calculate the value of a floating-point number that is stored in a computer given the
relevant floating-point format
COS2621/102/3/2023

Stallings

Study sections 10.1, 10.2, parts of section 10.3, and section 10.4.

Read parts of section 10.3.

5.1 Introduction 

Stallings: study section 10.1 The way in which integers and floating-point numbers are
stored in a computer is discussed. We look at some instructions that can be used on the
Intel x86 to do arithmetic and logical operations.

5.2 Integer representation 

Stallings: study section 10.2. There are a number of different ways in which integers can
be represented on a computer. Stallings only discusses sign-magnitude and twos
complement representation. Remember that integers can also be referred to as fixed-point
numbers.

5.3 Integer arithmetic 
Stallings: study the sections on negation, addition and subtraction in section 10.3.

Read the rest of section 10.3.

This section of the study guide contains examples that illustrate the use of arithmetic and bit-
43
COS2621/102/3/2023

manipulation instructions. You can use either DEBUG or NASM to assemble these
instructions to see what happens.

Remember that DEBUG treats all numbers as hexadecimal whereas NASM treats
numbers as decimal unless otherwise indicated.

5.3.1 Integer multiply and divide (IMUL and  IDIV) 

Activity 5.1
Consider the following arithmetic operations:

(a) a*b (both a and b are 8 bits long.)

(b) a/b (both a and b are 8 bits long and b  0.)

(c) a*b (both a and b are 16 bits long.)

(d) a/b (both a and b are 16 bits long and b  0.)

Assume that a = 16h = (22)10 and b = 07h = 710.

Very important: Note that the first operand, i.e. a, must first be loaded into AL/AX in order
to execute an IMUL/IDIV on 8/16 bits.

(a) a*b (both a and b are 8 bits long) use IMUL (integer multiplication)

mov al,16h ; a to AL for 8-bit multiplication


COS2621/102/3/2023

mov bl,07h ; b to BL

imul bl ; 16-bit product (9Ah = 15410) in AX

(b) a/b (both a and b are 8 bits long) use IDIV (integer division)

mov ah,0 ; Clear AH


mov al,16h ; Dividend in AX (AH:AL)
mov dl,07h ; Divisor in DL
idiv dl ; Integer division, 8-bit quotient(310)in AL,
; 8-bit remainder (=1) in AH

(c) a*b (both a and b are 16 bits long) use IMUL

mov ax,16h ; a to AX for 16-bit multiplication


mov bx,07h ; b to BX
imul bx ; 32-bit product in DX:AX

(d) a/b (both a and b are 16 bits long) use IDIV

mov dx,0 ; Clear DX


mov ax,16h ; Dividend in DX:AX
mov bx,07h ; Divisor in BX
idiv bx ; 16-bit quotient in AX,
; 16-bit remainder in DX

45
COS2621/102/3/2023

Things to remember: 

DEBUG assumes all values to be in hexadecimal.

NASM assumes all values to be in decimal unless otherwise indicated.

With IMUL, MUL, IDIV and DIV, the first operand is assumed to be in AL or AX. Be careful:
IMUL AL,BL will not be flagged as a syntax error but will give incorrect results because BL
will be ignored: the contents of AL will be multiplied with the contents of the first operand
as specified in the instruction, namely AL, i.e. IMUL AL,BL is interpreted as IMUL AL.

DX:AX is used for 16-bit multiplication operations giving a 32-bit result stored in the
combination of the DX and AX registers.

With 16-bit division operations the dividend is assumed to be in the 32-bit register DX:AX.
The quotient is stored in AX and the remainder is stored in DX.

5.3.2 Data movement (MOV) 

We will write a simple assembly language program to illustrate the movement of data
between registers and memory.

Activity 5.2

Evaluate a = a*b + c*d*e 

Use memory location temp as a temporary storage area. Assume that a, b, c, d and e are
8-bit integers and that they are stored in memory positions a, b, c, d and e
respectively. Note the following:
COS2621/102/3/2023

(i) The x86 assembly language does not allow direct data movement from one memory
position to another. Such data movement must occur via one of the registers.

(ii) The first operand is the destination operand, e.g. MOV AX,BX will result in the contents
of BX being stored in the AX register.

(iii) DEBUG and NASM do not allow the specification of a memory position in a
multiplication operation. Thus imul [a] is illegal in both DEBUG and NASM. However, it
is legal in some commercially available assemblers such as MASM.

AX = a*b: 

mov al,[a] ; Move the contents of ‘a’ to AL

mov bl,[b] ; Move the contents of ‘b’ to BL

imul bl ; Multiply the contents of AL with the contents of BL

; Product in AX

; Note that AL is the first operand by default


; (for 8-bit multiplication) and must not be
specified

AX = c*d 

mov [temp],ax ; Store the contents of AX in ‘temp’

mov al,[c] ; Move the contents of ‘c’ to AL

mov bl,[d] ; Move the contents of ‘d’ to BL

imul bl ; Multiply the contents of AL with the contents of


BL

; Product in AX

47
COS2621/102/3/2023

AX = c*d*e 

mov bl,[e] ; Move the contents of ‘e’ to BL

imul bl ; Multiply the contents of AL with the contents


of BL

; Product in AX

AX = a*b + c*d*e 

add al,[temp] ; Add contents of ‘temp’ to AX

mov [a],al ; Store the result in ‘a’

Our program might not give the correct result. Why not? Think about this for a moment.

We assumed that the result of c * d and of c * d * e would fit into AL, in other words into 8
bits.

Things to remember: 

MOV AL,[a] moves one byte from memory to register AL because AL is an 8-bit register,
therefore it is a byte operation.

MOV AX,[b] moves two bytes from memory to register AX because AX is a 16-bit register.
It is thus a word operation.

MOV [a],[b] is not allowed. You have to move via a register.


COS2621/102/3/2023

Activity 5.3

MOV [a],'N' is illegal in NASM and DEBUG because the size of the operands cannot be
determined, i.e. whether it should move 8 bits or 16 bits. We have to store the ASCII
character 'N' in either an 8-bit or a 16-bit register and move the contents of this register to
a.

mov cl,'N'

mov [a],cl

5.3.3 Bit manipulation 

5.3.3.1 Boolean operations

The instructions available in x86 Assembly Language for Boolean operations that can be
used for bit manipulation are AND, OR, NOT and XOR.

Activity 5.4

For Intel x86 machines: Remember that bits are numbered from right to left, starting from
0.

Suppose we want to determine whether or not bit 5 of the AL register is set to 1. We set up
a so-called mask in another register (BL in the code below) with all the bits equal to 0
except bit 5 which is equal to 1. Use BL for the mask (BL = 00100000).

When we execute AND BL,AL all the bits in the destination register, BL, will be set to 0 if

49
COS2621/102/3/2023

bit 5 of AL is equal to 0, otherwise bit 5 of BL will be equal to 1.

mov bl,20h ; 20h = 00100000, setting bit 5 to 1.

and bl,al

The destination register BL will contain all 0s if bit 5 of AL was equal to 0, otherwise bit 5 of
BL will be equal to 1.

Direct bit access 

Direct bit access instructions such as BSF, BSR, BT, BTC, BTR and BTS are available
COS2621/102/3/2023

but we will not use them in COS2621.

Shift and rotate instructions 

In this section we describe the shift and rotate instructions available on the Intel x86.

The SHL (Shift Logical Left) instruction 

Contents of AL CF The sign bit is treated as a data bit.


after execution
of instruction

10111011

SHL AL,1 01110110 1 Shifts each bit one position to the left, filling
with a 0 on the right (low-order bit).

High-order bit moves to Carry Flag (CF).

*SHL AL,2 11011000 1 Shifts each bit two positions to the left, filling
with 0s on the right. High-order bits move
through CF, so the last one to move out will be
in CF.

MOV CL,3 CL = 3

SHL 11000000 0 Shifts AL to the left 3 times.


AL,CL

* Not allowed in DEBUG. The constant may only be equal to 1.

51
COS2621/102/3/2023

The SHR (Shift Logical Right) instruction 

Contents of CF Explanation
AL

after
execution of
instruction

10111011

SHR AL,1 01011101 1 Shifts each bit one position to the right, filling
with 0 on the left (high-order bit).
Low-order bit moves to Carry Flag (CF).

*SHR AL,2 00010111 0 Shifts each bit two positions to the right, filling
with 0s on the left. Second bit out moves to
CF.

MOV CL,3 CL = 3

SHR 00000010 1 Shifts AL to the right 3 times.


AL,CL

* Not allowed in DEBUG. The constant may only be equal to 1.

The SAL (Shift Algebraic Left) and SAR (Shift Algebraic Right)  instructions 

The SAL instruction is identical to the SHL instruction.

SAR is not identical to SHR. The sign bit is not regarded as a data bit. Bits are shifted to
the right a specified number of times and the sign bit retains its original value. Low-
order bit moves to Carry Flag (CF).
COS2621/102/3/2023

Contents of CF Explanation
AL after
execution of
instruction

10111011

SAR AL,1 11011101 1 Shifts each bit one position to the right, filling left-
most position (high-order bit) with a copy of the
sign bit. Low-order bit (right-most bit) moves to
Carry Flag (CF).

*SAR 11110111 0 Shifts each bit two positions to the right,


AL,2 duplicating the sign bit on the left. Second bit
that moves out on the right-hand side moves to
CF.

MOV 00000111 AL = 07
AL,07

SAR AL,1 00000011 1 Shifts to the right. Duplicate sign bit on the left.
Sign bit retains its original value (0). Low-order bit
(right-most bit) moves to Carry Flag (CF).

* Not allowed in DEBUG. The constant may only be equal to 1.

The ROL (ROtate Left) and ROR (ROtate Right) instructions 

Contents of AL CF Explanation

after execution
of instruction.

10111011

ROL AL,1 01110111 1 Shifts each bit one position to the left, filling
right (low-order) bit with a copy of the sign bit.
A copy of the sign bit is also copied to the
Carry Flag (CF).

53
COS2621/102/3/2023

ROL AL,1 11101110 0 Shifts each bit to the left, duplicating the sign
bit on the right. The sign bit is also copied to
CF.

ROR AL,1 01110111 0 Shifts each bit to the right. The bit on the right
(low-order) moves into position on the left
(most-significant bit) and into the CF.

ROR AL,1 10111011 1

The RCL (Rotate through Carry Left) and RCR (Rotate through Carry right)

Contents of AL CF Explanation

after execution
of instruction

10111011 0

RCL AL,1 01110110 1 Shifts (rotates) each bit one position to the left,
filling right (low-order bit) with a copy of the CF.

The high-order bit moves into the Carry Flag


(CF).

RCL AL,1 11101101 0

RCR AL,1 01110110 1 Shifts (rotates) each bit to the right. The bit in
the CF moves into the position on the left
(most- significant) and the bit on the right
moves into the CF.

RCR AL,1 10111011 0


COS2621/102/3/2023

Activity 5.5

a Bit manipulation using shifts and masks

Suppose we need to extract bits 3 to 5 of the AL register.

mov bl,38h ; Mask for bits 3 to 5: 38h = 0011 1000


and bl,al ; Bits 3 to 5 in BL now contain the values
of the
; corresponding bits in AL and the rest of
the
; bits are set to 0
mov cl,3 ; Move 3 to CL
shr bl,cl ; Shift bits 3 to 5 to the right-hand side
of BL

NOTE: NASM will assemble and execute the instruction shr bl,3 while DEBUG will give
a syntax error. Beware if you code such an instruction in NASM and then use DEBUG to
trace the program. DEBUG interprets the assembled instruction differently, but executes it
correctly! Rather code shifts as shown in the example given above.

b Bit manipulation using shifts and the carry  flag: 

Suppose we want to determine the value of bit 0 of the AL register and jump to memory
position 200h if it is equal to 0.

shr al,1 ; Shift the bits in AL one position to the right


; The carry flag contains the bit that is
shifted out
jnc carry_n ; Jump to label carry_n if no carry, i.e.
; the carry flag is not set

55
COS2621/102/3/2023

5.4 Floating‐point representation 

Stallings: study section 10.4. Stallings only considers the IEEE and the IBM S390
standards. To give you some additional background, we look at different representations
that are used on other machines. These are the older IBM 370 format and the format used
on the DEC PDP/11 and VAX machines.

5.4.1 The IEEE standard 

The format for single-precision floating-point numbers as discussed in Stallings can be


represented as follows:

8 bits 23 bits

e f
s

To get the value of a number given a 32-bit bit pattern, we use the following formula:

value = (-1)s 1.f × 2 e - 127

Note the implied 1 to the left of the binary point. Remember that in the IEEE format the
number is normalised in such a way that we have one 1 to the left of the binary point.
COS2621/102/3/2023

Since this 1 is always present, it is not necessary to store it. This is known as a hidden bit.

Note that this formula cannot be used for numbers that have not been normalised.

Let us look at an example.

Activity 5.6

The IEEE format 

Give the representation of -7.6875 in IEEE floating-point format.

7.687510 = 111.10112

= 1.1110112 × 22 normalise

= 1.1110112 × 2(129 - 127) get the value of e

= 1.1110112 × 210000001 - 127


convert e to binary

Remember that we have a hidden bit to the left of the binary point and that this is not
stored as part of the number. This means that f = 1110110...0.

e = 10000001. The number is negative so s = 1.

s e f

57
COS2621/102/3/2023

1000000
1110110....0
1 1

5.4.2 The IBM 360/370 format 

The IBM 360/370 format for a single-precision floating-point number is as follows:

7 bits 24 bits

e f
s

value = (-1)s 0.f × 16 e - 64

Note that the radix of the exponent is 16 and not 2! The exponent is represented using
excess 64.

Let us consider an example.

Activity 5.7

The IBM 360/370 format 
Show how you would represent -7.6875 using the IBM 360/370 floating-point format.
COS2621/102/3/2023

7.687510 = 111.10112

= 0.011110112 × 161 normalise

= 0.011110112 × 16( 65 - 64) get the value of e

= 0.011110112 × 161000001 - 64
convert e to binary

So f = 011110110...0 and e = 1000001. The number is negative so s = 1.

s e f

100000
011110110....0
1 1

5.4.3 The DEC PDP 11/VAX format 

The format of a single-precision floating-point number in DEC PDP 11/VAX format is as


follows:

8 bits 23 bits

E f
s

value = (-1)s 0.1f × 2 e - 128 (e  0..0)

59
COS2621/102/3/2023

This format also uses a radix 2 for the exponent. Note that in this case, the 1 to the right of
the binary point in the formula. Again, since we are working with normalised numbers, it is
not necessary to store the first 1 after the binary point. So we again have a hidden bit in
this representation. Let us look at an example.

Activity 5.8

The DEC PDP 11/VAX format : 

Show how you would represent 7.6875 using the DEC single-precision floating-point
representation.

7.687510 = 111.10112

= 0.1111011 × 23 normalise

= 0.1111011 × 2131 - 128 get the value of e

= 0.1111011 × 210000011 - 128convert e to binary

So e = 10000011

The number is positive so s = 0.

We have a hidden bit to the right of the binary point so the first 1 of the significant is not
stored.

f = 1110110...0

s e f
COS2621/102/3/2023

1000001
1110110......0
0 1

61
COS2621/102/3/2023

5.5 Summary 

Stallings: section 10.7. Make sure that you understand the arithmetic, shift and logical
instructions discussed in this study unit and that you can convert floating-point numbers to
the format in which they will be stored. You should know the meaning of all the key terms
that are listed in this section.

5.6 Key Questions 

Work through the review questions at the end of the chapter.

----oooOooo----
COS2621/102/3/2023

15 Study unit 6
Instruction sets
16

This study unit supplements chapter 12 and Appendix B in Stallings. Several very

important concepts are discussed. These include operand types, instruction types and
types of operation. The use of subroutines and macros are discussed and we also look at
t i h i

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

● describe how instructions are represented in a computer

● distinguish different types of instruction

● distinguish different types of operand

● discuss the different types of operation that can be performed by a computer


program

● implement the operations discussed in this section on an Intel x86 machine

● define and use subroutines in assembly language

● describe and implement different parameter-passing methods

● describe what a macro is and use macros in assembly language

63
COS2621/102/3/2023

Stallings

Study sections 12.1 - 12.4; the first part of section 12.5; Appendix B.1, and also section
13.5.

Read the rest of section 12.5; Appendix B.2 to B.5.

6.1 Introduction 

Stallings: study section 12.1. Various important concepts regarding assembly


language are discussed in this study unit. It is important to understand these
concepts in order to master the practical work that is expected of you in this module.

6.2 Types of operand 

Stallings: study section 12.2. Operands are data on which machine instructions
operate. Make sure that you understand the different categories of data. Note that an
address is also a data item in its own right.

6.3 Data types 

Stallings: study section 12.3. It is important that you work through sections 4 to 6
of Appendix B in this study guide before continuing with this study unit. You will not
understand the examples if you do not know the different data types and how
storage space is reserved when using NASM.

Working with floating-point numbers in assembly language is quite complex so we


will only use integer data and characters or character strings in the programs we use
as examples.
COS2621/102/3/2023

6.4 Types of operation in assembly language 

Stallings: study section 12.4.

Stallings: study section 12.5 up to, but not including, the section on x86 SIMD
instructions. Read the rest of section 12.5.

Stallings: study Appendix B.1 and chapter 13.5. 

We consider some of the concepts discussed in this chapter of Stallings in more


detail:

6.4.1 Jumps and branches 

The JMP instruction is used for branching and is called an unconditional jump.

To branch or not to branch! A conditional jump uses the status of the flags to decide
whether or not to branch. A conditional branch frequently follows after a compare
statement, CMP.

Example: 

cmp al,6 ; Compare AL to 6

jl less_than ; Jump to less_than if AL is less than 6

65
COS2621/102/3/2023

We can also use the status of the carry or overflow flag for conditional branching:

shl ax,1 ; Shift AX one left

jc carry_set ; Jump to carry_set if carry flag is set

Note that a conditional jump instruction is only two bytes long. The destination address
is stored in one byte as an offset from the current value of IP, in other words, the
difference between the current value of IP and the destination address. This offset must
fit into one byte, otherwise NASM will flag an error. This means that we can only branch
one "byte" far!

Let us use an example to explain:

Suppose we want to assemble the instruction JL 300h at address 200h. You will see
that the offset from address 200h to address 300h is 100h bytes (300h - 200h). If you
try to assemble this instruction it will be flagged as an error by NASM because we have
only one byte to store the offset from 202h (the current value of IP which points to the
next instruction to be executed) to the destination address. This means that, from
address 202h, we cannot conditionally jump further than

address 281h forward (281h - 202h = 7Fh = 12710), or

address 182h backward (202h - 182h = 80h = - 12810)

Activity 6.1

Conditional branching 
COS2621/102/3/2023

Consider the following pseudo code:

temp = y;

x = 0;

top:

if temp < z then go to bottom;

x = x + 1;

temp = temp - z;

go to top;

bottom: ...
We can encode this pseudo code in x86 assembly language as follows:

org 0x100
jmp main ; Jump to main program

y: dw 0005 ; y = 5 for testing purposes


z: dw 0002 ; z = 2 for testing purposes

main:
mov ax,[y] ; Use AX as Temp (=y)
xor bx,bx ; BX = 0 (initial value of x = 0)
top:
cmp ax,[z] ; Is Temp < z ?
jl bottom ; Yes, go to bottom
inc bx ; x = x + 1

67
COS2621/102/3/2023

sub ax,[z] ; Temp = Temp - z


jmp top ; Jump to top

bottom:
int 20h ; Terminate program

6.4.2 Loop control 

There are, of course, various ways in which loop control can be handled. In x86 assembly
language, the CX register, in combination with the LOOP instruction, can be used for this
purpose. It works as follows:

The LOOP instruction 

mov cx,10 ; Set loop counter to decimal 10


loop_1:
.
.
loop loop_1 ; Decrement CX,

; repeat loop if CX <> 0

Initially, we set CX to the number of times we want the loop to be repeated. When the
LOOP instruction is executed, CX is decremented by 1. If CX ≠ 0, we branch back to
LOOP_1. If CX = 0, the instruction following the LOOP instruction is executed.

Activity 6.2
Use of the LOOP instruction 
COS2621/102/3/2023

Let us look at another example.

Write an assembly language program equivalent to the following short algorithm: This
algorithm implements the operation x = y * z by repeated addition.

Multiplication by repeated addition: 

69
COS2621/102/3/2023

x = 0;

for temp = y to 0

x = x + z;

The assembly language program for the above follows.

org 0x100
jmp main
;

; Data declarations
x: db 00 ; Use x=0, y=5 and z=4 for
y: db 05 ; testing purposes
z: db 04

main:

xor ch,ch ; Clear CH


xor al,al ; AL = x (=0)
mov cl,[y] ; CL = y
mov bl,[z] ; BL = z
loop_1:
add al,bl ; AL = AL + z
loop loop_1 ; Repeat loop if CX <> 0

mov [x],al ; x = y * z
int 20h

;end
COS2621/102/3/2023

The result after execution is AX = (20)10 = 0014h

Note that we assume that the result will fit into one byte.

6.4.3 Input and output 

Refer to the examples in Appendices C and D in this study guide. You will see that we use
a set of DOS and BIOS routines for all input and output. When we want to use one of these
routines, we have to set up the registers in a predetermined way and issue an interrupt
instruction. When the INT instruction is executed, control is transferred to either DOS or
BIOS (depending on the interrupt issued) that handles the I/O and returns control back to
our program.

Appendix D of this guide contains a number of I/O functions that we will find handy to use.

71
COS2621/102/3/2023

6.4.4 The use of subroutines or  procedures 

Subroutines

Procedures are used in Pascal, and methods in C++ and Java, to divide a program into
smaller portions. In assembly language, a subroutine can be regarded as the equivalent
of a procedure.

There are various reasons for using subroutines in a program. The program may be very
large and different parts of it may be written by different programmers. Each programmer
may write his/her parts of the program in the form of subroutines. One programmer will be
responsible for writing the main program and all the routines will eventually be linked
together into one program. Another reason may be that parts of the program are written in
assembly language for efficiency and the rest of the program in a high-level language like
C++ or Java. Thirdly, a subroutine may be reusable; written once and used by different
programs.

One of the reasons for using subroutines in COS2621 is to make the writing and testing of
our assembly language programs easier. The program can be divided into small routines
that can be tested in isolation. If we know that a routine is working correctly, there will be
no need to step through the code again as we test the rest of our program. The program
needs a main routine that will call the individual subroutines as required. All the code is
combined into one program. In COS2621, subroutines are not assembled and stored
separately.

A subroutine call can be represented as follows:

; main program ; subroutine definition

Prog_start: sub1: mov temp,ax


. .

. .

call sub1 mov ax,temp

sub ax,bx ret


COS2621/102/3/2023

The return address is stored on the stack.

When the CALL instruction is executed, the current value of the IP, i.e. the address of the
instruction following the call, is automatically pushed onto the stack. The address of the
first instruction in the subroutine is stored in the IP and execution carries on from that
point. When the RET instruction is encountered in the subroutine, the top of the stack is
popped into the IP and the calling program can start executing at the instruction following
the call. From this description the importance of returning from a subroutine to the calling
program via the RET instruction should be clear. One should never jump out of a
subroutine back to the calling program without restoring the state of the stack. Fortunately,
this is done automatically for us as part of the RET instruction.

When a program is very large it can be subdivided into separate subroutines that are
assembled individually and eventually linked together. This can be done using NASM, but
this will not be covered in COS2621.

6.4.5 Parameter Passing 

Parameters can be passed to the subroutine in a number of different ways. We look at the
following possibilities in this section:

1. By defining a block in memory, called a parameter block, where the parameters are
stored.
2. By storing the parameters in registers before calling the subroutine.
3. By pushing the parameters onto the stack.

In x86 assembly language, parameter passing can be done in any of the ways described
above. It is very important for reusability that the comments in the subroutine heading
describe very clearly where and how the subroutine expects to find the parameters and
where the result, if one is passed back to the caller, will be stored by the subroutine.

Calling by name 

73
COS2621/102/3/2023

If parameters are passed using a parameter block in memory (calling by name), the
address of the block is stored in a specific register before the subroutine is called. Let us
look at an example.

; Subroutine to accept a string of characters from the keyboard.

; The address of the parameter block must be in DX.

Accept_string:

mov ah,0Ah ; INT 21, function 0Ah

int 21h ; DOS system call

ret ; Return

The parameter block is defined elsewhere in the program as follows:


; Parameter block

parb: db 20 ; Maximum of 20 characters

db 0 ; Reserve space for actual length of string

resb 0 ; Reserve 20 bytes as input buffer

In the calling program, the address of the parameter block must be stored in DX before the
subroutine is called so that DOS will know where to find the parameters and where to
store the input string. See Appendix D.3.

This parameter-passing mechanism is suitable to use when we have one or more


parameters that may include data structures such as arrays or strings.

Calling by value (parameters passed in registers) 

If parameters are passed in registers (calling by value), the calling program must simply
store the parameters in the relevant registers before calling the subroutine.
This mechanism is fast but can only be used when we have to pass a few values that will
fit into registers. COS2621/102/3/2023

Call by value (parameters passed on stack) 

Parameters can also be passed on the stack although this may involve tricky
programming. Remember that the return address is pushed onto the top of the stack when

the subroutine is called.

This mechanism is suitable for passing a small number of individual values/addresses but
only in cases where there is a restriction on the number of available registers. It is not
suitable for passing parameters that involve relatively large data structures. Note that it will
be slower than passing parameters in registers since we have to manipulate the stack
which resides in memory.

We use the exercises in the following section to illustrate the different possibilities.

6.4.6 Examples of parameter‐passing  mechanisms 

Consider a subroutine that returns the largest of three numbers that are passed to it as
parameters. The following code forms the body of the subroutine, i.e. that part of the
subroutine that does the work and will be the same no matter how the parameters are
passed.

;
; We assume that the three numbers are in AX, BX and CX
; respectively. The result is returned in AX
;
body: cmp ax,bx ; AX > BX?
jg next1 ; Yes, compare next
mov ax,bx ; BX greater

next1: 75
cmp ax,cx ; AX > CX?
jg epilog ; Yes, we are done
COS2621/102/3/2023

mov ax,cx ; CX greater

;
; Now AX contains the largest of the three numbers
;

epilog: ...

Assumptions: Let us assume that the three values are stored in memory in A, B and
C respectively. The result must be stored in A. We also assume that the contents of
registers AX, BX, CX and DX will be undefined after the subroutine call.

Activity 6.3

The parameters are passed on the stack and the result is returned on the  stack. 

The three parameters are pushed onto the stack before the call. The result (i.e. the largest
number) is returned on the stack.

Calling program, prepare for call (start-up sequence):

Start-up sequence

push [A] ;

push [B] ;

push [C] ;
Push the three values into the stack

Prolog

On entering the subroutin (prolog):


pop dx ; Store the return address
pop ax ;
pop bx ; Pop the three values into AX,BCOS2621/102/3/2023
X,CX
pop cx ; respectively

Body of subroutine fits in here

.
Preparing for the return (epilog):

Epilog

push ax ; Return largest value on the stack


push dx ; Restore the return address
ret

Calling program, get the result (clean-up sequence):

Clean-up sequence

77
COS2621/102/3/2023

pop [D] ; Pop the result into D

Activity 6.4

Using registers to pass the parameters: 

The parameters are passed in AX, BX and CX respectively. The result is returned in AX.

Start-up sequence

Calling program, prepare for the call:

mov ax,[A] ;
mov bx,[B] ; Get values into registers
mov cx,[C] ;

On entering the subroutine:

Prolog

Nothing needs to be done in the prolog. The parameters are already in the required
registers.
COS2621/102/3/2023

Body

Body of subroutine fits in here.

Epilog

Prepare the result before leaving the subroutine:

Nothing further needs to be done in the epilog. The result is already in AX.

ret

Clean-up sequence

Calling program, get the result:

mov [D],ax ; Store result

Activity 6.5

Using a parameter block to pass the parameters: 

The address of the parameter block (in memory) is passed to the subroutine in the DX
79
COS2621/102/3/2023

register. The result is returned in the parameter block.

Calling program, prepare for the call:

Start-up sequence

mov dx,A ; Address of parameter block


; in memory

Prolog

On entering the subroutine:

mov si,dx ; SI points to parameter block


mov ax,[si]
mov bx,[si+2] ; Get the three values
mov cx,[si+4] ;

Body

Body of subroutine fits in here.

Epilog

Subroutine, store the result - prepare for return:


COS2621/102/3/2023

mov [si+6],ax ; Store result in the parameter

81
COS2621/102/3/2023

; block
ret

Clean-up sequence

Calling program, get the result: Nothing needs to be done in the clean-up sequence. The
result is already stored in memory at the required address.

Near and Far Calls 

The subroutine calls we have looked at so far are all near calls. This means that the main
program as well as the subroutine reside within the same segment. The value of the CS
register will be the same for both.

If the main program and the subroutine are not within the same segment, or if the
subroutine was assembled and stored as a separate unit, the main program has to make a
far call to the subroutine. When a far call is made, the value of the IP as well as the current
value of the CS register is stored on the stack. On return from the subroutine, the CS
register is restored to the code segment address of the caller and the IP register is
restored to point to the instruction following the call where the execution of the caller must
be resumed. We are only going to use near calls in our programs.

6.4.7 Recursion 

This section does not form part of the study material but is included for interest’s sake.
You have probably already encountered recursion in COS2611. DEBUG is an excellent
tool to use to see exactly what happens when we call a recursive routine. Use the
COS2621/102/3/2023

following example to step through the program and study the stack after each call and
after each return.

Calculate the sum of the numbers 1 to n 

Activity 6.6

The following program calculates the sum of the numbers 1 to n.

bits 16
org 0x100
jmp main ; Jump to main program
;

; This recursive subroutine calculates the sum of


; the numbers 1 to n (CX initially contains n).
; AX must contain 0 on first call. Result is returned in
; AX.
recur:
or cx,cx ; Is CX = 0?

jz return ; Yes, return


add ax,cx ; AX holds the sum
dec cx ; CX = CX-1
call recur ; Recursive call return:
(L2)

83
COS2621/102/3/2023

ret ; Return to main


;
main:

mov cx,6 ; Assume n = 6


mov ax,0 ; Initialise AX to 0.
call recur ; Call adder

int 20h ; Terminate program (L1)

CX = 0 (the base case) signals the termination of the recursive subroutine. The return
addresses of the recursive calls are pushed onto the stack by the CALL instruction.

Return address CX AX AX

on stack (dec) (hex)

1st call: L1 6 0 0

2nd cal L2 5 6 6

3rd call: L2 4 11 B

4th call: L2 3 15 F

5th call: L2 2 18 12

6th call: L2 1 20 14

7th call: L2 0 21 15

In our example 1 + 2 + 3 + 4 + 5 + 6 = 21(decimal) = 15h.


COS2621/102/3/2023

We suggest that you test the above program by using the T option of DEBUG. Inspect the
stack after each call, and after each return instruction has been executed.

Things to remember: 

The return address: In x86 assembly language, the CALL instruction pushes the offset of
the next instruction to be executed onto the stack and transfers control to the subroutine.
The RET instruction pops the address on top of the stack into the IP and execution
resumes from this location.

Parameter-passing methods: The advantages and disadvantages of each of the methods


discussed in this study unit have to be considered when we have to decide which will be
best for a particular implementation.

6.5 Assembly language 

Stallings: revise section 11.5. The main reason for using assembly language is to
improve the efficiency of a program if the execution time of a program is crucial.

There is also method in the madness of our teaching assembly language to our students!
It helps one to understand the underlying operations of a computer system and also to
understand the way in which a compiler operates.

6.5.1 Assembler directives 

85
COS2621/102/3/2023

Pseudo-instructions are also called assembler directives. These are instructions to the
assembler and do not form part of the program code that will be executed during run time.
DB and DW are examples of assembler directives that we have come across in our
programs so far. Assembler directives tell the assembler where and how to reserve
memory and how it should be initialised. There are several other assembler directives that
are important when we are implementing large programs but we will not consider these
here.

6.5.2 Macros 

It is important to note the difference between a macro and a subroutine. A macro is not the
same as a subroutine. We have already looked in detail at subroutines in the previous
section. When a subroutine is called, we branch to an area in memory where the
subroutine is stored and execute the code. Then we branch back to our main or caller
program. This happens at run time.

When a macro is called, the piece of code comprising the macro is duplicated in the
program. We call this process macro expansion. This happens during assembly time.

We use the following example to illustrate this concept:

Activity 6.7

The use of macros in assembly language programs. 

A macro gives a name to a piece of code. Whenever we refer to the macro, the code is
duplicated in the program during the assembly process.
COS2621/102/3/2023

bits 16
org 0x100
jmp main
mes1:

db 'Hello World',10,13,'$'
mes2:

db 'What a beautiful day!',10,13,'$'


;
; macro definition
%macro disp 1
mov dx,%1
mov ah,09
int 21h
%endmacro

;
; end of macro definition
main:
disp mes1
disp mes2
int 20h

The assembled program code is as follows:

1 bits 16

87
COS2621/102/3/2023

2 org 0x100
3 00000000 E92600 jmp main
4 mes1:
5 00000003 48656C6C6F20576F72- db 'Hello World',10,13,'$'
6 0000000C 6C640A0D24
7 mes2:
8 00000011 576861742061206265- db'What a beautiful
day!',10,13,'$'
9 0000001A 6175746966756C2064-

10 00000023 6179210A0D24
11
12 %macro disp 1
13 mov dx,%1
14 mov ah,09
15 int 21h
16 %endmacro
17
18 main:
19 disp mes1
20 00000029 BA[0300] <1> mov dx,%1
21 0000002C B409 <1> mov ah,09
22 0000002E CD21 <1> int 21h
23 disp mes2
24 00000030 BA[1100] <1> mov dx,%1
25 00000033 B409 <1> mov ah,09
26 00000035 CD21 <1> int 21h
COS2621/102/3/2023

27 00000037 CD20 int 20h


28

Note how the code within the macro definition is duplicated in the main program. The
macro definition does not exist in the assembled program.

6.6 Stacks and byte‐ordering 

NB: You should be able to manipulate the stack on an x86 machine. See section
4.5.1.4 in the study guide. We will consider the stack again in the next study unit.

6.7 Summary 

Stallings: section 12.7 Make sure that you understand the different categories of
data, the use of all the different kinds of instruction, and the use of subroutines, macros
and pseudo-instructions. You should also know the meaning of all the key terms that
are listed in section 12.7.

6.8 Key Questions 

Work through the review questions at the end of the chapter.

----oooOooo----

101
COS2621/102/3/2023

17 Study unit 7

Instruction Sets: Addressing modes and

This study unit supplements chapter 13 in Stallings.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

• identify the addressing mode used in a given instruction

• give examples of instructions in which specific x86 addressing modes are used

• discuss the advantages and disadvantages of different instruction formats


COS2621/102/3/2023

7.1 Addressing modes 

Stallings: study section 13.1. The addressing mode used in an instruction indicates
the way in which the operand is accessed. We have two operands in binary operations
such as addition, for example, but generally, at least one of the operands is stored in a
register.

Consequently, we refer to the addressing mode of the operand that is not obtained
directly from a register as the addressing mode of the instruction. The examples below
illustrate this principle.

7.2 Intel x86 and ARM addressing  modes 

Stallings: study section 13.2 excluding the section on the ARM addressing modes.

Read the rest of section 13.2, i.e. the section on ARM addressing modes.

We examine the addressing modes of the Intel x86 in more detail below.

A number of different addressing modes can be identified in the Intel x86 instruction set.
The addressing mode is determined by the operands in the instruction.

The following addressing modes are quite straightforward:

Register addressing: 

mov ax,bx ; Load the value of BX into AX

add ax,bx ; AX = AX + BX

103
COS2621/102/3/2023

Both operands are in registers. The first operand is always the destination operand.

Immediate addressing: 

mov ax,1 ; Load the value 1 into AX

mov bx,0x010C ; Load the hexadecimal value 010C

; into BX

One of the operands is a value that is stored as part of the instruction.

Direct addressing (displacement addressing): 

mov ax,[102h] ; Load the contents of memory

; location 102h into AX

mov [temp],bx ; Store the contents of BX in the

; memory location with label temp

Note: In contrast to this, mov bx, temp stores the address of the label temp in BX.

One of the operands is the address of the actual operand. This address is the offset
(displacement) from the start of the Data Segment.
COS2621/102/3/2023

Stallings: revise and study section 13.3. We use examples to illustrate the use of the
following two addressing modes where indirect addressing are used and which are a bit
more complicated. Both of these are examples of register indirect addressing.

Indirect addressing means that the operand given in the instruction contains the
address of the actual operand. On the Intel x86 we can only have register indirect
addressing using SI, DI, BP and BX. Hence indexed addressing and base-indexed
addressing, which we consider in the examples given in section 7.2.1 are both different
forms of register indirect addressing. We can also use BP and BX for indirect
addressing.

Base addressing: If BX or BP is used we call it base addressing.

Activity 7.1

7.2.1 Indexed addressing mode 

Revise section 4.5.1.3 in this study guide.

Consider the case where we want to access each individual element in a character
string. We can regard the string as an array of characters and use a pointer to access
each individual character. Suppose we have the following string that starts at memory
position 102h:

String S C I E N C E I S F U N

Offset 0 1 2 3 4 5 6 7 8 9 10 11 12 13

105
COS2621/102/3/2023

If we set SI (the source index register) to the start of the string, we can use SI as a
pointer to access the characters one at a time. The character 'S' is stored at offset 0
from the start of the string and the character 'N’ is stored at offset (13)10 from the start of
the string.

Example:

Suppose we want to access the character 'F’ which is stored at offset (11)10 from the
start of the string.

db 'SCIENCE IS FUN'
.
mov si,102h; Move addr of start of string to SI
add si,11 ; Add (11)10 to SI. NASM assumes that
; numbers are decimal
mov al,[si]; Move the contents of the address
; pointed to by SI to AL.

; AL will contain the character 'F'

Let us look at another example to illustrate how we can use indexed addressing to
access each element in the string.
COS2621/102/3/2023

Activity 7.2

Using an index to point to an array element 

Read each element of a string (array of characters), which we assume is in upper case,
from memory, convert it to lower case and store it in an output string.

Assume that the input string, 'SCIENCE IS FUN', is stored in memory. We use indexed
addressing as follows:

We use SI to point to the input string, so SI is initialised to the starting address of the
input string.

We use DI to point to the output string, so DI (Destination Index) is initialised to the


starting address of the output string.

Algorithm to solve the problem:

Do while not end_of_string

Move a character from the input string to AL

Convert to lower case (This is done by adding 20h to the contents of AL since
the difference between an upper and lower case ASCII character is 20h)

Store character in the output string

Increment SI

Increment DI

End do;

107
COS2621/102/3/2023

Solution 

Note that we do not test whether the character is in fact an upper case character, so the
program will give incorrect results if the input string contains characters that are not
upper case (which is indeed the case for the spaces in our string).

Note the use of indexed addressing in this example.

org 0x100
jmp main
in_str: db 'SCIENCE IS FUN'
out_str: times 14 db ' ' ; Reserve 14 spaces for
output
; string
out_len: equ $-out_str ; Define length of output
string
main:

mov si,in_str ; Start address of input


string

mov di,out_str ; Start address of output


string
COS2621/102/3/2023

mov cx,out_len ; Length of string


loop_1:
mov al,[si] ; Get one character
add al,20h ; Convert to lower case
mov [di],al ; Store in output string
inc si ; Adjust pointers
inc di

loop loop_1 ; If CX <> 0, get next one


int 20h ; Terminate program

Run this program under DEBUG and inspect the contents of memory where the output
string is stored. How do we know this address? We have to inspect the NASM output
listing which is as follows:

1 org 0x100

2 00000000 E91C00 jmp main

3 00000003 534349454E43452049- in_str: db 'SCIENCE IS FUN'

4 0000000C 532046554E

5 00000011 20<rept> out_str: times 14 db ' ' ; Reserve 14 spaces for

; output string

6 out_len: equ $-out_str ; Define length of output

; string

7 main:

8 0000001F BE[0300] mov si,in_str ; Start address of input


; str

9 00000022 BF[1100] mov di,out_str ; Start address of output

10 00000025 B90E00 mov cx,out_len ; Length of string

11 loop_1:

12 00000028 8A04 mov al,[si] ; Get one character

109
COS2621/102/3/2023

13 0000002A 0420 add al,20h ; Convert to lower case

14 0000002C 8805 mov [di],al ; Store in output string

15 0000002E 46 inc si ; Adjust pointers

16 0000002F 47 inc di

17 00000030 E2F6 loop loop_1 ; If CX <> 0, get next


one

18 00000032 CD20 int 20h ; Terminate program

The input string starts at offset 103h and the output string starts at offset 111h.

7.2.2 Base‐indexed addressing  mode 

Base-indexed addressing can also be used to access array elements. BX and BP can
be used as base registers. When we use this type of addressing mode, the base
register is normally set to the start of the array and the index register is used as an
offset from the start of the array.

Activity 7.3

Access array elements by using base-indexed addressing

org 0x100
;

; Program to select a classic movie from a list of 9


;
COS2621/102/3/2023

jmp main ; jump to main program


;

; Prompt message
;
message: db 'Please enter a theatre number',0ah,0dh,'$'
;
; List of movies you can select from
;
m_1: db 'Top Gun','$'
m_2: db 'Braveheart','$'
m_3: db 'Casablanca','$'
m_4: db 'The Rock','$'
m_5: db 'A few good men','$'

m_6: db 'Con Air','$'

m_7: db 'The Lion King','$'


m_8: db 'Kellys Heroes','$'
m_9: db 'The dirty dozen','$'

;
m_addr:
dw m_1, m_2, m_3, m_4, m_5, m_6, m_7, m_8, m_9

;
; Each of the values in m_addr occupies 2 bytes.
; This means that the first movie adress is at offset 0 in
; m_addr,
; the second movie address is at offset 2,

111
COS2621/102/3/2023

; the third movie address is at offset 4,


; the fourth,…, ninth movie addresses are at offsets
; 6,8,10,12,14,16 respectively.
;
; Display message on the screen
; DX points to start of message
;

display:
mov ah,09 ; Display message function
int 21h ; DOS system call
ret

;
; Accept a character from the keyboard
; Character (in ASCII) is returned in AL
; Character is not echoed to the screen
;
input:
mov ah,07 ; Accept char, no echo function
int 21h ; DOS system call
ret

;
; Display movie name corresponding to the theatre number
; input
; Movie number is in AL.
;
COS2621/102/3/2023

display_m:

xor ah,ah ; AH = 0
sub al,31h ; Offset = (AL 1)*2
shl al,1 ; Equivalent to AL*2
mov si,ax ; SI is used as an index
mov dx,[m_addr+si] ; DX points to movie name
call display

ret
main:

mov dx,message
call display
call input
call display_m
int 20h

Activity 7.4

Two‐dimensional arrays: 

Calculate the sum of all the elements in the second column of a 3 x 5 array.

org 0x100
jmp main ;Jump to main program

113
COS2621/102/3/2023

; First row of array


first_row:
db 00h,01h,02h,03h,04h
; Second row of array
second_row:
db 10h,20h,30h,40h,50h
; Third row of array
third_row:

db 60h,70h,80h,90h,0xa0
;
; Add the elements in the second column
main:
mov bx,first_row ; BX points to the first row

mov si,1 ; SI points to column 2

; (SI=0 for column 1 and


; SI=1 for column 2)
mov cx,3 ; Loop counter - add three
; elements
mov ax,0000 ; AX to contain the sum
;
sum:

add al,[bx+si] ; Add element to contents of AL


add bx,05 ; BX points to next row

loop sum ; Repeat the loop until CX=0


int 20h ; Terminate program
COS2621/102/3/2023

Run this program under DEBUG. The AX register should contain 0091h on
termination.

7.2.3 Stack addressing 

Stack Pointer (SP): The SP register contains the offset from the beginning of the stack
to the top of the stack. We use the instructions PUSH and POP to push values onto the
stack and to pop them off the stack respectively. This addressing mode is called stack
addressing.

PUSH: An item is stored on top of the stack and the stack pointer adjusted
accordingly. SP is decremented before a new item is placed on the stack. This means
that the stack grows from high memory to low memory. We say that the stack grows
backward in memory. SP points to the last item that was pushed onto the stack.

POP: An item is removed from the top of the stack and the stack pointer adjusted
accordingly. SP is incremented after an item has been removed from the stack. SP
points to the new top of stack.

Note that the operations of PUSH and POP are slightly different on some older
machines. This may not concern you. If you have an older machine though, this might
explain differences between the results obtained by you on your machine and the results
given in the next example which was tested on a relatively new Intel machine. If your
results are different, the following is the cause: On some of the older machines, when
the PUSH instruction is executed, SP is decremented after an item has been pushed on
the stack. This means that SP points to the next available position on the stack. With
the POP instruction, SP is incremented before the item on top of the stack is popped.

115
COS2621/102/3/2023

Activity 7.5

The state of the stack:

Assume that the initial values of the registers are:

AX = 00A5, BX = 0001, CX = 0002, SP = FFFC

The table given below shows the state of the stack and the registers after each
instruction listed has been executed. All values are in hexadecimal.

Content Con- Contents Contents Contents of Comment


s of AX tents of of CX of SP stack. It
BX (Points to ‘grows’
top of
stack.) from high to

low memory.

00A5 0001 0002 FFFC ? Points to current top of stack.

PUSH 00A5 0001 0002 FFFA 00A5 Contents of AX do not


AX change.

SP is decremented by 2.
(The stack grows from high
memory to low memory.)

PUSH 00A5 0001 0002 FFF8 0001 Contents of BX do not


BX change.
00A5
SP is decremented by 2.

PUSH 00A5 0001 0002 FFF6 0002 Contents of CX do not


CX change.
0001
SP is decremented by 2.
00A5

POP AX 0002 0001 0002 FFF8 0001 The value on top of the stack
(ie 0002) is popped into AX.
00A5 SP is incremented by 2.
COS2621/102/3/2023

After POP AX has been executed, AX contains the value that was on top of the stack,
namely 0002. The stack pointer is now pointing to the value 0001. The popped
value (0002) no longer forms part of the stack. Only the values below the stack pointer
form part of the stack.

Things to remember: 

 The stack grows backward in memory.


 The POP instruction moves the value on top of the stack into the operand. This
value does not form part of the stack any longer.
See also Example 6 in Appendix C of this guide.

7.3 Instruction Formats 

Stallings: study the first three pages of section 13.3.

Read the rest of section 13.3.

7.4 The Intel x86 and ARM instruction  formats 

Stallings: read section 13.4

7.5 Summary 

Stalling: section 13.7. You should be able to identify addressing modes used in Intel x86
instructions and to give examples of instructions where a specific addressing mode is
used. Make sure that you understand the issues involved when choosing appropriate
instruction formats and that you know the meaning of the key terms listed in section 13.7.

7.6 Key Questions 

Work through the review questions at the end of the chapter.

117
COS2621/102/3/2023

----oooOooo----

This study unit supplements chapter 4 of Stallings. Concepts pertaining to cache memory
principles, design and organisation are discussed in this study unit.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

 explain the characteristics of memory systems


 describe the memory hierarchy
 discuss cache memory principles
 discuss issues relevant to cache design
 describe the cache organisation of the Pentium 4

Cache memory

8.1 Computer memory systems 

Stallings: study section 4.1. The characteristics of memory systems are discussed.
These include memory capacity, the basic unit of transfer, the method of accessing and
performance. The memory hierarchy as well as the principle of locality of reference are
also explained.
COS2621/102/3/2023

8.2 Cache memory principles 

Stallings: study section 4.2. The structure of cache memory is explained. Stallings also
describes how a read from cache memory takes place to illustrate why this is much faster
than a read from main memory.

8.3 Elements of cache design 

Stallings: carefully read section 4.3 and study the last page. The concepts explained
here are often referred to in the media in advertisements of laptops, for example.

8.4 Intel x86 and ARM cache  organisations 

Stallings: study the section on the cache organisation of the Pentium 4 in section 4.4.

Stallings: read the rest of section 4.4 and read section 4.5. Note the difference between
the cache organisations of the Pentium 4 and the ARM processor.

8.5 Summary 
Make sure you understand the meaning of the key terms listed in this section.

8.6 Key Questions 

Work through the review questions at the end of the chapter.

---ooo0ooo---
119
COS2621/102/3/2023

Study unit 9
Internal memory

This study unit supplements chapter 5 of Stallings. The principles of dynamic and static
RAM are discussed as well as the different types of ROM. The principles of SDRAM
organisation are also considered.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

 describe the operation of a memory cell


 explain the difference between DRAM and SRAM
 discuss the different types of ROM
 explain the concepts of a hard failure and a soft error respectively
 and describe SDRAM organisation
COS2621/102/3/2023

Stallings

Study sections 5.1, 5.2 and 5.3.

121
COS2621/102/3/2023

9.1 Semiconductor main  memory 

Stallings: study section 5.1. The operation of a memory cell is explained. Stallings also
describes the operation of dynamic RAM (DRAM) and static RAM. Finally, the different
types of ROM are discussed. Pay special attention to the discussion on flash memory.

9.2 Error correction 

Stallings: study section 5.2. Make sure that you understand the difference between a
hard failure and a soft error. The principles on which error-correcting codes function are
discussed and the Hamming error-correcting code is described.

9.3 Advanced DRAM organisation 

Stallings: study section 5.3. Make sure that you understand the difference between
SDRAM and traditional DRAM.

9.4 Summary 

Make sure you understand the meaning of all the key terms in this section.

9.5 Key Questions 

Work through the review questions at the end of the chapter.

---oooOooo---
COS2621/102/3/2023

Study unit 10
External memory

This study unit supplements chapter 6 of Stallings. Magnetic disks are discussed as well
as optical storage devices.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

 discuss the physical characteristics of magnetic disks


 describe how data is organised and accessed on a magnetic disk
 discuss the parameters that play a role in the performance of magnetic disks
 describe different optical memory devices

123
COS2621/102/3/2023

Stallings

Study sections 6.1, 6.3 and 6.4.

Read sections 6.2 and 6.5.


COS2621/102/3/2023

10.1 Magnetic Disk 

Stallings: study section 6.1. The way data is stored on and retrieved from magnetic
disks is discussed. The physical characteristics of a magnetic disk are described as well
as the factors that play a role in the performance of a disk.

10.2 RAID 

Stallings: read section 6.2. The basic principles of a RAID scheme are discussed. This
section also contains detailed discussions of the various levels of RAID.

10.3 Solid state drives 

Stallings: study section 6.3. The principles on which different solid state storage
devices function are described.

10.4 Optical memory 

Stallings: study section 6.4. The principles on which different optical storage devices
function are described.

10.5 Magnetic tape 

Stallings: read section 6.5. The principles on which magnetic tape storage devices
function are described.

131
COS2621/102/3/2023

10.6 Summary 

Make sure that you understand the meaning of the key terms listed in this section.

10.7 Key Questions 

Work through the review questions at the end of the chapter.

---ooo0ooo---
COS2621/102/3/2023

Study unit 11
Input / Output

This study unit supplements chapter 7 of Stallings. Various aspects of Input/Output are
discussed including the operation of some external devices, the operation of I/O modules
and different I/O methods. Stallings also discusses external I/O interfaces like FireWire
and InfiniBand.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

 name different device categories


 discuss the functions and structure of I/O modules
 describe the principles of Programmed I/O
 describe the principles of Interrupt-driven I/O
 describe the principles of DMA
 discuss the evolution and characteristics of I/O channels
 describe different types of I/O interface
 explain the principles of point-to-point and multipoint configurations
 discuss the way in which a InfiniBand serial bus functions
 discuss the principles of Thunderbolt architecture

133
COS2621/102/3/2023

Stallings

Study sections 7.1 - 7.3, the first part of section 7.4, and sections 7.5 - 7.7.

Read the last part of section 7.4.


COS2621/102/3/2023

11.1 External devices 

Stallings: study section 7.1. The different categories in which external devices can be
classified are discussed. We look in some detail at the operation of the keyboard and
monitor and also disk drives. Note that ASCII is the US version of IRA referred to in this
section.

11.2 I/O modules 

Stallings: study section 7.2. The most important functions, as well as the structure of an
I/O module are discussed.

11.3 Programmed I/O 

Stallings: study section 7.3. The way in which Programmed I/O operates is discussed.

Stallings also gives a short description of the I/O commands as well as I/O instructions.

It is important to study this section together with the following two sections to clearly
understand the advantages and disadvantages of each method of communication.

11.4 Interrupt‐driven I/O 

Stallings: study section 7.4 up to (but not including) the section on the Intel Interrupt
Controller. Make sure that you understand how interrupts are used to implement this type
of I/O communication and that you can discuss the relevant design issues involved when
this method is used.

135
COS2621/102/3/2023

Read the rest of the section.

11.5 Direct Memory Access (DMA) 

Stallings: study section 7.5. The principles of Direct Memory Access I/O are discussed.
Note the comments regarding Programmed I/O and Interrupt-driven I/O.

11.6 I/O channels and processors 

Stallings: study section 7.6. Stallings gives a summary of the evolution of the I/O
function in computers. The characteristics of I/O channels are also considered.

11.7 The external interface: Thunderbolt and  InfiniBand 

Stallings: study section 7.7. Different types of interface are first considered and then

Stallings discusses point-to-point and multipoint configurations.

The principles of Thunderbolt technology are explained and we look at the configurations
involved. You need not go into the protocol details. You can read on the Internet about
Thunderbolt version 2 as well.

Stallings also discusses InfiniBand architecture. You need not go into the protocol details
(InfiniBand operation).

You can ignore section 7.8.

11.8 Summary 

Stallings: section 7.10. Make sure you understand the meaning of all the key terms in
this section.

11.9 Key Questions 

Work through the review questions at the end of the chapter.

----oooOooo----
COS2621/102/3/2023

Notes
Study unit 12
Reduced Instruction Set Computers
18

This study unit supplements chapter 15 of Stallings. RISC and CISC design principles, as
well as the RISC vs CISC controversy are discussed. Stallings also considers compiler-
based register optimisation.

Learning outcomes

Once you have mastered the study material in this study unit, you will be able to

 explain the advantages of using a large number of registers


 discuss the way in which compilers optimise register usage
 discuss the evolution of CISC machines
 describe the characteristics of RISC architectures
 discuss the RISC vs CISC controversy
 describe the way in which RISC and CISC design principles can be combined

Stallings

Study sections 15.1 - 15.4 and section 15.8

Read sections 15.5 - 15.7

137
COS2621/102/3/2023

12.1 Instruction execution characteristics 

Stallings: study the introduction to this chapter as well as section 15.1. The way in
which an instruction is executed is once again revised to help us understand what CISC
and RISC design principles are all about.

12.2 The use of a large register file 

Stallings: study section 15.2. One of the most important design principles of RISC
machines is the use of a large number of registers. The concept of register windows and
the use of a large register file versus the use of cache memory are discussed.

12.3 Compiler‐based register optimisation 

Stallings: study section 15.3. Compiler-based optimisation is discussed and the trade-
off between using this, rather than a large set of registers, is also considered.

12.4 Reduced Instruction Set Architecture  (RISC) 


Stallings: study section 15.4. The design principles of CISC machines versus RISC
machines are discussed. Each approach has its own advantages and disadvantages and it
was inevitable that these principles would be combined in some machines.

Stallings: read sections 15.5 - 15.7.

12.5 The RISC vs CISC controversy 

Stallings: study section 15.8. The merits of both the RISC and the CISC approaches
are discussed.

12.6 Summary 
Make sure you understand the meaning of all the key terms in this section.

12.7 Key Questions 
COS2621/102/3/2023

Work through the review questions at the end of the chapter.

---ooo0ooo---

19 Appendix A
20 The DOS DEBUG environment

Contents

A.1 Introduction

A.2 How to start DEBUG

A.3 DEBUG commands

A.3.1 A (Assemble)

A.3.2 R (Register)

A.3.3 T (Trace)

A.3.4 G (Go)

A.3.5 P (Proceed)

A.3.6 D (Dump or Display)

A.3.7 U ("Unassemble")

139
COS2621/102/3/2023

A.3.8 E (Enter)

A.3.9 N (Name)

L (Load)

W (W it )
A.3.10 H (Hexadecimal)

A.3.11 I (Input)

A.3.12 Q (Quit)

Note

 DEBUG does not allow variable names or labels. We have to work with actual
memory locations.
COS2621/102/3/2023

A.1 Introduction

DEBUG, which forms part of DOS within the Windows environment, is very useful for
writing and debugging small machine language and assembly language programs. We
suggest that you execute all the commands on your machine as you work through this
appendix. You will not learn much by just reading this section without using DEBUG.

We suggest that you create a directory (folder) called C2621 to store the programs that
you write for this module.

A.2 How to start DEBUG

Open a DOS-window, go to the C2621 directory by typing cd \c2621, and type debug
at the DOS prompt. DEBUG responds with a hyphen (-) called the ‘DEBUG prompt’.

c:\c2621>debug <Enter>

<Enter> means that you must press the Enter key.

A.3 Debug commands

A.3.1 A (Assemble)

The "a” command translates assembly language source statements into machine
code. One can use the "a" command to write and test small assembly language
programs.

141
COS2621/102/3/2023

We will now create a short program consisting of only six instructions. We want to
store this program from memory address 100h (h signifies a hexadecimal number).

At the DEBUG prompt, type the following:

a 100 and press the Enter key.

Key in the program as listed below and press the Enter key TWICE after you have
finished entering the program. We will use this program in the following sections to
explain some of the DEBUG commands. Do not get upset if you make a typing error as
you can always change a specific instruction. We will explain how to do this shortly.
DEBUG will warn you if you key in an illegal instruction and you will be allowed to key
in the correct one.

Example: (Your entries are shown in italics and DEBUG's responses in bold - DO NOT
TYPE the hyphen (-).) Type in only the instructions shown in italics.

(Ignore the first step (-a 100 <enter>) if you have already entered it.)

 a 100 <Enter>

nnnn:0100 mov ax,0015 <Enter>

nnnn:0103 mov cx,0023 <Enter>


COS2621/102/3/2023

nnnn:0106 sub cx,ax <Enter>


nnnn:0108 mov [120],al <Enter>

nnnn:010B mov cl,[120] <Enter>

nnnn:010F nop <

nnnn:0110 <EnE

nt

nnnn might differ from session to session. This is the address of the code segment,
which need not concern you at this stage. The numbers following after nnnn are
memory addresses specifying the address (called the "offset") at which each
instruction is stored.
.

The program is stored from position 0100h to position 010Fh in memory (remember
that, in DEBUG, all references to memory and all values are assumed to be in
hexadecimal). The length of the program in memory is: (010F - 0100 + 1) = 10h bytes.
You may have noticed that instructions may be one, two or three bytes in length. The
first byte contains the opcode and the other byte(s) contain(s) the operand(s). The
NOP instruction is an example of a one-byte instruction. The first two MOV
instructions occupy three bytes each, and the instruction SUB CX,AX occupies two
bytes. The last two MOV instructions occupy three and four bytes respectively. (You
may find it strange that these two MOV instructions are of different lengths. This is due
to the instruction format of the x86 machines. Instructions that involve the AX register
are sometimes shorter than similar instructions involving other registers.)

The AX-register is also called the accumulator.

You can change any of the instructions at any stage. Suppose that you made a typing
error and have typed SUB AX,AX instead of SUB CX,AX. You need not retype the
whole program. You may correct the instruction in the relevant memory locations

143
COS2621/102/3/2023

provided that the new instruction is of the same length as the one that it replaces,
otherwise it will overwrite the instruction that follows it. Type a (at the DEBUG prompt),
followed by the memory address where you want to store the corrected instruction.

- a 106
sub cx,ax <Enter>

nnnn:0108 <Enter>

A.3.2 R (Register)

The"r" command displays the contents of registers and allows you to change this
value.

r Display the contents of all the registers

rf Display the flags register

r register_name Display the contents of a specific register

Example to display and change the contents of the IP register:

- r ip <Enter>

IP 0180 This means that the current value of IP is 0180h. (You can now enter a
new value to be loaded into IP or press Enter to leave the register unchanged.)

A.3.3 T (Trace)
COS2621/102/3/2023

The "t" command allows you to execute a program step by step. We are now ready to
execute the program that we have entered and to inspect the registers after the
execution of each instruction. Enter the program as described under the Assemble
command (if you have not yet entered it). We want to execute instructions from
address 100h and must ensure that the IP register, which acts as the program counter,
contains the value 100h. To do this we use the "r ip" command and reset IP to 100h.
We will then enter the "t" command repeatedly until we get to the NOP instruction.

N.B. Do not  execute the instructions following  the "nop". We  do not know which instructions  or 


data might be stored there and something unforeseen might happen.  Reboot your machine and 
start again if things go wrong. 

The IP (Instruction Pointer) always points to the next instruction to be executed.

(Remember that your entries are printed in italics, DEBUG's responses in bold, and
comments in brackets):

145
COS2621/102/3/2023

Reset the IP register to 100h:

- r ip <Enter>

IP hhhh (hhhh is a 4 digit hexadecimal number. Key in 100 to set IP to


100h)

:100 <Enter>

We will now execute the program by tracing it instruction by instruction. We do this by


giving DEBUG the "t" (for trace) command repeatedly. The instruction starting at the
memory location pointed to by IP (i.e. 100h) will be executed first. In the explanation
that follows, we give a step-by-step explanation of the consequences of the execution
of each instruction.

Type:

t (at the debug prompt.) <Enter>

The instruction MOV AX,0015 stored at memory location 100h is executed. Examine
the contents of the AX, CX and IP registers after the execution of each instruction.

The response is as follows (after MOV AX,0015):


COS2621/102/3/2023

AX=0015 BX= CX=

IP=0103 NV UP EI PL NZ NA PO NC

nnnn:0103 B92300 MOV CX,0023

Your display will look slightly differently. We only show the information that interests us
at this stage.

First line of display above: The AX register contains 0015h as expected.

Second line of display above: IP points to address 0103h, which is the next
instruction to be executed. NV, UP, EI, PL, NZ, NA, PO and NC represent the status
flags. The ones that we are interested in are the following:

The first one - the Overflow flag. NV means No Overflow. OV means Overflow
occurred.

The fourth one - the Sign flag. PL means that the sign of the previous arithmetic
operation was PLus (positive). NG means it was NeGative.

The fifth one - the Zero flag. NZ means that the result of the previous arithmetic
operation was Not Zero. ZR means that is was ZeRo.

The last one - the Carry flag. NC means that No final Carry resulted from the previous
arithmetic operation. CY means that there was a final CarrY.
COS2621/102/3/2023

Third line of the display above: The hexadecimal number B92300h is stored at
segment nnnn and offset (address) 0103h. This value, i.e. B92300h, is the
hexadecimal representation of the machine code for the assembly language instruction
MOV CX,0023. This instruction is to be executed next since IP points to 0103h. Type t
again to execute the instruction pointed to by IP (the one in 0103h).

- t <Enter>

AX=0015 BX= CX=0023

nnnn:0106 29C1 SUB CX,AX

The contents of AX remain unchanged and 0023h is stored in CX as expected. IP


contains 0106h and points to the next instruction, i.e. SUB CX,AX, which is stored
from memory address 0106h. The machine code for this instruction is 29C1. Type t
again.

- t <Enter>

IP=0108 NV UP EI PL NZ AC PO NC

nnnn:0108 A22001 MOV [0120],AL DS:0120=??

151
COS2621/102/3/2023

The contents of AX remain unchanged. CX now contains 000Eh which is the result of
the subtraction. IP points to 0108h which contains the instruction MOV [0120],AL.
(Remember that AL is the low-order byte of AX). The machine code of the instruction
MOV [0120],AL is A22001h.
COS2621/102/3/2023

Note that additional information appears on the right-hand side of the third line of the
DEBUG display above. This tells us that memory location 0120h will be addressed
during the next instruction. At the moment it can contain anything (we indicated "any-
thing" by ??) that was stored there previously. Type t again.

- t <Enter>

AX=0015 BX= CX=000E

nnnn:010B 8A0E2001 MOV CL,[0120] DS:0120=15

The contents of AX and CX remain unchanged. IP points to the next instruction, for
example MOV CL,[0120], which is stored at memory address 010Bh (CL is the low-
order byte of CX). The machine code for this instruction is 8A0E2001h. The memory
location at address 120h now contains 15h. Type t again.

-t <Enter>

AX=0015 CX=0015

nnnn:010F 90 NOP

153
COS2621/102/3/2023

The contents of AX remain unchanged. The contents of memory address 0120h were
loaded into CL and it now contains 15h as expected. CH remains unchanged. IP
points to the next instruction, for esample NOP, which is stored from memory address
010F. The machine code for this instruction is 90h.

A.3.4 G (Go)

The "g" command executes a program up to a certain specified point (called a


breakpoint). Let us suppose that we are debugging a huge program and that we know
the exact location in memory (hundreds of statements from the beginning) at which
things start going wrong. It will be tedious to use the trace option to reach this point.
By specifying a breakpoint we can tell DEBUG to GO until this breakpoint is
encountered.

Suppose we want to execute up to location 108h. the instruction in 108h will be the one
which IP will point to when execution is halted. Reset IP to 100h and type g 108. All
the instructions of the program will be executed up to but not including the instruction
at address 108h.

NOTE: When we enter DEBUG commands, we do not type "h" to indicate hexadecimal
numbers since all numbers are assumed to be in hexadecimal.

A.3.5 P (proceed)

[NB: Use Proceed instead of Trace or Go when the next instruction to be executed is
COS2621/102/3/2023

an INT.]

The "p" command is similar to Trace except when instructions such as CALL, INT and
LOOP are encountered. If "p" is used, DEBUG will perform ALL the machine code
instructions associated with the instruction and will stop at the instruction following the
CALL, INT or LOOP. Proceed can be used to avoid tracing all the instructions of loops
or subroutines of which we do not want to see the detail. It will also avoid tracing
system calls like interrupts (INT instructions).

We will now add a new instruction, INT 20, to our program. We assume that you still
have the program in memory and that you are still in DEBUG. (If not, key in the
program again.)

Type:

- a 110 <Enter>
<Enter>
nnnn:0110 int 20

The INT 20 instruction causes the program to terminate and return to DEBUG.

Rerun your program and type p when INT 20 has to be executed. DEBUG will respond
with:

program terminated normally

-
A.3.6 D (Dump or Display)

155
COS2621/102/3/2023

This command can be used to examine in more detail the way our assembly language
instructions, and the data that is defined within the program, are stored in memory.

The "d" command displays a portion of memory in hexadecimal. d 100 10F will display
(list) the contents of memory locations from address 100h up to 10Fh.

- d 100 10F <Enter>

DEBUG responds with:

nnnn:0100 B8 15 00 B9 23 00 29 C1-A2 20 01 8A 0E 20 01 90

This is how the program is stored in memory - each instruction following immediately
after the previous one.

A.3.7 U ("Unassemble")

The u command "unassembles" (rather "disassembles") machine code instructions.


We can use this command to list the assembly language instructions associated with a
program stored in memory. U 100 10F will "unassemble" the instructions from memory
addresses 100h up to 10Fh. (It attempts to translate machine code instructions to
assembly language instructions.)
COS2621/102/3/2023

- u 100 10F <Enter>

DEBUG responds with:

nnnn:0100 B81500 MOV AX,0015


nnnn:0103 B92300 MOV CX,0023

nnnn:0106 29C1 SUB CX,AX

nnnn:0108 A22001 MOV [0120],AL

nnnn:010B 8A0E200 1MOV CL,[0120]

nnnn:010F 90 NOP

A.3.8 E (Enter)

The "E" command can be used for different purposes. We can use this command to
enter data or machine code instructions directly into memory. Type "e" (at the
DEBUG prompt) followed by the address and then the data or machine code that you
want to store in the memory locations, starting at the specified address.

Examples:

157
COS2621/102/3/2023

- e 106 23 67 2a <Enter>

Enter byte values. The values 23h, 67h and 2Ah will be stored in the three memory
iti 106h 107h d 108h ti l

- e 109 "I enjoy using DEBUG" <Enter>

Enter a character string. Each ASCII character in this string occupies 1 byte. The first
character, i.e. ‘I’, is stored in position 109h, the second in 10Ah and so on.

- e 108 29 C1 <Enter>

Enter the instruction SUB CX,AX (machine code 29C1h) directly into memory positions
108h d 109h

We can also use e to display the contents of memory locations.

Example: Display the contents of memory positions 108h and 109h.

- e 108 <Enter>

119C:0108 29. <Enter>

- e 109 <Enter>
COS2621/102/3/2023

119C:0109 C1. <Enter>

This means that 108h contains 29h and 109h contains C1h.

159
COS2621/102/3/2023

A.3.9 N (Name), L (Load) and W  (Write)

Suppose we created a program under DEBUG and we want to store this program for
future use. The "n" command is used to give a name to the executable program file in
which we want to store the program. The "w" command is used to write the file to disk,
but we must first specify how many bytes must be written. The combination of the BX
and CX registers (BX:CX) that forms a 32-bit register, is used to specify the number
of bytes to be written. Our programs are going to be relatively small, so BX will
normally contain 0000 and CX the size (in bytes) of the program.

Suppose we want to write 66h bytes, starting from memory location 100h. We want to
name the program beep.com. (Remember that we can only assemble .com files with
DEBUG.) Type the following at the DEBUG prompt:

-r bx <Enter.

bx ???? <Enter>
:0000

<Enter>
-r cx

cx ????

writing 66 bytes

The "l" command will load the contents of the current file into memory from address
CS:100 onwards. Thus, to load a file from disk into memory starting at location 100h, we
will type:
COS2621/102/3/2023

-n beep.com

-l

Note that we must first name the file.

CX will contain the length of the file after the load has been completed. In general, as we
have explained above, the 32-bit register which is formed by the combination of the BX
and CX registers, gives the length of the file being loaded/written. BX contains the high-
order and CX the low-order part of the file length. For small files, BX = 0 and CX contains
the length.

A.3.10 H (hexadecimal)

The "h" option is quite handy and can be used to do addition and subtraction of two
hexadecimal numbers.

Example: -h 65 23

0088 0042 

This means that 65h + 23h = 0088h and that 65h - 23h = 42h.

A.3.11 I (Input) and O (Output)

The "I" option is used to input and display one byte from a port, and the "o" option to
send one byte to a port.

A.3.12 Q (Quit)

Type q at the DEBUG prompt to exit from DEBUG and return to DOS.

161
COS2621/102/3/2023

21 Appendix B
22 NASM: THE NETWIDE ASSEMBLER

CONTENTS

B.1 Introduction

B.2 How to start NASM

B.3 Layout of a NASM source line

B.4 Assembling a complete program

B.5 Pseudo-instructions

B.6 Constants

B.6.1 Numeric constants

B.6.2 Character constants

B.6.3 String constants

B.6.4 Floating-point constants

B.7 Reserving space for data

B.7.1 Declaring initialised data


COS2621/102/3/2023

B.7.2 Declaring uninitialised data

B.7.3 Defining a symbolic constant

B.8 Repeating instructions

B.9 Local Labels

B.10 Critical expressions

B.11 Developing a modular program

163
COS2621/102/3/2023

B.1 Introduction

NASM (The Netwide Assembler) is an assembler for x86 assembly language. We will use
NASM to assemble x86 assembly language programs and create executable (.com) files.
However, we will use DEBUG to step through and debug our programs.

In this section we are going to show you how to use NASM. Note that this appendix was
compiled from the NASM User Manual available on the web. The assembly language
instructions for the Intel x86 are listed in Appendix E.

B.2 How to start NASM

You need to have a copy of NASM.exe in the directory (folder) in which you want to work,
say C2621. Create your source file and give it any name with an .asm file extension (we
will explain in section B3 how this should be done). Then type:

nasm -f bin name.asm -o name.com -l name.lst

where name.asm is the name of your source file containing assembly language
instructions,

name.com is the executable file that is created by NASM, and

name.lst is the output listing file that is produced by NASM.

(Note: -o is the alphabetic character "o" and not the digit zero, and -l is the alphabetic
character "l" and not the digit one.)
COS2621/102/3/2023

An .lst file will only be created once your source file is free of syntax errors. However, while
there are syntax errors in the source file, error messages with appropriate line numbers
will appear on the screen.

Making your life easier: When you install NASM on your machine from the CD that is
provided when you register for this module, a file called as.bat is also copied to your nasm
directory. We include this file to make the assembly process much easier. Instead of typing
the assembly line as given above, you need only type

as name

where "name" is the name of your program. The as.bat file will generate the assembly line
and your program will be assembled.

165
COS2621/102/3/2023

B.3 Layout of a NASM source  line

As is the case with most assemblers, each NASM source line is a combination of four
fields.

Field 1 Field 2 Field 3 Field 4

Label: Opcode Operand(s) ; Comment

Label1: mov ax,bx ;Move the contents of BX to AX

Most of these fields are optional; the presence or absence of any combination of a label,
an instruction and a comment is allowed. The type of instruction will determine the number
of operands (0 or more) the relevant instruction requires. (Appendix E contains a list of the
Intel x86 instructions.)

Spaces are allowed within a line. Labels may have spaces before them. The colon after a
label is optional, but we use it for the sake of clarity.

Labels: Valid characters in labels are letters, numbers, _, $, #, @, -,. (full stop), and ?
(question mark). Generally, the first character of an identifier (a label or a variable/constant
name) must be a letter. There are two exceptions to this rule:

 An identifier may be prefixed with a $-sign to indicate that it is intended to be


read as an identifier and not a reserved word. Thus, you can use an identifier
$EAX in your program; the $ as the first character distinguishes the identifier
from the EAX register.
 If a period is used as the first character of a label it means that the label is
local. (See Section B.9 for a discussion of local labels.)

Instructions: The opcode field contains the mnemonic (abbreviation) of the operation to
be performed by the instruction. Examples of mnemonics are the following:
COS2621/102/3/2023

MOV for moving data between registers, or between a register and memory,
and

SHL for shifting the contents of a register to the left.

Operands: Operands may take a number of forms. They can be

 registers, for example: AX, BX, CX


 labels or variable names, for example: mess, str1, loop1
 addresses, for example: the address 103, or [103] for the contents of address
103
 constants, for example: the decimal number 103, or 0xAB01 (the hex number
AB01)

B.4 Assembling a complete program

Enter the assembly language program given below using a text editor and save it as
prog1.asm. You have to use an ASCII editor. Notepad and Edit are suitable editors. The
program displays the message 'Hello World’ on the screen. (Note that the line number
must not be entered. We only give the line numbers for the explanation that follows.)

Open two DOS windows, one to run NASM and the other one for the editor. Work through
the following steps if you are not familiar with the way to do this. Keep all your NASM
programs in one folder (directory). We called our folder C2621. Create this folder and copy
the program files NASM.exe and AS.BAT to it.

Step 1 Right click on the DOS icon (or Command prompt for newer Windows
versions) on your PC. Select properties on the drop-down window. Select
screen and choose Window under Usage.

167
COS2621/102/3/2023

Step 2 Open a DOS window by double clicking on the DOS icon on your PC. You
should be in the NASM directory at this point.

Step 3 Type edit to use the standard editor. Use this editor to key in your program.
Save it with the name prog1.asm. Your program should be saved in the the
NASM directory.

Step 4 Minimise the Window in which edit is running.

Step 5 Open up a second DOS Window to run NASM. Type doskey. By enabling
the Doskey facility you can use the up and down arrow keys on your keyboard
to display and reuse previously entered DOS commands in the command line.
(On some machines this is not necessary since doskey is active by default.)

Step 6 We are now ready to assemble our first program. Type:

as prog1

The program will be assembled by NASM using the .ASM file as input and the
.LST and .COM files will be generated.

Step 7 If there are any syntax errors, minimise the Nasm window, maximise the edit
window and edit your program. Remember to save it again.

Repeat this Repeat the editing and assembling of your program until it is error-free. When
step back in the NASM window, use F3 to repeat the previous DOS command that
had been entered or use the up and down arrow keys on your keyboard to
display previous entered DOS commands in the command line.

Step 8 Run your program by typing prog1 in the DOS command line. The message

'Hello World' should be displayed on your screen.

When Close the DOS Windows by typing exit.

finished
COS2621/102/3/2023

Prog1.asm (Do not enter the line numbers; we only use line numbers in order to refer to
individual lines in the explanation that follows. Your listing file (ie the prog1.lst file) will have
line numbers):

1 bits 16
2 org 0x100 ; Start program at offset
100h
3 jmp main ; Jump to main program
4 message: db 'Hello World',0ah,0dh,'$'
5 main: mov dx,message ; Start address of message
6 mov ah,09 ; Prepare for
screen display

7 int 21h ; DOS interrupt 21h


8 int 20h ; Terminate program

Line 1: Compiler directive for using 16 bits. This is sufficient for our purposes.

Line 2: All .com programs start execution at offset 100h. For this reason, we start our
assembly at address 100h.

Line3: The convention we use is to have all data declarations at the beginning of the
program. Because execution always starts at address 100h, we jump to the first
executable instruction of the program.

Line 4: We declare a string ‘Hello World’ which we want to display on the screen. The
values 0ah and 0dh, which form part of the string to be displayed, are the ASCII characters
for a line feed and carriage return respectively. After displaying the message, the cursor

169
COS2621/102/3/2023

will thus go to the beginning of the next line. The ‘$’ sign at the end of the string indicates
the end of the output message.

Line 5: The main program starts here. Most of the I/O is done by means of the INT
instruction. The I/O is handled either by DOS or by BIOS. (Refer to Appendix D for details.)
We want to display a message on the screen and for this we make a request to DOS (also
called a DOS system call) by issuing the instruction int 21h. For such a system call,
DOS obtains details of the I/O request from certain registers. In lines 5 and 6, we set up
the registers for the INT 21h call to display a message on the screen. DX points to the start
address of the output message.

Line 6: For INT 21h, the AH register is used to tell DOS what I/O we want it to handle.
AH = 09 means that we want to display a message on the screen. (See Appendix D.3.)

Line 7: We use a software interrupt to hand control over to DOS which will handle the
I/O that we requested. DOS will display the message on the screen and return control to
our program.

Line 8: INT 20h terminates the program and goes back to DOS.

You can now use the text editor to inspect the NASM output, i.e. the prog1.lst file.
COS2621/102/3/2023

1 bits 16

2 org 0x100 ; Start program at 100h

3 00000000 E90E00 jmp main ; Jump to main program

4 00000003 48656C6C6F20576F72 message: db 'Hello World',0ah,0dh,'$'

5 0000000C 6C640A0D24

6 00000011 BA[0300] main: mov dx,message ; Start address of message

7 00000014 B409 mov ah,09 ; Screen display

8 00000016 CD21 int 21h ; DOS interrupt 21h

9 00000018 CD20 int 20h ; Terminate program

10

Note the following points when you study the .lst file:

The are four columns in the listing file:

Column 1: Line numbers (in decimal) as allocated by NASM. These numbers do not
necessarily correspond to the lines in your assembly language program. See lines
4, 5 and 6, for example.

Column 2: The addresses (in hexadecimal) corresponding to the instructions. Note that
these addresses are relative to address 100h. Look at line 4 above, for
example. The relative address is 3, but our program starts at 100h. This means
that the offset at which this message is stored is 103h.

Column 3: The hexadecimal representation of the machine code for each instruction or
data item.

Column 4: Assembly language instructions.

Debugging: To debug the program, type debug prog1.com at the DOS prompt.

171
COS2621/102/3/2023

DEBUG will load your program and you can execute it step by step to trace the execution
of the individual instructions as we have illustrated in Appendix A. Do an Unassembly of
the program. You will see that, in the DEBUG listing, the offset of 100h has already been
added to the addresses. Look at the machine code for the mov dx,mess instruction.

Debug gives it as: BA0301

NASM gives it as: BA[0300]

These two machine code instructions refer to the same memory position. The DEBUG
address refers to offset 103h in memory. The NASM instruction refers to relative address 3
which, when added to the offset of 100h, is equal to 103h.

B.5 Pseudo‐instructions

In addition to machine instructions, an assembly language program can also contain


commands to the assembler itself. One may, for example, ask the assembler to allocate
storage space. These commands are called pseudo-instructions. We are interested in the
following pseudo-instructions:

 DB, DW, DD, DQ and DT which are used to allocate storage space and initialise the
space to specified values
 RESB, RESW, RESD, RESQ and REST which allocate (reserve) storage space but
do not initialise it
 the EQU command for defining constants
 the TIMES prefix for repeating instructions or data

We will return to these pseudo-ops (in Section B.7) once we know what format NASM
expects data to be in.
COS2621/102/3/2023

B.6 Constants

Four types of constant can be defined: numeric, character, string and floating-point.

B.6.1 Numeric constants

A numeric constant is simply an integer. NASM allows integers to be specified in binary,


decimal, octal or hexadecimal representation.

NOTE: Decimal is the default.

Hexadecimal: suffix H (or h) or prefix 0x in the style of C.

We will use h or 0x.

Octal: suffix Q (or q)

Binary: suffix B (or b)

Examples: mov ax,100 ; Move the decimal number 100 to


the AX register

mov ax,9ah ; Move the hex number 9A to the AX


register

mov ax,0xa2 ; Move the hex number A2 to the AX register

; NASM requires the prefix 0x if the hex number starts with a letter

; If the prefix 0x is not given, the hex number is treated as a label

173
COS2621/102/3/2023

mov ax,777q ; Move the octal number 777 to the AX register

mov al,10010011b ; Move the binary number 10010011 to the


AL register

B.6.2 Character constants

A character constant consists of up to four characters enclosed in either single or double


quotes. The type of quotes used makes no difference to NASM. However, the use of
single quotes allows double quotes to appear within the constant and vice versa. A
character constant which consists of more than one character will be stored in little-endian
byte order (refer to Stallings, pages 381 - 385). In the case of mov ax,'ab', the constant
generated is 0x6261 and not 0x6162. However, if you store the value in memory, it will read
'ab' and not 'ba'. Create a source file as follows:

org 0x100 mov

ax,'ab' mov

[120h],ax

Listing file:

1 org 0x100
2 00000000 B86162 mov ax,'ab'
3 00000003 A32001 mov [120h],ax

Use DEBUG to execute the program (ie the .com file that is created by NASM) and inspect
the AX register and memory locations 120h and121h. You will find that AX = 6261h that
represents 'ba', while memory positions 120h and 121h contain 'a' and 'b' respectively. We
generally restrict the use of character constants to those consisting of only one character.
COS2621/102/3/2023

B.6.3 String constants

NASM distinguishes between character constants and string constants. Character


constants have a maximum length of four (more than four characters cannot fit into a 32-
bit register). A string constant (character string) looks like a character constant but may be
longer than four characters. Character strings can be defined using the DB and DW pseudo-
instructions. This means that db 'ab' will reserve two bytes. According to the NASM
manual:

"When used as an operand to db, a constant like 'ab' is treated as a string constant despite
being short enough to be a character constant, because otherwise db 'ab' would have the
same effect as db 'a', which would be silly. Similarly, three-character or four-character
constants are treated as strings when they are operands to dw. "

Let us look at a few examples: The following two declarations are equivalent:

db 'hello' ; String constant, 5 bytes are reserved

db 'h','e','l','l','o' ; This has the same effect: 5 bytes

; are reserved

Note that dw 'hello' is not equivalent to the above. The DW directive reserves words
(multiples of two bytes). In this case 6 bytes are reserved with the number 0 concatenated
at the end.

The DD directive reserves double words (ie multiples of four bytes).

The following two declarations are also equivalent:

dd 'ninechars' ; Doubleword string constant, 12


bytes
; are reserved

175
COS2621/102/3/2023

dd 'nine','char','s' ; Becomes three doublewords


(multiples of
; 4 bytes, 12 bytes in this case),
; concatenated at the end with three
; bytes, each containing 0 (zero).

To get the equivalent of the above using the db directive, we have to code

db 'ninechars',0,0,0

The following is the output listing of a small program to illustrate the above:

1 00000000 6E696E656368617273- dd 'ninechars'


2 00000000 000000

3 0000000C 6E696E656368617273- db
'ninechars',0,0,0
4 00000015 000000
5 00000018 68656C6C6F db 'hello'
6 0000001D 68656C6C6F db 'h','e','l','l','o'
7 00000022 68656C6C6F00 dw 'hello'
8 00000028 90 nop

From the above we see that string constants are extended to occupy a multiple of the
number of bytes associated with the relevant pseudo-operation.

(DB reserves 1, 2, 3, 4, etc. bytes; DW reserves 2, 4, 6, 8, etc. bytes; DD reserves 4, 8,


12, 16, etc bytes.)
COS2621/102/3/2023

B.6.4 Floating‐point constants

We will not use floating-point constants in the COS2621 module, but we include them for
interest’s sake. Floating-point constants are acceptable only as arguments to DD, DQ and
DT. They are expressed in the traditional form: digits, then a period, then optionally more
digits, then optionally an E followed by an exponent. The period is mandatory, so that
NASM can distinguish between dd 1, which declares an integer constant, and dd 1.0
which declares a floating-point constant.

Some examples:

dd 1.2 ; An easy one


dq 1.e10 ; 10,000,000,000
dq 1.e+10 ; Same as 1.e10
dq 1.e-10 ; 0.000 000 000 1
dt 3.141592653589793238462 ; pi

B.7 Reserving space for data

B.7.1 Declaring initialised data

DB, DW and DD are used to reserve space and to initialise these storage positions.

DB: define byte: 

db 0x55 ; Initialise one byte to 55h

177
COS2621/102/3/2023

db 0x55,0x56,0x57 ; Initialise three bytes to 55h, 56h


and 57h
; respectively
db 'a' ; Initialise one byte to 'a' (ASCII
61h)
db 'hello',13,10,'$' ; String constant 'hello', followed by
the

; decimal numbers 13 and 10 and the $-sign

DW: Define word (2 bytes) 

dw 0x1234 ; Initialise one word (two bytes)


to 1234h
; Note that these will be stored in
; reverse byte order in memory.
dw 'a' ; 0x61 0x00 (ASCII 'a' = 61h)
dw 'ab' ; 0x61 0x62 (ASCII 'a' and 'b'
; are equal to 61h and 62h respectively)
dw 'abc' ; 0x61 0x62 0x63 0x00 (string)
; Note that strings are not stored in
; reverse byte order

DD: Define double word (4 bytes) 

dd 0x12345678 ; Store the hex value 12345678 in one double


; word (stored in reverse byte order in memory)
dd 1.234567e20 ; Floating-point constant occupying 4 bytes
COS2621/102/3/2023

Activity B-1:

Set up a source file (let us call it db_dw.asm) with the following instructions:

bits 16
org 0x100 ; start program at offset
100h
L1: db 0x55
L2: db 0x55,0x56,0x57
L3: db 'a',0x55
L4: db 'hello',13,10,'$'

L5: dw 0x1234
L6: dw 'a'
L7: dw 'ab'
L8: dw 'abc'
L9: dd 0x12345678
L10: dd 1.234567

Use NASM to assemble this program. Then type debug db_dw.com to load the
executable file, and display from memory position 100h (refer to Appendix A, section
A.3.6). Let us investigate how the above data is stored in memory.

The dump is as follows (remember that all the values in the display are in hexadecimal):

0100:55 55 56 57 61 55 68 65 - 6C 6C 6F 0D 0A 24
34 12

179
COS2621/102/3/2023

corresponding to: 55h 55h 56h 57h a 55h h e - l l o 1310 1010 $


0x1234

0110:61 00 61 62 61 62 63 00 - 78 56 34 12 4B 06
9E 3F

corresponding to: a 00 a b a b c 00 - 0x12345678


1.234567

Note the following important points:

- The insertion of 00h in cases where DW was used and an uneven number of
characters was specified.

- The fact that dw 0x1234 stores the value 1234h in reverse byte order, while dw
'ab' does not.

B.7.2 Declaring uninitialised data

RESB, RESW and RESQ can also be used to reserve space but these pseudo-
instructions do not initialise the reserved storage positions.

Examples:

buffer: resb 64 ; Reserve 64 bytes


wordvar: resw 1 ; Reserve one word
realarray: resq 10 ; Reserve an array of ten
uninitialised
; floating-point numbers
COS2621/102/3/2023

B.7.3 Defining a symbolic constant

The pseudo-instruction EQU can be used to assign a name to a given constant value. This
is called a symbolic constant. When EQU is used, the source line has to contain a label.
The action of EQU is to associate the given label name with the value of the operand. This
definition is absolute, and cannot change later. (This happens at assembly time.) The
following program illustrates the concept:

2 00000000 E90500 jmp main


3 00000003 68656C6C6F message: db 'hello' ; Define
string (5 bytes)
4 msglen: equ $-message ; Defines msglen (=5)
5 00000008 B80500 main: mov ax,msglen

Use DEBUG to load the resulting .com file. Do an "unassembly" of the program and you
will notice that the instruction mov ax,msglen has been assembled to mov ax,0005.

The value of msglen is evaluated once only and is calculated as follows: msglen is equal
to the current memory address (ie 0008) minus the address of message (ie 0003). This
means that EQU associates $ with the current value of the program counter. In the
example given above, $ evaluates to the memory position at the beginning of the line
containing msglen (0008). Thus:

$ - memory_position_of_message = 8 - 3 = 5

Note that the operand to an EQU is a critical expression (see section B.10) and msglen
cannot be redefined later.

181
COS2621/102/3/2023

B.8 Repeating instructions

The TIMES pseudo-instruction causes the instruction (or pseudo-instruction) immediately


following it to be assembled a number of specified times.

For example:

times 10 db 'z'

will reserve 10 bytes and initialise these to the ASCII character 'z'. This means that the
pseudo-instruction db 'z' is repeated 10 times.

The argument to TIMES does not need to be a numeric constant. It can also be an
expression, as can be seen from the following example:

buffer: db 'hello world'


times 64-$+buffer db ' '

The second pseudo-instruction given above will store exactly enough extra spaces to
extend the total length of buffer to 64.

TIMES can also be applied to assembly language instructions, so we can code trivial loops
with it:

times 100 movsb


COS2621/102/3/2023

Note that there is no effective difference between

times 100 resb 1 and resb 100

except that the latter will be assembled about 100 times faster due to the internal structure
of the assembler.

B.9 Local Labels

NASM gives special treatment to symbols beginning with a period. A label starting with a
period is treated as a local label, which means that it is associated with the previous non-
local label.

Example:

label1: ; some code


.loop: ; some more code
.
.
jne .loop
ret
label2: ; some code

.loop ; some more code


.
.

183
COS2621/102/3/2023

jne .loop
ret

In the above code fragment, each JNE instruction (if taken) jumps to the .loop
immediately preceding it. The two definitions of .loop are kept separate by virtue of each
being associated with the previous non-local label. The first .loop is associated with
label1 whereas the second .loop is associated with label2.

B.10 Critical expressions

One limitation of NASM is that it is a two-pass assembler. It will always do exactly two
assembly passes. Because of this, it is unable to cope with source files that are complex
enough to require three or more passes. The first pass is used to determine the size of the
assembled code and data. This means that all the symbolic addresses the code refers to
during the second pass, when generation of code occurs, are known. NASM cannot
handle code the size of which depends on the value of a symbol declared after the code in
question.

Example (determine size of assembled code and data):

times (label-$) db 0
label: db 'Where am I?'

NASM will not accept this: since the address of label is not known yet, it cannot evaluate
the expression in the times pseudo-instruction when it is first encountered. It will just as
firmly reject the slightly paradoxical code

times (label-$+1) db 0
label: db 'NOW where am I?'
COS2621/102/3/2023

in which any value for the TIMES argument is undefined!

NASM does not allow these because of a concept called a critical expression. A critical
expression is defined as an expression the value of which is required to be computable in
the first pass of the assembler. This means that the evaluation of the expression must
depend only on symbols defined preceding it. Because of this, the arguments to the
TIMES family of pseudo-instructions are also critical expressions.

Critical expressions can crop up in other contexts as well.

mov ax,symbol1
symbol1 equ symbol2
symbol2:

On the first pass, NASM cannot determine the value of symbol1 because it is defined to
be equal to symbol2 which NASM hasn't seen yet. On the second pass, therefore, when it
encounters the line

mov ax,symbol1, it is unable to generate the code for it because it still doesn't know the
value of symbol1. On the next line, it would see the equ again and be able to determine
the value of symbol1, but by then it would be too late.

NASM avoids this problem by defining the right-hand side of an equ pseudo-instruction to
be a critical expression, so the definition of symbol1 would be rejected during the first
pass.

Note that not all forward references are rejected, of course. The following is an example of
an acceptable forward reference:

185
COS2621/102/3/2023

mov ax,[bx+offset]
offset equ 10

During pass one, NASM has to calculate the size of the instruction mov
ax,[bx+offset] without knowing the value of offset. It has no way of knowing that
offset is small enough to fit into a one-byte field and that it could therefore get away
with generating a shorter form of the effective-address encoding; for all it knows, in pass
one, offset could be a symbol in the code segment, and it might need the full four-byte
form. So it is forced to compute the size of the instruction to accommodate a possible four-
byte address part. In pass two, having made this decision, it is now forced to honour it and
keep the instruction large, so the code generated in this case is not as small as it could
have been. This problem can be solved by defining offset before using it, or by forcing a
byte size address part in the effective address by coding

[byte bx+offset].

B.11 Developing a modular program

Suppose we want to write a program that asks the user to enter his (her) name, Peter say,
on the keyboard and then displays the message "Hello Peter" on the screen. We can
break this up into three distinct parts:

1. Display a message on the screen (used for input prompt and for display of the
"Hello" message)

2. Accept a string of characters from the keyboard

3. A main program

The program could be written as follows (call the source code file prog2.asm for
example):
COS2621/102/3/2023

bits 16

org 0x100 ; Start program at offset 100

; This program accepts a user name from the keyboard

; and displays the message 'Hello user_name' on the screen

;--------------------- Jump over data declarations ------------------

jmp main ; Jump to main program

;--------------------- Data declarations ----------------------------

; prompt

message: db 'Enter your name please $'

; Input_buffer

in_buf: db 20 ; Length of input buffer (20 chars)

len_in: db 00 ; Length of input string will be stored here by DOS

user: times 20 db ' ' ; Reserve 20 storage positions for input buffer

cr_lf: db 0dh,0ah,'$' ; Carriage return, Line feed

187
COS2621/102/3/2023

out_mess: db 'Hello $' ; Output message

;---------------------- Display routine --------------------------

display: ; Display a message on the screen.

; The address of the message must be in DX.

mov ah,09h ; Request - display message

int 21h ; DOS system call

ret

;----------------------Get characters that are input by user -------------

get_chars: ; Accept a string of characters from the keyboard.

; The address of the input parameter block is in DX.

mov ah,0x0a ; Request - buffered keyboard input

int 21h ; DOS system call

ret

; -------------------- Main program ----------------------------

main:

mov dx,message ; Address of prompt

call display ; Display prompt

mov dx,in_buf ; Address of input buffer

call get_chars ; Get buffered keyboard input

mov dx,cr_lf ; Address of CR and LF


COS2621/102/3/2023

call display ; Send CRLF to screen

mov dx,out_mess ; Address of 'Hello'

call display ; Display 'Hello'

mov dx,user ; Address of user name entered

mov bx,user ; Get start of input string

add bl,[len_in] ; Add length of string entered to BL to point

; to 'Enter' (carriage return) keyed in at the end

; of the input string by the user

mov al,20h ; 20h = space (ASCII)

mov [bx],al ; Overwrite carriage return with a space

call display ; Display user name

int 20h ; Terminate program

189
COS2621/102/3/2023

The .lst file generated by NASM is as follows (because of the length of some of the lines in
the listing file, we do not show all the comments):

1 bits 16

2 org 0x100

3 ; This program accepts a user name from the keyboard

4 ; and displays the message 'Hello user_name' on the screen

5 ;

6 ;--------------------- Jump over data declarations

8 00000000 E95700 jmp main

9 ;

10 ;--------------------- Data declarations

11 ; prompt

12 00000003 456E74657220796F75- message: db 'Enter your name please $'

13 0000000C 72206E616D6520706C-

14 00000015 65617365202024

15 ;

16 ; Input_buffer

17 0000001C 14 in_buf: db 20

18 0000001D 00 len_in: db 00

19 0000001E 2020<rept> user: times 20 db ' '

20 ;

21 00000046 0D0A24 cr_lf: db 0dh,0ah,'$'


COS2621/102/3/2023

22 ;

23 00000049 48656C6C6F2024 out_mess: db 'Hello $'

24

25 ;

26 ;---------------------- Display routine

191
COS2621/102/3/2023

27 ;

28 display: ; Display a message on the screen.

29 ; The address of the message must be in DX.

30 00000050 B409 mov ah,09h

31 00000052 CD21 int 21h ; DOS system call

32 00000054 C3 ret

33 ;----------------------Get characters that are input by user

34 ;

35 get_chars:

36 ; The address of the input parameter block must be in DX.

37 00000055 B40A mov ah,0x0a

38 00000057 CD21 int 21h ; DOS system call

39 00000059 C3 ret

40 ; -------------------- Main program ----------------------------

41 main:

42 0000005A BA[0300] mov dx,message ; Address of prompt

43 0000005D E8F0FF call display ; Display prompt

44 00000060 BA[1C00] mov dx,in_buf

45 00000063 E8EFFF call get_chars

46 00000066 BA[4600] mov dx,cr_lf ; Address of CR, LF

47 00000069 E8E4FF call display ; Send CR to screen

48 0000006C BA[4900] mov dx,out_mess ; Address of Hello'

49 0000006F E8DEFF call display ; Display 'Hello'

50 00000072 BA[1E00] mov dx,user

51 00000075 BB[1E00] mov bx,user


COS2621/102/3/2023

52 00000078 021E[1D00] add bl,[len_in]

53

54

55 0000007C B020 mov al,20h ; space (ASCII 20h)

191
COS2621/102/3/2023

56 0000007E 8807 mov [bx],al

57 00000080 E8CDFF call display ; Display user name

58 00000083 CD20 int 20h ; Terminate program

We make use of INT 21h, function 0ah for buffered keyboard input (refer to Appendix D.3).
The DX register points to the parameter area for this function, i.e. label in_buf (relative
address 1Ch) in this case. This parameter area consists of three parts.

(i) The maximum number of characters that will be accepted by DOS. This is
set to 20 for this program.

(ii) DOS will insert the actual number of characters that was entered in this byte
(i.e. at relative address 1Dh).

(iii) The buffer for the actual user input at label user (ie at relative
address 1Eh).

DOS will only accept the string of input characters once you press the ‘Enter’ key. The
ASCII code for this key is 0Dh. This character is also written to the input buffer. Step
through the .COM program using DEBUG, i.e. type debug prog2.com at the DOS
prompt and execute the instructions one at a time using the T or P command. (Remember
to use the P command when you trace an INT instruction, otherwise you will go into the
DOS interrupt handler.)

Execute all the instructions up to the instruction at relative address 52h. (You can also use
the command G 152 to accomplish this.) Inspect the data area starting at 01Eh by typing D
11E. You will see the string that you entered, terminated by a carriage return (0Dh). We
need to remove the carriage return character in order to display the name entered,
otherwise it will be displayed and immediately cleared from the screen. We do this by
overwriting the 0Dh (ASCII carriage return) with a space (ASCII 20h) (see lines 55 and 56
in the listing file).

----oooOooo----
COS2621/102/3/2023

23 Appendix C
24 ASSEMBLY LANGUAGE PROGRAMS-EXAMPLES

CONTENTS

Example 1: Smallest of three numbers (MOV, CMP, JBE)

Example 2: Find the factorial of a number (IMUL, LOOP)

Example 3: DOS system call - INT 21h (General I/O)

Example 4: BIOS system call - INT 17h (printer output)

Example 5: BIOS system call - INT 10h (screen processing)

Example 6: Use the stack to manipulate a string

Example 7: DEBUG example (LEA, LOOP, INT 10h, INT 21h)

Example 8: ASCII character string to binary integer conversion

Example 9: Binary integer to ASCII string conversion

193
COS2621/102/3/2023

Example 10: Subroutines: String operations

Example 11: Subroutines: Count the number of vowels in a name


COS2621/102/3/2023

Example 1:   Smallest of three numbers (MOV, CMP, JBE) 

Write an assembly language program to compare the unsigned values in AL, BL and CL
respectively, and move the smallest to BH.

Solution: 

bits16
org 0x100
main:
mov al,7 ; In a big program one would read in the
mov bl,8 ; values for AL, BL and CL. Here we
initialse
mov cl,5 ; the values for testing purposes
mov bh,al ; Mov AL to BH
cmp bh,bl ; Compare BH to BL
jbe label_1 ; If BH <= BL, jump to label_1
; else
mov bh,bl ; move BL to BH
label_1:

cmp bh,cl ; Compare BH to CL


jbe label_2 ; If BH <= CL, jump to label_2,
; else
mov bh,cl ; mov CL to BH
label_2:

; BH contains the smallest value


int 20h ; Terminate program

195
COS2621/102/3/2023

Example 2:   Find the factorial of a number (IMUL,  LOOP) 

The following program calculates the factorial of a number using an iterative loop.

org 0x100
jmp main ; Jump to main program

number: dw 6 ; Use the number 6 to test the program

main:
mov ax,[number] ; AX = n (6 in this example)
mov cx,ax ; CX is used as a loop counter
dec cx ; CX = CX - 1 (next number)(n – 1)
repeat:
imul cx ; DX:AX = AX*CX (n * (n-1))
; We have two 16-bit operands and a 32-bit result
loop repeat ; Decrement CX. Repeat loop if CX <> 0
int 20h ; Terminate program

The answer is 6 × 5 × 4 × 3 × 2 × 1 = 720 (decimal) = 2D0h.

Example 3:   DOS system call ‐  INT 21h (General I/O) 

Use INT 21h to do the following:


COS2621/102/3/2023

(a) Read a string of characters from the keyboard.

(b) Display a string of characters on the screen.

(c) Read one character from the keyboard, and display it (one character) on the
screen (i.e. with echo).

(d) Write one character, ‘Q’ say, to the printer. (Use the default printer.)

(e) Use INT 21h (function 6) to read one character from the keyboard. Echo it to
the screen.

Refer to Appendix D.3 for details of DOS system calls.

Solution: 

(a)
org 0x100
jmp main
; Define input parameter block for string.
buffer: db 20 ; Maximum number of characters = 20
db 0 ; Actual number of characters entered
; is stored in this byte
resb 20 ; Reserve 20 bytes for input string
main:

mov ah,0ah ; Service - accept string


mov dx,buffer ; Address of parameter block

int 21h ; Read string


int 20h ; Terminate program

(b)
197
COS2621/102/3/2023

org 0x100
jmp main

buffer: db 'COS221 is fun',0ah,0dh,'$'

main: mov ah,09 ; Service - display string


mov dx,buffer ; Starting address of string
int 21h ; Display string
int 20h ; Terminate program

(c)
org 0x100
main:
mov ah,01 ; Service - get character from keyboard
int 21h ; Read character

int 20h ; Terminate program

The character entered by the user is stored in AL.

(d) The printing of a carriage return is to force immediate printing. Many printers keep
each character in an internal buffer until either a "carriage return" or "line feed" is
printed or the buffer is full. It is not necessary to set AH to 05 before calling INT 21h
for a second time. The contents of AH are not affected by INT 21h. The character
to be printed must be in DL before the system call.

bits 16
org 0x100
mov ah,05 ; Printer output
COS2621/102/3/2023

mov dl,51h ; ASCII character 'Q'


int 21h ; Display character
mov dl,0dh ; Carriage return
int 21h ; DOS System call
int 20h ; Terminate program

(e) The function does not wait for input from the user but returns to the program
immediately after the INT 21h has been executed. We have to test whether a key
has indeed been pressed on the keyboard. (See Appendix D.3.) This is called
"programmed I/O" as you will learn from the text book.

org 0x100
main:
mov ah,06 ; Service - char I/O. (DOS does not wait
for input)
mov dl,0xff ; DL = FFh means that we want input
read:

int 21h ; Read character into AL


jz read ; Repeat if nothing received yet
mov dl,al ; Input char received in AL
mov ah,02 ; Service - display char
int 21h ; Display character

int 20h ; Terminate program

One cannot really test this program using DEBUG because DEBUG also uses the
keyboard for commands.

199
COS2621/102/3/2023

Example 4:   BIOS system call ‐ INT 17h (Printer output) 

Use INT 17 to do the following:

(a) Print the character "Q".

(b) Write a string of characters to the printer one at a time. The end of the string
is indicated by "$".

Refer to Appendix D.2 for details of BIOS (Basic Input/Output System) printer services.

Solution:

(a)
bits 16
org 0x100
mov ah,00 ; Print a character
mov al,51h ; 51h = ASCII char 'Q'
mov dx,00 ; Printer port (default port = 0)
int 17h ; Print character
mov al,0dh ; 0Dh = ASCII for carriage return
int 17h ; Carriage return
int 20h ; Terminate program

(b) We assume that the end of the string is indicated by a "$".

bits 16
COS2621/102/3/2023

org 0x100
jmp main

mess: db 'What a beautiful day!',0dh,0ah,'$'

main: mov si,mess ; SI points to message


mov dx,00 ; Printer number 0
loop1: mov al,[si] ; Get the next character
cmp al,24h ; Is it '$'?
je finis ; Yes, we have finished
mov ah,00 ; Print a character
int 17h ; BIOS printer interrupt
inc si ; Point to next character
jmp loop1 ; Repeat loop
finis: int 20h ; Terminate program

Example 5:   BIOS system call ‐ INT 10h (Screen processing) 

Use INT 10h to do the following:

(a) Clear the screen.

(b) Position the cursor at row 12, column 40.

Refer to Appendix D.1 for BIOS screen services.

Solution: 
201
COS2621/102/3/2023

(a) Scrolling begins at row 0, column 0. The screen scrolls past until the bottom is
reached at row 18h (= 24) and column 4Fh (= 79). The whole screen will thus be
blanked out.

bits 16
org 0x100
mov ax,0600h ; Service - scroll up screen
mov cx,0000 ; Starting row:column
mov dx,184Fh ; Ending row:column

int 10h ; Scroll screen

int 20h ; Terminate program

(b)
bits 16
org 0x100

mov ah,02 ; Service - set cursor


mov bh,00 ; Screen number 0
mov dx,0a00h ; Row (10):Column (0)
int 10h ; Set cursor

int 20h ; Terminate program

Example 6:   Using the stack to manipulate a string 

Write an assembly language routine to load a string of bytes onto the stack and store them
from there in an array. The order of the string of bytes must stay unchanged.
COS2621/102/3/2023

Solution: 

This program assumes the length of the string to be 20 characters. Remember that the
last byte that was pushed onto the stack will be on top of the stack when we start popping.
This means that we get the last one first.

org 0x100
jmp main

string: db 'string 20 characters' ; Input string

array: times 20 db ' ' ; Output string (20 spaces)

main:

mov si,string ; SI contains the address of ‘string’


mov cx,20 ; CX is the loop counter (20
characters)
mov ah,0 ; Clear AH
loop1:

mov al,[si] ; Move one byte ito AL


push ax ; Push onto stack,
; (we can only push words, not bytes)
inc si ; Point to next byte
loop loop1 ; Decrement CX, repeat loop if CX <> 0

203
COS2621/102/3/2023

unpack:
mov di,array ; Address of output buffer in DI
add di,19 ; Start packing from the end to
; preserve the order
mov cx,20 ; CX again as loop counter
loop2:
pop ax ; Pop from stack into AX
mov [di],al ; Store byte in array
dec di ; Pointer one back
loop loop2 ; Repeat loop if CX <> 0
int 20h ; Terminate program

Example 7:   DEBUG EXAMPLE (LEA, LOOP, INT 10h, INT  21h) 

Consider the following DEBUG listing (remember that all values used in DEBUG are in
hexadecimal):

-a 100
119C:0100 jmp 134 ; Jump to main program
119C:0102 db 00 00 '$' 00
119C:0106 ;
119C:0106 ;Clear_Screen
119C:0106 mov ax,0600 ; Service - scroll up screen.
119C:0109 mov bh,07 ; Colour attributes: white (7) on
black (0).

119C:010B mov cx,00 ; Starting row:column.


COS2621/102/3/2023

119C:010E mov dx,184F ; Ending row:column.

119C:0111 int 10 ; BIOS system call.


119C:0113 nop
119C:0114 ret ; Return from subroutine.
119C:0115 ;
119C:0115 ;Set_Cursor
119C:0115 mov ah,02 ; Service - set cursor
position.

119C:0117 mov bh,00 ; Screen number 0.


119C:0119 mov dx,0000 ; Row (00): Column (00).
119C:011C int 10 ; BIOS system call.
119C:011E nop

119C:011F ret ; Retu rn from subroutine.


119C:0120 ;
119C:0120 ;Display_String
119C:0120 mov cx,100 ; Set loop counter, CX to 100h
(25610).
119C:0123 lea dx,[102] ; Load Effective Address (load
offset
119C:0127 ; address of string into DX).
119C:0127 mov ah,09 ; Service - display character
string;
119C:0129 ; end of string indicated by '$'.
119C:0129 mov bl,1 ; Value used for add
inside loop.
119C:012B int 21 ; DOS system call.

119C:012D add [102],bl ; Increment contents of memory


position

205
COS2621/102/3/2023

119C:0131 ; so that next character will be


displayed.
119C:0131 loop 012b ; Decrement CX, repeat loop if CX <>
0.
119C:0133 ret ; Return from subroutine.
119C:0134 ;
119C:0134 ;This program displays the complete ASCII string (except
'$')
119C:0134 ;on the screen.
119C:0134 ;
119C:0134 ;Main_Program
119C:0134 call 0106 ; Clear_Screen.
119C:0137 call 115 ; Set_Cursor.
119C:013A call 120 ; Display_String.
119C:013D int 20 ; Terminate program
119C:013F

Now answer the following questions:

a) What is the length of the program?

b) Which would be the 10th instruction to be executed?

c) Type G 0115 and use the Dump option of DEBUG to inspect the two-byte value on
top of the stack. What is the value of this number and what does it mean?

d) What is the purpose of the instruction at address 0123h?

e) Is the initial JMP instruction really necessary?

f) What would the value of CX be just before the instruction at address 0133h is
executed?
COS2621/102/3/2023

g) Why is CX set to 0000 at address 010Bh?

h) What would the effect be if the contents of address 0102h is changed from 00 to
24h?

i) Which displayable ASCII character can never be displayed on the screen by


this program?

j) Will the program still work if the instruction at address 0123h is replaced by MOV
DX,0102 by typing the following?

A 0123
----- :0123 MOV DX,102
----- :0126

Solution: 

a) The program occupies memory locations 0100h to 013Eh, thus a total of 003Fh
memory locations:

(013Eh - 0100h + 1) = 003Fh.

b) Instructions are executed in the following sequence:

1: jmp 0134 ; Jump to instruction at 0134.


2:call 0106 ; Call routine beginning at
0106.
3:mov ax,0600
4:mov bh,07
5:mov cx,00
6:mov dx,184F

207
COS2621/102/3/2023

7:int 10
8:nop
9:ret ; Return to instruction following the
call
10: call 0115

c) Run the program up to memory position 0115h by using the G (GO) option of
DEBUG. Remember that the instruction at address 0115h will not be executed.

Use the "R" command of DEBUG to display the contents of the registers and the status of
the flags. Locate (on your screen) the value of SP. When we ran the program we found
that SP=FFEAh. Therefore, the stack pointer points to offset FFEAh. (This address might
be different when you run the program. Use the value of SP as displayed on your
machine.)

Use the D (DUMP) option to display the contents of the memory position pointed to by SP.
In our case:

Contents of FFEA: 3Ah

Contents of FFEB: 01

(We look at two bytes because the SP register is 16 bits long.)

Remember that bytes are stored in reverse byte order in memory. Therefore the value
stored at the top of the stack is 013Ah.
COS2621/102/3/2023

When a CALL instruction is encountered, the address of the instruction following the call is
pushed onto the stack. When the RET instruction is executed in the subroutine, ie RETurn
to calling program, the address of the next instruction to be executed is popped from the
stack. Do not worry about this: this is all handled by the operating system. However, you
have to be aware of the fact that, when you enter a subroutine, the return address is
always on top of the stack.

In this case, 013Ah is the address of the instruction that the program will return to after
execution of the subroutine.

d) It loads the address 102h into the DX register (Load Effective Address).

e) Remember that DEBUG always starts executing at address 100h. The computer
will try to execute the data in memory position 0102h if the first instruction does not
jump to the main program.

f) CX acts as a loop counter and is decremented by 1 each time the LOOP instruction
is executed. As soon as CX = 0, the loop terminates and the instruction in the next
memory location is executed. Therefore, the instruction in 0133h will only be
executed when CX = 0.

g) CX specifies the starting row:column numbers where the cursor must be positioned
(CH = row position; CL = column position). In this case the cursor will be positioned
at row 0, column 0 (top left-hand corner).

h) Address 0102h contains the ASCII code of the first character that we want to
display. If we change the contents of 0102h from 0 to 24h, the display will start with
a different character.

209
COS2621/102/3/2023

i) The character "$". This character is used as a string delimiter, i.e. it indicates the
end of the string when INT 21h is used to display the string.

j) MOV DX,102 will have the same effect as LEA DX,[102]. However, the
LEA DX,[102] instruction occupies four bytes (0123h, 0124h, 0125h, 0126h)
whereas MOV DX,102 will occupy only three bytes (0123h, 0124h, 0125h). The
contents of byte 0126h will then not "make sense". We can rectify the situation by
storing NOP in 0126h.

Example 8:   ASCII character string to binary integer  conversion 

Give a detailed algorithm for the following problem:

Accept an ASCII character string that represents a decimal number from the keyboard
(maximum of four characters). Convert this string to a binary integer value that can be
used in arithmetic calculations. Multiply this number by 3 and print the answer in decimal.

Procedure Convert-to-integer (num-var)

BEGIN

Set pointer to input buffer.

IF NOT empty-string THEN

Initialise num-var (integer result) to 0

REPEAT

Load next character.

IF valid numeral THEN


COS2621/102/3/2023

Subtract 30h to get the numeric value

Mult. num-var with 10 (move digits one decimal position to the left)

Add new digit to num_var

END_IF

UNTIL invalid numeral

END

Procedure Convert-to-ascii (num-var)

BEGIN

Set pointer to end of output buffer

WHILE num-var > 0

DO

num-var = num-var / 10

Add 30h to remainder (convert to ASCII display code)

Store ASCII character in output string

Decrement pointer to output string

END_DO

Print output string

END

211
COS2621/102/3/2023

BEGIN {MAIN PROGRAM} 

Read ASCII string from keyboard (INT 21, function 0Ah)

Call Convert-to-numeric (num-var)

Multiply num-var by 3

Call Convert-to-ascii (num-var)

END {MAIN PROGRAM} 

See examples 9 and 10 for an implementation of these two algorithms.

The procedure for a floating-point number would be much more complicated.

Example 9:   Binary integer to ASCII string conversion 

It is important to remember that ALL output to the screen and to the printer must be in
ASCII code and that ALL input from the keyboard is received in ASCII.

This means that, in order to display or print a decimal value, say 6710, one has to convert
the integer value to a string consisting of two ASCII characters. Simply moving the integer
value to DL and writing it to the screen does not yield the desired result. For example:

mov ah,02 ; Display aracter.


a ch
mov dl,43h ; 43h = 6710
int 21h ; DOS system call.
COS2621/102/3/2023

The character "C" will be displayed, since 43h is the ASCII code for "C". To display the
number 67 on the screen, we have to write two characters, namely "6" and "7" to the
screen.

mov ah,2 ; Display a character.


mov dl,36h ; '6' to be displayed (ASCII for '6'
is 36h).

int 21h ; DOS system call.


mov dl,37h ; '7' to be displayed.

int 21h ; DOS system call.

We give the program to convert the positive binary integer value stored in AX to an ASCII
string and display it on the screen.

bits 16
org 0x100
jmp main
outputbuf: db ' ','$'
;

; This program converts the value stored in the AX register to


; an ASCII string and displays it on the screen.
;
main: mov di,outputbuf ; Address of output buffer
add di,4 ; Point to end of output buffer
mov bx,10 ; We divide by 10
loop1: xor dx,dx ; Set DX to 0 for the divide
operation
idiv bx ; Divide DX:AX by BX,

213
COS2621/102/3/2023

; result in AX and
; remainder in DX
add dx,30h ; Convert remainder to ASCII
mov [di],dl ; Move digit into output string (one
byte)
cmp ax,0 ; Is result = 0?
je finis ; Yes, then we have finished
dec di ; Pointer one back
jmp loop1 ; Repeat loop

finis: mov dx,outputbuf ; DX = address of output buffer


mov ah,09 ; Display function
int 21h ; Display string

int 20h ; Terminate program

Example 10:   Subroutines ‐ String operations 

Write the following routines using assembly language. Define data areas where
necessary.

(a) Convert the ASCII character in AL to lower case if it is a valid upper case
character.

(b) StrToNum is a subroutine that uses DS:DX as input. DS:DX points to an input
buffer that contains a string of characters representing a decimal integer entered from
the keyboard using INT 21h with AH = 0Ah. StrToNum must return the integer value of
the string of digits (ASCII string) in the AX register.
COS2621/102/3/2023

Solution: 

(a) The only difference between the ASCII codes for upper and lower case is bit 5 (set
to 1 for lower case and set to 0 for upper case), for example, the ASCII code for "a"
is 01100001 (61h) and for "A" it is 01000001 (41h). (The difference is 20h.)

org 0x100
jmp main ; Jump to main program
str1: db 'Invalid character.' , '$'
str2: db 'Enter a character:','$'
str3: db 0x0a,0x0d,'$'

;
disp_str:
mov ah,09 ; Service - display a string of characters
int 21h ; Display string

ret
;
; Read a character from the keyboard
; Character is returned in AL
;
read_char:
mov ah,01 ; Service - Read character and
; echo it to the screen
int 21h ; Read character from keyboard
ret

215
COS2621/102/3/2023

; Display line feed , carriage return


;
line_carr:
mov dx,str3 ; Address of CR, LF string
call disp_str ; Display string

ret
main:

mov dx,str2 ; Address of prompt


call disp_str ; Display prompt
call read_char ; Read character

cmp al,41h ; Compare character in AL with 'A' (ASCII


41h)

jl dis_err ; Jump if ASCII code of character in AL is


less

; than 41h, i.e. not a valid upper-case


letter

cmp al,0x5a ; Compare character in AL with 'Z' (ASCII


5Ah)

jg dis_err ; Jump if ASCII code of character in AL is

; greater than 5Ah, i.e. invalid


mov ah,20h ; 20h = 00100000

or al,ah ; Mask upper case with 20 to get lower


case,

; result in AL
push ax ; Store char temporarily

dis_char:
call line_carr
COS2621/102/3/2023

pop dx ; Pop char from the stack (into DL) to be


displayed
mov ah,02 ; Service - Display character in DL
int 21h ; DOS system call
int 20h ; Terminate program

dis_err:
call line_carr
mov dx,str1 ; Address of error message
call disp_str ; Display message

int 20h ; Terminate program

(b) Implementation of the ASCII string to binary integer conversion algorithm given
in example 8.

org 0x100
;

; The subroutine str_to_num converts an ASCII string (of digits)


to
; a binary integer value. The address of the string is passed in
DX.
; The end of the string is indicated by a carriage return.
; The result is returned in AX.
; We assume that the 0 <= number < 65536.
; The contents of the registers are not preserved.
; If an error occurred, AL is set to 'E'.
;
str_to_num:
xor ax,ax ; Initial value of AX = 0

217
COS2621/102/3/2023

xor bh,bh ; BH = 0
mov cx,10 ; To build integer in AX (multiply by 10)
mov si,dx ; DX points to start of input buffer
next_char:

mov bl,[si] ; Move contents of memory pointed to by SI


to BL
cmp bl,0Dh ; Is it a carriage return?
je finis ; Yes, we are done
cmp bl,39h ; ASCII for the character '9' is 39h
jg error ; > '9', invalid character
sub bl,30h ; Convert to numeric value (ASCII '0' =
30h).

jl error ; < 0, invalid character


imul cx ; DX:AX = AX * 10 (32-bit result)
add ax,bx ; Add next digit
inc si ; Pointer to next char
jmp next_char ; Repeat for next character
error:

mov al,'E' ; Flag an error


finis:

ret ; Return to calling program

Example 11:   Subroutines ‐ Count the number of vowels in a name 

Write an assembly language program that will count the number of vowels in a name and
surname entered from the keyboard (upper case) and display it on the screen. Make use
of subroutines.
COS2621/102/3/2023

219
COS2621/102/3/2023

;
; Program Count_Vowels
;
; This program accepts a name from the keyboard, counts the number
; of vowels in the name, and displays this number on the screen.
; Name must be entered in upper case.
;
bits 16
org 0x100
jmp main
prompt:
db 'Enter your name and surname in UPPERCASE'
db 13,10,'$'
input_buf:
db 40
db 0
resb 40
out_mess:

db 'Your name contains '


db ' '

mess2:
db ' vowels','$'
list_of_vowels:
db 'AEIOU'
cr_lf:
COS2621/102/3/2023

db 13,10,'$' ; carriage return and line feed


;

; This routine displays a prompt and reads a string of characters


; from the keyboard
;
disp_prompt:
mov ah,09 ; Service - display message
mov dx,prompt ; Address of message
int 21h ; DOS system call

mov ah,0ah ; Service - read string


mov dx,input_buf ; Address of input buffer
int 21h ; DOS system call

mov ah,09 ; Service - display message


mov dx,cr_lf ; Address of CR & LF
int 21h ; DOS system call
ret ; Return to main program

;
; This routine counts the number of occurrences of a specific
; vowel in the string. A running total of vowel count is kept in
DL.
;
count_vowels:
push si ; Store registers on stack
push cx

xor bl,bl ; Count = 0


mov si,input_buf+2 ; Address of input string
xor ch,ch ; CH = 0
COS2621/102/3/2023

mov cl,input_buf+1 ; CL = number of chars in input


; test character for all 5 vowels
next_byte:
lodsb ; Load byte from name string into AL

cmp ah,al ; Is it = current vowel?


jne next ; No, carry on
inc bl ; Yes, add 1 to count
next:

loop next_byte ; Repeat loop


add dl,bl ; Add count to running total
pop cx ; Restore registers
pop si
ret ; Return from call
;
; This routine converts the total number of vowels (in DX)
; to an ASCII string. This is displayed on the screen.
;
show_count:
mov ax,dx ; AX contains number of vowels
mov dl,10 ; Divisor = 10
mov di,mess2-1 ; DI points to end of string of
digits
;
; Get individual digits by repeated division by 10
;
divide:
idiv dl ; AX/DL, quotient in AL

221
COS2621/102/3/2023

; remainder in AH
add ah,30h ; Convert to ASCII (30h = '0')
mov [di],ah ; Move into output string
cmp al,0 ; Is quotient = 0?
je display_count ; Yes, jump to display
xor ah,ah ; Clear AH for next division
dec di ; Pointer one back
jmp divide ; Repeat loop

display_count:
mov dx,out_mess ; Address of output message
mov ah,09 ; Service - display message
int 21h ; DOS system call

ret ; Back to calling program


;

; Main program
;
main:

call disp_prompt ; Display prompt and get name


mov si,list_of_vowels ; Address of list of vowels
mov cx,5 ; Loop count (5 vowels)
xor dx,dx ; DL holds running total

loop1:
mov ah,[si] ; Get next vowel
call count_vowels ; Count current vowel
inc si ; Point to next vowel
COS2621/102/3/2023

loop loop1 ; Repeat loop


call show_count ; Display count of vowels
int 20h ; Terminate program

----oooOooo----

223
COS2621/102/3/2023

25Notes:
26 Appendix D
INTERRUPTS
27

CONTENTS

D.1 BIOS Interrupt 10h - Screen processing

D.2 BIOS Interrupt 17h - Printer output

D.3 DOS Interrupt 21h - General I/O

D.1   BIOS Interrupt 10h

INT 10h is used for screen handling. The specific function to be executed is specified in
AH. The interrupt may change the contents of AX. We list a few of the functions:

AH = 00:  Set video mode. 

225
COS2621/102/3/2023

AH = 00 and Set standard graphics mode - 320x200 resolution. The cursor


disappears

AL = 4: when graphics mode is set.

AH = 02: Set cursor position. The cursor is set according to row:column coordinates.

Set: BH = page number;

DH = row;

DL = column;

AH = 06: Scroll up screen. This function could be used to clear the entire screen.
Set:

AL = number of lines, 00 for scrolling up the entire screen;

CH = starting row;

CL = starting column;

DH = ending row;

DL = ending column;

BH is used to set screen attributes.

We can also set the colour attributes when we scroll the screen. The
attributes are specified in the BH register as follows:

Bit 6 4 3 0

Background colour Foreground colour


COS2621/102/3/2023

Foreground or  Foreground only 

background colour 

000 Black 1000 Grey

001 Blue 1001 Light blue

010 Green 1010 Light green

011 Cyan 1011 Light cyan

100 Red 1100 Light red

101 Magenta 1101 Light magenta

110 Brown 1110 Yellow

111 White 1111 High-intensity white

The following are examples of colour attribute settings:

BH = 07h for white (7) on black (0) (monochrome);

BH = 30h for black (0) on cyan (3) (colour);

BH = 14h for red (4) on light blue (1).

If bit 7 is set to 1, the text on the screen will blink.

AH=07:  Scroll down screen.  Set: 

AL = number of lines, 00 for scrolling down the entire screen;


227
COS2621/102/3/2023

CH = starting row;

CL = starting column;

DH = ending row;

DL = ending column.
COS2621/102/3/2023

D.2 BIOS Interrupt 17h

Interrupt 17h provides three functions for printing, specified by the AH register. The
following values specify the printer ports for INT 17h:

0 the default port

1 for LPT1

2 for LPT2

AH = 00: Print a character. Load the character to be printed in AL and the printer
number in DX. DOS will set AH to 01 if the character could not be printed,
otherwise AH = 00.

AH = 01: Initialise the printer port. Resets the printer and initialises it for output. The
system call returns a status code (similar to the status code for AH = 02) in
AH. The call returns 90h if the printer is selected and not busy. You can also
use this function to do a form feed.

AH = 02: Get printer port status. This function determines the status of the printer.
INT 17h returns a status code in AH which "describes" the status of the
printer. The printer number is specified in DX.

Bit number

7 6 5 4 3 0

Bit set to Acknowledg Selecte


Not Out of I/O Time
1 e-ment from d
busy paper error out
means printer

229
COS2621/102/3/2023

D.3 DOS Interrupt 21h

INT 21h is called a DOS function call or DOS system call. There are 87 different
functions supported by this interrupt. The functions are identified by a function number
placed in the AH register. Some of these are listed below.

AH  Purpose  Description 

0 Terminate program Terminates execution of program

1 Keyboard input Waits for keyboard input, displays it and returns it in AL

2 Display output Displays the character in DL on the screen

3 Auxiliary input Waits for a character from the communications port and
puts it in AL

4 Auxiliary output Outputs the character in DL to the communications port

5 Printer output Outputs the character in DL to the printer

6 Keyboard input/ Performs both input and output. It can also determine the input
output. status. Unlike the other input functions, it does
not wait for an input character. Also note that the input
character is not automatically displayed and that the
Ctrl-Break command does not terminate the
operation.
COS2621/102/3/2023

As usual, the DL register contains the output character and the AL register receives the
input character. You ask for input by placing the value FFh in the DL register. On return
from the function, the zero flag is set if no character is ready. If the zero flag is clear, it
means a character was read into the AL register. If the DL register contains any value
other than FFh, that character is sent to the standard output device. Also compare with
functions 7 and 8.

7 Keyboard input Waits for a character from the keyboard and puts it in
AL.

with no echo The character is not displayed on the screen.

8 Keyboard input Waits for a character from the keyboard, returns it in AL


and

with no echo terminates when Ctrl-Break is pressed.

9 Display string We have seen that functions 2 and 6 can display single
characters, but function 9 is much easier to use for
more than one character. Of course, non-displayable
characters (such as carriage return, line feed, and Esc)
can also be included in the string.

To use this function, you place the string somewhere in


memory and terminate it with a dollar sign. (You cannot
include a dollar sign in the string; use function 2 for this
purpose.) The address of the string is placed in the DX
register. Set AH register to 9 and execute the INT 21h
instruction.

0A Buffered keyboard Reads characters from the keyboard into memory


buffer.

231
COS2621/102/3/2023

Input DX points to the input buffer: 1st byte = max. number of


characters allowed and 2nd byte = actual number of
characters entered. The string is stored from the third
byte onwards.

0B Check keyboard Checks to see if a character is available from the


keyboard.

Status Sets AL = FFh if a character is ready. Otherwise AL = 0.

0C Clear keyboard Clears keyboard buffer and performs the INT 21h
keyboard input function as buffer specified in AL.

4C Terminate program. Returns control to DOS.

----oooOooo----
COS2621/102/3/2023

28 Notes:

233
COS2621/102/3/2023

29 Appendix E
30 The instruction set

Contents

E.1 Format of instructions

E.2 Instructions

E.1 Format of Instructions

The general format of an instruction is as follows (the square brackets indicate that an item
is optional in some statements):

[name] or [label:] mnemonic [operand(s)] [;comments]

where

name is optional and refers to the address of a data item.

label is optional and refers to the address of an instruction.


COS2621/102/3/2023

mnemonic is the operation code of an instruction.

operand(s) specifies the operand(s) for the specific instruction.

Examples:name/label  mnemonic  operand(s). 

mov ax,07
val1: db 45
label1: mov
bx,ax clc

Permissible characters for label and name: 

Alphabetic characters: A to Z and a to z

Digits: 0 to 9

Special characters: ?, @, -, $, and . (only if it is the first character).

The first character must be an alphabetic or special character ($ or .). The maximum
length of a name or label is 31 characters.

Register names, instruction mnemonics and compiler directives are reserved words and
may not be used as names or labels.

E.2 Instructions

The description of instructions as set out in this Appendix was mainly compiled from the
following book:

235
COS2621/102/3/2023

Peter Abel. IBM PC Assembly Language and Programming, 3rd edition, Prentice-Hall,
1995.

NOTATION USED: 

The flags are identified as follows:

OF: Overflow flag

DF: Direction Flag

IF: Interrupt flag

TF: Trap Flag

SF: Sign Flag (0 if positive, 1 if negative)

ZF: Zero Flag (0 for non-zero, 1 for zero)

AF: Auxiliary Flag

PF: Parity Flag (1 for even parity, 0 for odd parity)

CF: Carry Flag

reg: An 8-bit or 16-bit general purpose register

mem: A memory operand

reg_8: An 8-bit register operand

reg_16: A 16-bit register operand

segreg: A 16-bit segment register (CS, DS, ES, SS)

immed: An immediate operand (8, 16 or 32 bits long)

immed_8: An 8-bit immediate operand

immed_16: A 16-bit immediate operand


COS2621/102/3/2023

Generally, operand_1 and operand_2 of an instruction are referred to as the destination


operand and the source operand respectively. So, in the instruction MOV AX,BX for
example, operand_2 (the BX register) is the source operand and operand_1 (the AX
register) is the destination operand.

AAA: ASCII Adjust after Addition

Adjusts the result in AL after two ASCII digits have been added together.

AAD: ASCII Adjust before Division

Converts unpacked BCD digits in AH and AL to a single binary value in


preparation for the DIV instruction.

AAM: ASCII Adjust after Multiplication

Adjusts the result in AX after two unpacked BCD digits have been
multiplied together.

AAS: ASCII Adjust after Subtraction

Adjusts the result in AX after a subtraction operation where two ASCII


digits are involved.

ADC: ADD Carry

Adds the source and destination operands, and adds the contents of the
CF to the sum, which is then stored in the destination.

Format: ADC reg,reg ADC reg,immed


237
COS2621/102/3/2023

ADC reg,mem ADC mem,immed

ADC mem,reg ADC AX,immed

ADC AL,immed

Flags: OF, SF, ZF, AF, PF, CF

ADD: ADD binary numbers

Adds the source operand to the destination operand and stores the result
in the destination operand.

Format: ADD reg,reg ADD reg,immed


ADD reg,mem ADD mem,immed

ADD mem,reg ADD AX,immed

ADD AL,immed

Flags: OF, SF, ZF, AF, PF, CF

AND: AND's the bits in the source and destination operands. The result is
stored in the destination.

Format: AND reg,reg AND reg,immed


AND reg,mem AND mem,immed

AND mem,reg AND AX,immed

AND AL,immed

Flags: OF, SF, ZF, AF=?, PF, CF=0


COS2621/102/3/2023

BSF & BSR: Bit Scan

Scans a bit string for the first 1-bit. BSF scans from right to left and BSR
scans from left to right. Operand_2 contains the string to be scanned and
the position of the first 1-bit (if any) is placed in operand_1.

Format: BSF/R reg,reg BSF/R reg,mem

Flags: ZF

BT/BTC/BTR/BTS: Bit Test

BT copies a specific bit into the CF flag.

BTC complements the specific bit in operand 1.

BTR sets the specific bit to 0 (resets the bit).

BTS sets the specific bit to 1 (sets the bit)

Operand_1 contains the bit string to be tested.


Operand_2 indicates the position of the bit to be tested.

Format: BT/BTC/BTR/BTS reg,reg

BT/BTC/BTR/BTS mem,reg

BT/BTC/BTR/BTS reg,immed

BT/BTC/BTR/BTS mem,immed

Flags: CF
239
COS2621/102/3/2023

CALL: CALLs a near or far procedure

Decrements the SP (stack pointer) by 2 (or 4 for a far call).

If the procedure is NEAR (in the same segment): Pushes the current
location (only the offset) of the next instruction onto the stack and
transfers control to the destination.

If the procedure is FAR (in a different segment): Pushes the current


location (both segment and offset) of the next instruction onto the stack
and transfers control to the destination.

Format: CALL near_proc CALL reg16_pointer

CALL far_proc CALL mem16_pointer

CALL mem32_pointer
Flags: None

CBW: Convert Byte to Word

Converts a 1-byte signed value in AL to a word by duplicating the sign bit


(bit 7) of AL throughout AH. Duplicating the sign bit in this way is often
referred to as propagating the sign bit.

Format: CBW

Flags: None
COS2621/102/3/2023

CDQ: Convert Double word to Quad word

CLC: CLears Carry Flag

Clears the CF flag.

Format: CLC

Flags: CF=0

CLD: CLear Direction flag. Clears the DF flag.

Format: CLD

Flags: DF = 0

CLI: CLear Interrupt flag

Clears the IF flag.

Format: CLI

Flags: IF=0

241
COS2621/102/3/2023

CMC: CoMplement Carry flag

Complements the CF flag, i.e. reverses the CF bit value.

Format: CMC

Flags: CF is complemented.

CMP: CoMPares the contents of operand_1 and operand_2

Compares the destination to the source by doing an implied subtraction of


the source from the destination. The values of the operands do not
change.

Operands: reg,reg reg,immed

reg,mem mem,immed

mem,reg AX,immed

AL,immed

Flags: OF, SF, ZF, AF, PF, CF

CMPS/CMPSB/CMPSW/CMPSD: Compare Byte or Word string:

Compares strings of bytes (CMPSB), words (CMPSW), or double words


(CMPSD), addressed by DS:SI and ES:DI. A REPn prefix normally
precedes these instructions, for example REPE CMPSB. It carries out an
COS2621/102/3/2023

implied subtraction of the destination from the source. SI and DI are


incremented if the direction flag is clear, or they are decremented if the
direction flag is set. The DS:SI registers address operand_1 and the
ES:DI registers address operand_2. If the DF flag is zero, the operation
compares from left to right and increments the SI and DI. If the DF is 1, it
compares from right to left and decrements the SI and DI. Remember that
the operation increments/decrements by 2 with word operations.

A REPn prefix normally precedes these instructions, along with a


maximum value in CX. REPn decrements CX by 1 for each repitition. The
operation terminates when the compared value is found (REPNE) or not
found (REPE) or if CX = O. Note: DI and SI are advanced past the byte
that caused termination.

Format: [REPn] CMPSB/CMPSW/CMPSD (No operand)

CMPS segreg:source, ES:dest

CMPS source,dest

Flags: OF, SF, ZF, AF, PF, CF

CWD: Convert Word to Double word

Fills the DX with the sign bit (bit 15) of the AX register.

Format: CWD

Flags: None

CWDE: Convert Word to Double word Extended

243
COS2621/102/3/2023

Fills EAX with the sign bit of the AX register.

Format: CWDE

Flags: None

DAA: Decimal Adjust after Addition

Adjusts the binary sum in AL after two packed BCD values have been
added. The sum is converted to two BCD digits in AL.

Format: DAA

Flags: SF, ZF, AF, PF, CF, OF (undefined)

DAS: Decimal Adjust after Subtraction

Converts the binary result of a subtraction operation to two packed BCD


digits in AL.

Format: DAS

Flags: SF, ZF, AF, PF, CF, OF (undefined)

DB/DW/DD:  Define pseudo‐op: 
COS2621/102/3/2023

Pseudo-ops give information to the assembler regarding the reservation and


initialisation of memory.
DB Allocates one byte of storage

DW Allocates two bytes of storage


DD Allocates four bytes of storage

DEC: DECrement

Subtracts 1 from a byte, word or double word operand.

Format: DEC reg DEC mem

Flags: OF, SF, ZF, AF, PF

DIV: DIVide, unsigned

Divides an unsigned (the leftmost bit is treated as part of the data and not
as a sign) dividend by an unsigned divisor. If the divisor is 8 bits, the
dividend is assumed to be in AX, the quotient is stored in AL and the
remainder in AH. If the divisor is 16 bits, the dividend is assumed to be in
DX:AX, the quotient is stored in AX and the remainder in DX.

Format: DIV reg DIV mem

Flags: OF, SF, ZF, AF, PF, CF (all undefined)

245
COS2621/102/3/2023

ESC: ESCape

For use with coprocessors. Provides the coprocessor with an instruction


and an optional operand for execution.

Format: ESC immed,reg ESC immed,mem

Flags: None

HLT:  HaLT 

Stops the CPU until a hardware interrupt occurs. The CS and IP registers
point to the instruction following the HLT. As soon as the interrupt occurs,
these two registers are pushed onto the stack and the interrupt service
routine is executed. On return from the interrupt, processing resumes
following the HLT.

Format: HLT

Flags: None

IDIV: Integer (signed) DIVision

Divides a signed dividend by a signed divisor. Compare with DIV.

Dividend  Divisor  Quotient  Remainder 


COS2621/102/3/2023

(1st operand) (2nd operand)

AX (16 bits) reg/mem (8 bits) AL AH

DX:AX (32 bits)reg/mem (16 bits) AX DX

Format: IDIV reg IDIV mem

Note that we only specify the 2nd operand in the instruction. The first
operand is assumed to be in AX or AL.

Flags: AF, CF, OF, PF, SF, ZF (all undefined)

IMUL: Integer (signed) MULtiplication

Performs a signed integer multiplication on either AL or AX. Compare


with MUL.

Multiplicand Multiplier Product

(1st operand) (2nd operand)

AL (8 bits) reg/mem (8 bits) AX

AX (16 bits) reg/mem(16 bits) DX:AX

Format: IMUL reg IMUL mem

Note that we only specify the 2nd operand in the instruction. The 1st
operand is assumed to be in DX:AX or in AX.

247
COS2621/102/3/2023

Flags: OF, CF

SF, ZF, AF and PF (all undefined)

IN: INput from port

Inputs a byte or word from an input port into AL or AX. Operand_2 is a


port address expressed as either an 8-bit constant or a 16-bit address in
DX.

Format: IN AL,immed IN AL,DX

IN AX,immed IN AX,DX

Flags: None

INC: INCrement

Adds 1 to a register or memory position. The operation does not affect the
carry flag.

Format: INC reg INC mem

Flags: OF, SF, ZF, AF, PF

INT: INTerrupt
COS2621/102/3/2023

Generates a software interrupt, which in turn calls a BIOS or DOS routine.


INT performs the following:

Decrements the SP by 2

Pushes the flags onto the stack

Resets the IF and TF flags

Decrements the SP by 2

Pushes CS onto the stack

Places the high-order word of the interrupt service routine address in CS

Decrements SP by 2

Pushes IP onto the stack

Fills IP with the low-order word of the interrupt service routine address

Format: INT immed INT 3 (generates a breakpoint)

Flags: TF, IF

INTO: INTerrupt on Overflow

Causes an internal interrupt 4 if the overflow flag is set.

Format: INTO

249
COS2621/102/3/2023

Flags: IF, SF

IRET: Interrupt RETurn

Returns from an interrupt service routine. IRET retraces the steps that
the interrupt originally took and performs a return.
IRET performs the following:

 Pops the word at the top of the stack into the IP register.

 Increments SP by 2 and pops the top of the stack into the CS


register.

 Increments the SP by 2 and pops the top of the stack into the flags
register.

Format: IRET

Flags: All

JMP: Unconditional JuMP.

Jumps unconditionally to a label.

Format: JMP shortlabel JMP reg_16

JMP nearlabel JMP mem_16

JMP farlabel JMP mem_32


COS2621/102/3/2023

Flags: None

Conditional Jumps:Jcondition

Jumps if a specific flag condition is true.


Jump if Above, or Jump if Not (Below or Equal)
JA/JNBE
Jump if Above or Equal, or Jump if Not Below
JAE/JNB
Jump if Below, or Jump if Not (Above or Equal)
JB/JNAE
JBE/JNA Jump if Below or Equal, or Jump if Not Above

Jump if Carry
JC
Jump if CX is Zero, or if ECX is Zero
JCXZ/JECXZ
Jump if Equal, or Jump if Zero
JE/JZ
Jump if Greater, or Jump if Not (Less than or
JG/JNLE
Equal)

Jump if Greater or Equal, or Jump if Not Less


JGE/JNL
than

Jump if Less than, or Jump if Not (Greater or


JL/JNGE
Equal)

Jump if Less than or Equal, or Jump if Not


JLE/JNG
Greater

Jump if No Carry
JNC
Jump if Not Equal, or Jump if Not Zero
JNE/JNZ
Jump if No Overflow
JNO
Jump if No Parity, or Jump if Parity Odd
JNP/JPO
Jump if No Sign - jumps if an operation set
JNS
the sign to positive

Jump if an operation caused an Overflow


JO

251
COS2621/102/3/2023

Jump if Parity, or Jump if Parity Even


JP/JPE
Jump if an operation set the Sign to negative
JS

Format: Jump_condition short_label

Jump_condition mem

Flags: None in all cases

LAHF: Load flags into AH

Loads the lowest 8 bits of the flags register into the AH register.

Format: LAHF

Flags: None

LDS/LES/LGS/ Load Segment Register

LSS/LFS 
Initialises a far address and offset of a data item so that succeeding
instructions can access it.

Format: LDS/LES/LFS/LGS/LSS reg,mem32

Flags: None
COS2621/102/3/2023

LEA: Load Effective Address

Calculates and loads the 16-bit effective address (offset) of a memory


position into a register.

Format: LEA reg,mem

Flags: None

LOCK: LOCK the system bus

LODS/LODSB/LODSW: LOad String

Loads a memory byte or word addressed by DS:SI into AL or AX.

Format: LODS

LODSB

LODSW

Flags: None

LOOP: LOOP until complete

Executes a routine a specified number of times. The CX register must be


loaded with the iteration count before the start of the loop. Loop appears
at the end of the loop. It decrements CX and causes a jump if CX is not
equal to zero. If CX=0, the next instruction after LOOP is executed.
253
COS2621/102/3/2023

Format: LOOP short_label

Flags: None

LOOPE/LOOPZ: LOOP while Equal or while Zero

These instructions are similar to LOOP except that they terminate if CX=0
or if the ZF flag is set to zero (i.e. a non-zero condition).

LOOPNE/LOOPNZ: LOOP while Not Equal or loop while Not Zero

Similar to LOOP except that they terminate if CX=0 or if the ZF flag is set
to 1 (zero condition).

MOV: MOVe data

Moves (actually copies) a byte or word from a source (operand_2) to a


destination operand (operand_1).

Format: MOV reg,reg MOV reg_16,segreg

MOV mem,reg MOV segreg,reg_16

MOV reg,mem MOV mem_16,segreg

MOV reg,immed MOV segreg,mem_16

MOV mem,immed

Flags: None
COS2621/102/3/2023

MOVS/MOVSB/

MOVSW/MOVSD: MOVe String

Copies a byte, word or double word from memory addressed by DS:SI to


memory addressed by ES:DI. Normally used with the REP prefix and the
length in CX.

MOVS requires both operands to be specified. If DF=0, the operation moves


data from left to right and increments the DI and SI by 1, 2 or 4. If DF=1,
the operation moves data from right to left and DI and SI are
decremented. The REP instruction decrements CX by 1 for each
repetition. The operation terminates when CX=0.
Format: MOVS dest,source MOVS ES:dest,segreg:source

[REP] MOVSB/MOVSW/MOVSD (no operand)

Flags: None

MOVSX/MOVZX: Move and fill

MUL: MULtiply unsigned integers

Multiplies AX or AL by a source operand of 16 or 8 bytes respectively. In


the first case the product is stored in AX:DX and in the second case the
product is stored in AX.

Multiplicand  Multiplier  Product 

(1st operand) (2nd operand)

255
COS2621/102/3/2023

AX (16 bits) reg/mem DX:AX


AL (8 bits) reg/mem AX

Formats: MUL reg MUL mem

Note that we only specify the 2nd operand in the instruction. The first
operand is assumed to be in AX or AL.

Flags: Affects CF and OF. AF, PF, SF and ZF are undefined.

NEG: NEGate

NEG calculates the two's complement of a binary value.

Format: NEG reg NEG mem

Flags: OF, SF, ZF, AF, PF, CF

NOP: NO Operation

Do nothing. It is used to delay execution or to delete machine code


without affecting the rest of the code.

Format:NOP

Flags: None
COS2621/102/3/2023

NOT: Performs a logical NOT on an operand

Format: NOT reg NOT mem

Flags: None

OR: Performs a logical OR on two operands. The result is stored in operand_1 (the
destination operand).

Format: OR reg,reg OR reg,immed

OR mem,reg OR mem,immed
OR reg,mem OR AL,immed

OR AX,immed

Flags: OF=0, CF=0, SF, ZF, and PF are affected

AF is undefined

OUT: OUTput to a port

Transfers a byte or word from AL or AX to an output port. The port


address is either a constant in the range 0 to FFh or a variable in DX if the
value of the port address is greater than FFh.

257
COS2621/102/3/2023

Format: OUT immed_8, AL OUT DX,AL OUT DX,AX

Flags: None

POP: POPs a word or double word from the stack to a specified destination and adds
2 or 4 to the SP

Format: POP reg_16 POP mem_16 POP seg_reg

Flags: None

POPA: POP All general registers.

Pops the top 8 words from the stack into DI, SI, BP, SP, BX, DX, CX, AX,
in that order and increments the SP by 16. (Normally used when a
PUSHA was used to push the registers.)

Format: POPA

Flags: None

POPF/POPFD: POPs the Flags off the stack

Pops a word from the stack to the flags register and increments the SP by
2.

POPFD handles double words and increments SP by 4.


COS2621/102/3/2023

Format: POPF/POPFD

Flags: All

PUSH: PUSH a word or double word onto the stack

The SP is decremented by 2 or 4 and the operand is pushed onto the stack.

Format: PUSH reg_16 PUSH mem_16 PUSH seg_reg

Flags: None

PUSHA: PUSH All general registers.

Pushes the AX, CX, DX, BX, SP, BP, SI, DI, in that order, onto the stack
and decrements the SP by 16. (Normally, a POPA later pops the
registers.)

Format: PUSHA

Flags: None

PUSHF: PUSH all the Flags onto the stack

Decrements the SP by two and copies the flags register to the top of the stack.

Format: PUSHF

259
COS2621/102/3/2023

Flags: None

RCL/RCR: Rotate bits Left or Right through the Carry flag

RCL rotates (shifts) the destination operand to the left a number of times
as specified by the source operand. The carry flag is copied into the least
significant bit and the most significant bit is copied into the carry flag with
each shift. The CL register or a constant may be used to control the
number of rotations.

RCR rotates (shifts) the destination operand to the right a number of times
as specified by the source operand. The carry flag is copied into the most
significant bit and the least significant bit is copied into the carry flag with
each shift. The CL register or a constant may be used to control the
number of rotations.

Format: RCL/RCR reg,1 RCL/RCR mem,1

RCL/RCR reg,CL RCR/RCR mem,CL

Flags: OF, CF

REP/REPE/REPZ/REPNE/REPNZ: REPeats string

Repeats a string operation a specified number of times. These are


optional repeat prefixes coded before string instructions like CMPS,
MOVS, SCAS and STOS. CX must be loaded with a count prior to
execution. The operation decrements CX by 1 for each execution of the
string instruction. For REP, the operation repeats until CX is 0. For
REPE/REPZ, the operation repeats until CX is 0 or until ZF is 0 (nonzero
condition). For REPNE/REPNZ, the operation repeats until CX is 0 or
until ZF is 1 (zero condition).

REPeat string. Used as a prefix to MOVS/MOVSB/MOVSW/MOVSD


COS2621/102/3/2023

operations.

REP repeats a string operation a specified number of times. CX is used as a


counter and is decremented each time the instruction is repeated. The
operation repeats until CX=0.

REPE/REPZ repeats a string operation until CX=0 or ZF=0.

REPNZ/REPNE repeats a string operation until CX=0 or ZF=1.

Format: REP/REPE/REPZ/REPNE/REPNZ string_operation

Flags: Depends on the associated string operation

RET/RETN/RETF: RETurn from a procedure previously entered by a CALL

Returns from a procedure previously entered by a NEAR or FAR call.


NEAR: RET/RETN (return near) pops the word at the top of the stack
into IP and increments SP by 2.

FAR: RET/RETF pops the 2 words at the top of the stack into IP and
CS and increments SP by 4.

An optional immediate 8_bit operand (called a pop_value) is added to the


SP.

Format: RET RET immed_8

RETN RETN immed_8

RETF RETF immed_8

261
COS2621/102/3/2023

Flags: None

ROL/ROR: Rotate Left or Right

ROL rotates (shifts) the destination operand to the left a number of times as
specified by the source operand. The leftmost (most significant) bit is
rotated into the least significant position. The most significant bit also
moves into the carry flag for each shift. The CL register or a constant
may be used to control the number of rotations.

ROR rotates (shifts) the destination operand to the right a number of


times as specified by the source operand. The rightmost (least
significant) bit rotates into the most significant position. The least
significant bit also moves to the carry flag for each shift. The CL register
or a constant may be used to control the number of rotations.

Format: ROL/ROR reg,1 ROL/ROR mem,1

ROL/ROR reg,CL ROL/ROR mem,CL

Flags: OF,CF

SAHF: Store AH in the Flags register

Copies AH into bits 0 to 7 of the flags register.

Format: SAHF

Flags: SF, ZF, AF, PF, CF


COS2621/102/3/2023

SAL/SAR: Shift Arithmetic Left or Right

SAL shifts the destination operand to the left a number of times as


specified by the source operand. Zero is shifted into the least significant
bit and the most significant bit is shifted into the carry flag for each shift.
The CL register or a constant may be used as the source operand.

SAR shifts the destination operand to the right a number of times as specified
by the source operand. The most significant bit retains its previous value
which means that the sign bit is duplicated with each shift. The least
significant bit is shifted into the carry flag with each shift. The CL register
or a constant may be used as the source operand.

Format: SAL/SAR reg,1 SAL/SAR mem,1

SAL/SAR reg,CL SAL/SAR mem,CL

Flags: OF, SF, ZF, AF (undefined) PF, CF

SBB: SuBtract with Borrow

Subtracts the source operand from the destination operand and then
subtracts the value of CF from the destination. SBB is used in multiword
subtraction to carry an overflowed 1 bit into the next stage of arithmetic.

Format: SBB reg,reg SBB reg,immed

SBB reg,mem SBB mem,immed

SBB mem,reg SBB AL,immed

SBB AX,immed

263
COS2621/102/3/2023

Flags: OF, SF, ZF, AF, PF, CF

SCAS/SCASB/SCASW: SCAn String

Scans a string in memory pointed to by ES:DI for a value that matches a


value in AL or AX.

Format: SCAS operand SCASB (match with AL)

SCAS ES:operand SCASW (match with AX)

Flags: OF, SF, ZF, AF, PF, CF

SET: Set bytes conditionally

SHL/SHR: SHift logical Left or SHift logical Right

SHL is identical to SAL.

SHR shifts bits to the right a specified number of times and fills the bits on the
left with 0's.

The CL register or a constant (for some assemblers the constant may


only be a 1) may be used to control the number of shifts.

Formats: SHL/SHR reg,immed SHL/SHR


COS2621/102/3/2023

reg,CL SHL/SHR mem,immed SHL/SHR

mem,CL

Flags: OF, SF, ZF, AF (undefined), PF, CF

SHLD/SHRD: SHift Left or Right Double precision

STC: SeT Carry flag

Sets the CF to 1.

Format: STC Flags: CF=1

STD: SeT Direction flag

Sets the DF flag to 1. This is used for string operations. SI and/or DI will
be decremented by string operations which in turn causes string
operations to process strings from right to left.

Format: STD

Flags: DF=1.

STI: SeT the Interrupt flag

Sets the IF flag to 1 to enable maskable external interrupts.

265
COS2621/102/3/2023

Format: STI

Flags: IF =1.

STOS/STOSB/STOSW/ STOre String

STOSD 
Stores either AL (byte) or AX (word) in the memory position addressed by
ES:DI. DI is incremented if DF=0 and DI is decremented if DF=1
(compare with STD).

Format: STOS mem STOSB (stores AL)

STOS ES:mem STOSW (stores AX)

Flags: None

SUB: SUBtract
COS2621/102/3/2023

Subtracts the source operand from the destination operand. Result is


stored in the destination operand.

Format: SUB reg,reg SUB reg,immed

SUB reg,mem SUB mem,immed

SUB mem,reg SUB AL,immed

SUB AX,immed

Flags: OF, SF, ZF, AF, PF, CF

TEST: TEST bits

Tests individual bits in the destination operand against those in the source
operand. TEST performs a logical AND, but the destination operand is
not affected.

Format: TEST reg,reg TEST reg,immed

TEST reg,mem TEST mem,immed

TEST mem,reg TEST AL,immed

TEST AX,immed

Flags: OF=0, SF, ZF, AF (undefined), PF, CF=0.

WAIT: Put Processor in a WAIT state.

Allows the processor to remain in a wait state until an external interrupt


occurs in order to synchronize it with an external device or coprocessor.
267
COS2621/102/3/2023

XCHG: EXCHanGes operands

Exchanges the contents of the two operands.

Format: XCHG reg,reg XCHG reg,immed

XCHG reg,mem XCHG mem,immed

XCHG mem,reg XCHG AL,immed

XCHG AX,immed

Flags: None

XLAT: Translate bytes

Translate bytes into a different format, such as ASCII or EBCDIC. A table


has to be defined and pointed to by DS:BX. AL is used as an offset into
the table. Selects the byte from the table and stores it in AL.

Format: XLAT XLAT segreg:mem

XLAT mem

Flags: None

XOR: EXclusive OR

Performs a logical exclusive OR on the bits in two operands.


COS2621/102/3/2023

Format: XOR reg,reg XOR

reg,immed XOR reg,mem XOR

mem,immed

XOR mem,reg XOR AL,immed

XOR AX,immed

Flags: OF=0, SF, ZF, AF (undefined), PF, CF=0.

---oooOooo—

269
COS2621/102/3/2023

1 31 Appendix F
32 THE ASCII TABLE
ASCII-code Character ASCII-code Character ASCII-code Character

0000 0000 NUL 0011 0000 0 0110 0000 `

0000 0001 SOH 0011 0001 1 0110 0001 a

0000 0010 STX 0011 0010 2 0110 0010 b

0000 0011 ETX 0011 0011 3 0110 0011 c

0000 0100 EOT 0011 0100 4 0110 0100 d

0000 0101 ENQ 0011 0101 5 0110 0101 e

0000 0110 ACK 0011 0110 6 0110 0110 f

0000 0111 BEL 0011 0111 7 0110 0111 g

0000 1000 BS 0011 1000 8 0110 1000 h

0000 1001 HT, Tab 0011 1001 9 0110 1001 i

0000 1010 LF 0011 1010 : 0110 1010 j

0000 1011 VT 0011 1011 ; 0110 1011 k

0000 1100 FF 0011 1100 < 0110 1100 l

0000 1101 CR 0011 1101 = 0110 1101 m

0000 1110 SO 0011 1110 > 0110 1110 n

0000 1111 SI 0011 1111 ? 0110 1111 o

0001 0000 DLE 0100 0000 @ 0111 0000 p

0001 0001 DC1 0100 0001 A 0111 0001 q

0001 0010 DC2 0100 0010 B 0111 0010 r

0001 0011 DC3 0100 0011 C 0111 0011 s

0001 0100 DC4 0100 0100 D 0111 0100 t

0001 0101 NAK 0100 0101 E 0111 0101 u

0001 0110 SYN 0100 0110 F 0111 0110 v

0001 0111 ETB 0100 0111 G 0111 0111 w

0001 1000 CAN 0100 1000 H 0111 1000 x

0001 1001 EM 0100 1001 IJ 0111 1001 y

0001 1010 SUB 0100 1010 K 0111 1010 z

0001 1011 ESC 0100 1011 L 0111 1011 {

0001 1100 FS 0100 1100 M 0111 1100 |

0001 1101 GS 0100 1101 N 0111 1101 }

0001 1110 RS 0100 1110 O 0111 1110 ~

0001 1111 US 0100 1111 0111 1111 Delete

269
COS2621/102/3/2023

0010 0000 space 0101 0000 P

0010 0001 ! 0101 0001 Q

0010 0010 " 0101 0010 R

0010 0011 # 0101 0011 S

0010 0100 $ 0101 0100 T

0010 0101 % 0101 0101 U

0010 0110 & 0101 0110 V

0010 0111 ' 0101 0111 W

0010 1000 ( 0101 1000 X

0010 1001 ) 0101 1001 Y

0010 1010 * 0101 1010 Z

0010 1011 + 0101 1011 [

0010 1100 , 0101 1100 \

0010 1101 - 0101 1101 ]

0010 1110 . 0101 1110 ^

0010 1111 / 0101 1111 _


COS2621/102/3/2023

33 Bibliography

P. Abel. IBM PC Assembly Language and Programming, Fifth Edition. USA: Prentice-
Hall, 2001.
S.D. Burd. Systems Architecture, Sixth Edition. Canada: Course Technology, Thompson
Learning, 2010.
J.D. Carpinelli. Computer Systems: Organization & Architecture. USA: Addison Wesley
Longman, 2000.
R.C. Detmer. Introduction to 80x86 assembly language and computer architecture. Jones
& Bartlett Publishers, 2001.
J. Duntemann. Assembly Language Step-by-Step, Second Edition. USA: John Wiley &
Sons, 2000.

J.L. Hennessy & D.A. Patterson. Computer Architecture: A Quantitative Approach, 3rd
edition, Morgan Kaufmann Publishers, 2003.
V.P. Heuring & H.F. Jordan. Computer Systems Design and Architecture. USA: Addison-
Wesley, 1997.
K.R. Irvine. Assembly Language for the IBM PC, Second Edition. USA: Macmillan
Publishing Company, 1993.
N.S. Matlof. IBM Microcomputer Architecture and Assembly Language. A look under the
hood. USA: Prentice-Hall International, 1992.
W. Stallings. Computer Organization and Architecture. Designing for Performance,
9th edition. USA: Prentice-Hall International, 2013.
A.S. Tanenbaum. Structured Computer Organization, Fourth Edition. USA: Prentice-Hall
International, 1999.
M. Thorne. Computer Organization and Assembly Language Programming. For IBM PC’s and
Compatibles, 2nd Edition. The Benjamin/Cummings Publishing Company, 1991.

271

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy