【问题标题】:Interfacing Assembly language (x86) routines with C language将汇编语言 (x86) 例程与 C 语言接口
【发布时间】:2014-09-19 22:24:28
【问题描述】:

当我尝试从 C 程序调用汇编语言函数 (x86) 时,我遇到了一些问题。

我的汇编代码如下:

.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

然后,我从 C 中调用这个过程如下:

extern void putchar(char x);

int main(void)
{
    putchar('x');
    return 0;
}

要编译和链接,我使用以下命令行(按顺序)

tcc -c -ms pchar.c
tasm putchar.asm
tlink pchar putchar, pchar 

到目前为止,我们从 putchar.asm 中获得了 .obj,并通过链接这两个文件获得了 .exe 文件。

我还要提一下,我们(在课堂上)使用 turbo assembler 2.01 版 (tasm) 和 turbo link 2.0 版 (tlink) 和 Turbo C 版2.01 (tcc)

问题来了,当我运行 .exe 文件时,我得到了应有的输出“x”, 但它卡在那里,它没有结束。

如果有任何帮助,我将不胜感激,在此先感谢。

【问题讨论】:

  • 找不到任何明显的问题。使用调试器查看函数是否返回。另外,告诉你的学校,使用这些过时的东西会使学习变得更加困难,而且没有任何好处。

标签: c assembly x86 tasm


【解决方案1】:

我观察到的两种可能性是 AXDX 可能正在被调用例程使用。

我非常怀疑这是否会有所帮助,但请尝试在例行程序之前和之后推送和弹出它们。

通过调试确认或反驳这一点。在调用例程之前放置一个断点,然后跳过它(而不是进入它)查看编译器的代码是否要在调用 ASM 子例程之后使用 AXDX

哦,我同意亚历克西斯·威尔克的观点,请改名。

【讨论】:

  • 啊!好点子。 DX 可能需要保存。我很惊讶 AX 不会是返回寄存器。
  • @AlexisWilke 它被宣布为无效,谁能预测那些制造出比我们这些愚蠢的凡人更好的编译器的专家,你知道吗?
【解决方案2】:

我会说,ret 可能是错误的,您可能需要不同类型的退货。

如果我是正确的,可能还有一个从堆栈中删除参数的帕斯卡约定。应该是这样的:

ret 4

注意:由于您是 16 位,它可能是 ret 2 而不是 ret 4。这取决于all 指令之前使用的推送指令。

否则,可能通过将putchar 的声明更改为__cdecl

extern __cdecl void putchar(char x);

请注意,在调试器中,您会看到堆栈是否在返回时得到处理(即add sp, 4“丢失”输入参数——因为您是 16 位,它可能是 2 而不是 4。)

我仍然对您使用 bp+4 而不是 bp+8 感到惊讶。你是 16 位的,哇!

更多关于calling conventions


旁注:

您可能希望避免使用名为 putchar() 的函数,因为它是在标准库中定义的,尽管在您的情况下您肯定不会受到该问题的影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 2015-04-05
    • 1970-01-01
    • 2022-11-15
    相关资源
    最近更新 更多