A little history ("cultural information")
In 1964, IBM came out with the IBM 360, which was the first 8-bit
machine. The word went from 36 bits to 32 bits; 6-bit BCD became
EBCDIC. The 360/30F, called the "Fat 30" has lots of memory --
64k RAM! Programs were submitted with punched cards, 80 columns
by 12 rows. PL/1 (Programming Language 1) was the high-level
language of choice, somewhat like FORTRAN (Formula Translation),
also the early predecessor of Pascal. The college has a 360/308X.
IBM has implemented this machine on CMOS, and has 4 processors
on a card, which you can also put in a PC (given the right kind
of bus). In 1975, the first micro computer appeared, the 4004.
They built programmable calculators with it. Then appeared the
8008, which was replaced with the 8-bit micro computers, the 8080
and the Z80.
In 1988, the 8086 appeared, which was the first widely used
16-bit machine. It's descendants, the 80186, 80286, 80386, 80486,
Pentium (80586). The 80386 was the first 32-bit machine in this
group, and the Pentium was the first 64-bit machine in the group.
Each of these machines doubled or tripled the speed and power
of its predecessor.
CP/M was written for the 8-bit 8008, 8080 and Z80.
Jeff Petersen of Seattle Computer wrote DOS for the 16-bit 8088.
Bill Gates wrote BASIC that ran under CP/M. IBM asked him to
write an O/S for their machine, so Billy boy paid Jeff Petersen
$50,000 for DOS. The rest is history... I bet Jeff Petersen is
kicking himself today.
Win NT is a true 32-bit system, while Win95 still has dos
embedded in it. The more bits of your o/s the more "bandwidth"
of your CPU is used at once -- so the more information is
transmitted at once.
If I might interject my opinion here again, I'd point out that
as computer hardware becomes more powerful, programmers become
lazier, so it is always necessary to have better hardware than
is actually available in order to have your programs perform
satisfactorily. If all lazy programmers were taken out and shot,
and we all wrote everything to work on a '386, imagine how
splendid performance would be. It would not be impossible to
implement our functionality in this environment, it might only
be harder and take longer.
While the IBM 704 cost millions of dollars, the 80486 is millions
of times faster and costs under $1000. The power and population
of computers is growing exponentially, while the cost is falling
on a similar curve. Maybe eventually it will cost only pennies to
make a computer, and replace many things that we use today. For
example, the credit cards will become "smart cards" with a little
computer on them.
When the UNIVAC 1 was first produced, it was thought that a total
of no more than 6 would be made. Before the UNIVAC 2 appeared,
30 UNIVAC 1's had been sold.
The professor believes that this will change society even more
than the advent of the printing press.
Knowledge of application software, such as word processors,
spreadsheets, Windows are required for even a secretarial
job these days.
About 99% of the computer literate population uses this type
of application software, 80% know how to work with windows,
1% know a language such as C, C++, Pascal and Delphi, and
about .001% know assembler. Those who know BIOS and, on a
lower level, machine language, must be really, really small!
(Luckily we can get at that through assembler.) The professor
says we are a "highly select group." I think we're all just
nuts. (Which would explain a lot.)
The high-level languages, such as C++ and Delphi are often
accessible through a GUI interface and english-like
statements, while in assembler, our mnemonics are more
abstract and like polish notation. Polish notation is named
for a polish mathematician who felt that mathematical
expressions were obscured by parenthesis, and felt that
notation could be clearer if these could be eliminated.
For example c(a+b) could more clearly noted as cab+*
(this guy must've been nuts!)
In assembler when we write MOV A,B A is the destination
and B is the source. A copy of the contents of B is placed
into B. This would be like saying +*cab (which imo is neither
more or less clear than cab+*, which doesn't seem very
clear at all)
Most assembler statements work like MOV A,B. 2 operands and
one operation. the operation comes first. One operand
will contain the result, the other one contains the source.
ADD AX, 3 means that 3 will be added to the existing contents
of AX.
In the expression 3 + 4 = 7, 3 is called the addend, 4 is the
augend, and 7 is the sum.
MOV AX, 3 (AX is now 3)
ADD AX, 4
AX now has the value 7.
The register is both the addend and the sum, while the value
is the augend, however these concepts are somewhat arbitrary
in assembler.
MOV AX, 3 is called an immediate instruction because one
value is in the instruction itself, as opposed to somewhere in
memory.
When you start DEBUG, it initializes all the registers to
particular values. (Some will be 0; others will have other
values.
---------------------------------------------------------------
Now he's gonna talk about numbering systems.
3784 means 4x10^0 (anything ^0 = 1) 1
+ 8x10^1 8x10 = 80
+ 7x10^2 7x100 = 700
+ 3x10^3 3x1000 = 3000
-------------------
3784
This number, a could be represented as
a(4)xB^3 + a(3)xB^2 + a(2)xB^1 + a(1)xB^0
so 101101 in base 2 could be represented as
1x2^5 + 1x2^3 + 1x2^2 + 1x2^0 =
32 + 8 + 4 + 1 = 45 in decimal
or in hexadecimal as 2D. This is very easy if you memorize the
binary values from 0 - 15 and their corresponding hex digits
DEC HEX BIN OCTAL (Octal was important when the computers
0 0 0 0 had 36 bits. 3 digits per word.)
1 1 1 1
2 2 10 2
3 3 11 3
4 4 100 4
5 5 101 5
6 6 110 6
7 7 111 7
8 8 1000 10
9 9 1001 11
10 A 1010 12
11 B 1011 13
12 C 1100 14
13 D 1101 15
14 E 1110 16
15 F 1111 17
16 10 10000 20
Here's my added example. Say we had a numbering system where
the only digits were MARS. (called martian) (If you're having
difficulty with numbering systems, you should check the examples
in the Duntemann book recommended last week, were some alien
beings have numbers like foobity-fooby-foo-ba...)
Here are the numbers.
0 M
1 A
2 R
3 S
4 AM
5 AA
6 AR
7 AS
8 RM
9 RA
10 RR
12 RS
13 SM
14 SA
15 SR
16 SS
17 AMM
Ok, now he asks: what is 53 decimal in binary?
Keep dividing by 2 and write down the remainder
quotient remainder
53/2 = 26 1
26/2 = 13 0
13/2 = 6 1
6/2 = 3 0
3/2 = 1 1
1/2 =0 1 (biggest power of 2, because it represents
the most divisions!)
Starting from the bottom, this produces 110101.
53 in hexadecimal
53/16 = 3 5
3/16 = 0 3, so the number is 35
also notice that 0011 binary = 3 hex and 0101 binary = 3 hex, so
we get the binary from the hex 11 0101
-------------------------------------------------------------------
SIGNED NUMBERS
Imagine that you had the number 00000010. This is a positive
number. Negative numbers are represented in "2's complement"
Step 1: Switch all the bits
11111101
Step 2: Add 1.
11111110
The above number is -2.
To prove this, add it to +2 to make sure you get 0.
00000010
11111110
--------
100000000 (the extra 1 falls off the end, so the byte can
only hold all of those 0's and therefore the result should
be considered 0)
(If you were doing 16-bit math,
00000000 00000010 = 2
11111111 11111110 = -2
-----------------
100000000 00000000
There's still an extra 1, which "falls off" and is still
ignored, so that the result is still considered 0. I would
therefore imagine that 32-bit arithmetic would be similar.)
---------------------------------------------------------------------
subtraction
3 minuend
-1 subtrahend
--------
2 difference
The computer actually takes the 2's complement of the subtrahend
and ADDS it to the minuend -- it can only add. This is wired into
the microcode so asm SUB is still one step in machine code.
---------------------------------------------------------------------
more on DEBUG
DEBUG is a mini-assembler operating system.
You can write asm code, read from the disk, write to the disk
and so on.
Appendix B contains a lot of information (however it is not
100% complete)
Write commands at the
-
prompt.
?
displays a list of the debug commands.
Here are some things DEBUG can do:
a assembles 8086/8087/8088 mnemonics
some examples of mnemonics are MOV copies result from source to
dest, ADD adds copy of value in source to dest,
SUB subtracts copy of value in source from dest.
c compares two portions of memory
d displays contents of memory
----------------------------------------------------------------------
some stuff about the hardware and how instructions are
executed
Floating point instructions didn't used to be wired into the
CPU until the advent of the 386DX.
For example, the 8086 was the CPU, you could get the 8087 fpu
the 286 had a 287 fpu separate.
or a 386SX + separate 387 fpu = 386DX.
486SX is 486DX with FPU disabled. What a scam! Then you had
to buy a separate 487 FPU. There is no pentium with separate
fpu.
SLC- and DLC- chips do special stuff like work at lower voltage,
shut themselves off in disuse.
The power pc has a motorola 601, 602, 603, 604 or 615, which
is RISC (reduced instruction set computer) instruction set
intel architecture is cisc (complex instruction set computer).
Might take 15 cisc instructions to make 1 risc instructions.
@ risc instruction is much faster than @ cisc instruction.
When instructions are executed, it took a number of steps:
* fetch the instruction from memory, bring it into the IR
(instruction register)
* examine & decode the instruction, to set its switches to
do the right thing (to route the information for the
instruction to the right place)
* fetch operands
* perform operation
* send results to destination
(These things take longer to do when the instructions are
simpler)
To speed up the cisc architecture, a pipeline was developed --
while an instruction is moving to the IR, another is being
decoded, another is having its operands fetched, and so on.
So that finally, when the operation is ready to be performed,
only one machine cycle is required.
There are many different kind of MOV instructions (approx 30)
immediate value to register
memory to register
register to register
register to memory
immediate value to memory
YOU CANNOT MOVE MEMORY TO MEMORY (the machine is not wired to
do this one)
and so on. Each of these has a different OP code, but you
don't have to remember all of them.
Things take place in different "time dimensions" in the computer.
The machine has a number of clocks
crystal timer ticks millions of times/second MHz of PC is # of
times/second this particular timer ticks
The CPU ticks at, for example 100 MHz, which has this little
crystal clock attached to it. (100 million ticks per second)
ISA bus is meanwhile ticking at about 8MHz.
INTEL makes some bus-controlling chip sets, such as the triton,
enterprise, and so on, which are used in the PCI bus, which
works at up to 66 MHz.
The system timer ticks 18.2 times/second. This is used to
time communications through the serial port, which are
synchronous, because their speed and movement is controlled
by this clock. This speed of the system timer is constant
no matter what the speed of your cpu or bus.
Async designs have been proposed to allow faster things to
happen at a greater rate than slower things.
Even access to memory must be controlled, because dynamic
ram forgets what's there if it's not regenerated every millionth
of a second. So the CPU can't examine memory while it's being
refreshed.
Static ram was made out of little magnetic "donuts", which had
a bunch of wires running through the hole. (These were hand-
wired. Cost = $10/bit!) It would retain its charge when you
turned off the machine, but it was very slow, because a finite
amount of time is required to magnetize the memory, known as
a cycle time.
Dynamic memory also has a cycle time, because even though it
is much faster, it still takes a finite amount of time to change
the charge in the transistors.
--------------------------------------------------------------------
Some DEBUG stuff
Display one of the exercises (#3 in last week's homework)
Remember that there is a segment address and an offset address for
each location in memory, which is written this way:
SEGMENT:OFFSET, for example 1A3C:0106
For example, segment 0000 can have offsets between (& including)
0000 and FFFF. FFFF = 0 thru 65535 (65536 bytes).
When you start DEBUG, it chooses an address for you to work at
that is not already in use.
Saying
a 100
means that you will start assembling your
program at offset 100 in a segment chosen by DEBUG, for example,
155D. It then prompts you with the segment and offset location
where you can enter an instruction.
After you press enter it prompts you with the next available
location for an instruction, depending on how much the first one
took up.
Numbers entered into debug are hex, and the addresses are hex
unless otherwise noted.
Send a form feed to the printer
MOV AH, 5
MOV DL, C
INT 21 call to DOS "please look at the AH register"
when dos sees this it sends the FF to the ptr
INT 20 ends execution
to save this program on diskette as page.com:
name it:
-n a:page.com
now put an 8 into register CX to tell it how long the code is.
-r cx
(some#):8
now write it to the disk
-w
now quit debug
-q
a:page
--------------------------------------------------------------------
DOS INTERRUPTS
see p. 571
MOV AH, 5 you will see in the book that 5 is printer output -
sends the character in DL to stdprn,
MOV DL, C this is the byte to send to the printer, which
causes a formfeed (won't have any particular effect if you're
not directly connected to a printer (i.e., if you're on a
network))
INT 21 let dos have a look at these registers now that they're
ready
INT 20
character set we have to work with
A..Z, a..z, digits 0..9,
special characters ? @ _ , " & $ % : ! . [ ] < (and so on)
constants ABC 2134 546 (1+2)/3
integers numeric digits
in TASM, (not debug) we will have numbers
by default they are decimal, this
can be specifically designated by a "d"
hex is denoted by "h"
octal is denoted by "q" or "o"
binary is denoted by "b"
characters or strings
"a" or 'a' 1 byte
"jib" uses up 3 bytes
an assembler statement : (@ component is optional below!)
[name] [mnemonic] [operands] [comment]
any line of code can have a name, which is referred to as a
label, for example:
L1:
MOV AX, 3
MOV AX,3 is now referred to by the label L1. Give control
to this line of code with a statement like:
JMP L1
which resets the IP, and execution continues from there.
(There are conditional jumps, such as JP and JN (jump if
positive, jump if negative), which will be discussed later.)
Each asm instruction translates directly into one machine
language statement.
By default, in TASM, a name may be up to 32 characters in
length (31 characters or shorter); however it has the
capacity to allow you to make the name up to 255 characters
in length (must set an option to be able to do so). The
characters which compose a name are alphabetic, numerals, and
the symbols: ? _ @ $ .
Name must not begin with a numeral. (Alpha, symbols, ok)
DEBUG
a 120
DW 0010
DW 0020
a 100
MOV AX, [0120]
ADD AX, [0122]
MOV [0124], AX
might want to do a
d 120
before and after tracing this to see what happens to memory
notice how the two bytes are reversed, so 0010 is displayed as
10 00, but is treated correctly as 0010 when it's moved to
AX.
"DEBUG IS NOT A STABLE ENVIRONMENT"
My observation has been that often you may want to restart
debug before trying this, because debug is not exactly a
great app builder, and it doesn't appear to let you just go
set memory locn's to your heart's content (even though you
should be able to), and the best thing to do is start and
restart.
NOTE: The book has some examples that are somewhat obsolete.
-------------------------------------------------------------
Notes on the "hello world" program handed out last week:
.model small
.stack 100h
.data now begins the data segment
a dw 0010h
b dw 0020h
sum dw
.code now begins the code segment
next 2 lines of code set up the
registers so that it can find a
when it gets to mov ax,a
there is no mov instructions that will get the
contents of a and b
mov ax,@data
mov ds,ax
mov ax,a
add ax,b
mov sum,ax put copy of ax contents into sum
The assembler code looks different than the debug code
(Sorry, folks, I'm not taking notes on how to use the
lab pc's because I don't intend to do so.)
When using TASM, name the source files with an .asm
extensions
---------------------------------------------------------------
in TASM, leave off the .dosseg, it's a remanant from the
old days.
might want to put in a comment
type in and save the following code
; This is my hello world program
.model small
.stack 100h ;(256 bytes of stack space)
.data
hello_message db "hello, Maggie",0dh,0ah,"$"
.code
main proc
mov ax, @data ;segment address of data goes into ax
mov ds,ax ;data segment pointer has to be in ds,
; but we can't put it there directly, only
; can set ds from another register
mov ah, 9 ; tells dos int 21 what to do
mov dx, offset hello_message
int 21 ; dos looks at ah, sees the 9, will output
; from ds:dx until it finds a $ then returns
; to program
mov ax,4c00h ; dos halt code
int 21 ; return to dos with 4c00
main endp
end main
;generally you use db for a string declaration
;odh,oah is a cr/lf (\r\n)
;$ is end of string for dos
; it will continue to print until it finds a $
;one main in asm, just like in c
assemble the code with
TASM /zi /l /hello
where hello is the name of your .asm source code
zi adds debug info
l causes production of lst file
This will produce an object module (.obj)
End result would be the files:
hello.lst
hello.obj
now must make this executable with link editor
TLINK /vi hello
produces hello.exe
which you can run by typing hello (if you're feeling
brave)
you could also run by saying TD hello, which
runs the TASM debugger, or by saying debug hello,
which will run the [somewhat inferior] dos debug
program you're already familiar with.
[back to the main csc220 page] [To the downloadable files] [To Maggie's homepage]