Pages

Assembly ( Dasar-Dasar )

Kamis, 03 Februari 2011


1. Introduction
================


What is it?
-----------
Assembly language is a low-level programming language. The syntax is nothing like 
C/C++, Pascal, Basic, or anything else you might be used to.


Why learn it?
-------------
If you ask someone these days what the advantage of assembly is, they will tell you it's 
speed. That might have been true in the days of BASIC or Pascal, but today a C/C++ 
program compiled with an optimized compiler is as fast, or even faster than the same 
algorithm in assembly. According to many people assembly is dead. So why bother 
learning it?
1. Learning assembly will help you better understand just how a computer works.
2. If windows crashes, it usually returns the location/action that caused the error.
However, it doesn't return it in C/C++. Knowing assembly is the only way to track
down bugs/exploits and fix them.
3. How often do you wish you could just get rid of that stupid nag screen in that
shareware app you use? Knowing a high-level language wont get you very far when you
open the shit up in your decompiler and see something like CMP EAX, 7C0A
4. Certain low level and hardware situations still require assembly
5. If you need precise control over what your program is doing, a high level language
is seldom powerful enough.
6. Anyway you put it, even the most optimized high level language compiler is still 
just a general compiler, thus the code it produces is also general/slow code. If 
you have a specific task, it will run faster in optimized assembly than in any other
language.
7. "Professional Assembly Programmer" looks damn good on a resume.
My personal reason why I think assembly is the best language is the fact that you're
in control. Yes all you C/C++/Pascal/Perl/etc coders out there, in all your fancy
high level languages you're still the passenger. The compiler and the language itself
limit you. In assembly you're only limited by the hardware you own. You control the
CPU and memory, not the otherway around.


What will this tutorial teach you?
----------------------------------
I tried to make this an introduction to assembly, so I'm starting from the beginning.
After you've read this you should know enough about assembly to develop graphics
routines, make something like a simple database application, accept user input, 
make Win32 GUIs, use organized and re-useable code, know about different data types
and how to use them, some basic I/O shit, etc. 


2. Memory
==========
In this chapter I will ask you to take a whole new look at computers. To many they
are just boxes that allow you to get on the net, play games, etc. Forget all that 
today and think of them as what they really are, Big Calculators. All a computer does
is Bit Manipulation. That is, it can turn certain bits on and off. A computer can't
even do all arithmetic operations. All it can do is add. Subtraction is achieved
by adding negative numbers, multiplication is repeaded adding, and dividing is 
repeaded adding of negative numbers.


Number systems
--------------
All of you are familiar with at least one number system, Decimal. In this chapter I 
will introduce you to 2 more, Binary and Hexadecimal.



Decimal
Before we get into the other 2 systems, lets review the decimal system. The decimal
system is a base 10 system, meaning that it consists of 10 numbers that are used to make
up all other number. These 10 numbers are 0-9. Lets use the number 125 as an example:
Hundreds Tens Units
Digit 1 2 5
Meaning 1x10^2 2x10^1 5x10^0
Value 100 20 5
NOTE: x^y means x to the power of y. ex. 13^3 means 13 to the power of 3 (2197)
Add the values up and you get 125.

Make sure you understand all this before going on to the binary system!


Binary
The binary systems looks harder than decimal at first, but is infact quite a bit easier
since it's only base 2 (0-1). Remember that in decimal you go "value x 10^position" to
get the real number, well in binary you go "value x 2^position" to get the answer. 
Sounds more complicated than it is. To better understand this, lets to some converting.
Take the binary number 10110:
1 x 2^4 = 16
0 x 2^3 = 0
1 x 2^2 = 4
1 x 2^1 = 2
0 x 2^0 = 0
Answer: 22


NOTE: for the next example I already converted the Ax2^B stuff to the real value: 
2^0 = 1 
2^1 = 2
2^2 = 4 
2^3 = 8
2^4 = 16
2^5 = 32
etc....

Lets use 111101:
1 x 32 = 32
1 x 16 = 16
1 x 8 = 8
1 x 4 = 4
0 x 2 = 0
1 x 1 = 1
Answer: 61

Make up some binary numbers and convert them to decimal to practise this. It is very 
important that you completely understand this concept. If you don't, check Appendix B
for links and read up on this topic BEFORE going on!

Now lets convert decimal to binary, take a look at the example below:
238 / 2 remainder: 0
119 / 2 remainder: 1
59 / 2 remainder: 1
29 / 2 remainder: 1
14 / 2 remainder: 0
7 / 2 remainder: 1
3 / 2 remainder: 1
1 / 2 remainder: 1
0 / 2 remainder: 0
Answer: 11101110

Lets go through this:
1. Divide the original number by 2, if it divides evenly the remainder is 0
2. Divide the answer from the previous calculation (119) by 2. If it wont
divide evenly the remainder is 1.
3. Round the number from the previous calculation DOWN (59), and divide it by 2.
Answer: 29, remainder: 1
4. Repeat until you get to 0....
The final answer should be 011101110, notice how the answer given is missing the 1st 0?
That's because just like in decimal, they have no value and can be omitted (023 = 23).

Practise this with some other decimal numbers, and check it by converting your answer
back to binary. Again make sure you get this before going on!

A few additional things about binary:
* Usually 1 represents TRUE, and 0 FALSE
* When writing binary, keep the number in multiples of 4
ex. DON'T write 11001, change it to 00011001, remember that the 0 in front 
are not worth anything
* Usually you add a b after the number to signal the fact that it is a binary number
ex. 00011001 = 00011001b


