代码之家  ›  专栏  ›  技术社区  ›  schoppenhauer

在gcc中复制和调用x86 AT&T汇编程序中的函数

  •  1
  • schoppenhauer  · 技术社区  · 16 年前

    .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

    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时,它也不起作用,同样的错误。

    我不知道我可能做错了什么。有人能帮帮我吗?

    1 回复  |  直到 16 年前
        1
  •  6
  •   moonshadow    16 年前

    您有以下问题:

    • lcall*(%eax)期望从eax指向的内存中读取一个地址,并跳转到那里。此外,它预计读取48个字节,其中前16个是段。我已经用call*%eax替换了你的lcall;也相应地用rets替换了lret。

    • 对printregs的调用被组装为一个相对调用,由于您正在执行的指令与组装时的目标相对偏移量不再相同,因此会出现问题。我把它换成了

      movl $printregs, %ecx
      call *%ecx
      

    • 最后,to_gen_inner在进入时设置了stackframe,但在退出时未能将其销毁

    .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
    

    …它在这里为我建造和运行。希望这能有所帮助。