Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Assembly language from C++

This is my programming assignment. I need to find out the largest among the array of integers using a method written in 8086 programming language. This is my attempt :

  #include <iostream.h>
    #include <conio.h>

    int returnLargest(int a[])
    {
        int max;
        asm mov si,offset a

        for(int i=0;i<6;i++) //Assuming six numbers in the array...Can be set to a variable 'n' later
        {
              asm mov ax,[si]
              asm mov max,ax
              asm inc si
              cout<<max<<"\n";    //Just to see what is there in the memory location
        }

        asm mov si,offset a
        asm mov cx,0000h

        asm  mov dx, [si]

            asm mov cx,06h

        skip: asm   mov si,offset a
        asm mov bx,[si]
        asm        mov max,bx
        asm inc si
        abc: asm   mov bx,max
           asm     cmp [si],bx
        asm jl ok
           asm     mov bx,[si]
              asm  mov max,bx
        ok: asm loop abc
        asm mov ax,max
        return max;
    }
    void main()
    {
        clrscr();
        int n;
        int a[]={1,2,3,4,5,6};
        n=returnLargest(a);
        cout<<n; //Prints the largest
        getch();
    }

The expected answer is

1 2 3 4 5 6 6. But what I get is this : enter image description here

Here I sit down and think... Is'nt it the value at the index i of array actually stored in the memory? Because atleast we were taught that if a[i] is 12(say) then ith memory location has the number 12 written inside it.

Or if the value is'nt stored at the memory location, How do I write into the memory location so as to accomplish the desired task?

Also I request you all to link some material on net/paperback so as to brush-up on these concepts.

EDIT :

The same code in assembly works just fine...

data segment
    a   db  01h,02h,03h,04h,05h,06h,'$'
    max db  ?
data ends

code segment
    start:
        assume cs:code,ds:data
        mov ax,data
        mov ds,ax

        mov si,offset a
        mov cx,0000h

        back:   mov dl,byte ptr [si]
                cmp dl,'$'
        je skip
        inc cx
                inc si
        jmp back

    skip:   mov si,offset a
                mov bl,byte ptr[si]
                mov max,bl
        inc si
        abc:    mov bl,max
                cmp [si],bl
        jl ok
                mov bl,[si]
                mov max,bl
    ok: loop abc
        mov al,max
        int 03h
code ends
    end start
like image 808
Kameron Avatar asked Nov 09 '11 16:11

Kameron


People also ask

Can you use assembly in C?

We can write assembly program code inside c language program. In such case, all the assembly code must be placed inside asm{} block. Let's see a simple assembly program code to add two numbers in c program.

What is asm () in C?

The asm keyword allows you to embed assembler instructions within C code. GCC provides two forms of inline asm statements. A basic asm statement is one with no operands (see Basic Asm), while an extended asm statement (see Extended Asm) includes one or more operands.

Why is the code of entry () in assembly and not in C?

The entry point is in assembly because during the early boot phase there is NO facility to call C functions. Before we can call a C function the system should already have a valid stack.


2 Answers

mov si,offset a is incorrect. When you have a function parameter declared as int a[], the function actually receives a pointer. Since you want the pointer value (a) rather than its address (&a in C, offset a in assembly), use mov si, a.

Additionally, inc si doesn't seem right - you need to increase si by sizeof(int) for each element.

Edit:

You are mixing C++ code (for loop, cout) with your assembly. The C++ code is likely to use the same registers, which would cause conflicts. You should avoid doing this.

You also need to find out which registers your function is allowed to change according to the calling convention used. If you use any registers which aren't allowed to change, you need to push them at the beginning and pop them at the end.

like image 170
interjay Avatar answered Oct 12 '22 21:10

interjay


You will have to make sure your compiler doesnt use your registers. Best way would be to write the entire function in assembly and implement a desired calling convention (c-call or stdcall - whatever). Then call that function from C/C++.

However if you know you will use only one compiler and how it works you shouldnt have any problems by inlining assembler, but it's really a pitfall.

like image 3
stefan Avatar answered Oct 12 '22 22:10

stefan