ConstsVarsAndDataTypes.pdf
(
388 KB
)
Pobierz
AoA.book
Constants, Variables, and Data Types
Constants,
Variables, and Data Types
Chapter One
olume One discussed the basic format for data in memory
.
V
olume
T
w
o co
v
ered ho
w a computer sys
-
tem ph
ysically or
g
anizes that data.
This chapter fi
nishes this discussion by connecting the concept of
data
epr
esentation
to its actual ph
ysical representation.
As the title implies, this chapter concerns itself with
three main topics: constants, v
ariables and data structures.
This chapter does not assume that you’
v
e had a
formal course in data structures, though such e
xperience w
ould be useful.
1.1
Chapter Overview
This chapter discusses ho
w to declare and use constants, scalar v
ariables, inte
gers, reals, data types,
pointers, arrays, and structures.
Y
ou must master these subjects before going on to the ne
xt chapter
. Declar
-
ing and accessing arrays, in particular
, seems to present a multitude of problems to be
ginning assembly lan
-
guage programmers. Ho
we
v
er
, the rest of this te
xt depends on your understanding of these data structures
and their memory representation. Do not try to skim o
v
er this material with the e
xpectation that you will
pick it up as you need it later
.
Y
ou will need it right a
w
ay and trying to learn this material along with later
material will only confuse you more.
1.2
Some Additional Instructions: INTMUL, BOUND, INTO
This chapter introduces arrays and other concepts that will require the e
xpansion of your 80x86 instruc
-
tion set kno
wledge. In particular
, you will need to learn ho
w to multiply tw
o v
alues; hence the fi
rst instruc
-
tion we will look at is the
intmul
(inte
ger multiply) instruction.
Another common task when accessing
arrays is to check to see if an array inde
x is within bounds.
The 80x86
bound
instruction pro
vides a con
v
e
-
nient w
ay to check a re
gister’
s v
alue to see if it is within some range. Finally
, the
into
(interrupt on o
v
erfl
o
w)
instruction pro
vides a quick check for signed arithmetic o
v
erfl
o
w
.
Although
into
isn’
t really necessary for
array (or other data type access), its function is v
ery similar to
bound
, hence the presentation at this point.
The
intmul
instruction tak
es one of the follo
wing forms:
// The following compute destreg = destreg * constant
intmul(
constant, destreg
16
);
intmul(
constant, destreg
32
);
// The following compute dest = src * constant
intmul(
constant, srcreg
16
, destreg
16
);
intmul(
constant, srcmem
16
, destreg
16
);
intmul(
constant, srcreg
32
, destreg
32
);
intmul(
constant, srcmem
32
, destreg
32
);
// The following compute dest = dest * src
intmul( srcreg
16
, destreg
16
);
intmul( srcmem
16
, destreg
16
);
intmul( srcreg
32
, destreg
32
);
intmul( srcmem
32
, destreg
32
);
Note that the syntax of the
intmul
instruction is different than the
add
and
sub
instructions. In particular,
note that the destination operand must be a register (
add
and
sub
both allow a memory operand as a destina-
tion). Also note that
intmul
allows three operands when the first operand is a constant. Another important
Beta Draft - Do not distribute
© 2001, By Randall Hyde
Page
393
V
r
Chapter One
Volume Three
difference is that the
intmul
instruction only allows 16-bit and 32-bit operands; it does not allow eight-bit
operands.
intmul
computes the product of its specified operands and stores the result into the destination register.
If an overflow occurs (which is always a signed overflow, since
intmul
only multiplies signed integer values),
then this instruction sets both the carry and overflow flags.
intmul
leaves the other condition code flags unde-
fined (so, for example, you cannot check the sign flag or the zero flag after
intmul
and expect them to tell you
anything about the
intmul
operation).
The
bound
instruction checks a 16-bit or 32-bit register to see if it is between one of two values. If the
value is outside this range, the program raises an exception and aborts. This instruction is particularly useful
for checking to see if an array index is within a given range. The
bound
instruction takes one of the follow-
ing forms:
bound(
reg
16
, LBconstant, UBconstant
);
bound(
reg
32
, LBconstant, UBconstant
);
bound(
reg
16
, Mem
16
[2]
);
1
bound(
reg
32
, Mem
32
[2]
);
2
The
bound
instruction compares its register operand against an unsigned lower bound value and an unsigned
upper bound value to ensure that the register is in the range:
lower_bound <= register <= upper_bound
The form of the
bound
instruction with three operands compares the register against the second and third
parameters (the lower bound and upper bound, respectively)
3
. The
bound
instruction with two operands
checks the register against one of the following ranges:
Mem
16
[0] <= register
16
<= Mem
16
[2]
Mem
32
[0] <= register
32
<= Mem
32
[4]
If the specified register is not within the given range, then the 80x86 raises an exception. You can trap
this exception using the HLA
try..endtry
exception handling statement. The excepts.hhf header file defines an
exception,
ex.BoundInstr
, specifically for this purpose. The following code fragment demonstrates how to
use the
bound
instruction to check some user input:
program BoundDemo;
#include( “stdlib.hhf” );
static
InputValue:int32;
GoodInput:boolean;
begin BoundDemo;
// Repeat until the user enters a good value:
repeat
// Assume the user enters a bad value.
mov( false, GoodInput );
1. The “[2]” suggests that this variable must be an array of two consecutive word values in memory.
2. Likewise, this memory operand must be two consecutive dwords in memory.
3. This form isn’t a true 80x86 instruction. HLA converts this form of the bound instruction to the two operand form by cre-
ating two readonly memory variables initialized with the specified constant.
Page 394
© 2001, By Randall Hyde
Beta Draft - Do not distribute
Constants, Variables, and Data Types
// Catch bad numeric input via the try..endtry statement.
try
stdout.put( “Enter an integer between 1 and 10: “ );
stdin.flushInput();
stdin.geti32();
mov( eax, InputValue );
// Use the BOUND instruction to verify that the
// value is in the range 1..10.
bound( eax, 1, 10 );
// If we get to this point, the value was in the
// range 1..10, so set the boolean “GoodInput”
// flag to true so we can exit the loop.
mov( true, GoodInput );
// Handle inputs that are not legal integers.
exception( ex.ConversionError )
stdout.put( “Illegal numeric format, reenter”, nl );
// Handle integer inputs that don’t fit into an int32.
exception( ex.ValueOutOfRange )
stdout.put( “Value is *way* too big, reenter”, nl );
// Handle values outside the range 1..10 (BOUND instruction)
/*
exception( ex.BoundInstr )
stdout.put
(
“Value was “,
InputValue,
“, it must be between 1 and 10, reenter”,
nl
);
*/
endtry;
until( GoodInput );
stdout.put( “The value you entered, “, InputValue, “ is valid.”, nl );
end BoundDemo;
Program 1.1
Demonstration of the BOUND Instruction
Beta Draft - Do not distribute
© 2001, By Randall Hyde
Page 395
Chapter One
Volume Three
The
into
instruction, like
bound
, also generates an exception under certain conditions. Specifically,
into
generates an exception if the overflow flag is set. Normally, you would use
into
immediately after a signed
arithmetic operation (e.g.,
intmul
) to see if an overflow occurs. If the overflow flag is not set, the system
ignores the
into
instruction; however, if the overflow flag is set, then the
into
instruction raises the HLA
ex.IntoInstr
exception. The following code sample demonstrates the use of the
into
instruction:
program INTOdemo;
#include( “stdlib.hhf” );
static
LOperand:int8;
ResultOp:int8;
begin INTOdemo;
// The following try..endtry checks for bad numeric
// input and handles the integer overflow check:
try
// Get the first of two operands:
stdout.put( “Enter a small integer value (-128..+127):” );
stdin.geti8();
mov( al, LOperand );
// Get the second operand:
stdout.put( “Enter a second small integer value (-128..+127):” );
stdin.geti8();
// Produce their sum and check for overflow:
add( LOperand, al );
into();
// Display the sum:
stdout.put( “The eight-bit sum is “, (type int8 al), nl );
// Handle bad input here:
exception( ex.ConversionError )
stdout.put( “You entered illegal characters in the number”, nl );
// Handle values that don’t fit in a byte here:
exception( ex.ValueOutOfRange )
stdout.put( “The value must be in the range -128..+127”, nl );
// Handle integer overflow here:
/*
exception( ex.IntoInstr )
Page 396
© 2001, By Randall Hyde
Beta Draft - Do not distribute
Constants, Variables, and Data Types
stdout.put
(
“The sum of the two values is outside the range -128..+127”,
nl
);
*/
endtry;
end INTOdemo;
Program 1.2
Demonstration of the INTO Instruction
1.3 The QWORD and TBYTE Data Types
HLA lets you declare eight-byte and ten-byte variables using the
qword,
and
tbyte
data types, respec-
tively. Since HLA does not allow the use of 64-bit or 80-bit non-floating point constants, you may not asso-
ciate an initializer with these two data types. However, if you wish to reserve storage for a 64-bit or 80-bit
variable, you may use these two data types to do so.
The
qword
type lets you declare
quadword
(eight byte) variables. Generally,
qword
variables will hold
64-bit integer or unsigned integer values, although HLA and the 80x86 certainly don’t enforce this. The
HLA Standard Library contains several routines to let you input and display 64-bit signed and unsigned inte-
ger values. The chapter on advanced arithmetic will discuss how to calculate 64-bit results on the 80x86 if
you need integers of this size.
The
tbyte
directive allocates ten bytes of storage. There are two data types indigenous to the 80x87
(math coprocessor) family that use a ten byte data type: ten byte BCD values and extended precision (80 bit)
floating point values. Since you would normally use the
real80
data type for floating point values, about the
only purpose of tbyte in HLA is to reserve storage for a 10-byte BCD value (or other data type that needs 80
bits). Once again, the chapter on advanced arithmetic may provide some insight into the use of this data
type. However, except for very advanced applications, you could probably ignore this data type and not suf-
fer.
1.4 HLA Constant and Value Declarations
HLA’s CONST and VAL sections let you declare symbolic constants. The CONST section lets you
declare identifiers whose value is constant throughout compilation and run-time; the VAL section lets you
declare symbolic constants whose value can change at compile time, but whose values are constant at
run-time (that is, the same name can have a different value at several points in the source code, but the value
of a VAL symbol at a given point in the program cannot change while the program is running).
The CONST section appears in the same declaration section of your program that contains the STATIC,
READONLY, STORAGE, and VAR, sections. It begins with the CONST reserved word and has a syntax
that is nearly identical to the READONLY section, that is, the CONST section contains a list of identifiers
followed by a type and a constant expression. The following example will give you an idea of what the
CONST section looks like:
const
pi: real32 := 3.14159;
MaxIndex: uns32 := 15;
Delimiter: char := ‘/’;
BitMask: byte := $F0;
Beta Draft - Do not distribute
© 2001, By Randall Hyde
Page 397
Plik z chomika:
brosaczony
Inne pliki z tego folderu:
Volume5.pdf
(23 KB)
Volume4.pdf
(29 KB)
Volume3.pdf
(27 KB)
Volume2.pdf
(24 KB)
Volume1.pdf
(29 KB)
Inne foldery tego chomika:
Pliki dostępne do 01.06.2025
Pliki dostępne do 19.01.2025
Angielski dla dzieci
Antyki
Audiobook
Zgłoś jeśli
naruszono regulamin