内联汇编中慎用eax,ecx,edx

来源:互联网 发布:直筒和滚筒洗衣机 知乎 编辑:程序博客网 时间:2024/05/21 08:54

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <wtypes.h>


// 测试vc6默认对寄存器保存情况:

// ebp总是在函数开始push, ebx、esi、edi如果用到也会push, eax、ecx、edx则永远不push

int asm_add(int a, int b)
{
__asm
{
mov eax, a
add eax, b
mov esi, eax
mov edi, eax
mov ebx, eax
mov ecx, eax
mov edx, eax
}
}


int add(int a, int b)
{
    return a + b;
}


int main( void )
{
int result = 0;
//0. 调用内联汇编add
result = asm_add(100, 200);
printf("asm_add result=%d\n", result);


//1. 直接调用add
result = add(1, 2);
printf("C++ call result=%d\n", result);


//2. 汇编调用
__asm
{
push 3
push 4
call add
mov result, eax
add esp, 8
}
printf("ASM call result=%d\n", result);


//3. ShellCode 模式调用
// 注意:通过函数名得到的地址是 jmp Add 指令的地址,而不是add函数的实际地址
// jmp Add机器码格式为:jmp(占一字节) + 四字节偏移地址,共占5字节
// (DWORD*)(JmpAddr+1)为偏移值,由于JmpAddr为jmp Add 指令的地址
// 因此需要加上jmp Add自身的5个字节,得到函数Add的实际地址
    BYTE* JmpAddr = (BYTE*)add;
    DWORD offset = *((DWORD*)(JmpAddr + 1)) + 5;
    BYTE* pFuncAddr = (BYTE*)(((DWORD)JmpAddr) + offset);
// 将函数Add的数据拷贝到FuncByte
BYTE FuncByte[512] = {0};
    for(int i=0; i<512; i++)
    {
        if((FuncByte[i] = pFuncAddr[i] ) == 0xC3)
break;
    }

    __asm
{
        lea eax, FuncByte
push 5
push 6
mov edx, 1 ;设置标志 用ecx时,在 Release 下会崩溃
;Release 模式下,add 中用到ecx,其值被修改,
;且函数退出是没有还原
call __label
__label:
        cmp edx, 0
je __ret
xor edx, edx ;清楚标志
jmp eax ;调用Add函数
__ret:
        mov result, eax ;获取返回值
add esp, 8 ;平衡push 100,push 200
    }
printf("ShellCode call result=%d\n", result);


system("pause");
    return 0;
}

原创粉丝点击