Google

星期二, 十二月 18, 2007

Learning Assembler with Delphi 2

Basic Assembler Operations
Lets first define a few symbols for the purpose of this document.


reg1, reg2,... refer to any of the general 32bit registers eax, ebx, ecx and edx.

mem1, mem2,... refers to any memory expression either explicit [1536], implicit [edx] or pascal pointer Count. The brackets refer to the contents of the value, so [edx] is the memory location at address edx. The compiler knows a pascal pointer is a memory expression so brackets aren't required.

exp1, exp2... explicit values such as 10 in decimal, 0Ah in hex.

dest refers to the parameter into which the result of the operation will be stored.

src refers to the source of any extra data required by the operation.

For each operation at least one of dest and src must be a register or an implicit memory address, ie a memory address dependant on the value of a specified register.

And now to the operations:

add dest,src
reg1,reg2
reg1,mem1
reg1,exp1
mem1,reg1
performs integer addition on dest and src, storing the resutling value in dest.

and dest,src
reg1,reg2
reg1,mem1
reg1,exp1
mem1,reg1
performs the logical binary operation 'and' on dest and src, storing result in dest.

dec dest
reg1
mem1
subtracts one from the value of dest.

inc dest
reg1
mem1
adds one to the value of dest.

mov dest,src
reg1,reg2
reg1,mem1
reg1,exp1
mem1,reg1
copy the value of src and store in dest.

not dest
reg1
mem1
inverts the binary value of dest and stores the result in dest.

or dest,src
reg1,reg2
reg1,mem1
reg1,exp1
mem1,reg1
performs an inclusive 'or' operation on dest and src storing result in dest

shl dest,src
reg1,exp1
shifts the binary digits of dest, src places to the left and stores the result in dest. This is a quick way to multiply by a power of two.

shr dest,src
reg1,exp1
shifts dest, src places to the right. Quick division by a power of two.

sub dest,src reg1,reg2
reg1,mem1
reg1,exp1
mem1,reg1
subtracts the value of src from dest, storing the result in dest.

xor dest,src
reg1,reg2
reg1,mem1
reg1,exp1
mem1,reg1
performs an exclusive 'or' operation on dest and src storing the result in dest.

Special cases, multiply and divide
The operations for multiplication and division operate on the 64bit value formed by combining the values of eax and edx where the latter is the most significant value. For example if eax = AAAAAAAAh and edx = BBBBBBBBh then the 64bit value would be BBBBBBBBAAAAAAAAh.

div src
reg1
mem1
performs an unsigned divide on the 64bit value discussed above, the divisor being src. The quotient being stored in eax, the remainder in edx, and src is unaffected. If quotient is too large to be stored in eax or the value of src is zero, the cpu will generate an error and stop program execution.

idiv src
reg1
mem1
same as div but performs a signed divide.

mul src
reg1
mem1
performs an unsigned multiplication of eax and src. The resulting 64bit value is stored in eax and edx as above.

imul src
reg1
mem1
same as mul but signed.

Labels and Jumps
This section is really no more than a precursor to the section on flow control. A label is just an address in memory, and a jump just tells the cpu to look to a different address for the next line to execute. This is best illustrated by example

...
jmp @label1 { jump to label1 }
... { these }
... { next }
@label2: { instructions }
... { are }
jmp @label2 { never }
... { used }
@label1:
... { now we start execution again }



Note that the declaration of a delphi label starts with '@' and ends with ':'. The reference of a label does not include the ':'.

Controlling the flow
If we are going to produce really useful code, at some point we shall need to implement conditional statements such as while..do and repeat..until. Just one instruction combines the conditional possibilities available

cmp dest,src
reg1,reg2
reg1,mem1
reg1,exp1
and sets the result flags accordingly. What the flags are, and how they are set, will not be covered here. All you need know is the result of the following combinations of instructions.

cmp dest,src
je @label if dest = src then jump to @label.

cmp dest,src
jle @label if dest =<> src then jump to @label.

cmp dest,src
jg @label if dest > src then jump to @label.

cmp dest,src
jge @label if dest => src then jump to @label.

cmp dest,src
jl @label if dest < dest =" src"> src then jump to @label.



Whilst the jump operations are equivalent to a goto statement, the call and its associated ret operation form the basis of procedural programming. It is common to see assembler routines of the following form

...
jmp @mainroutinestart
@localprocedure: {start of local procedure}
{some code}
ret {return from procedure}
@mainroutinestart:
{some code}
call @localprocedure
{some code}
...



Furthermore, conditional calls can be constructed thus

...
cmp eax,12
{if eax = 12 jump over call to procedure}
je @skipcall
{if eax <> 12 call procedure}
call @localproc
@skipcall:
...



Using a combination of compare's, conditional jump's and procedural call's all of the elements of structured programming maybe implemented.

0 条评论:

发表评论

<< 主页

辽ICP备05003652号
流风洄雪听天籁,轻云蔽日看落花

Powered by Blogger