ASM function in C

Hello!

I want to create function that returns the position of an element found in an array. If the element isn't in that array, it will return -1.

In C language, the function looks like that:

1
2
3
4
5
6
7
8
9
int find(int *a, size_t n, int x)
{       int i;
        for(i=0; i<n; i++)
        { 
             if(x == a[i])
                return i;
         }
         return -1;
}         


Well, I want to write that function in ASM, and then to insert it into a C program, using the asm{ ... } label (or whatever it is).

I found in a book, the implementation in ASM of that function and I tried to write it in a C function, as you may see in the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<stdio.h>


int cauta(int near *a, size_t n, int x)
{
    asm{
          push si
          push cx
          push dx

          mov si, a
          mov cx, n
          jcxz not_gasit
          mov dx, x
          sub si, 2
    }
    reluare:
              asm{
                    add si, 2
                    cmp [si], dx

                    loopnz reluare

                    jnz not_gasit
                    mov ax, n
                    sub ax, cx
                    dec ax
                    jmp final
              }
    not_gasit:
              asm mov  ax, -1
    final: asm{
                  pop dx
                  pop cx
                  pop si
    }
    return _AX;
}


int main()
{
         int a[100];

         a[0] = 4;
         a[1] = 5;
         a[2] = 1;
         a[3] = 9;
         printf("%d", cauta(a, 4, 1);
}


The problem is that I get some errors:

1
2
3
4
5
6
D:\C++ Projects\Preparing for ONI\main.c|4|error: expected ';', ',' or ')' before '*' token|
D:\C++ Projects\Preparing for ONI\main.c||In function 'main':|
D:\C++ Projects\Preparing for ONI\main.c|49|warning: implicit declaration of function 'cauta'|
D:\C++ Projects\Preparing for ONI\main.c|49|error: expected ')' before ';' token|
D:\C++ Projects\Preparing for ONI\main.c|50|error: expected ';' before '}' token|
||=== Build finished: 3 errors, 1 warnings ===|


How can I fix that?

Thank you respectfully.
Nobody?
What compiler/platform are you using?

It looks like the compiler didn't recognize the near keyword on line 4. The near keyword is a throwback to 16 bit memory architectures and is obsolete on 32 bit machines. That also caused your function call not to be recognized on line 49.

If you truely need the near keyword, you should check your compiler documentation. There may be a compile time switch to enable it, or it might be _near depending on the implementation, if it's supported at all.


I use the gcc compiler, in Code::Blocks IDE. I forgot to mention that I compile it with a x64 architecture machine.

If I remove the near keyword, I get 5 errors, so it must to be there.

Thank you for your answer.
I was going to suggest:
1. rewrite the C version using pointers rather than array indexing.
2. get the compiler to output intermediate asm code, which you can then borrow for getting the appropriate syntax.
3. tweak or replace the generated code as required.
According to this page, there are no near or far keywords in gcc.
http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Keyword-Index.html

Why are you trying to use 16 bit pointers in a 64 bit environment?
Chervil: I tried to do that a few months ago, but the output code is absolutely understanable. For a simple Hello World program, I get over 500 lines of ASM code. I don't really know if that is ok...

AbstractionAnon: I didn't create that function in ASM. As I said below, I found it in a book, and I just copied it in the Code::Blocks environment to see if it works. So the "near" keyword belongs to the implementation found in that book.
CosminNTG wrote:
For a simple Hello World program, I get over 500 lines of ASM code. I don't really know if that is ok...

That's not normal at all. You might be seeing a bunch of boilerplate code in there, but for a hello world program, the code that actually outputs should only be a few lines.
What I did was create a simple function, such as "add two integers and return the result". But I gave the function and variables very distinctive names. That way, it was very easy to identify the relevant part of the code, and I ignored the rest.
Allright, but if you don't really know the ASM syntax, I think that is very difficult to consider just a part of that code. I mean...what if you miss some very important instruction, for instance to clear the memory or something like that?
It will all be grouped together. The boilerplate will be in front and behind it. Grab a manual for your given architecture and use that as a reference.
I don't know, I suggested using the code generated by the compiler precisely to avoid such problems. If that approach doesn't work for you, that's fine too.
Are you doing this to learn asm, or are you doing this because you think you can write a more efficient find loop than C?

Frankly, with today's optimizing compilers it is hard to write something more efficient than what the compiler generates with the highest optimization level.
I am doing this because I want some fast routines, and I heard that in ASM all those instructions are really fast because ASM is a low-level language.

For instance, that code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
int add(int NUMBER1, int NUMBER2)
{
    return NUMBER1+NUMBER2;
}
int main()
{
    int VARIABLEX, VARIABLEY;
    VARIABLEX = 5;
    VARIABLEY = 8;
    cout<<add(VARIABLEX, VARIABLEY);
    return 0;
}


in ASM looks like that: http://pastebin.com/Jv47wcUt

It has 8448 lines!
in ASM looks like that:
It has 8448 lines!

Did you compile in debugging mode? Release mode should give more compact code.
The name of the function "add" isn't particularly distinctive - rather the opposite.

Still, I don't wish to waste your time with this if it isn't proving fruitful.
It has 8448 lines!

Only a few lines are code. Specifically, there's your function "add":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__Z3addii:
LFB938:
        .file 1 "D:/C++ Projects/bac_aux/main.cpp"
        .loc 1 4 0
        pushl   %ebp
LCFI0:
        movl    %esp, %ebp
LCFI1:
        .loc 1 5 0
        movl    12(%ebp), %eax
        movl    8(%ebp), %edx
        leal    (%edx,%eax), %eax
        .loc 1 6 0
        leave
        ret


it obviously isn't using optimization, here's what gcc generates on an intel architecture with -O3:

1
2
3
4
_Z3addii:
.LFB983:
        leal    (%rdi,%rsi), %eax
        ret


Taking your original find loop, I got the following with VS2010.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
; 2    : {   for(int i=0; i<n; i++)

	push	ebp
	mov	ebp, esp
	mov	ecx, DWORD PTR _n$[ebp]
	xor	eax, eax
	push	esi
	test	ecx, ecx
	je	SHORT $LN2@find
	mov	edx, DWORD PTR _x$[ebp]
	mov	esi, DWORD PTR _a$[ebp]
$LL4@find:

; 3    :     {   if(x == a[i])

	cmp	edx, DWORD PTR [esi+eax*4]
	je	SHORT $LN5@find

; 2    : {   for(int i=0; i<n; i++)

	inc	eax
	cmp	eax, ecx
	jb	SHORT $LL4@find
$LN2@find:

; 4    :                 return i;
; 5    :     }
; 6    :     return -1;

	or	eax, -1
$LN5@find:
	pop	esi

; 7    : }         

	pop	ebp
	ret	0


I really doubt you're going to be able to write anything faster than that.
It's really a fallacy that asm is faster than C/C++ for well written code.
Topic archived. No new replies allowed.