从程序集(x86 / 64)调用read syscall会产生分段错误(编译器构造)

克里斯·赞

我正在为一种类似C的语言构建一个编译器,并且试图将一个在程序集中实现的基本“ void readString(int,char *)”函数与我的编译器生成的程序集链接起来。

编译后的类似C的文件是

void main () {
    char t[20];     
    readString(7,t); // Read 7 bytes and place them in t buffer
}

编译后,结果文件为:out.s文件(注意,调用约定为:通过堆栈传递参数。此语言中,整数的大小为2字节):

.$0:
.globl main
main:
pushq %rbp
movq %rsp,%rbp
subq $20,%rsp

.$1:
movw $7,%ax  # Push first argument in the stack
pushw %ax

.$2:
leaq -20(%rbp),%rax # Push address of the second arg in the stack
pushq %rax

.$3:
subq $8,%rsp   # this is not important, needed for the convention being followed
pushq 16(%rbp) # pushing "access link",
call _readString 
addq $26,%rsp # caller clears the "leftovers" 

.$4:
.$main_0_11:
movq %rbp,%rsp
popq %rbp
ret

reads.asm中的库函数代码:

.intel_syntax noprefix
            .global _readString

_readString     push    rbp
            mov     rbp, rsp
            push    rdi
            push    rsi

            mov     rdi, [rbp+32]           # First argument 
            mov     rsi, [rbp+34]           # Second Argument

            mov     rdx, rdi

doRead:
            mov     byte ptr [rsi], 0x00
            xor     rax, rax
            mov     rdi, rax
            syscall                         # read syscall, reads up to $rdx bytes
            or      rax, rax                # nothing read
            jz      finish                  #
            add     rsi, rax                #
            cmp     byte ptr [rsi-1], 0x0a  # check if last character read was '\n'
            jne     addZero                 #
            sub     rsi, 1                  # if so, replace with '\0'
addZero:
            mov     byte ptr [rsi], 0x00
finish:
            pop     rsi
            pop     rdi
            pop     rbp
            ret

链接/运行如下

$ gcc -c out.s
$ gcc -c reads.s 
$ gcc out.o reads.o 
$ ./a.out
[2] Segmentation fault  ./a.out

描绘通话约定的图片

调用约定

克里斯·赞

好的,正如@David Hoelzer所建议的那样,我再次检查了“ readString”从堆栈中获取参数的方式,并按顺序对它们进行了反转!

因此,reads.asm的第一行将变为

_readString:
            push    rbp
            mov     rbp, rsp
            push    rdi
            push    rsi

            movzx   edi, word ptr [rbp+40] # Get first argument, check comments for more info
            mov     rsi, [rbp+32]  # Second Argument


            mov     rdx, rdi

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

程序集x86 64 Linux AT&T:打印例程分段错误

x86程序集可以在x64处理器上工作吗?

x86 程序集:调用 malloc 不会将指向已分配内存的指针放在 EAX 寄存器中

为什么在从gcc编译的C“ Hello World”程序调用printf x86程序集之前修改%al寄存器和堆栈

x86_64程序集execve * char [] syscall

从C程序调用x86汇编函数时出现分段错误

如何清理格式错误的x86_64程序集?

x64 Appdomain中的x86程序集-x86 exe正常工作,x86 dll失败

尝试在 x64 RedHat 环境中编译 x86 C 程序 [第 2 部分]

如何确定.NET程序集是为x86还是x64构建的?

x64 C ++ / CLI程序集仍然引用x86 .NET库

平台目标(x86 / x64 / AnyCPU)是否对.net卫星程序集很重要

以下x86_64程序集为何给我一个分段错误?

x86_64程序集字符串操作导致分段错误

从C程序调用x86 Assembly函数时检索到错误的矩阵值

x86 处理器可以调用多少个子程序?

使用x86或x86_64程序集反转字符串的最简洁方法是什么?

为什么该程序会产生分段错误?

在32位x86 AT&T程序集上调用C函数的问题

此程序集x86代码的反编译(C)代码结构是什么?

基本的Linux x86程序集最小数目返回错误

将大型数组写入内存 x86 程序集 - 使用堆栈空间的段错误

包装器__m256的包装器,使用构造函数产生分段错误-Windows 64 + MinGW + AVX问题

在寄存器中存储未签名的字符(x86程序集)

访问程序集x86中的寄存器的值时访问写冲突

针对同一VS2012项目中的x86和x64程序集;参考

使用NASM为x86_64环境编译32位程序集

在x86上编译x64 DLL

x86-64程序集XMM1寄存器丢失其值