Write up on Tech Geek History: Assembly Language’s Index /Offset

Peer to Peer Journal Articles

Literature Review

Chapter 1:  Assembly Language’s Index /Offset

There is no such thing Geometrically as a Perfect Line, Circle, or Rectangle nor Triangle

Core of creating Data to place hold  and geometrically “  “ perfect the Table or “ “. Opens the Research Topic of Indexing in Assembly Language:

Using an index register to process an array To process an array in a loop, we can put the offset into a register. The register we use to hold an offset is called an index register. Traditionally the registers used for this purpose are esi or edi. The ‘I’ stands for “index.” To initialize an index register, zero it out: sub esi,esi ; index register Then use the register in place of the constant: add eax,[arr+esi].

This line of code can be reused in a loop by changing the value of esi:

To process an array using an index register, start with initializing a loop counter: to do that, put the number of values in the array into ecx.

Also, the index register to 0. In the loop, increment the index register by the size of each array element, which is 4 for a doubleword. In this example, we’ll sum the 4 values in the arr array; that means we must also set sum (eax) to 0 and add each array value into eax:

mov ecx, 3 ; l

oop counter sub esi,esi ;

 index register sub eax,eax ; sum = 0

top: add eax,[arr+esi]

add esi,4 ; increment index loop top Using a base register to process an array Another way to process an array is to use a base register.

While the index register holds the offset of the array from the beginning of the array, the base register holds the address of the array from the beginning of the data segment: Suppose the data segment looks like the following (the left column is the offset of each item from the beginning of the data segment, measured in bytes). .data 0000 x dword 10 0004 arr dword 5, 7, 19 0010 n dword 3 If we were to list all the elements individually, the address of each element would be clearer: .data 0000 x dword 10 0004 arr dword 5 0008 dword 7 000C dword 19 0010 n dword 3 arr +0 +4 +8 <– index register contents 5 7 19 0004 0008 000C <– base register contents

Description

To process an array using a base register, you must put the address of the first element of the array into a base register. Traditionally the base register is ebx. The instruction to put the address of an array into a register is lea, or load effective address: lea ebx,arr Using the example above, this puts 0004 into ebx. Base register notation is the following: [ebx] To move the first value from the array into eax, write the following: mov eax,[ebx] To change to the next value in the array, increment ebx by the size of each array element; in an array of dwords, this is 4: add ebx,4 To process an array using a base register, start with initializing a loop counter Also initialize the index register to 0. In the loop, increment the base register by the size of each array element, which is 4 for a doubleword: To process an array using a base register, start by initializing a loop counter. Also initialize the base register to the initial address of the array. In the loop, increment the base register by the size of each array element, which is 4 for a doubleword. In this example, we’ll sum the 4 values in the arr array; that means we must also set

sum (eax) to 0 and

add each array value

into eax: mov ecx,3 ;

loop counter lea ebx, arr ;

base register sub eax,eax ;

sum = 0 top:

 add eax,[ebx]

add ebx,4 ; increment base register loop top

Passing an array as a parameter Between index register and base register notation, index register notation is clearer and easier to read. However, it is necessary to use base register notation when sending an array as a parameter to a procedure. A procedure can’t refer to any variables declared in main, and the array is declared in main.

.data 0000 x dword 10 0004

arr dword 5, 7, 19 0010

 n dword 4

To send an array as a parameter to a procedure, you must pass the base address of the array. It is most efficient to pass the address in ebx. In addition, you must pass the number of filled positions in the array; this is not passed by address or reference, but by value: you put the value of n into a register. It is most efficient to put that value into ecx, which Is where it will be used. To pass an array arr and n as parameters to the function addup, do the following. The function will return the sum in eax: lea ebx,arr mov ecx,n call addup mov sum,eax ; store return value Inside the function, you can begin to process the array directly using base address notation, since the address is already in ebx, and the loop counter is already in ecx. addup proc sub eax, eax ; sum = 0 addtop: add eax,[ebx] add ebx,4 loop addtop ret addup endp What’s wrong with this? We haven’t pushed and popped registers that are changed but that are not used to return a value. Those would be ebx and ecx, so we modify the code as follows: addup proc push ebx push ecx sub eax, eax ; sum = 0 addtop: add eax,[ebx] add ebx,4 loop addtop pop ecx pop ebx ret addup endp

With the .OFFSET directive you tell the assembler to give the location counter a new offset relative to the start of the section.

When the assembler encounters the .OFFSET directive, it moves the location counter forwards to the specified address, relative to the start of the section, and places the next instruction on that address. If you specify an address equal to or lower than the current position of the location counter, the assembler issues an error.

A label is not allowed with this directive.

