Hello everybody,

I'm somewhat new to assembly language and am currently having some issues with make a simple loop and was wondering If I could get some advice on what I'm doing wrong. I'm using inline assembly on the DMC compiler.


Thanks,


Sari

main.c


#include <stdio.h>
#include <stdlib.h>

//Variable Declaration
char hey[] = "Hello World!!!";
char cool[] = "\nROAR!!!!!!!!!!";
char format[] = "%s\n\n%s\n\n";
char title[] = "title EXtreme ASM Logic";
char pause[] = "PAUSE";
int x = 0;
//End variable declarations

void printrnt() {
asm {
#include "printing.asm"
}
}

int main() {

asm {
mov ecx, x
mov eax, offset title
push eax
call system
pop ebx
}

run:

asm {
//loop, not working
call printrnt
inc ecx
cmp ecx, 25

jne run

//end loop, not working

}
done:

asm {
mov eax, offset pause
push eax
call system
pop ebx

mov eax, 0
call _exit
}
}


printing.asm


//Move our variables into the C Paramenters
pusha
mov eax, offset cool
push eax
mov eax, offset hey
push eax
mov eax, offset format
push eax
//Call our functions
call printf
//Clean it up
pop ebx
pop ebx
pop ebx

popa
Posted on 2010-10-28 09:15:56 by sari
sari,

You may as well attach compiled PE, not everyone here has Digital Mars C at hand to compile sources.

ecx can be easily trashed by call printrnt, see calling conventions. Single debugging session probably can show that.
Posted on 2010-10-28 12:04:14 by baldr
As baldr pointed out, if you are going to use the ecx register for loop control you must save it prior to calling C functions since eax, ecx, and edx are are considered volatile and will in most circumstances be trashed by the called routine.

The following should provide the quick fix:


push ecx
call  printrnt
pop  ecx


Another thing to avoid is modifying register ebx unless you have saved it within your function's prologue.  EBX is a non-volatlie register as per x86 C calling convention so get used to saving it first before using it and then restoring it before your function exits.  Instead of the 3 pop ebx simply do an add esp, 12 which restores the stack pointer.  The printrnt function is declared as void so you're not returning anything anyways.

Also, a stylistic note - I see you've basically defined your labels outside of the asm{} block.  You should be able to define your entire assembly within one asm {} bracket inside the function.  At least this is how I do it when writing 32-bit code with VS.  Try it with your compiler though to see if it works.

Hope this helps  ;)

Posted on 2010-10-28 17:33:03 by p1ranha
Thanks for the responses guys,

Baldr:

I was just looking for obvious errors in the assembly, I know most people don't use Digital Mars ;.

p1ranha:

Thanks, I'll try that now :).


Thanks,


Sari
Posted on 2010-10-28 19:53:16 by sari
Thanks, p1ranha, it works perfectly. Quick question though.

Why would I have to push ecx if I you pusha in the body of the function?

Lol, I feel like such a noob :P
Posted on 2010-10-28 20:03:51 by sari

Why would I have to push ecx if I you pusha in the body of the function?


If memory serves me right, pusha is a 16-bit opcode.  You probably wanted pushad which is it's 32-bit equivalent.  Using pushad you technically would be fine, but remember that it pushes ALL general purpose registers - a slower operation than only pushing one or two registers.  Avoid that unless the function you are writing is going to use all those registers.  In your printing.asm even the pushad would not be necessary provided you replaced the pop ebx's with add esp, 12.  Doing so will eliminate a total of 5 CPU operations decreasing program size and increasing speed - the twin goals of writing assembler in the first place! :)

You basically want to wrap your call with the push ecx before the call (and the pop ecx afterwards) to remind yourself that printrnt calls print() which is going to destroy your ecx loop counter contents.


Lol, I feel like such a noob :P


In time, that too will pass.  You've come to the right place for guidance.  The folks on this board are for the most part very friendly ( except when we get requests from students asking us to write all their code for them because they've skipped class and the assignment is due tomorrow  :P
Posted on 2010-10-28 21:06:28 by p1ranha
Thanks, I appreciate it, I've seen some threads like that, don't think I'd be dumb enough to skip class in the first place :D.


Thanks again,

Sari

P.S. Very Informative post :)
Posted on 2010-10-28 21:50:19 by sari