3

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.

starblue
  • 55,348
  • 14
  • 97
  • 151
foregam
  • 33
  • 3

4 Answers4

4

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
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 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 Oct 03 '10 at 16:13
  • I'm pretty sure the free download for Turbo C includes a debugger. http://edn.embarcadero.com/article/20841 – Hans Passant Oct 03 '10 at 16:56
1

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
  • 1,009
  • 1
  • 9
  • 21
0

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
  • 166,664
  • 26
  • 169
  • 251
-1

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
  • 106,608
  • 13
  • 126
  • 198
  • Your answer doesn't make sense to me. Note that the OP is invoking `setval(&a, &b);` to pass by pointer, and `sum(a, b);` to pass by value. – ChrisW Oct 03 '10 at 15:38
  • 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 Oct 03 '10 at 15:41
  • I was referring to _setval, not _sum – foregam Oct 03 '10 at 15:42