Using assembly routines with C on DOS
Question
I've been playing with DOS real mode assembly for a while and now I want to utilize some routines in a C program. I'm using Turbo C 2.01 and TASM 3.0. I'm however unable to modify a variable passed by address, see the _setval routine below. I don't need/want inline assembly. A simple example:
foo.c
#include <stdio.h>
extern void setval(int *x, int *y);
extern int sum(int x, int y);
int main()
{
int result, a, b;
result = a = b = 0;
setval(&a, &b);
result = a + b;
printf("a+b=%i, a=%i, b=%i\n", result, a, b);
result = 0;
a = 42;
b = 19;
result = sum(a, b);
printf("a+b=%i, a=%i, b=%i\n", result, a, b);
return 0;
}
foortn.asm
public _setval
public _sum
.model small
.stack
.data
.code
_setval proc near
push bp
mov bp, sp
mov word ptr [bp+4], 42
mov word ptr [bp+6], 19
pop bp
ret
endp
_sum proc near
push bp
mov bp, sp
mov ax, word ptr [bp+4]
add ax, word ptr [bp+6]
pop bp
ret
endp
end
I compile it like this:
tcc -c -ms foo.c
tasm /ml foortn.asm
tcc foo.obj foortn.obj
The result is:
a+b=0, a=0, b=0
a+b=61, a=42, b=19
I'm obviously missing something, but what?
Hans, Mark and Bill, thank you very much for your prompt and helpful responses.
Solution
This:
mov word ptr [bp+4], 42
mov word ptr [bp+6], 19
is writing to the stack, not the addresses on the stack. You'll need to read the addresses on the stack, then write to them instead:
mov bx,[bp+4] ; get the address of (a)
mov [bx],42 ; Write to that address
mov bx,[bp+6] ; (b)
mov [bx],19 ; write
OTHER TIPS
Your current code is overwriting the passed pointer. You need to retrieve the pointer and write through it. Something like this:
mov ax, word ptr [bp+4]
mov word ptr [ax], 42
Write this code in C first and look at the assembly code that it generates to get this right.
Try replacing:
mov word ptr [bp+4], 42
mov word ptr [bp+6], 19
with
mov bx, word ptr [bp+4]
mov [bx], 42
mov bx, word ptr [bp+6]
mov [bx], 19
I don't know assembler ... but C
passes everything by value.
In sum
[bp+4] is 42 (or 19); in add
setval
[bp+4] is 0xDEADBEEF 0xDECAFBAD (or whatever)