2009-03-12 2 views
1

에서 86 AT & T-어셈블러에서 호출하는 기능 나는 내가로 to_gen_inner의 기능 코드를 복사하는 수행 할 작업,복사 및 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 

사실 gcc를 위해 AT & T 어셈블러 구문에 다음 코드를 썼다 메모리 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 <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을 사용하고 있는데, 이것은 절대 호출, 호출, ret와 함께 생각된다.

내가 잘못하고있는 것을 모른다. 아무도 도와주지 못하니?

답변

6

다음과 같은 문제가 발생 :

  • copy_bytes로 호출 스택을 설정, 당신은 pushl $의 to_gen_inner이 to_gen_inner을 pushl하지 원하는을

  • (후자는 메모리 to_gen_inner 포인트의 내용을 밀어) copy_bytes 내부 로컬 StackFrame을에 값을 복사 할 때, 당신은 쓸 필요가
  • 항상 EAX에게

  • LCALL의 * (% eax에) expe의를 작성하는 대신, 당신은 단지에 매개 변수를 읽어 등록 cts는 EAX가 가리키는 메모리에서 주소를 읽고 그곳으로 점프합니다. 또한 48 바이트를 읽을 것으로 예상되며 처음 16 개는 세그먼트입니다. 나는 당신의 전화를 통화 * % eax로 바꿨다. 또한 lrets를 rets로 바 꾸었습니다.

  • printregs에 대한 호출은 상대 호출로 어셈블됩니다.이 호출은 실행중인 명령어가 더 이상 타겟 어셈블리어와 상대 오프셋이 같지 않으므로 폭발적입니다. 나는 to_gen_inner이 항목에 StackFrame을을 설정하지만 출구에 그것을 파괴하지 (어느 것이 %의 ECX를 삭제 한 사용자 수) 마지막으로

    • movl $printregs, %ecx 
      call *%ecx 
      

    로 대체했습니다

수정 된 코드는 모두 다음과 같습니다.

.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 

... 나를 위해 제작되고 실행됩니다. 희망이 도움이됩니다.

+0

흠. 이상한. 당신의 코드는 * % eax (그냥 내가했던 것)를 호출해도 작동한다. 내 코드가 실패한 주된 이유가 이런 것 같아. 어쨌든. 고맙습니다. – schoppenhauer

+0

Ah - 그것은 통화처럼 보입니다 * % eax vs call * (% eax) - 전자는 % eax의 주소로 분기하고, 후자는 % eax가 가리키는 메모리에 포함 된 주소를 호출합니다. 답변을 수정할 것입니다. – moonshadow