Showing posts with label COLAB. Show all posts
Showing posts with label COLAB. Show all posts

Friday 16 February 2018


CENG 222 – Computer Organization
Lab Work 5

Jump and Labels

JMP instruction allows to “jump” into an address of a instruction in our program. You can make loops by using JMP. Usage of JMP:

JMP <address or label name>

In assembly programs, we generally use labels to mark a starting point of a code. They end with a colon sign (“:”). Example:

L1:
           
            MOV …
            SUB …
           
            JMP L1            ; Jump into the first instruction after the label “L1”.

Testing conditions and Conditional Jump

In order to test a condition, you can use SUB or AND instructions. For example you can test A = B, A > B, A >= B, A < B and A <=B conditions using SUB. You can also test the status of any bit of a register by using AND. These instructions will modify the flag bits according to the results they produce. Therefore, you can make a conditional jump using flag bits’ status. However, SUB and AND instructions also store the result into the destination register. If you just want to test the condition without modifying operands, you need to use CMP and TEST instructions. These instructions are used to modify just the flag bits.

CMP is the same as SUB but it does not modify the destination. TEST is the same as AND but it does not modify the destination. However they both modify the flag bits.
Analyze the code below:

           
            MOV CX, 0
L1:
            CMP CX, 10
            JE L2                           ; Go to L2 if CX = 10
            INC CX
            JMP L1                        ; Go to L1 (CMP instruction)
L2:
           

Some of conditional jump instructions are:

JE, JNE, JZ, JNZ, JG, JNG, JL, JNL, JLE, JGE, JNLE, JNGE

JE:       Jump if equal to
JNE:    Jump if not equal to
JZ:       Jump if zero
JNZ:    Jump if not zero
JG:      Jump if greater than
JNG:   Jump if not greater than
JL:       Jump if less than
JNL:    Jump if not less than
JLE:    Jump if less than or equal to
JGE:    Jump if greater than or equal to
JNLE: Jump if not less than nor equal to (same as JG)
JNGE: Jump if not greater than nor equal to (same as JL)

Please note that conditional jump instructions are useless alone, but if you use an instruction that modifies flag bits, before the jump instruction, you can make IF…THEN…ELSE structures. For example:

            CMP var1, var2           ; Compare var1 and var2
            JG L1                           ; Jump to L1 if var1>var2

                                            ; “IF” block
                                            ; These instructions will be executed if var1<=var2

            JMP L2                        ; End of “IF” block, we need to jump L2
L1:

                                            ; “ELSE” block
                                            ; These instructions will be executed if var1>var2

L2:                                           ; End of “IF…ELSE” block


LOOP instruction

LOOP instruction allows creating a simple loop using CX register as a counter.

Usage:
LOOP <address of label>

You need to initialize CX first for the number of repentance of the loop. Analyze the code below:

            MOV CX, 10              ; Loop 10 times
L1:
           
                                            ; Instructions in the loop
           
            LOOP L1

LOOP instruction simply decrements CX and tests if it is zero. If not zero, then jump. Otherwise, continue.

EXPERIMENTS
1.      Find the sum [1+2+3+4+5+...+10] by using both compare-jump combination and loop instruction.
2.      Find the sum [1+3+5+..+17] by using both compare-jump combination and loop instruction.
3.      Find the sum of numbers between 0 and 20 that are not divisible by 4
4.      Write a program to find the factorial of the number given in AL register. (Assume that the number is sufficiently small so that the factorial wont be larger than 32 bits)


CENG 222 – Computer Organization
Lab Work 4

Logical Operations

Some of bitwise logical operations are:
AND, OR, NOT, XOR

Bitwise logical instructions apply the operation between each corresponding bits.

Examples:
AND data, ax               ; data = data AND ax
OR dx, ax                    ; dx = dx OR ax
NOT cl                        ; cl = NOT cl
XOR ax, ax                   ; ax = ax XOR ax

Shift Operations
Shift operations basically shift the bits of the given target (given as first parameter) by a number (given by second parameter)

Some Shift Operations are:
SHL,SHR (logical/unsigned),SAL, SAR(arithmetic/signed)

