goldenprize
goldenprize

Reputation: 1

Interfacing Assembly language (x86) routines with C language

i've been having some issues when I try to call an assembly language function (x86) from a C program.

My assembly code is the following:

.model small
.code 
.stack 100h
public _putchar
;---------------------
;Putchar proc
;---------------------
    _putchar proc 
        push bp
        mov bp,sp
        mov dl,[bp+4]
        mov ah,2
        int 21h
        pop bp
        ret
    _putchar endp
end

Then, I call this procedure from C as follows:

extern void putchar(char x);

int main(void)
{
    putchar('x');
    return 0;
}

To compile and link, i use the following command lines (in order)

tcc -c -ms pchar.c
tasm putchar.asm
tlink pchar putchar, pchar 

So far, we got the .obj from putchar.asm, and the .exe file from linking the 2 files.

I should also mention that we (in class) use the turbo assembler version 2.01 (tasm) and the turbo link version 2.0 (tlink) and the Turbo C version 2.01 (tcc)

The issue comes here, when I run the .exe file I get the output 'x' as it should be, but it gets stuck there, it doesnt end.

I would appreciate any help, thanks in advance.

Upvotes: 0

Views: 696

Answers (2)

Alexis Wilke
Alexis Wilke

Reputation: 20741

I would say, maybe the ret is wrong, you may need a different type of return.

Possibly one which also removes the parameter from the stack, pascal convention if I'm correct. It would be something like this:

ret 4

Note: since you are in 16 bits, it may be ret 2 instead of ret 4. It would depend on the push instruction used before the all instrution.

Otherwise, maybe by changing the declaration of putchar with __cdecl.

extern __cdecl void putchar(char x);

Note that in a debugger you would see whether the stack is taken cared of on return (i.e. add sp, 4 to "lose" the input parameter--since you are in 16 bits, it may be 2 and not 4.)

I'm still surprised that you used bp+4 and not bp+8. You are in 16 bits, wow!

More about calling conventions.


Side note:

You may want to avoid using a function named putchar() since it is defined in the standard library although in your case you are most certainly not affected by that problem.

Upvotes: 1

User.1
User.1

Reputation: 2642

The two possibilities that I observe are AX and DX may be in use by the calling routine.

I seriously doubt that this will help, but try pushing and popping those before and after the routine.

Confirm or refute this with debug. Put a breakpoint before you call the routine, and step over it (not into it) see if the compiler's code wants to use either AX or DX after the call to your ASM subroutine.

Oh, and I concur with Alexis Wilke, change the name.

Upvotes: 1

Related Questions