栈帧模拟(协程前奏)

2020-02-21  本文已影响0人  滩主

EIP Instruction Pointer Register

指令语义

push %eax
# 等价于
subl $4, %esp
movl %eax (%esp)

pop %eax
# 等价于
movl (%esp), %eax
addl $4, %esp

call %eax
# 等价于
push %eip
jmp %eax

ret
# 等价于
pop %eip

leave
# 等价于
movl %ebp %esp
popl %ebp

轻松跳转

// hay.s
.global hay
hay:
    nop

// main.c
#include <stdio.h>

int main()
{
    asm(
        "jmp hay"
    );
    return 0;
}

天秀跳回

# myjmp.s
.global setjmp
.global longjmp

setjmp:
    mov 4(%esp), %eax
    mov    %ebx, (%eax)
    mov    %esi, 4(%eax)
    mov    %edi, 8(%eax)
    mov    %ebp, 12(%eax)
    lea 4(%esp), %ecx
    mov    %ecx, 16(%eax)
    mov  (%esp), %ecx
    mov    %ecx, 20(%eax)
    xor    %eax, %eax
    ret

longjmp:
    mov  4(%esp),%edx
    mov  8(%esp),%eax
    test    %eax,%eax
    jnz 1f
    inc     %eax
1:
    mov   (%edx),%ebx
    mov  4(%edx),%esi
    mov  8(%edx),%edi
    mov 12(%edx),%ebp
    mov 16(%edx),%ecx
    mov     %ecx,%esp
    mov 20(%edx),%ecx
    jmp *%ecx

// main.c
#include <stdio.h>

typedef struct jmp_buf
{
    int ebx;
    int esi;
    int edi;
    int ebp;
    int esp;
    int next;
} jmp_buf_t ;

int setjmp(jmp_buf_t*);
void longjmp(jmp_buf_t*,int);

int main()
{

    jmp_buf_t env;
    int i = setjmp(&env);
    printf("i = %d\n", i);

    if (i != 0) return 0;

    longjmp(&env, 2);

    return 0;
}
# kwtch.s
.global myswtch
.global exit_resume
myswtch:
  movl 4(%esp), %eax
  movl 8(%esp), %edx

  # Save old callee-save registers
  pushl %ebp
  pushl %ebx
  pushl %esi
  pushl %edi

  # Switch stacks
  movl %esp, (%eax)
  movl %edx, %esp

  # Load new callee-save registers
  popl %edi
  popl %esi
  popl %ebx
  popl %ebp
  ret

exit_resume:
  movl (%ebp),%esp

  popl %edi
  popl %esi
  popl %ebx
  popl %ebp
  ret
#include <stdio.h>
#include <stdlib.h>

struct context {
  int  edi;
  int  esi;
  int    ebx;
  int    ebp;
  int    eip;
};

struct resume {
    int ret;
};

void myswtch(struct context **old, struct context *new);
void exit_resume();

void hello();

int main()
{

    struct context* ctx;
    char tmp[102400];
    struct context* dest = &tmp[sizeof(tmp)-sizeof(struct context)-sizeof(struct resume)];
    dest->ebp = &ctx;
    dest->eip = &hello;
    struct resume* destResume = &tmp[sizeof(tmp)-sizeof(struct resume)];
    destResume->ret = &exit_resume;
    printf("debug\n");
    myswtch(&ctx,dest);
    printf("debug1\n");

    return 0;
}

void hello()
{
    printf("hello\n");
}
上一篇下一篇

猜你喜欢

热点阅读