See 8086 help for detailed explanation of instructions. 

Rotate Operations
Shift operations work like shift operations, they the bits of the given target (given as first parameter) by a number (given by second parameter), the shifted bits are attached to the other side of the target.

Some Rotate Operations Are:
ROL, ROR (without carry), RCL, RCR (with carry)

See 8086 help for detailed explanation of instructions.

 

EXPERIMENT 1

Given bit values
A = 10101010b
B = 11001100b
C = 11110000b

Compute the following logical operations:
  • A  AND  B
  • A OR (B   AND   C)
  • A OR B OR (NOT C)
  • (A  AND B) OR (A   AND (NOT  C))

EXPERIMENT 2

Perform the following operations without using a MUL/ IMUL or DIV/IDIV command.
Hint: When you apply a single shift operation for a number you can multiply it or divide it by 2. Shift left for multiplying, shift right for dividing.

  • 0FAAh *2
  • 0FAAh / 2
  • FFAAh  / 2
  • FFAAh * 2
  • 00AAh * 5 ( Hint: 5*x = 4*x + x)
  • 00FBh *  2 + 000Bh * 4
  • 00AAh * 18

EXPERIMENT 3

Consider using logical and shift operations for the following assignments.
Hint:
AND AL, 11111101b; command will change the second bit of AL to 0, without changing the other bits
similarly
 OR AL, 00000010b will change the second bit of AL to 1, without changing the other bits
  • Assign  AX any value. Get the 4th bit of AX to the first bit of BX. All the other bits of BX should be zero
  • Get the  3rd bit of AL to 5th bit of AH. Other bits of AH should be unchanged.
  • Get the 2nd and 3rd bits of AH to 1st and 2nd bits of AL


CENG 222 – Computer Organization
Lab Work 3

Special Register: FLAGS

The flags register is unlike the other registers on the microprocessor. The other registers hold eight or 16 bit values. The flags register is simply a collection of one bit values which help determine the current state of the processor. Although the flags register is 16 bits wide, some of them are used. Of these flags, four flags you use all the time: zero, carry, sign, and overflow. These flags are the 8086 condition codes. The flags register appears below:
Zero flag bit is set when last instruction produces 0 as a result.
Carry flag bit is set when last instruction produces a number with a carry.
Sign flag bit is set when last instruction produces a negative number.
Overflow flag bit is set when last instruction produces a number which cannot fit in register.

Flag bits are generally used for testing the conditions. For example, if you want to test whether A = B, you need to subtract A from B, then if you have a result 0, zero flag will be set. Therefore, you need to check zero flag to obtain the result of the condition.

Arithmetic operations

Some of the arithmetic operations that are supported by Intel microprocessors are:
ADD, ADC, INC, DEC, SUB, MUL, IMUL, DIV, IDIV

ADD <destination>, <addend>                    ; destination = destination + addend

ADD instruction adds <addend> to <destination>.

ADD ax, bx                ; ax = ax + bx
ADD var, 2                 ; var = var + 2
ADD al, cl                   ; al = al + cl

ADC <destination>, <addend>                    ; destination = destination + addend + C

ADC instruction adds <addend> + Carry to <destination>. It is used to add large sized numbers.
Let AX:BX be 32 bits number. Let CX:DX be another 32 bits number. In order to add these numbers together using 16-bits microprocessor, we need to use ADC.

ADD BX, DX                        ; Add low order digits
ADC AX, CX             ; Add high order digits together with carry

The instructions above simply calculates: (AX:BX) = (AX:BX) + (CX:DX)

INC <destination>                                         ; destination = destination + 1;
DEC <destination>                                       ; destination = destination - 1;

INC instruction increments and DEC instruction decrements the destination.

INC dx
DEX al
INC var


SUB <destination>, <subtrahend>              ; destination = destination – subtrahend

SUB instruction subtracts <subtrahend> from <destination>.

SUB var, 2                  ; var = var - 2;
SUB bl, cl                   ; bl = bl – cl;
SUB bx, ax                 ; bx = bx – ax;

MUL <multiplicand>

