[英]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.