关于PHP中的opcode

简介

1、当Zend engine解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode),opcode是一个四元组,(opcode, op1, op2, result),它们分别代表操作码,第一操作数,第二操作数,结果

2、因为PHP是构建在Zend虚拟机(Zend VM)之上的,所以PHP的opcode就是Zend虚拟机中的指令

opcode结构

struct _zend_op {
        opcode_handler_t handler;
        znode_op op1;
        znode_op op2;
        znode_op result;
        ulong extended_value;
        uint lineno;
        zend_uchar opcode;
        zend_uchar op1_type;
        zend_uchar op2_type;
        zend_uchar result_type;
};

1、 opcode_handler_t  opcode的函数指针 参考地址 opcode handler

2、result

我们看一下两个输出函数 ,echo 和 print

void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
{
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

        opline->result_type = IS_TMP_VAR;
        opline->result.var = get_temporary_variable(CG(active_op_array));
        opline->opcode = ZEND_PRINT;
        SET_NODE(opline->op1, arg);
        SET_UNUSED(opline->op2);
        GET_NODE(result, opline->result);
}
/* }}} */

void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
{
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

        opline->opcode = ZEND_ECHO;
        SET_NODE(opline->op1, arg);
        SET_UNUSED(opline->op2);
}
/* }}} */

我们可以看到print有result的设置 op2均为使用,从这里我们也能看出print和echo的区别来,print有返回值,而echo没有,这里的没有和返回null是不同的, 如果尝试将echo的值赋值给某个变量或者传递给函数都会出现语法错误

3、op1,op2 记录参数

4、lineno 对应的行号

5、opcode 对应相应的操作

6、extended_value   和CPU的指令类似,有一个标示指令的opcode字段,以及这个opcode所操作的操作数,PHP不像汇编那么底层, 在脚本实际执行的时候可能还需要其他更多的信息,extended_value字段就保存了这类信息

关于result op1 op2的结构znode

typedef union _znode_op {
        zend_uint      constant;
        zend_uint      var;
        zend_uint      num;
        zend_ulong     hash;
        zend_uint      opline_num; /*  Needs to be signed */
        zend_op       *jmp_addr;
        zval          *zv;
        zend_literal  *literal;
        void          *ptr;        /* Used for passing pointers from the compile to execution phase, currently used for traits */
} znode_op;

typedef struct _znode { /* used only during compilation */
        int op_type;
        union {
                znode_op op;
                zval constant; /* replaced by literal/zv */
                zend_op_array *op_array;
                zend_ast *ast;
        } u;
        zend_uint EA;      /* extended attributes */
} znode;

 op_type

#define IS_CONST    (1<<0)
#define IS_TMP_VAR  (1<<1)
#define IS_VAR      (1<<2)
#define IS_UNUSED   (1<<3)    /* Unused variable */
#define IS_CV       (1<<4)    /* Compiled variable */

IS_CONST:表示常量,例如$a = 1; $b = "hello";这些代码生成OP后,1和"hello"都是以常量类型操作数存在。
IS_TMP_VAR:表示临时变量,临时变量一般在前面加~来表示,这是一些OP执行过程中需要用到的中间变量,例如初始化一个数组的时候,就需要一个临时变量来暂时存储数组zval,然后将数组赋值给变量。
IS_VAR: 一般意义上的变量,以$开发表示
IS_UNUSED : 暂时不介绍,从名字来看应该是标识为不使用
IS_CV:这种类型的操作数比较重要,此类型是在PHP后来的版本中(大概5.1)中才出现,CV的意思是compiled variable,即编译后的变量,变量都是保存在一个符号表中,这个符号表是一个哈希表,试想如果每次读写变量的时候都需要到哈希表中去检索,势必会对效率有一定的影响,因此在执行上下文环境中,会将一些编译期间生成的变量缓存起来,此过程以后再详细介绍。此类型操作数一般以!开头表示,比如变量$a=123;$b="hello"这段代码,$a和$b对应的操作数可能就是!0和!1, 0和1相当于一个索引号,通过索引号从缓存中取得相应的值。

u

此字段为一个联合体,根据op_type的不同,u取不同的值。比如op_type=IS_CONST的时候,u中的constant保存的就是操作数对 应的zval结构。例如$a=123时,123这个操作数中,u中的constant是一个IS_LONG类型的zval,其值lval为123

时间: 2024-12-29 16:43:14

关于PHP中的opcode的相关文章

置换python2.7.13的opcode遇到的一些坑