MUL instruction multiplies AX or AL register by <multiplicand>. Destination is AX and DX. If <multiplicand> is an 8-bits number, it will be multiplied by AL. The destination is AX. If <multiplicand> is a 16-bits number, it will be multiplied by AX. The destination is (DX:AX). Here are some examples to make it clear:

MUL DL                     ; AX = AL * DL
MUL BX                    ; (DX:AX) = AX * BX
MUL var                     ; AX = AL * var         (Assuming var is a byte)
MUL var                     ; (DX:AX) = AX * var           (Assuming var is a word)

IMUL is the same as MUL, but it is used for signed numbers which are stored in 2’s complement format.

DIV <divisor>

DIV instruction divides AX or (DX:AX) by <divisor>.
If <divisor> is an 8-bits number,
            AL = AX / <divisor>
            AH = AX mod <divisor>
If <divisor> is a 16-bits number,
            AX = (DX:AX) / <divisor>
            DX = (DX:AX) mod <divisor>


Here is piece of code for division.

MOV AX, 1000
MOV DL, 30
DIV DL

The code above divides 1000 by 30. The quotient (33) will be in AL. The remainder (10) will be in AH. If the number is in <divisor> is too small or zero, the quotient will be too large to fit in AL. Therefore you need to select the registers according to their sizes. For example if you want to divide 1000 by 3, you will get 333 as a quotient which cannot be stored in 8-bits register AL! In order to do this, you need to use 16-bits division. Here is how:

MOV AX, 1000          ; The number is 1000.
MOV DX, 0                ; DX = 0, so (DX:AX) is 0000:1000 = 1000.
MOV BX, 3                ; Divisor is 3
DIV BX                      ; AX = (DX:AX) / 3 = 1000 / 3 = 333. AX is capable to store 333.
                                    ; DX = (DX:AX) mod 3 = 1000 mod 3 = 1.

IDIV is the same as DIV, but it is used for signed numbers which are stored in 2’s complement format.

EXPERIMENTS Advanced Arithmetic Operations
I) Write assembly program to do the following substractions.For each value, what is the hexadecimal result? What is the decimal result? Investigate Carry and Sign and Zero Bits.
  • 01h – 01h
  • 00h + 00h
  • 265Ch - 1AFFh.
  • 0000h - 0001h

II)  Write assembly programs to find the sum of the following hexadecimal numbers. For each summation answer following questions. Does the result fit in a 16 bit register? Why? Investigate the Carry and sign bits.
  • 0Fh + 01h
  • FFFFh + 0001h
  • 0FAAh + 1B04h +  F0A0h.

III) Write assembly programs to do the following computations. Chose registers according to the data and state how the resulting number is represented.
  • 03h * 05h
  • A1A1h * 00F0h
  • (A5C4h * 0040h) + 00FFh
  • (A5C4h / 0004h) – 0A0Ah
  • 02h * AAh * F2h




CENG 222 – Computer Organization
Lab Work 2

Arithmetic operations

Some of the arithmetic operations that are supported by Intel microprocessors are:
ADD, ADC, INC, DEC, SUB, MUL, IMUL, DIV, IDIV

ADD <destination>, <addend>                    ; destination = destination + addend

ADD instruction adds <addend> to <destination>.

ADD ax, bx                ; ax = ax + bx
ADD var, 2                 ; var = var + 2
ADD al, cl                   ; al = al + cl

INC <destination>                                         ; destination = destination + 1;
DEC <destination>                                       ; destination = destination - 1;

INC instruction increments and DEC instruction decrements the destination.

INC dx
DEX al
INC var


SUB <destination>, <subtrahend>              ; destination = destination – subtrahend

SUB instruction subtracts <subtrahend> from <destination>.

SUB var, 2                  ; var = var - 2;
SUB bl, cl                   ; bl = bl – cl;
SUB bx, ax                 ; bx = bx – ax;

EXP1 – Direct Addressing and Arithmetic Operations

