views:

152

answers:

4

Hello,

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.

A: 

I don't know assembler ... but C passes everything by value.

In sum [bp+4] is 42 (or 19); in addsetval [bp+4] is 0xDEADBEEF 0xDECAFBAD (or whatever)

pmg
Your answer doesn't make sense to me. Note that the OP is invoking `setval(` to pass by pointer, and `sum(a, b);` to pass by value.
ChrisW
Why is C in backticks?
Roger Pate
Yes, and then he's using [bp+4] the exact same way in (`word ptr [bp+4]`) the assembler. That's what I found strange, even not knowing assembler: I thought they would need to be different some way (and, no, I have no idea how different)
pmg
I was referring to _setval, not _sum
foregam
+1  A: 

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
BillP3rd
+4  A: 

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.

Hans Passant
Oh... I see. Indeed you're right, the pointer gets overwritten. Thank you very much, I had completely overlooked this. I'll look for a decent DOS debugger, debug.com left me speechless.
foregam
I'm pretty sure the free download for Turbo C includes a debugger. http://edn.embarcadero.com/article/20841
Hans Passant
A: 

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
Mark Tolonen