简体   繁体   English

如何在x86程序集中调用fgets?

[英]How to call fgets in x86 assembly?

According to the documentation for fgets() , the function takes three parameters: 根据fgets()的文档 ,该函数有三个参数:

  • char * - a string that will hold the input char * - 一个保存输入的字符串
  • int - an integer that represents the maximum number of characters to read int - 一个整数,表示要读取的最大字符数
  • FILE * - a FILE * to the stream to read from FILE * - 要读取的流的FILE *

I have no trouble calling the function. 我可以轻松调用该函数。 I just push the three parameters onto the stack, call the function, and increase ESP by 12. 我只需push三个参数push堆栈,调用该函数,并将ESP增加12。

My problem is with parameter #3. 我的问题是参数#3。 What should be passed in as the FILE * for standard input? 作为标准输入的FILE *应该传递什么? In C, I can just use stdin , but I don't know what the equivalent is in x86 assembly. 在C中,我可以使用stdin ,但我不知道x86程序集中的等价物是什么。


Update: I'm using NASM on Linux. 更新:我在Linux上使用NASM。

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. stdin的问题在于它是一个宏,它不仅扩展到特定于平台的东西,而且很可能很难从手工装配中访问。 If you're willing to sacrifice stdio and use POSIX calls instead, stdin is the same as the well-known file descriptor #0. 如果您愿意牺牲stdio并使用POSIX调用,则stdin与众所周知的文件描述符#0相同。 You can therefore pass 0 to read and get almost what you were looking for. 因此,您可以传递0read并获得您所寻找的几乎所有内容。 I'm pretty sure this is more assembler-friendly than the stdin C macro. 我很确定这比stdin C宏更易于汇编。

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. 如果程序集是C / C ++代码的子例程,则大多数运行时环境提供了通过外部引用直接访问stdin变量的方法。 Check the stdio.h header file (or maybe whatever it includes). 检查stdio.h头文件(或者它包含的任何内容)。 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. 通常的嫌疑人似乎是名为__stdin变量或名为__stdio[]的FILE *数组,其中前3个元素是stdin,stdout和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. 如果C被用作其他语言(如汇编)的库,那么你必须自己调用C运行时init。 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 . 如果我不知道如何,我会编写一个“hello world”类型的C程序,并使用调试器逐步完成它,看看它是如何设置stdin

Another completely different approach would be to call fopen() to obtain a FILE * of a file to read. 另一种完全不同的方法是调用fopen()来获取要读取的文件的FILE *。

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. stdin是一个只存在于C中的概念。它的定义取决于你的C编译器和库,并且由于宏等,从汇编程序调用可能非常困难。

One thing you could try is treating it as if stdin was a global variable of register size. 您可以尝试的一件事就是将其视为stdin是寄存器大小的全局变量。 Load it into a register (using whatever name mangling conventions your C compiler uses), then push it onto the stack. 将其加载到寄存器中(使用C编译器使用的任何名称修改约定),然后将其推入堆栈。 If this doesn't work, you'll need to examine the C library source code to see how it does things. 如果这不起作用,您需要检查C库源代码以查看它是如何工作的。

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. 或者,您可以使用可能更适合汇编程序使用的较低级操作系统调用 - 但是,由于您未指定操作系统,因此很难更具体。

This is pure assembly making use of libc. 这是使用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. Libc不是为了支持这种事情。

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. 即使您可以弄清楚如何进行这种调用,stdin也指向一个相当复杂的,依赖于OS或开发系统的FILE数据结构,它由libc使用在运行main()之前调用的例程进行初始化。 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. 这就是为什么简单的C语言“Hello world”程序在任何平台上都可以生成相当大的可执行文件。

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. 如果你编写一个简单的C程序,从stdin读取一些信息,然后反汇编整个事情并准确理解它在做什么,你就会有一个良好的开端。 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. 但是要做到这一点并不会很快,你学到的东西肯定不会从Windows上的Visual Studio移植到Linux上的gcc。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM