指令长度

python

python的指令定长,长度为16bit,其中8bit操作码,8bit操作数。

///@file: Python-3.6.0\Include\code.h
typedef uint16_t _Py_CODEUNIT; #ifdef WORDS_BIGENDIAN
# define _Py_OPCODE(word) ((word) >> 8)
# define _Py_OPARG(word) ((word) & 255)
#else
# define _Py_OPCODE(word) ((word) & 255)
# define _Py_OPARG(word) ((word) >> 8)
#endif ///@file: Python-3.6.0\Python\ceval.c
PyObject *
_PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
{
///...
#define NEXTOPARG() do { \
_Py_CODEUNIT word = *next_instr; \
opcode = _Py_OPCODE(word); \
oparg = _Py_OPARG(word); \
next_instr++; \
} while (0)
}

lua

lua一条指令的长度为一个int,也就是32bit,其中操作码为6bit,剩余的操作数有26bit。由于操作数中有一些用来编码寄存器的编号,所以单条指令比python的指令要长(32bit vs 16 bits)。

///@file: lua-5.3.4\src\lopcodes.h
/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
'A' : 8 bits
'B' : 9 bits
'C' : 9 bits
'Ax' : 26 bits ('A', 'B', and 'C' together)
'Bx' : 18 bits ('B' and 'C' together)
'sBx' : signed Bx A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
represented by 2*max), which is half the maximum for the corresponding
unsigned argument.
===========================================================================*/ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */

add为例

add是我们最为熟悉的基础操作,可能大家上学最开始学习的就是加法,设置不需要上学大家都需要使用加法。

python

python的加法默认就是取栈顶最顶端的两个元素,求和之后再次压入堆栈顶端。

        TARGET(BINARY_AND) {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *res = PyNumber_And(left, right);
Py_DECREF(left);
Py_DECREF(right);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}

lua

在lua的操作中,加法的a = b + c,三个操作数都是由指令中的寄存器指定,而不是跟栈顶位置强绑定。

      vmcase(OP_ADD) {
TValue *rb = RKB(i);
TValue *rc = RKC(i);
lua_Number nb; lua_Number nc;
if (ttisinteger(rb) && ttisinteger(rc)) {
lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
setivalue(ra, intop(+, ib, ic));
}
else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
setfltvalue(ra, luai_numadd(L, nb, nc));
}
else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
vmbreak;
}

指令生成

在lua的指令生成中,对于a = b * c + d * e的解析时,在第一个表达式b * c 完成之后,解析 d * e之前,已经为b * c的结果分配了寄存器。这也是lua的一个重要特点:它并没有语法树,虚拟机指令是在语法解析的同时实时生成的。作为对比,如果要使用基于堆栈的虚拟机,那么在对a计算加法的时候,必须要先完成bc和de两个子表达式的计算只有才能生成两个子表达式的加法。

/*
** Process 1st operand 'v' of binary operation 'op' before reading
** 2nd operand.
*/
void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
switch (op) {
case OPR_AND: {
luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */
break;
}
case OPR_OR: {
luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */
break;
}
case OPR_CONCAT: {
luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */
break;
}
case OPR_ADD: case OPR_SUB:
case OPR_MUL: case OPR_DIV: case OPR_IDIV:
case OPR_MOD: case OPR_POW:
case OPR_BAND: case OPR_BOR: case OPR_BXOR:
case OPR_SHL: case OPR_SHR: {
if (!tonumeral(v, NULL))
luaK_exp2RK(fs, v);
/* else keep numeral, which may be folded with 2nd operand */
break;
}
default: {
luaK_exp2RK(fs, v);
break;
}
}
}

lua寄存器编号溢出

寄存器编号最短是8bits,这8bits可表示的正整数最大值是256,如果表达式太复杂,是不是会造成寄存器编号无法编码到指令中呢?

生成测试代码

tsecer@harry: cat genloop.py
import sys
sys.setrecursionlimit(1500) def pexp(level):
if level > 0:
print('( a + ', end='')
pexp(level - 1)
print(')', end='')
print('a = 1')
pexp(1000)
tsecer@harry: python3 genloop.py > reg.overflow.lua

生成的lua代码大致这样