1.      Convert your year of birth to a hexadecimal number and store write it to memory address 0200h. Is 1 byte enough to store the number? Why/why not? Do the writing to memory accordingly.
2.      Get the last 4 digits of your student number and write it to next memory address. Consider which memory address you should be using according to the answer of the first question.
3.      Find the sum of these two numbers. Store the result in register DX.
4.      Subtract first number from second store the result in register CX.

EXP2 – Indirect Addressing and Arithmetic Operations

1.      Store 50 (decimal) in memory address 0300h, this time use indirect addressing (access with [BX] ). Is 1 byte enough to store the number? Why/why not? Do the writing to memory accordingly.
2.      Store 51  in next address. Consider which memory address you should be using according to the answer of the first question.
3.      Store 52  in next address.
4.      Find the sum of 3 numbers. Store the result in the next adress.

EXP3 – Advanced Data Transfer

Analyze the assembly code below:

title Register test program

.model small
.stack 100h
.data
msg db "AB",0dh,0ah,'$'

.code
main proc
     mov ax,@data
     mov ds,ax

; Add your code here
; ------------------

; ------------------

     mov ah,9
     mov dx,offset msg
     int 21h

     mov ax, 4c00h
     int 21h
main endp

end main

The program above prints “AB” to the console. The message “AB” is stored at msg in data segment. Therefore, “offset msg” is the starting address of the string. Modify the code according to the following experiments (Try both MOV and LEA commands) :

1-      Copy the second byte stored at “msg” (which is ‘B’ currently) to the first byte. The output should be “BB”. In order to do that, load 2-bytes data stored at “msg” into a 16-bits register. Copy one part of the register to the other part. Then, write your register back to msg.
2-      Copy the first byte stored at “msg” (which is ‘A’ currently) to the second byte. The output should be “AA”. To achieve this, load the first byte stored at “msg” into one 8-bits register (high or low part) and copy it onto the other part and write the data stored in register back to msg.
3-      Load the data stored at “msg” into one register and swap the high and low parts of the register using a temporary 8-bits register. Then write back your “swapped” register onto msg. The output should be “BA”.

Advanced usage of MOV in MASM


Previously we used “offset” to point a memory location, but MASM supports a more user friendly way. As explained in previous lab, MASM does not support a moving operation to a memory location directly pointed by an immediate data but actually, currently used Intel microprocessors support it! Fortunately, some advanced usage of MOV instructions in MASM make it possible. Analyze the source and assembled code below:

Source Code
Assembled code
title Register test program

.model small
.stack 100h
.data
msg db "AB",0dh,0ah,'$'

.code
main proc
       mov ax,@data
       mov ds,ax

       mov al,msg
       mov msg+1,al

       mov ah,9
       mov dx,offset msg
       int 21h

       mov ax, 4c00h
       int 21h
main endp

end main









3BA6:0000 B8A73B    MOV AX,3BA7
3BA6:0003 8ED8      MOV DS,AX

3BA6:0005 A00800    MOV AL,BYTE PTR [0008]
3BA6:0008 A20900    MOV BYTE PTR [0009],AL

3BA6:000B B409      MOV AH,09
3BA6:000D BA0800    MOV DX,0008
3BA6:0010 CD21      INT 21

3BA6:0012 B8004C    MOV AX,4C00
3BA6:0015 CD21      INT  21

Since “msg” is defined in data segment, if we use it without “offset”, it denotes the data pointed by msg (not the address of it). As we can see in the assembled code the address is inside [] brackets. ([0008]). Note that if we use “msg+1”, it means that the data stored in the memory location msg+1 that is [0009]. Here it is clear that MASM automatically calculates offsets and uses [] to point the data.
You can choose to use “offset” and denote pointer operations by yourself or use MASM to interpret the instructions. It is important to learn the usage of offset in order to understand how the operation is done exactly. Please do not go any further without understanding the code above.

LEA (Load effective address) instruction


If we use “offset”, we need the following instruction to get the address of a data:
MOV DX, offset msg

Here, msg is defined as name of the data itself. Another way to do this without using offset:
LEA DX, msg
Both instructions above, loads the address of msg into DX.

CENG 222 – Computer Organization
Lab Work 1


16-bits Intel microprocessors have some capabilities of moving data from register to register; register to memory, and vice versa.

