The end of Chapter 3
You can't POP into CS or IP.
INC and DEC do not affect the carry flag (No Carry is indicated after
these operations.)
ADD and SUB affect all the flags. Is signed arithmetic required? If signed
arithmetic is required, you have to pay attention to the sign flag; if it is
not required, you still have to worry about the overflow flag. The overflow
flag means that you have lost precision (you got the wrong answer) --
think of this as you having "flow into sign position, and no flow out" or
"flow out of sign position and no flow in" -- the sign bit changed
in a way that will change the number.
For example, if you try to add the following hexidecimal numbers: 8000 +
8000, you get 0. These are the largest negative numbers you can have -- in
binary, they are 1000 0000 0000 0000.
At this point, he did some examples of positive and negative binary numbers.
(Omitted here.)
To show the true value of a negative hexidecimal number, such
as -000A, you must take the 16's compliment like this:
10000
-000A
--------
FFF6
or, the easier way: show as binary, take twos compliment, then translate
back to hexidecimal
-000A = 00001010
11110101 (flip all bits)
1 (add one)
----------
11110110 = F6
-----------------------------------------------------------------
Chapter 4
Remember when inputting from the keyboard, the numbers that go into
the AL register are ASCII, so if you typed in 123, AL would get 31,
32 and 33.
Now he reviews ASCII and hexidecimal vs. decimal.
When a BIOS or DOS call is needed, find the function in a "table"
(which interrupt (int)) and what to put in register.
After the function executes, look at registers or screen for result.
P. 121 shows the DOS call to 0Ch, which clears the input buffer and
invokes the input function. (This to be used in problem 5 on the quiz.)
MOV AH, 0Ch
MOV AL, 1
INT 21h
MOV char, AL
;The above code reads in one ascii value from the keyboard and stores
;it in the variable called char. (DOS looks at AH and AL to figure out
;what to do.)
AND char, 01011111 b ; y = 79h (0111 1001), Y = 59h (0101 1001)
; AND 01011111
; 10001001
; ----------
; 01011001
; Will change a lower case y to an uppercase Y; if already
; uppercase, remains unchanged. Makes it not case-sensitive.
CMP char, 'Y' ; did the user type a Y?
JNE output_message ; Go to output_message if user didn't type Y (if
; Zero flag isn't = 1
output_message: ; Print something like "You didn't type Y"
We use 0Ch because it is a good idea to clear the input buffer first,
in case there is a spurious character waiting there.
-----------------------------------------------------------------
The INTEL is a CISC (Complex Instructino Set Code), whereas the
Sun and Motorola 601, 602 and 603 chips are RISC (Reduced Instruction
Set Code). RISC machines are not capable of performing as many
complex functions as the CISC. For example, they don't have LOOP
instructions or string function; because of this, it was thought
that they would be much faster; however the INTEL has managed to
keep up with this. In RISC machines, each instruction requires less
microcode to execute. They also have more registers in the CPU.
-----------------------------------------------------------------
The assembly process is essentially a 2 pass operation:
(1) Finds values of symbols, does some translation to hex code.
(2) Completes translation, creates .obj module, and possibly .lst
and .map.
Assembler has many commands, pseudo operations and mnemonics.
A command is a directive to the assembler, for example:
.data
.code
main
Mnemonics are real operaions or instructions, for example:
mov
add
jmp
cmp
A pseudo-op is not a machine operation, instead they help to
prepare of your proram
dw
db
equ
=
-----------------------------------------------------------------
You might want to think about making a batch file to assemble
and link your program:
HIS VERSION:
@echo off
cls
TASM /zi /l %1
IF ERRORLEVEL 1 GOTO END
TLINK /v %1
IF ERRORLEVEL 1 GOTO END
TD %1
:END
MY VERSION:
TASM /zi /l %1
TLINK /v %1
(I don't use the echo off, because I like to see the output, since
I usually make some stupid syntax errors, which may take several
tries to rectify before it assembles correctly. tlink won't work
if tasm fails, and will give one line of error message. I don't call
TD from the batch, I run it off a desktop shortcut or in a separate
DOS box, so I can see the history of the last couple of things I
compiled in the original DOS window. All a matter of personal
preference (and whether or not you have control over the setup of
your PC. May as well mention that I use the Delphi editor, since I
work with it all day long, it is very convenient for me, and is far
superior to EDIT, which stinks. So, I have 3 windows open, one dos
box where I call my batch file, one where I run td, and another
where I have Delphi running.))
save as cp.bat
then call it by, for example:
cp myprog
-----------------------------------------------------------------
If you say
A = 37
then wherever A is seen in your program, it is replaced with a 37.
You can reassign it later if you like. It is not unlike a #DEFINE
in C or a $DEFINE in Delphi.
NOT the same as saying
A db 37
which creates a variable, initialized with the value of 37.
You could say
A equ 37
which is almost the same as A = 37, but does not allow the value of
the symbol (A, in this case) to be changed.
You can also use equ like a compiler macro:
address equ offset
-----------------------------------------------------------------
Arithmetic operatior precedence
()
+ - (unary)
*
/
mod
+
-
boolean (AND OR NOT XOR)
-----------------------------------------------------------------
OFFSET
PTR
LABEL
.data
blist db 10,20,30,40
wlist dw 1000,2000,3000
mov di, offset blist ; di points to the first element of blist
mov bx, offset blist+1 ; points to second element of blist
mov al, [di] ; AL is 10. Indirect addressing.
mov ah, [bx] ; AH is 20.
mov ax, bx ; AX is 1.
(Long review of addressing omitted. My suggestion: go back to your
C notes or textbook and review the difference betweeen & and *, or
to your Pascal textbook and review the difference between @ and ^.)
-----------------------------------------------------------------
; function
call_me proc
push ax
push bx
; stuff
mov cx, 2
mov bx, 3
; more stuff
pop bx
pop ax
ret
call_me endp
invoke the function by:
call call_me ; pushes location counter into stack
ret ; uses stack to supply return address
if the function is in the middle of your other code, you
have to issue a jump to the first line of code after the
procedure. for example:
mov di, offset a
jmp around
; function code here
around: ; the rest of the code
Important: you must have the same # of pops as pushes in
the function or you won't go back to the proper place
in your code.
Suppose you had to read a character:
input proc
mov ah, 0Ch
mov al, 1
int 21h
ret
input endp