繁体   English   中英

从汇编代码调用fgets

[英]call fgets from assembly code

我想知道如何从汇编代码中调用fgets。 我读了这些与这个问题完全相同的问题: 如何在x86程序集中调用fgets? 而这一个: 如何在汇编语言中使用c库函数fgets? 但是它们都不满足有两个原因:1。我真的想使用fgets,因为我希望我的代码可以在windows和linux上运行(我正在使用NASM)2。我查看了fgets的反汇编版本,遗憾的是,它没有提供必要的细节来重现它命名stdin如何在汇编中表示。 这是我使用gcc -S fgets.c获得的C和汇编代码。

fgets.c

#include <stdio.h>
int main()
{
    char name[15];
    fgets(name, 16, stdin);
    return 0;
}

fgets.s

    .file   "fgets.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    call    ___main
    movl    __imp___iob, %eax
    movl    %eax, 8(%esp)
    movl    $16, 4(%esp)
    leal    17(%esp), %eax
    movl    %eax, (%esp)
    call    _fgets
    movl    $0, %eax
    leave
    ret
    .def    _fgets; .scl    2;  .type   32; .endef

首先,我不擅长阅读AT&T语法,因此很容易理解上面的汇编源码。 所以任何人都可以帮我解决:(i)我的本地变量name在哪里? 在ESP + 17? (ii)如果__imp___iob代表stdin ,那么来自哪里以便我可以使用它?

谢谢

是的,名字在esp + 17。 你应该明智地初始化它。 cdecl调用约定中的参数从右到左传递,堆栈中最右边的最深。 __imp___iob从CRT导出,您将在stdio.h头文件中找到它。 搜索stdin。 __imp前缀是一种Microsoft约定,可以更快地从DLL导出。 实现这一点显然是编译器的工作。

(i)我的本地变量name在哪里? 在ESP + 17?

是的 - 当您进行调用时,实际上“名称”会衰减到指针 - 整个数组都在堆栈中。 第一个字节位于ESP + 17,其余字节跟随。 请注意,代码使用leal来获取数组第一个字节的地址以传递给fgets()

(ii)如果__imp___iob代表stdin,那么来自哪里以便我可以使用它?

您应该能够使用为您的机器定义的任何stdin 例如,在我的Mac上,它最终成为___stdinp 您可以追踪系统标头中的定义(从stdio.h开始)。 您可能需要一个.globl指令来使汇编程序不要抱怨,但它应该正确链接。 __imp___iob看起来是你的正确选择。

这是我在stdio.h找到的内容:

#if __DARWIN_UNIX03
#define stdin   __stdinp
#define stdout  __stdoutp
#define stderr  __stderrp
#else /* !__DARWIN_UNIX03 */
#define stdin   (&__sF[0])
#define stdout  (&__sF[1])
#define stderr  (&__sF[2])
#endif /* __DARWIN_UNIX03 */

我的汇编代码中需要额外的_ ,因为编译器无法解决它。

暂无
暂无

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

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