Hexadecimal
Some of you may have notice some consistency in things like RAM for example. They seem
to always be a multiple of 4. For example, it is common to have 128 megs of RAM, but
you wont find 127 anywhere. That's because computer like to use multiples of 2, 4, 8, 
16, 32, 64 etc. That's where hexadecimal comes in. Since hexadecimal is base 16, it is 
perfect for computers. If you understood the binary section earlier, you should have
no problems with this one. Look at the table below, and try to memorize it. It's not
as hard as it looks.
Hexadecimal Decimal Binary
0h 0 0000b
1h 1 0001b
2h 2 0010b
3h 3 0011b
4h 4 0100b
5h 5 0101b
6h 6 0110b
7h 7 0111b
8h 8 1000b
9h 9 1001b
Ah 10 1010b
Bh 11 1011b
Ch 12 1100b
Dh 13 1101b
Eh 14 1110b
Fh 15 1111b

NOTE: the h after each hexadecimal number stands for 

Now lets do some converting:
Hexadecimal to Decimal
2A4F

F x 16^0 = 15 x 1 = 15
4 x 16^1 = 4 x 16 = 64 
A x 16^2 = 10 x 256 = 2560
2 x 16^3 = 2 x 4096 = 8192
Answer: 10831

1. Write down the hexadecimal number starting from the last digit
2. Change each hexadecimal number to decimal and times them by 16^postion
3. Add all final numbers up

Confused? Lets do another example: DEAD
D x 1 = 13 x 1 = 13
A x 16 = 10 x 16 = 160
E x 256 = 14 x 256 = 3584
D x 4096 = 13 x 4096 = 53248
Answer: 57005

Practise this method until you get it, then move on.

Decimal to Hexadecimal
Study the following example:
1324

1324 / 16 = 82.75
82 x 16 = 1312
1324 - 1312 = 12, converted to Hexadecimal: C

82 / 16 = 5.125
5 x 16 = 80
82 - 80 = 2, converted to Hexadecimal: 2

5 / 16 = 0.3125
0 x 16 = 0
5 - 0 = 5, converted to Hexadecimal: 5

Answer: 52C

I'd do another example, but it's too much of a pain in the ass, maybe some other time.

Learn this section you WILL need it!
This was already one of the hardest parts, the next sections should be a bit easier

Some additional things abot hexidecimal
1. It's not uncommon to say "hex" instead of "hexidecimal" even thechnicaly speaking
"hex" means 6, not 16.
2. Keep hexidecimal numbers in multiples of 4, adding zeros as necessary
3. Most assemblers can't handle numbers that start with a "letter" because they don't
know if you mean a label, instruction, etc. In that case there are a number of
other ways you can express the number. The most common are:
DEAD = 0DEADh (Usually used for DOS/Win)
and
DEAD = 0xDEAD (Usually used for *Nix based systems)
Consult your assembler's manual to see what it uses.


By the way, does anyone think I should add Octal to this...?




Bits, Nibbles, Bytes, Words, Double Words
-----------------------------------------
Bits are the smallest unit of data on a computer. Each bit can only represent 2 numbers,
1 and 0. Bits are fairly useless because they're so damn small so we got the nibble.
A nibble is a collection of 4 bits. That might not seem very interesting, but remember
how all 16 hexadecimal numbers can be represented with a set of 4 binary numbers? 
That's pretty much all a nibble is good for.

The most important data structure used by your computer is a Byte. A byte is the 
smallest unit that can be accessed by your processor. It is made up of 8 bits, or
2 nibbles. Everything you store on your hard drive, send with your modem, etc is in 
bytes. For example, lets say you store the number 170 on your hard drive, it would look
like this:

+---+---+---+---+---+---+---+---+
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
+---+---+---+---+---+---+---+---+
7 6 5 4 3 2 1 0
H.O Nibble | L.O Nibble 

10101010 is 170 in binary. Since we can fit 2 nibbles in a byte, we can also refer
to bits 0-3 as the Low Order Nibble, and 4-7 as the High Order Nibble
Next we got Words. A word is simply 2 bytes, or 16 bits. Say you store 43690, it would
look like this:


+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
High Order Byte | Low Order Byte

Again, we can refer to bits 0-7 as Low Order Byte, and 7-15 as High Order Byte.
Lastly we have a Double Word, which is exactly what it says, 2 word, 4 bytes, 8 nibbles
or 32 bits.

NOTE: Originally a Word was the size of the BUS from the CPU to the RAM. Today most
computers have at least a 32bit bus, but most people were used to 
1 word = 16 bits so they decided to keep it that way.



The Stack
---------
You have probably heard about the stack very often. If you still don't know what it 
means, read on. The stack is a very useful Data Structure (anything that holds data).
Think of it as a stack of books. You put one on top of it, and that one will be the 
first one to come of next. Putting stuff on the stack is called Pushing, getting stuff
from the stack is called Poping. For example, say you have 5 books called A, B, C, D,
and E stack on top of each other like this:
A
B
C
D
E
Now you add (push) book F to the stack:
F
A
B
C
D
E
If you pop the stack, you get book F back and the stack looks like this again:
A
B
C
D
E
This called LIFO, Last In, First Out.
So what good is all this? The stack is extremely useful as a "scratchpad" to 
temporarily hold data.




