在DOS系统上,如何使用汇编例程与C语言配合使用?

3

我已经玩了一段时间的DOS实模式汇编,现在我想在C程序中利用一些例程。我正在使用Turbo C 2.01和TASM 3.0。然而,我无法修改通过地址传递的变量,请参见下面的_setval例程。我不需要/想要内联汇编。一个简单的例子:

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

我这样编译它:
tcc -c -ms foo.c
tasm /ml foortn.asm
tcc foo.obj foortn.obj

结果是:
a+b=0, a=0, b=0
a+b=61, a=42, b=19

我显然缺少了什么,但是是什么呢?

Hans、Mark和Bill,非常感谢你们迅速而有用的回复。

4个回答

4

您当前的代码正在覆盖传递的指针。您需要检索指针并通过它进行写入操作。就像这样:

mov ax, word ptr [bp+4]
mov word ptr [ax], 42

首先在C语言中编写这段代码,然后查看生成的汇编代码以使其正确。


哦...我明白了。确实,你是对的,指针被覆盖了。非常感谢你,我完全忽略了这一点。我会寻找一个不错的DOS调试器,debug.com让我无语。 - foregam
我非常确定Turbo C的免费下载包含调试器。http://edn.embarcadero.com/article/20841 - Hans Passant

1

尝试替换:

mov word ptr [bp+4], 42
mov word ptr [bp+6], 19

使用

mov bx, word ptr [bp+4]
mov [bx], 42
mov bx, word ptr [bp+6]
mov [bx], 19

0

这个:

mov word ptr [bp+4], 42
mov word ptr [bp+6], 19

正在向堆栈写入,而不是堆栈上的地址。您需要读取堆栈上的地址,然后才能对它们进行写入:

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

-1

我不懂汇编语言...但是C所有内容通过值传递。

sum中,[bp+4]等于42(或19);在addsetval中,[bp+4]等于0xDEADBEEF 0xDECAFBAD(或其他任何值)


你的回答对我来说没有意义。请注意,OP正在调用setval(&a,&b);以通过指针传递,而sum(a,b);则是通过值传递。 - ChrisW
是的,然后他在汇编语言中也完全以相同的方式使用[bp+4](word ptr [bp+4])。这就是我觉得奇怪的地方,即使不懂汇编语言:我认为它们需要以某种方式不同(不,我不知道有多么不同)。 - pmg
我指的是_setval,而不是_sum。 - foregam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接