我正在和nasm打交道,在没有问题地做了hello world之后,我想我应该试着做一些c集成。
我正在使用c打开一个文件,然后我想使用为打开的文件返回的指针来处理文本。然而,当我在rdi中使用指针调用fgetc时,我得到一个“没有这样的文件或目录”,后面跟着一个segfault。
我做错了什么?
int64_t asmFunc(FILE* a, char* b);
int main()
{
int num;
FILE *fptr;
size_t line_buf_size = 0;
char *ret = malloc(100);
fptr = fopen("./test.txt","r");
if(fptr == NULL)
{
printf("Error!");
exit(1);
}
printf("%ld", asmFunc(fptr, ret));
return 0;
}
global asmFunc
section .text
extern fgetc
asmFunc:
call fgetc ; segfault occurs here.
(...)
ret
发布于 2019-04-27 23:50:28
您需要学习并遵循Linux x86-64 ABI规范中记录的calling conventions,特别是它的§3.2.3参数传递部分。因此,指针值fptr
在%rdi
中,指针值ret
在%rsi
中,您可能应该为asmFunc
推送一个调用帧
另请阅读x86 calling conventions维基百科。
如果您能够在一些example.c
文件中编写与asmFunc
等效的C语言代码(甚至是简化的代码),我建议您使用gcc -O -fverbose-asm -Wall -S example.c
编译它,并查看发出的example.s
汇编文件以获取灵感。大多数情况下,这类函数的第一条机器指令不是call
(而是称为function prologue的指令,它更改堆栈指针%esp
并在call stack上分配一些调用帧)
例如,在我的Linux/Debian/x86-64操作系统上,安装了gcc-8。
void asmfunc(FILE* fil, char*s) {
fputc ('\t', fil);
fputs (s, fil);
fputc ('\n', fil);
fflush (fil);
}
被编译成:
.text
.globl asmfunc
.type asmfunc, @function
asmfunc:
.LFB11:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
pushq %rbx #
.cfi_def_cfa_offset 24
.cfi_offset 3, -24
subq $8, %rsp #,
.cfi_def_cfa_offset 32
movq %rdi, %rbx # fil, fil
movq %rsi, %rbp # s, s
# /tmp/example.c:4: fputc ('\t', fil);
movq %rdi, %rsi # fil,
movl $9, %edi #,
call fputc@PLT #
# /tmp/example.c:5: fputs (s, fil);
movq %rbx, %rsi # fil,
movq %rbp, %rdi # s,
call fputs@PLT #
# /tmp/example.c:6: fputc ('\n', fil);
movq %rbx, %rsi # fil,
movl $10, %edi #,
call fputc@PLT #
# /tmp/example.c:7: fflush (fil);
movq %rbx, %rdi # fil,
call fflush@PLT #
# /tmp/example.c:8: }
addq $8, %rsp #,
.cfi_def_cfa_offset 24
popq %rbx #
.cfi_def_cfa_offset 16
popq %rbp #
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE11:
.size asmfunc, .-asmfunc
.ident "GCC: (Debian 8.3.0-6) 8.3.0"
但是请注意,在某些情况下,GCC有能力(例如使用-O2
)进行tail-call优化,并且可能会专门调用一些leaf-functions。
https://stackoverflow.com/questions/55882234
复制相似问题