Segment: Offset
--------------
Everything on your computer is connected through a series of wires called the BUS. The
BUS to the RAM is 16 bits. So when the processor needs to write to the RAM, it does
so by sending the 16 bit location through the bus. In the old days this meant that 
computers could only have 65535 bytes of memory (16 bits = 1111111111111111 = 65535). 
That was plenty back than, but today that's not quite enough. So designers came up 
with a way to send 20 bits over the bus, thus allowing for a total of 1 MB of memory
In this new design, memory is segmented into a collection of bytes called Segments, 
and can be access by specifying the Offset number within those segments. So if the 
processor wants to access data it first sends the Segment number, followed by the 
Offset number. For example, the processor sends a request of 1234:4321, the RAM would 
send back the 4321st byte in segment number 1234.
This all might sound a bit complicated, but study it carefully and you should be able
to master segment:offset.
The best way to picture seg:off is with a 2 dimensional array. Remember that X,Y shit 
you had to learn in grade 9 math?
Look at the diagram below, the * is located at 4:3. The Y-axis is equal to the segment,
and the X-axis is the offset.


+--+--+--+--+--+
5 | | | | | |
+--+--+--+--+--+
4 | | |* | | |
Y axis +--+--+--+--+--+
3 | | | | | |
+--+--+--+--+--+
2 | | | | | |
+--+--+--+--+--+
1 | | | | | | Assembly
+--+--+--+--+--+
1 2 3 4 5 
X axis 

To get the physical address do this calculation:
Segment x 10h + Offset = physical address
For example, say you have 1000:1234 to get the physical address you do:
1000 X 10h = 10000

10000
+ 1234
------
11234

This method is fairly easy, but also fairly obsolete. Starting from the 286 you can 
work in Protected Mode. In this mode the CPU uses a Look Up Table to compute the 
seg:off location. That doesn't mean that you cannot use seg x 10h + off though, you 
will only be limited to working in Real Mode and your programs can't access more than 
1 MB. However by the time you know enough to write a program even close to this limit, 
you already know how to use other methods (for those comming from a 50 gig hard drive 
world, a program that's 1 MB is about 15x bigger than this text file is).

Registers
---------
A processor contains small areas that can store data. They are too small to store
files, instead they are used to store information while the program is running.
The most common ones are listed below:

General Purpose:
NOTE: All general purpose registers are 16 bit and can be broken up into two 8 bit
registers. For example, AX can be broken up into AL and AH. L stands for Low
and H for High. If you assign a value to AX, AH will contain the first part of
that value, and AL the last. For example, if you assign the value DEAD to AX,
AH will contain DE and AL contains AD. Likewise the other way around, if you
assign DE to AH and AD to AL, AX will contain DEAD
AX - Accumulator. 
Made up of: AH, AL
Common uses: Math operations, I/O operations, INT 21
BX - Base
Made up of: BH, BL
Common uses: Base or Pointer
CX - Counter
Made up of: CH, CL
Common uses: Loops and Repeats
DX - Displacement
Made up of: DH, DL
Common uses: Various data, character output
When the 386 came out it added 4 new registers to that category: EAX, EBX, ECX, and EDX.
The E stands for Extended, and that's just what they are, 32bit extensions to the
originals. Take a look at this diagram to better understand how this works:

| EAX |

+----+----+----+----+
| | | AH | AL |
+----+----+----+----+

| AX |

Each box represents 8 bits
NOTE: There is no EAH or EAL


Segment Registers:
NOTE: It is dangerous to play around with these!
CS - Code Segment. The memory block that stores code
DS - Data Segment. The memory block that stores data
ES - Extra Segment. Commonly used for video stuff
SS - Stack Segment. Register used by the processor to store return addresses from 
routines

Index Registers:
SI - Source Index. Used to specify the source of a string/array
DI - Destination Index. Used to specify the destination of a string/array
IP - Instruction Pointer. Can't be changed directly as it stores the address of the 
next instruction.

Stack Registers:
BP - Base pointer. Used in conjunction with SP for stack operations
SP - Stack Pointer. 

Special Purpose Registers:
IP - Instruction Pointer. Holds the offset of the instruction being executed
Flags - These are a bit different from all other registers. A flag register is only 1 
bit in size. It's either 1 (true), or 0 (false). There are a number of flag registers 
including the Carry flag, Overflow flag, Parity flag, Direction flag, and more. You 
don't assign numbers to these manually. The value automatically set depending on the 
previous instruction. One common use for them is for branching. For example, say you 
compare the value in BX with the value in CX, if it's the same the flag would be set to 
1 (true) and you could use that information to branch of into another area of your 
program.

There are a few more registers, but you will most likely never use them anyway.


Exercises:
1. Write down all general purpose registers and memorize them
2. Make up random numbers and manually convert them into Binary and hexadecimal
3. Make a 2D graph of the memory located at 0106:0100
4. Get the physical address of 107A:0100



3. Getting Started
===================
Now finally on to real assembler! Believe me, I'm getting sick of all this background
shit :)


Getting an Assembler
--------------------
There are quite a few available these days. All code in this tutorial has been tested
with TASM, so you should have no problems if you have it. A86 should also work with
thise code, but I can't guarentee that.
A86 - Available from: [Only registered and activated users can see links. ]
License: Shareware
Price: A86 only - US$50+Tax/SH
A86 + Manual + D86 + 32bit version of each - US$80+Tax/SH
Manual - US$10+Tax/SH
TASM - Available from: [Only registered and activated users can see links. ]
License: Gotta buy it
Price: US$129.95+Tax/SH
There are tons more out there, check [Only registered and activated users can see links. ], I know they have a few. However as
said before, all programs in this tutorial have only been tested with TASM. If
you are low on cash, just get A86 and evaluate for longer than you're supposed to.


