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

时间:2016-10-02 17:16:06

标签: assembly compiler-construction x86 system-calls static-linking

我正在为类似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

描述调用约定的图片

calling convention

1 个答案:

答案 0 :(得分:1)

好的,正如@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