【问题标题】:Write a fopen function in assembly在汇编中编写一个 fopen 函数
【发布时间】:2018-08-23 08:49:16
【问题描述】:

我正在尝试在 turbo c++ 3.0 中实现fopen,我需要将它写在 asm inline 中。

我写了一个代码,但是(没有意外......)它不起作用(编译失败)。

代码在这里:

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>

int my_fopen_w(char fname[])
{
    int fd;
    char status;
    status = 'w'; // I need to write to a file and delete previous content
    asm{
        mov bl, status
        xor bh,bh
        push bp
        mov bp, sp
        push bx
        push fname
        //Same as fopen now fopen(file path= fname, "w" = bx)
        call _fopen
        add sp,8

        // Returned value in AX register 
        mov fd, ax  // That line may be incorrect, my teacher demands an Integer returned value  

    }
    return fd;
}

我收到一个错误:turbo c 无法识别_fopen 呼叫。

感谢您的帮助。

海姆

【问题讨论】:

  • 您需要以某种方式将_fopen 声明为全局对象(即在您的汇编代码开头的.global _fopen
  • 你为什么要练习 MS DOS 的汇编程序编程?
  • @Haim 为什么你的学校教你成为 1990 年的程序员?你需要问他们为什么不教你一些实际上会给你工作的东西。
  • 现在已经不是问题了,我求助,我练习组装的原因并不重要。
  • 插入对 _fopen 的 c-call 并查看生成的 asm 代码。也许,还有另一个 _,你必须调用 __fopen?

标签: c file fopen inline-assembly turbo-c++


【解决方案1】:

这似乎是 Turbo C 3.0 中的一个错误。 TCC 3.0 默认将 C 库链接到 CODE 段,因此您可以使用 C 函数的地址加载AX(您不需要下划线),然后使用CALL AX

#include <stdio.h>

int main ( void )
{
    char fname[] = "noname.txt";
    char status[] = "wb";
    FILE * fd;
    asm{
        lea ax, status
        push ax
        lea ax, fname
        push ax

        lea ax, fopen
        call ax

        pop cx
        pop cx
        mov fd, ax
    }
    return 0;
}

请注意:fopen 需要两个指向两个字符串的指针。这两个指针在编译时都是未知的。所以你必须在运行时使用LEA 来获取它们,除非其他人(操作系统、C 启动代码等)已经为你获取了指针:

#include <stdio.h>

FILE*  my_fopen_w(char fname[])
{
    FILE * fd;
    char  status[]="wt";
    int my_fd;

    asm{
        lea ax, status
        push ax
        mov ax, fname               // fname was passed as a pointer ("Call by value")
        push ax

        lea ax, fopen
        call ax

        pop cx
        pop cx
        mov fd, ax
    }
    return fd;
}

int main(int argc, char *argv[])
{

  FILE * fd;

  fd = my_fopen_w(argv[1]);         // argv[1] is a pointer to a string
  fputs("Here I am.", fd);
  fclose(fd);

  return 0;

}

【讨论】:

  • 首先非常感谢您!!它真的通过编译。但它无法运行......我可以t open a new file, the program doesnt 显示失败,但文件没有创建!
  • @Haim - 如果 rkhb 的回答解决了您提出的问题,请考虑接受它(如果您也想支持它)。至于您的代码不起作用,那是因为您在某些地方使用了 LEA,您应该使用 MOV。一个可能有效的修订版在这里:capp-sysware.com/misc/stackoverflow/asmio.c
  • 谢谢谢谢谢谢!!!!!!!!!!!!!它的工作!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!谢谢!!!!!!你救了我的命!!!!
  • 所以问题是 Turbo C 不允许 call fopen 像 OP 的第二个示例那样显示“操作码和操作数的无效组合”的屏幕截图?这很奇怪;也许它不知道如何做 rel16 偏移,只知道绝对。顺便说一句,LEA 相对于mov ax, offset fopen 的优势为零。将lea 用于[disp16] 寻址模式只会浪费一个字节的代码大小。但是,您确实希望 lea 用于非静态数组:它们可能编译为 lea ax, [bp-8] 或其他任何内容,因为您创建了一个本地 char 数组(将字符串字节复制到堆栈),而不是 static const.
  • 只是一个旁注。这个错误似乎特定于 Turbo-C 的内部汇编程序。我同意@PeterCordes 的观点,它看起来不处理内联汇编中的相对调用。今天早上我碰巧解决了这个问题,并注意到如果您使用 TCC 3.0x -B 选项进行编译,它确实有效。 -B 将强制 TCC 输出一个汇编文件,然后在外部调用 TASM 将文件汇编成一个对象(绕过内部汇编程序)。使用-B,它似乎确实有效。
猜你喜欢
  • 2016-06-14
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-06
相关资源
最近更新 更多