Program Layout
--------------
It is good programming practise to develop some sort of standard by which you write your
programs. In this chapter you will learn about a layout of .COM and .EXE files that is 
excepted by both, TASM and A86. 


.COM
Lets look at the source code to a very simple program:

MAIN SEGMENT
ASSUME CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN

ORG 100h

START:
INT 20
MAIN ENDS
END START

This program does absolutely nothing, but it does it well and fast. Lots of code for 
something that doesn't do shit. Lets examine that more closely:

MAIN SEGMENT - Declares a segment called MAIN. A .COM file must fit into 1 segment of
memory (aka. 65535 bytes - stack - PSP)

ASSUME CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN - This tells the assembler the initial values of 
the CS,DS,ES, and SS register. Since a .COM
must fit into one segment they all point to the
segment defined in the line above.
ORG 100h - Since all .COM files start at XXXX:0100 you declare the entry point to be 
100h. More on this later.

START: - A label

INT 20 - Returns to DOS

MAIN ENDS - Ends the MAIN segment

END START - Ends the START label

NOTE: This is the kind of layout we will use most of the time. Maybe later (Chapter 9+)
We get into the next one...

Now how do you make this shit into an actual program? First, type this program out in
your favourite editor (notepad, dos edit, etc). If you have A86, just get into DOS, 
than into the directory A86 is in and type "a86 filename.asm". If you have TASM, 
get into DOS and into the tasm directory and type "tasm filename.asm", then type
"tlink /t filename.obj". In both cases you will get a file called Filename.com. More
on what .com is and does later.



.EXE
Take a look at the following code:

DOSSEG
.MODEL SMALL
.STACK 200h
.DATA
.CODE

START:
INT 20
END START

Again, his program does absolutely nothing. Lets examine each line in detail:

DOSSEG - sorts the segments in the order:
Code
Data
Stack
This is not required, but recommended while you're still learning

.MODEL SMALL - selects the SMALL memory model, available models are:
TINY: All code and data combined into one single group called DGROUP. Used for .COM
files.
SMALL: Code is in a single
 
segment. All data is combined in DGROUP. Code and data 
are both smaller than 64k. This is the standard for standalone assembly 
programs.
MEDIUM: Code uses multiple segments, one per module. All data is combined in DGROUP
Code can be larger than 64k, but data has to be smaller than 64k
COMPACT: Code is in a single segment. All near data is in DGROUP. Data can be more 
than 64k, but code can't.
LARGE: Code uses multiple segments. All near data is in DGROUP. Data and code can be
more than 64k, but arrays can't.
HUGE: Code uses multiple segments. All near data is in DGROUP. Data, code and arrays
can be more than 64k
Most of the time you want to use SMALL to keep the code efficient.

.STACK 200h - sets up the stack size. In this case 200h bytes

.DATA - The data segment. This is where all your data goes (variables for example).

.CODE - The code segment. This is where your actually program goes.

START: - Just a label, more on that later

INT 20 - exits the program, more on that later

END START - Take a wild guess on what this does! Not required for all assemblers, I 
know TASM needs it, and A86 doesn't.

NOTE: For .EXE files, DON'T use the /t switch when linking!


Exercises:
1. Make a program that uses the LARGE memory model, sets up a 100h long stack, and exits
to DOS.







4. Basic ASM
=============
In this chapter we actually start making some working code


Basic Register operations
-------------------------
You already know what registers are, but you have yet to learn how to modify them.
To assign a value to a register:

MOV DESTINATION, VALUE

For example, say you want AX to equal 56h:
MOV AX,56h
You can also use another register as the value:
MOV AX,BX
Remember how all general purpose registers are made up of a H and a L register? Now you
can actually use that info:
MOV AL,09
Now AL equals 09 and AX equals 0009

The next register operator is XCHG, which simply swaps 2 registers. The syntax is:

XCHG REGISTER1, REGISTER2

For example, consider the following code:

MOV DX,56h
MOV AX,3Fh
XCHG DX,AX

1. DX is equal to 3Fh
2. AX is equal to 56h
3. DX and AX get swapped and AX now equals 56h, and DX equals 3Fh

NOTE: NEVER try to exchange a 8 bit (h/l) register with a 16 bit (X)!!
The following code is invalid:
XCHG AH,BX

Next we got 2 simple operations, INC and DEC.
INC increment a register's value and DEC decrements it.

Example:

MOV DX,50h
INC DX

DX is now equal to 51h (50h + 1h = 51h).

Example:

MOV DX,50h
DEC DX

DX is now equal to 4F (50h - 1h = 4Fh).



Stack operations
----------------
Now it's time to put that stack shit to some actual use. And it's very easy to. There
are 6 stack operators, 2 of which you will use most of the time. The syntax is:
POP REGISTER
PUSH REGISTER
Lets say you want to temporarily store the value in AX on the stack for later use, 
simply do:
PUSH AX
Now you played around with AX and want to restore the original value:
POP AX

NOTE: The stack will only accept 16 bit registers! That shouldn't be a problem though
since the 16 bit registers include the value of the 8 bit.

This next bit of code does some poping and pushing, take a guess on what BX and AX are
equal to at the end.

MOV AX,51h
MOV BX,4Fh

XCHG AX,BX

PUSH AX
MOV AX,34h

POP BX

PUSH BX

POP AX

