根据文档fgets()
,该函数采用三个参数:
- char * - 将保存输入的字符串
- int - 一个整数,表示要读取的最大字符数
- FILE * -
FILE *
要读取的流
我可以毫无问题地调用该函数。我只是push
将三个参数入栈,调用函数,并加ESP
12。
我的问题是参数#3。什么应该作为FILE *
标准输入传入?在 C 中,我可以使用stdin
,但我不知道 x86 程序集中的等价物是什么。
更新:我在 Linux 上使用 NASM。
问题stdin
在于它是一个宏,它不仅扩展到特定于平台的东西,而且很可能难以从手工组装中访问。如果您愿意牺牲stdio
并改用 POSIX 调用,stdin
则与众所周知的文件描述符 #0 相同。0
因此,您可以传递read
并获得几乎您正在寻找的东西。我很确定这比stdin
C 宏更适合汇编程序。
如果程序集是 C/C++ 代码的子例程,大多数运行时环境都提供了一种通过外部引用直接访问标准输入变量的方法。检查 stdio.h 头文件(或者可能包含的任何内容)。通常的嫌疑人似乎是命名的变量__stdin
或命名为 FILE * 的数组,例如__stdio[]
前 3 个元素是 stdin、stdout 和 stderr。
如果 C 被用作其他语言(如汇编)的库,那么您必须自己调用 C 运行时 init。这可能很难识别。如果我不知道怎么做,我会写一个“hello world”类型的 C 程序,并用调试器单步执行它,看看它是如何设置的stdin
。
另一种完全不同的方法是调用fopen()
以获取要读取的文件的 FILE *。
stdin
是一个只存在于 C 中的概念。它的定义取决于你的 C 编译器和库,并且由于宏等原因,可能很难从汇编器中调用。
您可以尝试的一件事是将其视为stdin
寄存器大小的全局变量。将其加载到寄存器中(使用 C 编译器使用的任何名称修改约定),然后将其压入堆栈。如果这不起作用,您将需要检查 C 库源代码以了解它是如何工作的。
或者,您可以使用更适合汇编程序使用的较低级别的操作系统调用 - 但是,由于您没有指定您的操作系统,因此很难更具体。
这是使用 libc 的纯汇编。——乔治·爱迪生
那么答案将完全取决于开发系统和操作系统。Libc 的目的不是支持这种东西。
即使您知道如何进行这种调用,stdin 也指向一个相当复杂的、依赖于操作系统或开发系统的 FILE 数据结构,该结构由 libc 使用在 main() 运行之前调用的例程进行初始化。所以在纯汇编中,你也必须做所有这些。这就是为什么一个简单的 C 语言“Hello world”程序可以在任何平台上生成相当大的可执行文件的原因。
如果您编写一个简单的 C 程序,从标准输入读取一些信息,然后反汇编整个程序并准确了解它在做什么,那么您将有一个良好的开端。但是这样做不会很快,而且你学到的东西肯定不能从 Windows 上的 Visual Studio 移植到 Linux 上的 gcc。