a = 1
( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ( a + ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

嵌套层数先溢出

执行之后发现还没有到寄存器分配就已经报错,而此时freereg只用到了99个。

tsecer@harry: src/luac -l reg.overflow.lua
src/luac: reg.overflow.lua:2: too many C levels (limit is 200) in main function near 'a'
tsecer@harry:
(gdb) bt
#0 errorlimit (fs=0x7fffffffbab0, limit=200, what=0x4268ae "C levels") at lparser.c:80
#1 0x00000000004101c5 in checklimit (fs=0x7fffffffbab0, v=201, l=200, what=0x4268ae "C levels") at lparser.c:93
#2 0x0000000000410cff in enterlevel (ls=0x7fffffffbaf0) at lparser.c:334
#3 0x0000000000412ab1 in subexpr (ls=0x7fffffffbaf0, v=0x7fffffff1320, limit=0) at lparser.c:1051
#4 0x0000000000412c15 in expr (ls=0x7fffffffbaf0, v=0x7fffffff1320) at lparser.c:1079
#5 0x00000000004124ac in primaryexp (ls=0x7fffffffbaf0, v=0x7fffffff1320) at lparser.c:877
#6 0x0000000000412541 in suffixedexp (ls=0x7fffffffbaf0, v=0x7fffffff1320) at lparser.c:898
#7 0x0000000000412871 in simpleexp (ls=0x7fffffffbaf0, v=0x7fffffff1320) at lparser.c:978
#8 0x0000000000412b25 in subexpr (ls=0x7fffffffbaf0, v=0x7fffffff1320, limit=10) at lparser.c:1059
#9 0x0000000000412b88 in subexpr (ls=0x7fffffffbaf0, v=0x7fffffff14d0, limit=0) at lparser.c:1069
(gdb) p fs->freereg
$6 = 99 'c'
(gdb)

对应的代码

static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
BinOpr op;
UnOpr uop;
enterlevel(ls);
///...
} static void enterlevel (LexState *ls) {
lua_State *L = ls->L;
++L->nCcalls;
checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels");
} /*
** maximum depth for nested C calls and syntactical nested non-terminals
** in a program. (Value must fit in an unsigned short int.)
*/
#if !defined(LUAI_MAXCCALLS)
#define LUAI_MAXCCALLS 200
#endif

修改LUAI_MAXCCALLS宏

如果把LUAI_MAXCCALLS这个值修改的足够大呢,例如1024?可以看到,lua依然有运行时检测会提前结束(而不是生成错误的字节码):

/* Maximum number of registers in a Lua function (must fit in 8 bits) */
#define MAXREGS 255
/*
** Check register-stack level, keeping track of its maximum size
** in field 'maxstacksize'
*/
void luaK_checkstack (FuncState *fs, int n) {
int newstack = fs->freereg + n;
if (newstack > fs->f->maxstacksize) {
if (newstack >= MAXREGS)
luaX_syntaxerror(fs->ls,
"function or expression needs too many registers");
fs->f->maxstacksize = cast_byte(newstack);
}
}

通过gdb看调用链入下图所示

Breakpoint 2, luaK_checkstack (fs=0x7fffffffbab0, n=1) at lcode.c:365
365 luaX_syntaxerror(fs->ls,
(gdb) p fs->freereg
$2 = 254 '\376'
(gdb) bt
#0 luaK_checkstack (fs=0x7fffffffbab0, n=1) at lcode.c:365
#1 0x0000000000420e55 in luaK_reserveregs (fs=0x7fffffffbab0, n=1) at lcode.c:376
#2 0x0000000000421a4f in luaK_exp2nextreg (fs=0x7fffffffbab0, e=0x7ffffffe0d90) at lcode.c:706
#3 0x0000000000421b08 in luaK_exp2anyreg (fs=0x7fffffffbab0, e=0x7ffffffe0d90) at lcode.c:725
#4 0x0000000000421cb2 in luaK_exp2RK (fs=0x7fffffffbab0, e=0x7ffffffe0d90) at lcode.c:775
#5 0x0000000000422800 in luaK_infix (fs=0x7fffffffbab0, op=OPR_ADD, v=0x7ffffffe0d90) at lcode.c:1106
#6 0x0000000000412bb9 in subexpr (ls=0x7fffffffbaf0, v=0x7ffffffe0d90, limit=0) at lparser.c:1067
#7 0x0000000000412c67 in expr (ls=0x7fffffffbaf0, v=0x7ffffffe0d90) at lparser.c:1079
#8 0x00000000004124fc in primaryexp (ls=0x7fffffffbaf0, v=0x7ffffffe0d90) at lparser.c:877
#9 0x0000000000412591 in suffixedexp (ls=0x7fffffffbaf0, v=0x7ffffffe0d90) at lparser.c:898
#10 0x00000000004128c3 in simpleexp (ls=0x7fffffffbaf0, v=0x7ffffffe0d90) at lparser.c:978
#11 0x0000000000412b77 in subexpr (ls=0x7fffffffbaf0, v=0x7ffffffe0d90, limit=10) at lparser.c:1059
#12 0x0000000000412bda in subexpr (ls=0x7fffffffbaf0, v=0x7ffffffe0f40, limit=0) at lparser.c:1069

作者的说明

在lua作者的说明文档中,有大量的篇幅(第7部分"The Virtual Machine")说明了lua在实现时在基于stack和register之间的考虑。在5.0之前,lua一直使用的是基于堆栈的虚拟机,在2003年发布的5.0版本之后,lua开始使用基于寄存器的虚拟机。

作者提到两个优点:

  • 避免push/pop操作

    使用寄存器避免了代价很高的push/pop操作,因为操作数必须在栈顶,所以在执行动作之前必须要先push到堆栈上,反之在动作完成之后从堆栈上pop掉。考虑到这些push和pop可能会涉及到数值拷贝,或者操作数引用计数的增加,这个代价比较高。
  • 实时生成代码

    Some authors also defend registerbased virtual machines based on their suitability for on-the-fly compilation。

指令指针(pc)递增的时机

在lua和python中都有一个有意思的现象,就是先取出指令内容,然后递增pc指针,然后再解码并执行指令(注意:不是在指令解码并执行之后才递增pc)。这样的好处个人理解是对于call这种指令,在解码执行前就递增的话,当执行call的时候,自动保存的返回地址就是下一条指令,这样实现call指令更简单一些。

这一点应该和硬件CPU的处理方法相同,这也意味着,当在gdb中设置数据断点时,命中之后pc指针指向的是触发该断点指令的下一条指令。

lua

lua的解码执行

/* fetch an instruction and prepare its execution */
#define vmfetch() { \
i = *(ci->u.l.savedpc++); /* main loop of interpreter */
for (;;) {
Instruction i;
StkId ra;
vmfetch();

python

lua的解码执行

#define NEXTOPARG()  do { \
_Py_CODEUNIT word = *next_instr; \
opcode = _Py_OPCODE(word); \
oparg = _Py_OPARG(word); \
next_instr++; \
} while (0) for (;;) {
NEXTOPARG();
dispatch_opcode:
#ifdef DYNAMIC_EXECUTION_PROFILE
#ifdef DXPAIRS
dxpairs[lastopcode][opcode]++;
lastopcode = opcode;
#endif
dxp[opcode]++;
#endif #ifdef LLTRACE
/* Instruction tracing */ if (lltrace) {
if (HAS_ARG(opcode)) {
printf("%d: %d, %d\n",
f->f_lasti, opcode, oparg);
}
else {
printf("%d: %d\n",
f->f_lasti, opcode);
}
}
#endif switch (opcode) { /* BEWARE!
It is essential that any operation that fails sets either
x to NULL, err to nonzero, or why to anything but WHY_NOT,
and that no operation that succeeds does this! */ TARGET(NOP)
FAST_DISPATCH();

文档资料

指令周期这个文档还可以看到提前递增pc的重要原因:现在的cpu都是流水线的,在取指令之后递增pc,这样在指令解码执行的时候,取地址的逻辑单元就可以继续取指令,从而形成流水线。

In simpler CPUs, the instruction cycle is executed sequentially, each instruction being processed before the next one is started. In most modern CPUs, the instruction cycles are instead executed concurrently, and often in parallel, through an instruction pipeline: the next instruction starts being processed before the previous instruction has finished, which is possible because the cycle is broken up into separate steps.[1]

栈和寄存器虚拟机比较(以python和lua为例)的更多相关文章

  1. Cortex-M3 在C中上报入栈的寄存器和各fault状态寄存器

    因为在标准C语音中是不能获取SP指针的.因而,如果想通过C代码来获取入栈的寄存器值,需要配合一小段汇编代码来获取当前的SP值,然后再把这个SP值以参数形式传送给C代码,最后以指针的形式把栈中的各寄存器 ...

  2. Python、Lua和Ruby之优劣

    Python.Lua和Ruby之优劣 Python Python的优点:1.Python比其它语言有更多扩展模块.2.在网上可以找到很多Python教程.不仅如此,还有大量的英文书籍和资料.Pytho ...

  3. Python、Lua和Ruby——脚本大P.K.

    转自Python.Lua和Ruby--脚本大P.K. Python versus Lua Versus Ruby Python.Lua和Ruby--脚本大P.K. Tom Gutschmidt 著 赖 ...

  4. UltraEdit配置python和lua环境

    [语法高亮] 在UltraEdit的wordfile中添加python和lua的语法支持(红色的为python,蓝色的为lua): /L10"Python" Line Commen ...

  5. Python和Lua的默认作用域以及闭包

    默认作用域 前段时间学了下Lua,发现Lua的默认作用域和Python是相反的.Lua定义变量时默认变量的作用域是全局(global,这样说不是很准确,Lua在执行x = 1这样的语句时会从当前环境开 ...

  6. Python、Lua和Ruby比较——脚本语言大P.K.

    译者按:Python.lua和ruby在C/C++是日渐式微的情况下,在java/.net的围歼中努力抗争的三个当红小生.在Tom Gutschmidt的著作<Game Programmng w ...

  7. Python中的单例设计

    01. 单例设计模式 设计模式 设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案 使用 设计模式 是为了可重用代码.让代码更容易被他人理解.保 ...

  8. Cobra —— 可视化Python虚拟机 and 图解python

    http://blog.csdn.net/balabalamerobert http://blog.csdn.net/efeics/article/category/1486515  图解python ...

  9. 用两个栈实现队列(C++ 和 Python 实现)

    (说明:本博客中的题目.题目详细说明及参考代码均摘自 “何海涛<剑指Offer:名企面试官精讲典型编程题>2012年”) 题目 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 a ...

  10. 【剑指Offer】09. 用两个栈实现队列 解题报告(python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人微信公众号:负雪明烛 目录 题目描述 解题方法 一个栈用来保存输入,一个栈用来输出 日 ...

随机推荐

  1. P7213 [JOISC2020] 最古の遺跡 3

    这个题刚好是一个月前我们学校联赛组的人考的题的 T4 .今天有幸看见原题. 我当时顺便看了他们的题.想了一个小时,才想出来了如下的麻烦做法. 然后教练让我来讲这个题,我讲得很累,大家也都没有改. 题意 ...

  2. Vulnhub:mhz_c1f靶机

    kali:192.168.111.111 靶机:192.168.111.197 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --script=http-enum 192.168. ...

  3. JAVA-GUI创作学校管理系统

    1.对于学校的管理系统,我们先做一个简单的一个需求分析,我们需要做学生信息管理,教师信息管理,课程的信息管理.我们要根据自己的需求进行数据库的编写. 简单的添加了几个 2.然后我们通过eclipse+ ...

  4. 记录下vue表单验证

    公共common文件夹下建立validate.js /* 是否邮编*/ export function validateMail(rule, value,callback) { const reg = ...

  5. Centos 升级glibc 亲测好用

    wget http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz  tar zxf glibc-2.18.tar.gz cd glibc-2.18/ mkdir ...

  6. Qt使用图片旋转绘制圆环,圆弧类UI界面(方法可适用于winform和WPF等其余UI绘制)

    先上效果图: 这个主要是一个试剂杯盘的循环图,相信大家伙一定都想到了使用GDI和三角函数来进行计算,但如果没有实际尝试,可能会踩一些坑,留此文帮助大家方便快捷的绘制出类似圆环的UI效果. 这里主要是使 ...

  7. 硬件IIC的7位从机地址查询方式读写参考代码

    目录 本文中使用582测试,在整合先前博客中的代码的基础上,加上读写超时,加上返回值,加上16位从机寄存器地址的判断,希望读写各用一个函数就能解决硬件IIC的使用问题. #include " ...

  8. 以EEPROM为例的硬件IIC的使用

    目录 参考调试MPU6050与EEPROM的经验,整合了目标内存/寄存器地址是否为16位的情况,合并了单字节与多字节间的操作,添加了返回值与读写超时功能:硬件IIC的7位从机地址查询方式读写参考代码 ...

  9. CSS3实现图片滚动

    body{ margin: 0; padding: 0px; } #banner{ margin:20px auto; width: 600px; position: relative; overfl ...

  10. Windows10 WSL开启SSH登录

    1.wsl 安装ssh服务(使用的是ubuntu)sudo apt install openssh-server 2.修改配置文件sudo vim /etc/ssh/sshd_config关键的几处修 ...