First AX is equal to 51h and BX to 4Fh, than the 2 get exchanged. Now we got
AX = 4Fh and BX = 51h. AX gets pushed on the stack, then set to 34h:
AX = 34h and BX = 51h. BX gets poped, than pushed:
AX = 34h and BX = 4Fh. Finally AX gets poped. So the final result is:
AX = 4Fh and BX = 4Fh.

Next we got the two variations of the stacks registers, POPF and PUSHF. These two
place the flag register on the stack. Sounds more complicated than POP and PUSH, but
it's actually easier. The syntax is:
POPF
PUSHF
No operand is required. For example, say you want AX to hold the current flag register
value:

PUSHF
POP AX

PUSHF puts it on the stack, POP AX places it into AX.

The last two stack operators are PUSHA and POPA.
PUSHA puts all general purpose registers on the stack
POPA retrieves all general purpose registers from the stack
NOTE: These 2 are 32bit instructions, so they only work on a 386+ and will not
work with .COM files.

Example:
MOV AX,1h
MOV BX,2h
MOV CX,3h
MOV DX,4h

PUSHA

MOV AX,5h
MOV BX,6h
MOV CX,7h
MOV DX,8h

POPA

At the end of this program, all registers are restored to their initial value

Practise some of these instructions! If you make a program containing everything 
you've learned so far it won't do anything, but if it doesn't crash it most likely 
worked. So code some simple programs and play around with the values and registers. 




Arithmetic operations
---------------------
Everyone loves arithmetic. Especially if you do it in hex or binary. For those who 
don't know what arithmetic is, it's just adding and subtracting. Multiplying and 
dividing are really just repeated additions and subtractions. So in short, it's a 
fancy name for grade 3 math. In this chapter I will introduce you to the 4 basic 
arithmetic operators, ADD, SUB, MUL, DIV . There are a few more that I will cover 
later.
Lets start with ADD. The syntax is:
ADD REGISTER1, REGISTER2
ADD REGISTER, VALUE

Example 1:
MOV AX,5h
MOV BX,4Fh

ADD AX,BX

This adds AX and BX and stores the resulting value in AX. So after running this 
program AX = 9h

Example 2:
MOV AX,5h

ADD AX,4Fh

The result is the same as in example 1. AX is set to 5h, and 4Fh is added to it.

Now lets go on to SUB. The syntax is:
SUB REGISTER1, REGISTER2
SUB REGISTER, VALUE

Example 1:
z

This will subtract the value of BX from the value of AX. In this case the result would
be 4A.

NOTE: If you still don't completely get hexadecimal, you can easily check this by
converting 5, 4F, and 4A to decimal.
4F = 79
4A = 74
5 = 5

As with ADD you can also use a value:
MOV BX,4Fh

SUB BX,5h

Which leaves you with BX = 4A

Next in line is the MUL operator. Syntax:
MUL REGISTER

Notice that only one operant is required. That's because the processor assumes that you 
want to multiply the give register with AX or AH.

Example:
MOV AX,5h
MOV BX,4Fh

MUL BX

This leaves AX equal to 18B (4Fh x 5h = 18B). Notice that the result is stored in AX,
or AH, depending on what was used for the operation.

Finally we have the DIV operator. Syntax:
DIV REGISTER

Just like the MUL operator, there is only one operand, and AX is assumed to be the 
second one.

Example:
MOV AX,5h
MOV BX,4Fh

DIV BX

Now AX equals Fh since 4Fh / 5h = Fh.
NOTE: The result is rounded to the next lowest number:
4Fh = 79
5h = 5
79 / 5 = 15.8

15 = Fh

NOTE: For now it's fine if you use MUL and DIV, but they are very slow operators.
That means if you need speed (in graphics for example), NEVER use MUL/DIV!
You can use Shifting combined with addition/subtraction to achieve code
that can sometimes be 3000% faster! However shifting is a bit difficult to
understand if you don't know much about assembly yet, I will completly discuss
them in the graphics part of this tutorial.



Bit wise operation
-----------------
Sounds hard but is very easy. There are 4 bit wise operators: AND, OR, XOR, and NOT.
What these do is compare two values bit for bit. This can be extremely useful!

AND syntax:
AND REGISTER1, REGISTER2
AND REGISTER, VALUE

AND returns 1 (TRUE) only if BOTH operands are 1 (TRUE)

Example 1:
MOV AX,5h
MOV BX,6h

AND AX,BX

The result is stored in AX. So for this example AX = 4. Lets look at that result more
closely:
5h = 101b
6h = 110b

101b
110b
---
100b

100b = 4h

Example 2:
MOV AX,5h

AND AX,6h

The result is the same as in Example 1 (AX = 4h).

AND truth table:
0 AND 0 = 0
1 AND 0 = 0
0 AND 1 = 0
1 AND 1 = 1


OR syntax:
OR REGISTER1, REGISTER2
OR REGISTER, VALUE

OR returns 1 (TRUE) if either operand is 1 (TRUE).

Example 1:
MOV AX,5h
MOV BX,6h

OR AX,BX

AX is now equal to 7h

5h = 101b
6h = 110b

101b
110b
----
111b

111b = 7h

OR truth table:
0 OR 0 = 0
1 OR 0 = 1
0 OR 1 = 1
1 OR 1 = 1


XOR syntax:
XOR REGISTER1, REGISTER2
XOR REGISTER, VALUE

XOR returns 1 (TRUE) if one or the other operand is 1 (TRUE), but not both

Example:
MOV AX,5h
MOV BX,6h

XOR AX,BX

AX is not equal to 3h

5h = 101b
6h = 110b

101b
110b
----
011b

11b = 3h

XOR truth table:
0 XOR 0 = 0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0


