gpt4 book ai didi

c - 关于从 Assembly 调用 C 函数,反之亦然

转载 作者:太空宇宙 更新时间:2023-11-04 07:07:21 24 4
gpt4 key购买 nike

我尝试过从 C 调用 ASM,反之亦然。至少目前它运行完美,但我有疑问。这是我的代码:

test.S 紧随其后:

.text               

.global _start


.global _main
.type _main, @function


.global writeMe
.type writeMe, @function

_start:

#; Write hello world for 5 times.
#; Jump exit and call C function after that.
#; C function calls writeMe assembly function
#; Exit with syscall

xorl %ecx, %ecx #; ecx = 0
call _get_eip #; get eip without labels. Just for research.
pushl %eax #; push to stack
incl %ecx #; ++ecx
pushl %ecx #; push to stack

movl $len,%edx #; tell length of string
movl $msg,%ecx #; tell string position
movl $1,%ebx #; fd = stdout
movl $4,%eax #; syscall = write
int $0x80 #; perform call

popl %ecx #; pop counter

movl %ecx, %eax #; eax = ecx
cmpl $0x5, %eax #; compare 0x5 and eax
je _exit #; eax == 0x5, jump exit

_jmp:
popl %eax #; pop instruction pointer
jmpl %eax #; jmp

_exit:
call _main #; call C function
movl $0,%ebx #; EXIT_SUCCESS
movl $1,%eax #; syscall = exit
int $0x80 #; perform call
ret

_get_eip: #; function for getting eip
popl %eax #; pop eip
pushl %eax #; push again to return
ret #; return location

writeMe: #; function for writing, called from C
popl (__eip) #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len

movl $1, %ebx #; fd = stdout
movl $4, %eax #; syscall = write
int $0x80 #; perform call

pushl (__eip) #; push return location
ret #; return location

writeMe2: #; function for writing, called from C
popl %ecx #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len

movl $1, %ebx #; fd = stdout
movl $4, %eax #; syscall = write
int $0x80 #; perform call

subl $0x0C, %esp #; restore stack
ret

.data

__eip: .long

msg:
.ascii "Hello, world!\n\0"
len = . - msg

main.C 紧随其后:

extern void writeMe(const char *msg, int len);

int _strlen(const char *msg) {
int _len = 0;
while (*msg++ != 0x0)
_len++;
return _len;
}

void _main() {

const char * szmsg = "Hello, world!\n";
writeMe(szmsg, _strlen(szmsg));
}

我的输出与我预期的一样。

Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!

我的问题如下:

1)

.type writeMe, @function

这段代码是什么意思? “GCC”的信息?它有什么作用?我必须这样做吗?

2)

我必须写这个通知操作吗?如果函数在 C 文件中声明?

.type _main, @function

_main 在C 文件中声明,我必须写吗?

3)

popl (__eip)                #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
........
pushl (__eip) #; push return location

我在 writeMe 中使用过这段代码,它安全吗?换句话说,我可以弹出参数,还是 GCC 会自动弹出它?

popl %ecx               #; pop return location
popl %ecx #; pop first argument, msg
popl %edx #; pop second argument, len
....
subl $0x0C, %esp #; restore stack

我在第二个函数中使用了这段代码。我问你,哪一个是安全正确的?

4)从 C 调用汇编函数后是否需要恢复寄存器?(我听说我必须恢复 EDI,但其他人呢?)

感谢您的所有回复。

最佳答案

1) 设置函数的符号类型。不需要,除非在特殊情况下,例如共享库。

2) 不,编译器已经为 C 中定义的函数完成了。

3) 这两个都是错误的。您应该访问相对于 esp 的参数,或者在设置标准堆栈框架之后,相对于 ebp

4) 您应该阅读相应的 ABI 文档以获取有关调用约定的信息。通常,您可以使用 eaxecxedx,其余部分必须保留。

关于c - 关于从 Assembly 调用 C 函数,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31464610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com