Example

  .SECTION .text

  nop

  nop

  nop

  .OFFSET 0x20   ; the assembler places

  nop            ; this instruction at address 0x20

                 ; relative to the start of the section.

  .ENDSEC

  .SECTION .text

  nop

  nop

  nop

  .OFFSET 0x02   ; WRONG: the current position of the

  nop            ; location counter is 0x0C.

  .ENDSEC

The main tools to write programs in x86 assembly are the processor registers. The registers are like variables built in the processor. Using registers instead of memory to store values makes the process faster and cleaner. The problem with the x86 serie of processors is that there are few registers to use. This section describes the main use of each register and ways to use them. That in note that the rules described here are more suggestions than strict rules. Some operations need absolutely some kind of registers but most of the you can use any of the freely.

Here is a list of the available registers on the 386 and higher processors. This list shows the 32 bit registers. Most of the can be broken down to 16 or even 8 bits register.

General registers

EAX EBX ECX EDX

Segment registers

CS DS ES FS GS SS

Index and pointers

ESI EDI EBP EIP ESP

Indicator

EFLAGS

General registers
As the title says, general register are the one we use most of the time Most of the instructions perform on these registers. They all can be broken down into 16 and 8 bit registers.

32 bits :  EAX EBX ECX EDX

16 bits : AX BX CX DX

 8 bits : AH AL BH BL CH CL DH DL

The “H” and “L” suffix on the 8 bit registers stand for high byte and low byte. With this out of the way, let’s see their individual main use

EAX,AX,AH,AL : Called the Accumulator register.

               It is used for I/O port access, arithmetic, interrupt calls,

               etc…

EBX,BX,BH,BL : Called the Base register

               It is used as a base pointer for memory access

               Gets some interrupt return values

ECX,CX,CH,CL : Called the Counter register

               It is used as a loop counter and for shifts

               Gets some interrupt values

EDX,DX,DH,DL : Called the Data register

               It is used for I/O port access, arithmetic, some interrupt

               calls.

Segment registers

Segment registers hold the segment address of various items. They are only available in 16 values. They can only be set by a general register or special instructions. Some of them are critical for the good execution of the program and you might want to consider playing with them when you’ll be ready for multi-segment programming

CS         : Holds the Code segment in which your program runs.

             Changing its value might make the computer hang.

DS         : Holds the Data segment that your program accesses.

             Changing its value might give erronous data.

ES,FS,GS   : These are extra segment registers available for

             far pointer addressing like video memory and such.

SS         : Holds the Stack segment your program uses.

             Sometimes has the same value as DS.

             Changing its value can give unpredictable results,

             mostly data related.

Indexes and pointers

Indexes and pointer and the offset part of and address. They have various uses but each register has a specific function. They some time used with a segment register to point to far address (in a 1Mb range). The register with an “E” prefix can only be used in protected mode.

ES:EDI EDI DI : Destination index register

                Used for string, memory array copying and setting and

                for far pointer addressing with ES

DS:ESI EDI SI : Source index register

                Used for string and memory array copying

SS:EBP EBP BP : Stack Base pointer register

                Holds the base address of the stack

SS:ESP ESP SP : Stack pointer register

                Holds the top address of the stack

CS:EIP EIP IP : Index Pointer

                Holds the offset of the next instruction

                It can only be read

The EFLAGS register

The EFLAGS register hold the state of the processor. It is modified by many intructions and is used for comparing some parameters, conditional loops and conditionnal jumps. Each bit holds the state of specific parameter of the last instruction. Here is a listing :

Bit   Label    Desciption

—————————

0      CF      Carry flag

2      PF      Parity flag

4      AF      Auxiliary carry flag

6      ZF      Zero flag

7      SF      Sign flag

8      TF      Trap flag

9      IF      Interrupt enable flag

10     DF      Direction flag

11     OF      Overflow flag

12-13  IOPL    I/O Priviledge level

14     NT      Nested task flag

16     RF      Resume flag

17     VM      Virtual 8086 mode flag

18     AC      Alignment check flag (486+)

19     VIF     Virutal interrupt flag

20     VIP     Virtual interrupt pending flag

21     ID      ID flag

Those that are not listed are reserved by Intel.

Undocumented registers

There are registers on the 80386 and higher processors that are not well documented by Intel. These are divided in control registers, debug registers, test registers and protected mode segmentation registers. As far as I know, the control registers, along with the segmentation registers, are used in protected mode programming, all of these registers are available on 80386 and higher processors except the test registers that have been removed on the pentium. Control registers are CR0 to CR4, Debug registers are DR0 to DR7, test registers are TR3 to TR7 and the protected mode segmentation registers are GDTR (Global Descriptor Table Register), IDTR (Interrupt Descriptor Table Register), LDTR (Local DTR), and TR.

Bottom of Form

Leave a Comment

Your email address will not be published. Required fields are marked *