我在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,它也没有工作,同样的错误.
我不知道我做错了什么.有人可以帮帮我吗?
您有以下问题:
在设置堆栈以调用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
...为我建立和运行.希望有所帮助.