Commonly used 16-bits registers are:

AX, BX, CX, DX, SI, DI, SP, DS

First four registers (AX, BX, CX, and DX) consist of two 8-bits parts called high part (denoted by ‘H’) and low part (denoted by ‘L’).

AX = AH, AL                        BX = BH, BL             CX = CH, CL             DX = DH, DL

Note that the high part register is the most significant byte and the low part is the least significant byte of the whole 16-bits register.

Assembly instructions of moving data using memory and registers are given below:

§  Parameters of instructions are denoted by <…> symbols for explaining the usage of the instruction.
§  [] braces in Macro assembly has the same function with * operator in C language. For example, [AX] denotes the data or memory location where AX points to.

1-    Immediate data to register

            MOV <destination register>, <data>

      MOV AX, 4C00H                  ; AX = 4C00h
      MOV DL, 120                        ; DL = 120

      Size of data and destination register must be equal!

2-    Register to register

            MOV <destination register>, <source register>

            MOV AX, CX            ; AX=CX
      MOV CL, BH             ; CL=BH
     
      Note that size of destination and source registers must be the same!

3-    Memory to register (Direct addressing)

            MOV <destination register>, [<address>]

            MOV AX, [1BFFH]               ; Copy 2-bytes (word) data stored at address 1BFF to AX
            MOV DL, [offset msg]           ; Copy 1-byte data at msg to DL

Important:  Size of the data read from memory is determined by the size of the destination register!


4-    Memory to register (Indirect addressing)

            MOV <destination register>, [<register>]

            MOV AX, [BX]         ; AX = (*BX)
      MOV DL, [BX]          ; DL = (*BX)

Important:  Size of the data read from the memory location pointed by register, is determined by the size of the destination register!

5-    Register to memory

            MOV [<register>], <source register>

            MOV [BX], DX         ; *BX = DX    (Writes 2 bytes)
            MOV [BX], DL          ; *BX = DL     (Writes 1 byte)
            MOV [1BFFH], AX   ; *(1BFFH) = AX;      (Writes 2 bytes)
           
Note: Size of the data written is the size of register.

6-    Immediate data to memory
           
            MOV [<register>], <data>

            MOV [BX], 20h         ; *BX = 0020h
            MOV [BX], 4C00h     ; *BX = 4C00h
            MOV [1BFFH], 20h   ; *(1BFFH) = 20h;
           
If the source data is 1-byte, size of the data written to the memory is 16-bits unless you state the size. Leading zeros will be added automatically.

MOV [BX], 20h          ; Copy the word (2-bytes) data to the memory
                                    ; block started at BX. (*BX = 0020h)
MOV WORD PTR [BX], 20h            ; Exactly the same as above
MOV BYTE PTR [BX], 20h              ; Copy 1 byte (*BX = 20h)

If the source data is 2-bytes, size of the data written to the memory is 16-bits and you cannot state the size.
Experiments

Analyze the assembly code below:

title Register test program

.model small
.stack 100h
.data
msg db "AB",0dh,0ah,'$'

.code
main proc
     mov ax,@data
     mov ds,ax

; Add your code here
; ------------------

; ------------------

     mov ah,9
     mov dx,offset msg
     int 21h

     mov ax, 4c00h
     int 21h
main endp

end main

The program above prints “AB” to the console. The message “AB” is stored at msg in data segment. Therefore, “offset msg” is the starting address of the string. Modify the code according to the following experiments:

1-      Copy the second byte stored at “msg” (which is ‘B’ currently) to the first byte. The output should be “BB”. In order to do that, load 2-bytes data stored at “msg” into a 16-bits register. Copy one part of the register to the other part. Then, write your register back to msg.
2-      Copy the first byte stored at “msg” (which is ‘A’ currently) to the second byte. The output should be “AA”. To achieve this, load the first byte stored at “msg” into one 8-bits register (high or low part) and copy it onto the other part and write the data stored in register back to msg.
3-      Load the data stored at “msg” into one register and swap the high and low parts of the register using a temporary 8-bits register. Then write back your “swapped” register onto msg. The output should be “BA”.