主要有两个坑 1.XXXSLICE相关的opcode #define SLICE #define SLICE_1 #define SLICE_2 #define SLICE_3 #define STORE_SLICE #define STORE_SLICE_1 #define STORE_SLICE_2 #define STORE_SLICE_3 #define DELETE_SLICE #define DELETE_SLICE_1 #define DELETE_SLICE_2 #define

PHP Opcode内核实现 - [ PHP内核学习 ]

catalogue 1. Opcode简介 2. PHP中的Opcode 3. opcode翻译执行(即时解释执行) 1. Opcode简介 opcode是计算机指令中的一部分,用于指定要执行的操作, 指令的格式和规范由处理器的指令规范指定. 除了指令本身以外通常还有指令所需要的操作数,可能有的指令不需要显式的操作数. 这些操作数可能是寄存器中的值,堆栈中的值,某块内存的值或者IO端口中的值等等 通常opcode还有另一种称谓: 字节码(byte codes). 例如Java虚拟机(JVM),.

86-中间代码opcode的执行

86-中间代码opcode的执行 假如我们现在使用的是CLI模式,直接在SAPI/cli/php_cli.c文件中找到main 函数, 默认情况下PHP的CLI模式的行为模式为PHP_MODE_STANDARD. 此行为模式中PHP内核会调用php_execute_script(&file_handle TSRMLS_CC);来执行PHP文件. 顺着这条执行的线路,可以看到一个PHP文件在经过词法分析,语法分析,编译后生成中间代码的过程: EG(active_op_array) = zend_c

Python的运行机制--操作码(opcode)解析

上一篇文章<Python的运行机制--pyc文件浅析>中已经对Python的运行单元PyCodeObject结构体作了初步的了解,但是要真正理解Python的运行机制, 还要通过分析Python的opcode才行.opcode的解释执行通过ceval.c中的以下函数: PyObject *PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) 来实现,所以这个函数是研究opcode的重点,对于opcode有什么不明白的地方都可以通过这个函数中相应

i春秋——“百度杯”CTF比赛 十月场——Vld(Vulcan Logic Dumper 、php opcode、sql 报错注入)

打开题目看到提示 "do you know Vulcan Logic Dumper?" ,再查看源码看到"<!-- index.php.txt ?>",访问后发现一堆看不懂的东西 这肯定就是所谓的Vulcan Logic Dumper了,先了解下相关概念 PHP内核-Zend引擎:http://www.php.cn/php-weizijiaocheng-355597.html PHP中的opcode:https://blog.csdn.net/weiyu

深入理解PHP opcode优化

1.概述 PHP(本文所述案例PHP版本均为7.1.3)作为一门动态脚本语言,其在zend虚拟机执行过程为:读入脚本程序字符串,经由词法分析器将其转换为单词符号,接着语法分析器从中发现语法结构后生成抽象语法树,再经静态编译器生成opcode,最后经解释器模拟机器指令来执行每一条opcode. 在上述整个环节中,生成的opcode可以应用编译优化技术如死代码删除.条件常量传播.函数内联等各种优化来精简opcode,达到提高代码的执行性能的目的. PHP扩展opcache,针对生成的opcode基于

OPCode 详解

OpCode 操作码(Operation Code, OPCode):描述机器语言指令中,指令要执行某种操作的机器码 OPCode在不同的场合中通常具有不同的含义,例如PHP虚拟机(Zend VM).java虚拟机(JVM)以及一些软件保护虚拟机中的最小操作单元都可以称之为OPCode. 常用字节 常用单字节OPCode概览A -- 40~4F opcode asm using 0x40 inc eax emit(0x40) 0x41 inc ecx emit(0x41) 0x42 inc ed

python下编译py成pyc和pyo

其实很简单,用python -m py_compile file.py python -m py_compile /root/src/{file1,file2}.py编译成pyc文件.也可以写份脚本来做这事:Code: import py_compile py_compile.compile('path') //path是包括.py文件名的路径 用python -O -m py_compile file.py 编译成pyo文件.1.其中的 -m 相当于脚本中的import,这里的-m py_co

问道python之基础篇【二】python入门

问道python之基础篇[二] Python入门 1.python的工作过程 python解释器把源代码转换为字节码的中间形式,然后再把它翻译成机器使用的机器语言并运行. 2.pyc文件 2.1.什么是pyc文件 执行python代码时,如果导入了其他的.py文件,那么在执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器编译之后产生的字节码. ps:代码经过编译可以产生字节码:字节码通过反编译也可以得到代码. Pyc文件一般由3个部分组成: 最开始4个字节是一个Maig