And finally we have NOT. NOT is the easiest one as it simply inverts each bit.

NOT syntax:
NOT REGISTER
NOT VALUE

Example:
MOV AX,F0h

NOT AX

AX is now equal to F since

F0h = 11110000
Invert it:
00001111
which is:
F

NOTE: The windows calculator won't work for this, do it by hand.

NOT truth table:
NOT 1 = 0
NOT 0 = 1 



Interrupts
---------
Interrupts are one of the most useful things in assembly. An interrupt is just what it
says, a interruption to the normal execution of a program. The best way to illustrate 
this is one of those "Press any key to continue" things. The program is running but 
when you press a key it stops for a split second, check what key you pressed and 
continues. This kind of interrupt is known as a Hardware Interrupt because it uses 
hardware (the keyboard). The kind of interrupts you will use in your assembly programs
are know as Software Interrupts because they are caused by software, not hardware. An 
example of a software interrupt is reading and writing to a file. This is a DOS 
interrupt because it is done by DOS, than there are other interrupts done by other 
things. For example your BIOS or Video Card all have build in interrupts at your 
exposure. So how does the computer know what interrupt is what? Each interrupt is 
assigned a number and stored in the Interrupt Vector Table (IVT for short). The IVT is
located at 0000:0000 (remember the segment:offset shit. This location would be the 
origin if plotted on a 2D graph). All interrupt handlers are 1 DWORD in size 
(double word, 32bit, or 4 bytes). So the handler for interrupt 1h can be found at 
0000:0004 (since it's a DWORD it goes up by 4 bytes). The most common interrupt is 
21h and can be found at 0000:0084.

So how do you use interrupts? 
Very simple:
INT interrupt

For example, in the Program Layout section earlier the program contain the line
INT 20h
The interrupt 20h returns to DOS.

Some interrupts like this one only have one function, but other have many more. So how
does the operating system know what function you want? You set the AX register up.

Example: 
MOV AH,02
MOV DL,41

INT 21
INT 20

This program is quite amazing. It prints the character A. Lets make it even better
by plugging it into our layout:

MAIN SEGMENT
ASSUME DS:MAIN,ES:MAIN,CS:MAIN,SS:MAIN

START:
MOV AH,02h
MOV DL,41h

INT 21h
INT 20h
MAIN ENDS
END START

Save it and assemble it. Refer back to chapter 2 if you forgot how to do that.
So what is happening here?
First it does the familiar set up, than it set AH to 02, which is the character output
function of interrupt 21. Then it moves 41 into DL, 41 is the character A. Finally
it calls interrupt 21 which displays the A and quits with interrupt 20.
How do you know what you have to set all those registers to? You get a DOS interrupt
list. Check Appendix B for urls.
Quite an accomplishment there, after reading 970 lines of boring text you can finally
make a 11 line program that would take 1 line to do in Perl! Pad yourself on that back
and lets move on.


Exercises:
1. Make a program that gets the value from AX, puts it into DX and BX, then multiplies
the values in DX and BX and stores the result in CX.
This sounds easier than it really is, use the stack to help you out.
2. Make a program that prints out the string ABC, than quits to DOS
Hint: A = 41, B = 42, C = 43
3. Make a program that performs ALL bit wise operations using the values 5h and 4Fh



5. Tools
=========
Throughout this tutorial you have been using no software other than your assembler.
In this chapter you will learn how to master other software that can be of tremendous
help to you.



Debug
-----
Lets start with something that's not only very useful, but also free and already
on your computer.
Get into dos and type "debug", you will get a prompt like this:
-
now type "?", you should get the following response:
assemble A [address]
compare C range address
dump D [range]
enter E address[list]
fill F range list
go G [=address] [addresses]
hex H value1 value2
input I port
load L [address] [drive] [firstsector] [number]
move M range address
name N [pathname] [arglist]
output O port byte
proceed P [=address] [number]
quit Q
register R [register]
search S range list
trace T [=address] [value]
unassemble U [range]
write W [address] [drive] [firstsector] [number]
allocate expanded memory XA [#pages]
deallocate expanded memory XD [handle]
map expanded memory pages XM [Lpage] [Ppage] [handle]
display expanded memory status XS

Lets go through each of these commands:


Assemble:
-a
107A:0100
At this point you can start assembling some programs, just like using a assembler. 
However the debug assembler is very limited as you will probably notice. Lets try
to enter a simple program:
-a
107A:0100 MOV AH,02
107A:0102 MOV DL,41
107A:0104 INT 21
107A:0106 INT 20
-g
A
Program terminated normally

That's the same program we did at the end of the previous chapter. Notice how you
run the program you just entered with "g", and also notice how the set-up part is not 
there? That's because debug is just too limited to support that.
Another thing you can do with assemble is specify the address at which you want to start,
by default this is 0100 since that's where all .COM files start.


Compare:
Compare takes 2 block of memory and displays them side by side, byte for byte. Lets do
an example. Quite out of debug if you haven't already using "q".
Now type "debug c:\command.com"
-c 0100 l 8 0200
10A3:0100 7A 06 10A3:0200
This command compared offset 0100 with 0200 for a length of 8 bytes. Debug responded
with the location that was DIFFERENT. If 2 locations were the same, debug would just 
omit them, if all are the same debug would simply return to the prompt without any
response.


Dump:
Dump will dump a specified memory segment. To test it, code that assembly program again:
C:\>debug
-a
107A:0100 MOV AH,02
107A:0102 MOV DL,41
107A:0104 INT 21
107A:0106 INT 20
-d 0100 l 8
107A:0100 B4 02 B2 41 CD 21 CD 20 ...A.!.

The "B4 02 B2 41 CD 21 CD 20" is the program you just made in machine language.
B4 02 = MOV AH,02
B2 41 = MOV DL,41
CD 21 = INT 21
CD 20 = INT 20
The "...A.!." part is your program in ASCII. The "." represent non-printable characters.
Notice the A in there.


Enter:
This is one of the hard commands. With it you can enter/change certain memory areas.
Lets change our program so that it prints a B instead of an A.
-e 0103 <-- edit program at segment 0103
107A:0103 41.42 <-- change 41 to 42
-g
B
Program terminated normally
-
Wasn't that amazing?


Fill:
This command is fairly useless, but who knows....
It fills the specified amount of memory with the specified data. Lets for example clear
out all memory from segment 0100 to 0108, which happens to be our program.
-f 0100 l 8 0 <-- file offset 0100 for a length of 8 bytes with 0
-d 0100 l 8 <-- verify that it worked
107A:0100 00 00 00 00 00 00 00 00 .......
Yep, it worked.


Go:
So far we used go (g) to start the program we just created. But Go can be used for much
more. For example, lets say we want to execute a program at 107B:0100:
-r CS <-- set the CS register to point to 107B
CS 107A
:107B
-g =100
You can also set breakpoints.
-a <-- enter our original program so we have something
107A:0100 MOV AH,02 to work with
107A:0102 MOV DL,41
107A:0104 INT 21
107A:0106 INT 20
-g 102 <-- set up a break point at 107A:0102
At this point the program will stop, display all registers and the current instruction.


Hex:
This can be very useful. It subtracts and adds to hexadecimal values:
-h 2 1
0003 0001 <-- 2h + 1+ = 3h and 2h - 1h = 1h
This is very useful for calculating a programs length, as you will see later.


Input:
This is one of the more advanced commands, and I decided not to talk about it too much
for now. It will read a byte of data from any of your computers I/O ports (keyboard,
mouse, printer, etc).
-i 3FD
60
-
Your data may be different.
In case you want to know, 3FD is Com port 1, also known as First Asynchronous Adapter.


Load:
This command has 2 formats. It can be used to load the filename specified with the
name command (n), or it can load a specific sector.
-n c:\command.com
-l
This will load command.com into debug. When a valid program is loaded all registers will 
be set up and ready to execute the program.
The other method is a bit more complicated, but potential also more usefull. The syntax
is 
L 
-l 100 2 10 20 This will load starting at offset 0100 from drive C (0 = A, 1 = B, 2 = C, etc), sector 10h for 20h sectors. This can be useful for recovering files you deleted. Move: Move takes a byte from the starting address and moves it to the destination address. This is very good to temporary move data into a free area, than manipulate it without having to worry about affecting the original program. It is especially useful if used in conjunction with the r command to which I will get later. Lets try an example: -a <-- enter our original program so we have something 107A:0100 MOV AH,02 to work with 107A:0102 MOV DL,41 107A:0104 INT 21 107A:0106 INT 20 -m 107A:0100 L 8 107B:0100 <-- more 8 bytes starting from 107A:0100 into 107B:0100 -e 107B:0103 <-- edit 107B:0103 107B:0103 41.42 <-- and change it 42 (B) -d 107A:0100 L 8 <-- make sure it worked 107A:0100 B4 02 B2 41 CD 21 CD 20 ...A.!. -d 107B:0100 L 8 107A:0100 B4 02 B2 42 CD 21 CD 20 ...B.!. -m 107B:0100 L 8 107A:0100 <-- restore the original program since we like the changes. Name: This will set debug up with a filename to use for I/O commands. You have to include the file extension, and you may use addition commands: -n c:\command.com Output: Exactly what you think it is. Output sends stuff to an I/O port. If you have an external modem with those cool lights on it, you can test this out. Find out what port your modem is on and use the corresponding hex number below: Com 1 = 3F8 - 3FF (3FD for mine) Com 2 = 2F8 - 2FF Com 3 = ??? - ??? (if someone knows, please let me know, I would assume though that it's 0F8 - 0FF.) Now turn on the DTA (Data Terminal Ready) bit by sending 01h to it: -o XXX 1 <-- XXX is the com port in hex As soon as you hit enter, take a look at your modem, you should see a light light up. You can have even more fun with the output command. Say someone put one of those BIOS passwords on "your" computer. Usually you'd have to take out the battery to get rid of it, but not anymore: AMI/AWARD BIOS -o 70 17 -o 71 17 QPHOENIX BIOS -o 70 FF -o 71 17 QGENERIC -o 70 2E -o 71 FF These commands will clear the BIOS memory, thus disabling the password. Please note however that these are fairly old numbers and BIOS makes constantly change them, so they might not work with your particular BIOS. Proceed: Proceeds in the execution of a program, usually used together withy trace, which I will cover later. Like the go command, you can specify an address from which to start using =address -p 2 Debug will respond with the registers and the current command to be executed. Quite: This has got to be the most advanced feature of debug, it exits debug! -q Register: This command can be used to display the current value of all registers, or to manually set them. This is very useful for writing files as you will see later on. -r AX AX: 011B :5 - Search: Another very useful command. It is used to find the occurrence of a specific byte, or series of bytes in a segment. The data to search for can by either characters, or a hex value. Hex values are entered with a space or comma in between them, and characters are enclosed with quotes (single or double). You can also search for hex and characters with the same string: -n c:\command.com <-- load command.com so we have some data to search in -l -s 0 l 0 "MS-DOS" <-- search entire memory block for "MS-DOS" 10A3:39E9 <-- found the string in 10A3:39E9 NOTE: the search is case sensitive! Trace: This is a truly great feature of debug. It will trace through a program one instruction at a time, displaying the instruction and registers after each. Like the go command you can specify where to start executing from, and for how long. -a <-- yes, this thing again 107A:0100 MOV AH,02 107A:0102 MOV DL,41 107A:0104 INT 21 107A:0106 INT 20 -t =0100 8 If you leave out the amount of instructions that you want to trace, you can use the proceed (p) to continue the execution as long as you want.

8 komentar:

  1. Anonim mengatakan...:

    i have one question for you to help me in my assignment...can u answer it for me.....State the contents of RAM locations 0xl2 and WREG after the following program:
    MOVLW 0 ; move 0 WREG to clear it (WREG:0)
    MOVWF 0xl2 ; move WREG to location 0xl2 to clear it
    MOVLW 0x22 ; load WREG with value 0x22
    ADDWF 0x12, F ; add WREG to location0xl2,location 0x12:sum
    ADDWF 0x12, F ; add WREG to location 0x12, location 0x12:sum
    ADDWF 0x12, F ; add WREG to location}xl2,location 0x12:sum
    ADDWF 0x12, F ; add WREG to location}xl2,location 0xl2:sum

    how to answer it and why???

  1. Anonim mengatakan...:

    I believe this is one of the so much important info for me.

    And i am satisfied reading your article. However wanna statement on some common issues, The site style is perfect,
    the articles is truly excellent : D. Good process, cheers
    My webpage: direct download movies

  1. Anonim mengatakan...:

    I know this if off topic but I'm looking into starting my own weblog and was curious what all is needed to get setup? I'm assuming having a
    blog like yours would cost a pretty penny?
    I'm not very internet smart so I'm not 100% certain. Any suggestions or advice would be greatly appreciated. Many thanks
    My web site : piano lessons

  1. Anonim mengatakan...:

    Good respond in return of this question with real arguments and telling all on the topic of that.
    My webpage > damaged skin

  1. Anonim mengatakan...:

    Definitely believe that which you stated. Your
    favorite justification appeared to be on the internet the
    easiest thing to be aware of. I say to you,
    I certainly get annoyed while people consider worries that they
    plainly do not know about. You managed to hit the nail upon the top as well as defined out
    the whole thing without having side-effects , people can
    take a signal. Will likely be back to get more. Thanks
    Feel free to visit my blog post :: http://propertyinturkeyforsale.net/property-antalya/

  1. Anonim mengatakan...:

    Dzisiaj rynek możliwości rachunkowych nie bedzie musiał upominać się na brak sławy.
    To wszystko ze względu na fakt, iż znacznie wiecej ludzi decyduje się na zarejestrowanie swojej firmy.
    Takie wyjście może być dla licznych ludzi niezwykle kuszące, bo jest oczywiste, że
    dobrze jest stać się szefem samym dla siebie.
    Generalnie z założenia swojej działalności wynika wiele
    obowiązków, jakie mogą pociągnąć do odpowiedzialności każdego z
    przedsiębiorców. W szczególności wówczas gdy chodzi o podatki.

    Jednakowoż, wówczas gdy korzysta on z ewidencji profesjonalnego biura rachunkowego,
    to nie powinien się niczym zamartwiać.
    Also see my site :: Extor opinie

  1. Anonim mengatakan...:

    Jedną pośród branży, które na dzień dzisiejszy
    pełnią niezwykle ważną rolę na rynku gospodarczym jest księgowość.
    To ona będzie odpowiedzialna za ewidencję wszystkich zdarzeń transakcyjnych na gospodarczym
    rynku, które mogą być wyrażone w pieniężnych wartościach.
    Ona także będzie przedmiotem zainteresowania wszystkich przedsiębiorców, którzy zdecydowali się na
    stworzenie prywatnej działalności gospodarczej.
    Ostatecznie wszyscy z nich są przymuszeni do rozliczeń z instytucjami państwowymi, jako element gospodarki krajowej.

    Ujmując ją jako element nauki można ją rozpatrywać na parę różnych działów.
    my web site - Extor opinie

  1. Anonim mengatakan...:

    Na dzień dzisiejszy biura rachunkowe nie muszą upominać
    się na niewielką liczbę klientów. Przychodzą do nich głównie właściciele firm, którzy mają jednoosobowe
    działalności. Takich przedsiębiorców jest teraz na rynku naprawdę sporo.
    Prowadząc oraz obsługując na własną rękę firmę, nie można o wszystko zadbać osobiście.
    Z uwagi na to korzystają oni z możliwości
    oferowanych na rynku, jakie są się doskonałym wyjściem.
    Wybraną z dziedzin, która zajmuje się obsługą takiej
    działalności jest właśnie rachunkowość proponująca usługi księgowe, jaka ma czuwać na zgodnością finansów w firmie.
    Also visit my blog post - biuro rachunkowe Extor

Poskan Komentar

Ayo gan Komentarnya jangan lupa,,,biar tambah semangat yang upload Film dan Game dan berita juga update artikelnya, kalau ada link yang mati laporkan juga disini ya...

 
gamers holic dan security web dan aneka ragam © 2011 | Designed by Bingo Cash, in collaboration with Modern Warfare 3, VPS Hosting and Compare Web Hosting
Related Posts Plugin for WordPress, Blogger...