Reputation: 1
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
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
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