Accessing Assembly language from C++
Asked Answered
T

2

5

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
Trepidation answered 9/11, 2011 at 16:4 Comment(6)
So you want too import 8086 assembler into a c++ compiler rather than write the function in C++?Gregorio
One difference is that your assembly is using an array of bytes, and the C++-with-assembly is using array of int (which are probably 4 bytes each). You should check that you're reading and writing the correct number of bytes, and incrementing your pointers by the correct amount.Ailment
@Mike Seymour Yes. that is the difference but I have been careful in counting the bytes in assembly(refer the code, it checks for $ as end symbol) where as in C++ I am just manually keeping the counter to 6. Then why does random values get print???Trepidation
Uhh, are you sure that cout<<max<<"\n"; or your looping code leaves si untouched? I wouldn't count on it.Kentiga
I can't believe this is a homework assignment...Kiyokokiyoshi
actually this is my personal attempt... Homework assignment was simpler... i.e. Writing an assembly code to find maximum of THREE numbers and then to use a method in c++ to call that method... That is done.Trepidation
T
7

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.

Thorr answered 9/11, 2011 at 16:14 Comment(2)
I tried out what you said... Not getting it... Can you please show the code?Trepidation
Instead of mov si,offset a write mov si, a, and instead of inc si write add si, something where something is the size of an int (I'm not sure if you're allowed to write sizeof(int) in inline assembly - if not, use a number).Thorr
M
3

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.

Mady answered 9/11, 2011 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.