如何在 x86 汇编中调用 fgets?

发布于 2024-09-18 11:36:58 字数 550 浏览 1 评论 0原文

根据 fgets() 的文档 ,该函数采用三个参数:

  • char * - 将保存输入的字符串
  • int - 表示要读取的最大字符数的整数
  • FILE *< /strong> - 要读取的流的 FILE *

我调用该函数没有任何问题。我只是将三个参数推入堆栈,调用该函数,并将ESP增加12。

我的问题是参数#3。标准输入的 FILE * 应该传入什么?在 C 中,我可以只使用 stdin,但我不知道 x86 汇编中的等效项是什么。


更新:我在 Linux 上使用 NASM。

According to the documentation for fgets(), the function takes three parameters:

  • char * - a string that will hold the input
  • int - an integer that represents the maximum number of characters to read
  • FILE * - a FILE * to the stream to read from

I have no trouble calling the function. I just push the three parameters onto the stack, call the function, and increase ESP by 12.

My problem is with parameter #3. What should be passed in as the FILE * for standard input? In C, I can just use stdin, but I don't know what the equivalent is in x86 assembly.


Update: I'm using NASM on Linux.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏夜暖风 2024-09-25 11:36:59

stdin 的问题在于它是一个宏,不仅扩展为特定于平台的内容,而且很可能难以从汇编中手动访问。如果您愿意牺牲 stdio 并使用 POSIX 调用,则 stdin 与众所周知的文件描述符 #0 相同。因此,您可以将 0 传递给 read< /a> 并得到几乎你正在寻找的东西。我非常确定这比 stdin C 宏更适合汇编程序。

The problem with stdin is that it's a macro that expands to something not only platform-specific, but most likely difficult to access from assembly by hand. If you're willing to sacrifice stdio and use POSIX calls instead, stdin is the same as the well-known file descriptor #0. You can therefore pass 0 to read and get almost what you were looking for. I'm pretty sure this is more assembler-friendly than the stdin C macro.

独自←快乐 2024-09-25 11:36:59

如果程序集是 C/C++ 代码的子例程,则大多数运行时环境都提供通过外部引用直接访问 stdin 变量的方法。检查 stdio.h 头文件(或者它包含的任何内容)。通常的嫌疑人似乎是名为 __stdin 的变量或名为 __stdio[] 的 FILE * 数组,其中前 3 个元素是 stdin、stdout 和 stderr。

如果 C 被用作其他语言(如汇编)的库,那么您必须自己调用 C 运行时 init。这可能很难识别。如果我不知道怎么做,我会编写一个“hello world”类型的 C 程序,并使用调试器单步调试它,看看它如何设置 stdin

另一种完全不同的方法是调用 fopen() 来获取要读取的文件的 FILE *。

If the assembly is a subroutine to C/C++ code, most runtime environments provide a means of directly accessing the stdin variable through an external reference. Check the stdio.h header file (or maybe whatever it includes). The usual suspects seem to be variables named __stdin or an array of FILE * named something like __stdio[] where the first 3 elements are stdin, stdout, and stderr.

If C is being used as a library for some other language (like assembly), then you'll have to call the C runtime init yourself. That can be tricky to identify. If I had no idea how, I'd write a "hello world" type C program and step through it with a debugger to see how it sets up stdin.

Another completely different approach would be to call fopen() to obtain a FILE * of a file to read.

木有鱼丸 2024-09-25 11:36:59

stdin 是一个仅存在于 C 中的概念。它的定义取决于您的 C 编译器和库,并且由于宏等原因,从汇编程序调用可能非常困难。

您可以尝试的一件事是将其视为 stdin 是寄存器大小的全局变量。将其加载到寄存器中(使用 C 编译器使用的任何名称修改约定),然后将其推入堆栈。如果这不起作用,您需要检查 C 库源代码以了解它是如何工作的。

或者,您可以使用可能更适合汇编程序使用的较低级别操作系统调用 - 但是,由于您没有指定您的操作系统,因此很难更具体。

stdin is a concept which only exists in C. Its definition depends on your C compiler and library, and due to macros and the like, it may be very difficult to invoke from assembler.

One thing you could try is treating it as if stdin was a global variable of register size. Load it into a register (using whatever name mangling conventions your C compiler uses), then push it onto the stack. If this doesn't work, you'll need to examine the C library source code to see how it does things.

Alternately, you could use lower-level operating system calls that may be more amenable to assembler usage - however, since you didn't specify your OS, it's hard to be more specific.

他夏了夏天 2024-09-25 11:36:59

这是使用 libc 的纯汇编。 ——乔治·爱迪生

那么答案将完全取决于开发系统和操作系统。 Libc 的目的并不是支持这种东西。

即使您能够弄清楚如何进行此类调用,stdin 也会指向一个相当复杂的、操作系统或开发系统相关的 FILE 数据结构,该数据结构由 libc 使用在 main() 运行之前调用的例程进行初始化。因此,在纯组装中,您也必须执行所有这些操作。这就是为什么一个简单的 C 语言“Hello world”程序可以在任何平台上生成相当大的可执行文件的原因。

如果您编写一个简单的 C 程序,从 stdin 读取一些信息,然后反汇编整个程序并准确理解它在做什么,那么您将有一个良好的开端。但这不会很快完成,而且您所学到的知识肯定无法从 Windows 上的 Visual Studio 移植到 Linux 上的 gcc。

This is pure assembly making use of libc. – George Edison

Then the answer will depend entirely on the development system and operating system. Libc is not aimed at supporting this kind of thing.

Even if you could figure out how to do this kind of call, the stdin points to a fairly complex, OS- or development system-dependent FILE data structure which is initialized by libc using routines that are called before main() is run. So in pure assembly, you'd have to do all that, too. This kind of thing is why a simple C-language "Hello world" program makes a fairly good-sized executable on any platform.

If you write a simple C program that reads some info from stdin, and then disassemble the whole thing and understand exactly what it's doing, you'll have a good start on this. But it won't be quick to do this, and what you learn certainly won't be portable from, say, Visual Studio on Windows to gcc on Linux.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文