当前位置:  开发笔记 > 后端 > 正文

在gCS中复制和调用x86 AT&T-Assembler中的函数

如何解决《在gCS中复制和调用x86AT&T-Assembler中的函数》经验,为你挑选了1个好方法。

我在AT&T汇编语法中为gcc编写了以下代码

.global main
.section .data

to_gen_inner: #x f, implicit n
        pushl %ebp
        movl %esp, %ebp
        movl $0xFF00FF00, %eax
        call printregs
        lret

.set to_gen_inner_len, . - to_gen_inner

.section .text

main:
        pushl %ebp
        movl %esp, %ebp

        #allocate memory
        pushl $to_gen_inner_len
        call malloc
        popl %ecx

        pushl $to_gen_inner_len
        pushl to_gen_inner
        pushl %eax
        call copy_bytes
        popl %eax
        popl %ecx
        popl %ecx

        lcall *(%eax)

        movl %ebp, %esp
        popl %ebp
        ret

printfregs:
        .ascii "eax: %8X\nebx: %8X\necx: %8X\nedx: %8X\n\0"

printregs:
        pushl %edx
        pushl %ecx
        pushl %ebx
        pushl %eax
        pushl $printfregs
        call printf
        popl %ecx
        popl %eax
        popl %ebx
        popl %ecx
        popl %edx
        lret

copy_bytes: #dest source length
        pushl %ebp
        movl %esp, %ebp

        subl $24, %esp

        movl 8(%ebp), %ecx # dest
        movl %eax, -4(%ebp)

        movl 12(%ebp), %ebx # source
        movl %eax, -8(%ebp)

        movl 16(%ebp), %eax # length
        movl %eax, -12(%ebp)

        addl %eax, %ecx # last dest-byte
        movl %ecx, -16(%ebp)

        addl %eax, %edx # last source-byte
        movl %ecx, -20(%ebp)

        movl -4(%ebp), %eax
        movl -8(%ebp), %ebx
        movl -16(%ebp), %ecx

        copy_bytes_2:
        movb (%ebx), %dl
        movb %dl, (%eax)
        incl %eax
        incl %ebx
        cmp %eax, %ecx
        jne copy_bytes_2

        movl %ebp, %esp
        popl %ebp
        ret

实际上,我想要做的是将函数代码复制to_gen_inner到我用malloc分配的内存中,然后跳转到它.此代码会产生分段错误.gdb sais:

Program received signal SIGSEGV, Segmentation fault.
main () at speicher3.S:32
32              lcall *(%eax)
Current language:  auto; currently asm
(gdb) disas $pc-5 $pc+5
Dump of assembler code from 0x80483eb to 0x80483f5:
0x080483eb :   add    %al,(%eax)
0x080483ed :   pop    %eax
0x080483ee :   pop    %ecx
0x080483ef :   pop    %ecx
0x080483f0 :   lcall  *(%eax)
0x080483f2 :   mov    %ebp,%esp
0x080483f4 :   pop    %ebp
End of assembler dump.
(gdb) disas $pc-6 $pc+5
Dump of assembler code from 0x80483ea to 0x80483f5:
0x080483ea :   add    %al,(%eax)
0x080483ec :   add    %bl,0x59(%eax)
0x080483ef :   pop    %ecx
0x080483f0 :   lcall  *(%eax)
0x080483f2 :   mov    %ebp,%esp
0x080483f4 :   pop    %ebp
End of assembler dump.
(gdb)

我其实不知道为什么.我已经在使用lcall和lret,我读到的是绝对调用,有call和ret,它也没有工作,同样的错误.

我不知道我做错了什么.有人可以帮帮我吗?



1> moonshadow..:

您有以下问题:

在设置堆栈以调用copy_bytes时,你想要pushl $ to_gen_inner而不是pushl to_gen_inner(后者将内存的内容推送到to_gen_inner指向)

当将值复制到copy_bytes内的本地堆栈帧时,您需要将刚刚读取参数的寄存器写入,而不是始终写入EAX

lcall*(%eax)期望从EAX指向的内存中读取一个地址,然后跳转到那里.此外,它预计读取48个字节,前16个是段.我用呼叫*%eax替换了你的lcall; 因此也用rets替换了这些lrets.

对printregs的调用被组装为一个相对调用,由于你正在执行的指令不再与目标组装时的相对偏移量相同,因此它会爆炸.我用它替换了它

movl $printregs, %ecx
call *%ecx

(这会影响%ecx)

最后,to_gen_inner在进入时设置堆栈帧,但在退出时无法销毁它

修复所有这些后,代码如下所示:

.global main
.section .data

to_gen_inner: #x f, implicit n
        pushl %ebp
        movl %esp, %ebp
        movl $0xFF00FF00, %eax
        movl $printregs, %ecx
        call *%ecx
        movl %ebp, %esp
        popl %ebp        
        ret

.set to_gen_inner_len, . - to_gen_inner

.section .text

main:
        pushl %ebp
        movl %esp, %ebp

        #allocate memory
        pushl $to_gen_inner_len
        call malloc
        popl %ecx

        pushl $to_gen_inner_len
        pushl $to_gen_inner
        pushl %eax
        call copy_bytes
        popl %eax
        popl %ecx
        popl %ecx

        call *%eax

        movl %ebp, %esp
        popl %ebp
        ret

printfregs:
        .ascii "eax: %8X\nebx: %8X\necx: %8X\nedx: %8X\n\0"

printregs:
        pushl %edx
        pushl %ecx
        pushl %ebx
        pushl %eax
        pushl $printfregs
        call printf
        popl %ecx
        popl %eax
        popl %ebx
        popl %ecx
        popl %edx
        ret

copy_bytes: #dest source length
        pushl %ebp
        movl %esp, %ebp

        subl $24, %esp

        movl 8(%ebp), %ecx # dest
        movl %ecx, -4(%ebp)

        movl 12(%ebp), %ebx # source
        movl %ebx, -8(%ebp)

        movl 16(%ebp), %eax # length
        movl %eax, -12(%ebp)

        addl %eax, %ecx # last dest-byte
        movl %ecx, -16(%ebp)

        addl %eax, %edx # last source-byte
        movl %ecx, -20(%ebp)

        movl -4(%ebp), %eax
        movl -8(%ebp), %ebx
        movl -16(%ebp), %ecx

        copy_bytes_2:
        movb (%ebx), %dl
        movb %dl, (%eax)
        incl %eax
        incl %ebx
        cmp %eax, %ecx
        jne copy_bytes_2

        movl %ebp, %esp
        popl %ebp
        ret

...为我建立和运行.希望有所帮助.

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有