首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在x86 AT&T汇编器中复制和调用函数

在x86 AT&T汇编器中复制和调用函数
EN

Stack Overflow用户
提问于 2009-03-12 18:16:03
回答 1查看 4.4K关注 0票数 1

我用AT&T汇编语法为gcc写了下面的代码

代码语言:javascript
复制
.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:

代码语言:javascript
复制
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 <main+23>:   add    %al,(%eax)
0x080483ed <main+25>:   pop    %eax
0x080483ee <main+26>:   pop    %ecx
0x080483ef <main+27>:   pop    %ecx
0x080483f0 <main+28>:   lcall  *(%eax)
0x080483f2 <main+30>:   mov    %ebp,%esp
0x080483f4 <main+32>:   pop    %ebp
End of assembler dump.
(gdb) disas $pc-6 $pc+5
Dump of assembler code from 0x80483ea to 0x80483f5:
0x080483ea <main+22>:   add    %al,(%eax)
0x080483ec <main+24>:   add    %bl,0x59(%eax)
0x080483ef <main+27>:   pop    %ecx
0x080483f0 <main+28>:   lcall  *(%eax)
0x080483f2 <main+30>:   mov    %ebp,%esp
0x080483f4 <main+32>:   pop    %ebp
End of assembler dump.
(gdb)

其实我也不知道为什么。我已经在使用lcall和lret了,我读到的是绝对调用,而call和ret也不起作用,同样的错误。

我不知道我会做错什么。有谁能帮帮我吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-03-12 21:39:17

您有以下问题:

  • 当为调用copy_bytes设置堆栈时,你想要的是pushl $to_gen_inner而不是pushl to_gen_inner (后者将to_gen_inner指向的内存的内容推入)
  • 当将值复制到copy_bytes内部的本地堆栈框架时,你需要写入刚刚读取参数的寄存器,而不是总是写入EAX
  • lcall *(% EAX )期望从EAX指向的内存中读取地址,然后跳转到那里。此外,它预计读取48个字节,其中前16个字节是段。我已经用call *%eax;替换了你的lcall,还用rets替换了lrets。对printregs的accordingly.
  • the调用被汇编成了一个相对调用,由于你正在执行的指令不再像它被汇编时那样相对于目标的相对偏移量,这个调用就失败了。我已经将其替换为

移动$printregs,%ecx调用*%ecx

(这会使%ecx成为垃圾)

  • 最后,to_gen_inner在进入时设置了堆栈,但在退出

时未能将其销毁

修复所有这些问题后,代码看起来如下所示:

代码语言:javascript
复制
.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

...which在这里为我构建和运行。希望这能有所帮助。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/639848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档