@zhongdao
2017-12-22T11:09:02.000000Z
字数 32201
阅读 4005
未分类
拟定目录大纲:
Part1: 比特币与区块链
1. 比特币技术原理
2. 比特币协议
3. 硬分叉
4. 侧链设计原理
5. 侧链开发
6. 智能合约设计原理
7. 智能合约开发
8. 区块链生态介绍
9. 区块链应用
Part2: 区块链设计与实现笔记
1. 区块链原理机制与背景
2. 区块链基本结构
3. 加解密算法实现
4. 区块数据结构从定义到初步实现
5. 区块节点读取验证与挖矿
6. 节点和应用程序之间协议
7. 节点之间沟通
Part3: 区块链相关基础知识
1. 计算机基础知识
1. Linux相关说明
3. 密码学相关说明
4. 程序开发语言相关说明
5. 虚拟机语言
第三期课程:
区块链设计与实现笔记v1: https://www.zybuluo.com/zhongdao/note/933849
Part1: 比特币与区块链v2
Part2: 区块链设计与实现笔记v2 https://www.zybuluo.com/zhongdao/note/992471
Part3: 区块链相关基础知识v2
若有更正请联系: 李君
邮件: junlicn@foxmail.com
2017.12.20
实际自动导航目录:
区块链技术开发公开课:
授课老师: 辕询, 李涛涛
直播地址: http://itgege.gensee.com/webcast/site/entry/join-b0836bdd98c24eb78c67d3a0993b1589
根据老师公开课上讲的内容, 构造一个完整笔记,便于学习和掌握. 随着课程的进展, 不断添加和整理.
此文档的完整内容来自:公开的课程内容、源代码,资料、搜索引擎搜到的资料、相关技术书籍上的资料等, 我对内容做了整理,使得易于阅读和条理化,对于部分代码添加了注释和自己的理解, 若有错误请沟通纠正。
其中引用到一些同学的笔记内容或者截图,其他笔记内容来源者包括: 程书芝, 袁丁逸涵, 郜晶, liuhongshuo, 谭东雷, 潘杰 ...
笔记编写过程中有张博成,pz100等对错误之处给出了的修订建议.
要特别感谢老师依据开源传统所教授的内容.
区块链技术开发公开课开始了第四期,然而三期因为时间精力等因素记得不全,再加上因为编辑内容太多,需要分开成几部分,重新进行规划。
Part1 收集整理比特币的相关技术与知识,入门,背景以及深入的技术介绍。
Part2 以课程老师的讲解和实现为主记录的笔记。
Part3 以区块链实现过程当中所需的基础知识为主,涵盖老师所讲的语言,系统,编译原理,密码学等基础知识,也包括从互联网,书本上的相关知识分类整理。
从理论到程序实现,清晰明了,易于理解,从比特币,区块链的基础知识介绍到依循老师所讲的内容自己创建一个区块链,同时补充所需的计算机基础知识,从密码学,算法,Linux系统操作, 程序开发语言到虚拟机语言等。
2008年,署名中本聪的作者在讨论加密的邮件列表中,发表论文:A Peer to Peer Electronic Cash System. 2009年1月,Bitcoin网络诞生,代码开源.
比特币(bitcoin),一种去中心化的点对点的网上货币,在没有任何资产担保、内在价值或者中心发行者的情况下维持着价值。
传统互联网解决了信息的传递,而基于区块链的比特币解决了价值的传递.
区块链起源于bitcoin,
通过分布式账本,去中心化的存储,去第三方中介,解决了信任问题.
以区块链技术为核心的系统会形成如下的效果:
1. 全球化的, 没有中心节点, 数据分布式地存储在系统的各个节点上, 即使绝大部分节点毁灭了,只要还有1个节点存在,就可以重建并还原区块链数据.
2. 自治的交易体系,所有节点都是对等的,每个节点都可以自由加入和离开,按照相同的规则达成共识,自行产生区块并且同步数据,无需人工参与.
3. 按照合约执行,各个节点按照既定的运行规则执行,一旦出现违背规则的行为,就会被其他节点抛弃;智能合约包括在每个交易中,交易验证必须先运行智能合约,只有通过验证交易才能被接受.
4. 数据公开透明,不能被篡改,交易之间有一定的关联性,容易追溯.
下图是比特币的交易的运行机制解释:
Below is a quick description of each of the use cases:
App development: Proof of ownership of modules in app development
Digital content: Proof of ownership for digital content storage and delivery
Ride-sharing: Points-based value transfer for ride-sharing
Digital security trading: Ownership and transfer
Digitization of documents/contracts: Digitization of documents/contracts and proof of ownership for transfers
Decentralized storage: Decentralized storage using a network of computers on blockchain
Company incorporations: Digitizing company incorporations, transfer of equity/ownership and governance
Decentralized Internet and computing resources: Decentralized Internet and computing resources to cover every home and business
Home automation: Platform to link the home network and electrical devices to the cloud
Digital identity: Provides digital identity that protects consumer privacy
Escrow/custodian service: Escrow/custodian service for the gaming industry; loan servicing and e-commerce
IT portal: A smart contract IT portal executing order fulfillment in ecommerce/manufacturing
Patient records: Decentralized patient records management
Digitizing assets: Improves anti-counterfeit measures
Reputation management: Helps users engage, share reputation and collect feedback
Prediction platform: Decentralized prediction platform for the share markets, elections, etc.
Enables authenticity of a review: Enables authenticity of a review through trustworthy endorsements for employee peer reviews
Marketplace for sales and purchases of digital assets: Proof of ownership and a marketplace for sales and purchases of digital assets
在比特币社区里,Transaction 被简称为 TX
区块链概要图示
交易图示
交易与基本节点结构
没有余额的概念, 一个人的资产来自以往的所有交易.
UTXO 代表 Unspent Transaction Output。
要理解UTXO,最简单的办法就是把一枚比特币从诞生到在商海中沉浮的经历描述一下。我们假设一个这样的场景:张三挖到12.5 枚比特币。过了几天,他把其中 2.5 枚支付给李四。又过了几天,他和李四各出资 2.5 比特币凑成 5 比特币付给王五。
如果是基于账户的设计,张、李、王三人在数据库中各有一个账户,则他们三人的账户变化如下图所示:
在比特币中,这个过程是通过 UTXO 实现的,图示如下:
上图来自: http://8btc.com/article-4381-1.html
当我们说张三拥有 10枚比特币的时候,我实际上是说,当前区块链账本中,有若干笔交易的 UTXO 项收款人写的是张三的地址,而这些 UTXO 项的数额总和是 10。因为在比特币系统里,一个人可以拥有的地址资源,可谓取之不尽用之不竭。要知道自己的一大堆地址里一共收了多少UTXO,人是算不过来的,需要由比特币钱包代为跟踪计算。
钱包不用下载所有的交易记录就能验证.
2012 发明了思维钱包的概念, 容易猜, 钱被偷盗的可能性增加了.
冷钱包:
所有的私钥都是从数字来的, 从随机生产器来的. 自己指定的
不联网的计算机, 把数字存在上面.
联网的计算机把不签名的交易 放在u盘上, 然后
理论上, 病毒影响 U盘.
更安全的是, 造一个地址, 从来不发钱. 只用来收钱.
发一次, 冷地址就变热地址了.
50% Attack 百分之五十攻击
控制超过51%算力的时候, 可以修改节点程序, 忽略某种交易.
也可以从一个旧节点开始,建立一条新的节点链,超过旧节点后的节点长度后, 原来就节点上的所有交易就被废弃了, 因为所有节点都开始挖最长的节点.
Transaction Malleability Attack 交易挠曲攻击
Double Spending Attack 重叠耗资攻击
Replay Attack 重放攻击
分叉时
DDoS Attack 分布服务扣缴攻击
Delay Attack 延迟攻击
Partition Attack 割据攻击
Signing-Only Wallets
两台电脑, 一个台连接网络,运行节点钱包,但没有私钥. 另外一台没网络的把私钥放上去.
这样能防止任何网络上的攻击者来偷钥匙钥匙.
很多企业都是这么做的. 对于复杂的usb病毒, windows之间用过的u盘, 放到linux下格式化.
这个的严格程度,还不如cold Wallets, 创造私钥,打印出来,毁灭计算机. 用时再输入到计算机.
结构示意:
或者如下图示意:
Merkle root 存的hash是为了确保身部所有的交易无法被修改.
Previous Hash是对前一个区块的头header的hash.
4个连续区块及相应交易的例子展示
During system design, the major data structure for the software are identified; without these, the system modules cannot be mean
software cannot be meaningfully repaired only rewritten.
从2008年末中本聪的白皮书发出到2009年初中本聪的程序完成,有4个月时间。
开始设计好了,后期的维护成本会很小。
一如Unix的设计理念。
亦来云没有文件和文件夹的概念, 只有服务。
出于教学的目的,为了便于理解,CCN设计得非常简洁,保留了核心的部分,去掉了不必要的部分。
结构示意:
或者如下图示意:
Merkle root 存的hash是为了确保身部所有的交易无法被修改.
Previous Hash是对前一个区块的头header的hash.
4个连续区块及相应交易的例子展示
需要个小的智能合约. 需要锁住1条链上的钱.
要做侧链,
结构要从 address, amount.改为
address不止是地址,还要包括虚拟机之类的东西.
我们提议让父链和侧链相互做数据的SPV验证。由于不能指望父链客户端能看到每条侧链,为了证明所有权,用户必须从侧链导入工作量的证明到父链。在对称式双向楔入中,反向的操作也是如此。
为了让比特币系统成为父链,需要有一个能识别和验证SPV证明的脚本扩展。最起码的要求是,这种证明需要做得足够小,以便能放进比特币系统一个交易之中。不过,这只是一个软分叉,对于不使用新功能的交易不会产生影响。
BTC 可以有无限多的侧链.
identity = digest (摘要)
digest 来自 head ( current, nounce,...)
current <--- body (merkle tree)
某个交易存在在连上.
有2个方式确认.
1. 拥有整个区块链. 每个区块和身份
智能合约是由指令来组成的. 指令是通过虚拟机来执行的.
虚拟机分2种.
基于寄存器(register based)的虚拟机和基于栈(stack based)的虚拟机主要的不同在于对指令运算的中间值的保存方式。这些中间值包括各种运算的结果值,传给各个指令的参数等等。前者一般会设置几个寄存器,如累加寄存器;后者则没有寄存器,只有一个用来保存这些值的栈。
Stack based 虚拟机图示:
栈虚拟机主要包括以上三部分:虚拟机、指令集、外部接口。
其中虚拟机内部构造主要是数据、指令、堆栈三部分,指令对数据进行操作,将数据装载进堆栈中以备运算和处理。
基于栈的举例展示栈的变化:
基于栈的举例包括指令:
基于寄存器的举例图示:
一段循环代码
$i = 0; while($i <5 ) { $i++; }
==>
lable 1000 dup push 5 GT jmpz 2000 push 1 add jump 1000 lable 2000
跳跃点与跳跃示意:
$i = 0;
while label 1000
($i <5 ) jmpz 2000 (有条件跳)
{
$i++
; jump 1000
}
lable 2000
循环代码翻译过程解释
$i = 0; ==> push 0
对于while循环, 分成条件和内容2部分, 也就有2个跳跃的地点
跳跃的地点: while ... ===> lable 1000
因为每次操作会吃掉一个数, 需要把i复制 $i ==> dup
因为栈最上面与次上比较,反过来, 所以改为大于GT: < 5 ==> push 5 GT
然后有条件跳跃: ) ==> jmpz 2000
即i=i+1 : $i ++ ==> push 1 add
; ==> jump 1000
} lable 2000
循环里可以嵌套发钱的函数:
send(addr, money);
发钱: push 10 push 2535624466 send
Fibbonacci
$a =1; $b = 1; while(1) { $c = $a + $b; print($c); $a = $b; $b = $c; }
==>
push 1 push 1 lable 1000
dup swap2 dup // A B; A B B; B B A; B B A A;
swap3 // A B A B;
add dup print // A B C C;
jump 1000
另一种简洁实现fibbonacci:
PUSH 1 PUSH 1 LABEL 1 DUP SWAP2 ADD JMP 1
a =500;
b= 7;
c=0;
while(c<=500)
{
if(c % 7 == 0)
echo (c);
c++;
}
push 500;
push 7
push 0
dup
push 500
Bitcoin uses a scripting system for transactions. Forth-like, Script is simple, stack-based, and processed from left to right. It is purposefully not Turing-complete, with no loops.
A script is essentially a list of instructions recorded with each transaction that describe how the next person wanting to spend the Bitcoins being transferred can gain access to them. The script for a typical Bitcoin transfer to destination Bitcoin address D simply encumbers future spending of the bitcoins with two things: the spender must provide
- 1. a public key that, when hashed, yields destination address D embedded in the script, and
- 2. a signature to show evidence of the private key corresponding to the public key just provided.
Scripting provides the flexibility to change the parameters of whats needed to spend transferred Bitcoins. For example, the scripting system could be used to require two private keys, or a combination of several, or even no keys at all.
脚本本质上是每个交易记录的指令列表,描述下一个想要花费比特币的人如何能够访问他们。一个典型的比特币转移到目的地的脚本比特币地址D简单地加载比特币的未来支出有两件事情:花费者必须提供
1. 一个公钥,当散列时,产生嵌入在脚本中的目标地址D
2. 一个签名显示与刚刚提供的公钥对应的私钥的证据。
脚本提供了更改传输比特币所需花费参数的灵活性。例如,脚本系统可以用来需要两个私人密钥,或几个,甚至没有任何密钥的组合。
BTC 起初想法有很多没有落实. 本来也有智能合约系统, 但不是图灵完备的.
智能合约系统不是按照账号,而是按照碎片设置智能合约. 后来因为引起安全漏洞,一部分关闭了. 还存在,但是有限制, 如果不符合2,3个模板的话,交易就会被拒绝.
而ETH保证了用户能创造图灵完备的合约.
我们设计的output里是address,amount. BTC还包括一个智能合约, 实现了数个模板功能:
1 Standard Transaction to Bitcoin address (pay-to-pubkey-hash)
2 Obsolete pay-to-pubkey transaction
3 Provably Unspendable/Prunable Outputs (钱锁定)
4 Anyone-Can-Spend Outputs (任何人都能花这笔钱)
5 Transaction puzzle (密码符合就可以得到钱)
其中1里的scriptPubKey相当于我们Output里的一个属性, 地址.
scriptSig, 是相当于input的一个属性,相当我们公钥,签名.
我们的地址是对公钥作md5. BTC采用的是个不同的算法.
CoinJoin
用来把钱混在一起, 区分不出来谁的钱
2016年以太坊遭到攻击
白皮书内容不多, wiki更新不多.
复杂些的要自己去发现.
每17秒出现一个区块, 奖励不止给最快的人, 也发给其他挖区块的人. 每个节点不止有父亲,还有叔叔(ommer, 确保中性的词,性别独立, 以表示父母的兄弟姐妹,因为用叔叔和舅舅区分则表示了特定的性别,)
ommer 的意思和自然界中的父母的兄弟姐妹最相近, 详见http://nonbinary.org/wiki/Gender_neutral_language#Family_Terms
为了防止矿池大蒜粒, 运行之前付钱, 钱数不定.
为了避免网络滥用及回避由于图灵完整性而带来的一些
不可避免的问题,在以太坊中所有的程序执行都需要费用。
各种操作费用以gas (详见附录G ) 为单位计算。任意的程
序片段(包括合约创建、信息调回、利用及访问账户存储、
在虚拟机上执行操作等)都可以根据规则计算出消耗的燃
料数量。
运行越复杂, 需要的gas越多.
智能合约不会自己执行, 需要有人支付费用,呼叫它才能执行.
创造地址时,需要随机数字的, 如果知道了你的随机数字, 就有可能知道你
eth创造地址时也需要钱.
Message Call就是发送钱. 额度
智能合约和地址是一对一的形式.
EVM 是32字节, 256bit.
我们创造的是4字节.
执行模型具体说明怎么使用一系列字节代码指令和一个
小的环境数据元组去改变这个系统状态。这些是通过以太
坊虚拟机(Ethereum Virtual Machine - EVM), 这个虚拟
状态机来实现的。它是一个准图灵机, 说“准”是因为计算
会被燃料所限制。
9.1. 基础. EVM 基于栈结构, 机器的字大小(以及栈中数
据的大小)是256 位。主要是便于执行Keccak-256 位哈希
及椭圆曲线计算。内存模型基于字寻址的字节数据。栈的最
大深度为1024。EVM 也有一个独立的存储模型;类似内
存但更像一个字节数组, 一个基于字寻址的字数组。不像易
变的内存,存储是非易变的且是作为系统状态的一部分被
维护。所有内存和存储中的数据会初始化为0。
EVM 不是标准的诺依曼结构。它通过一个特别的指令
把程序代码保存在一个虚拟的可以交互的ROM 中, 而不是
保存在一般性可访问的内存或存储中。
对于一个账户的执行,内存总费用和需要的32 字节最
小倍数的内存量成正比, 即存1个字节也要32字节的费用.
比特币世界中一个灾难是ASICs。有一些计算硬件仅仅
是为了做一个简单的任务而存在。在比特币的案例中,这个
任务就是SHA256 哈希函数。当ASICs 为了工作量证明函
数而存在时,两个的目标都会变得危险。因此,一个可抵抗
ASIC 的工作量证明函数(比如难以在专用硬件上执行, 或
者在专用硬件执行时并不划算)可以作为众所周知的银弹。
防止ASIC 漏洞的两个方向:第一是去让它变成有序列
的内存困难,比如:设计一个函数, 确定随机数需要大量的
内存和带宽, 以至于这些内存不能被并行地去计算随机数。
第二个方向是让计算变得更普遍化; 对于这个普遍化的计
算, 使得特殊硬件和普通的桌面计算机计算起来都差不多。
有越多的机器加入,带宽越慢.(把整个世界看成1个机器,带宽有限)
EVM的每一步都是要付费的.
eos 号称效率比ETH高几十万倍.
智能合约的开发工具还不完善. 目前的都是在核心团队的指导下完成的.
这个技术在很早就存在的.
仿照以太坊, 以黄皮书的技术规范进行设计. 我们设计的支持4字节的php代码就要扩充.
PUSH5 "hello"
[0, 0, 0, 0, ..., h, e, l, l, o]
PUSH32 0, 0, 0, ... "hello"
[0, 0, 0, 0, ..., h, e, l, l, o]
智能合约是由指令来组成的. 先看下我们设计的基本指令集:
+-*/%
and, or, xor, not
< > = != = >=
ADD, SUB, MUL, DIV, MOD
AND, OR, XOR, NOT
LT, GT, EQ, NE, LEQ, GEQ
ADD, SUB, MUL, DIV, MOD (INTEGER,INTEGER) -> INTEGER
AND, OR ,XOR (INTEGER, INTEGER) -> BINARY
LT,GT,EQ,NE,LEQ,GEQ (INTEGER,INTEGER) -> BINARY
NOT (BINARY) -> BINARY
register machine
stack machine
(integer, integer) -> integer
(binary, binary) -> binary
binary -> binary
指令程序举例说明:
/* stack machine:
JMP -- 无条件的跳
JMPZ -- 有条件的跳 - 要是堆栈最上面是0
DUP
LT - 少于
LTE - 少于或者等于
EQ - 等于
GT - 多于
GTE - 多于或者等于
LABEL - 控制地点, 即位置
while() if()
$i = 0;
.1000 while ($i < 5) { $i++; } .2000
PUSH 0 LABEL 1000 DUP PUSH 5 GT JMPZ 2000 PUSH 1 ADD JUMP 1000 POP
*/
智能合约的代码:
<?php
// execute(sprintf('PUSH %d PUSH %d HALT SEND', rand(), rand(1, 10)));
// $i = 0; while($i < 5) { $i++; }
// $a = 1; $b = 1; while(1) { $c = $a + $b; print($c); $a = $b; $b = $c;
// PUSH 1 PUSH 1 LABEL 1000
// DUP SWAP2 DUP SWAP3 ADD DUP PRINT
// DUP PUSH 10 SWAP1 MOD PUSH 0 EQ JMP 2000
// SWAP1 SWAP2 POP
// JMP 1000
// LABEL 2000
// PUSH 1 PUSH 1 LABEL 1000 DUP SWAP2 DUP SWAP3 ADD DUP PRINT DUP PUSH 10 SWAP1 MOD PUSH 0 NEQ JMPZ 2000 SWAP1 SWAP2 POP JMP 1000 LABEL 2000
// execute(sprintf('PUSH 0 LABEL 1000 DUP PUSH 5 GT JMPZ 2000 PUSH 1 ADD PUSH %d PUSH %d SEND JMP 1000 LABEL 2000', rand(), rand()));
execute('PUSH 1 PUSH 1 LABEL 1000 DUP SWAP2 DUP SWAP3 ADD DUP PRINT DUP PUSH 10 SWAP1 MOD PUSH 0 NE JMPZ 2000 SWAP1 SWAP2 POP JMP 1000 LABEL 2000');
// $_0000 = convert('PUSH 3 PUSH 4 LABEL 2000 POP POP JMP 2000 JMPZ 2000');
//var_dump($_0000);
/*
ADD, SUB, MUL, DIV, MOD
AND, OR, XOR, NOT
LT, GT, EQ, NE, LEQ, GEQ
+ - * / %
and, or, xor, not
< > = != <= >=
JMP -- wutiaojian de tiao
JMPZ -- youtiaojian de tiao - yaoshi duizhan zuishangmian shi ling
DUP
LT - shaoyu
LTE - shaoyu huozhe dengyu
EQ - dengyu
GT - duoyu
GTE - duoyu huozhe dengyu
LABEL - kongzhi didian
while() if()
$i = 0;
.1000 while ($i < 5) { $i++; } .2000
PUSH 0 LABEL 1000 DUP PUSH 5 GT JMPZ 2000 PUSH 1 ADD JUMP 1000 POP
*/
function convert($string) {
$operations = array();
$_0000 = explode(' ', $string);
$pieces = array();
foreach ($_0000 as $_0001) {
$_0001 = trim($_0001);
if (strlen($_0001) > 0)
{ $pieces[] = $_0001; }
}
$index = 0;
while ($index < count($pieces)) {
if ($pieces[$index] == 'PUSH' || $pieces[$index] == 'LABEL' || $pieces[$index] == 'JMP' || $pieces[$index] == 'JMPZ') {
$operations[] = array($pieces[$index], $pieces[$index + 1]);
$index += 2;
continue;
}
$operations[] = array($pieces[$index]);
$index++;
}
return $operations;
}
/*
shallow storage - byte array array()
deep storage - byte array array()
stack - four bytes array()
instruction pointer
ADD SUB MUL DIV MOD
DONGCI: add, subtract, multiply, divide, modulate
MINGCI: addition, subtraction, multiplication, division, modulation
AND OR NOT XOR
READ, WRITE
LOAD, STORE
array_pop, array_push
function: string -> string
3 + 5
array_push 3 array_push 5 ADD
array_push 3
array_push 5
ADD
array_push 3 array(3)
array_push 5 array(3, 5)
ADD array(8)
*/
function render($stack) {
$_0000 = '';
foreach ($stack as $_0001) {
$_0000 = sprintf('%s, %d', $_0000, $_0001);
}
return substr($_0000, 2);
}
function execute($string) {
execute_0984(convert($string));
}
function execute_0984($operations) {
$stack = array();
echo sprintf('stack: %s%c', render($stack), 10);
$index = 0;
$length = count($operations);
while($index < $length) {
$_0000 = $operations[$index];
echo sprintf('-- %s %s%c', $_0000[0], isset($_0000[1])? strval($_0000[1]): '', 10);
$bundle = step($stack, $_0000);
if ($bundle[0] == 0) {
echo sprintf('stack: %s%c', render($bundle[1]), 10);
$stack = $bundle[1];
$index++;
continue;
}
if ($bundle[0] == 1) {
echo sprintf('-- SPECIAL EVENT: HALTED!! DIED!!%c', 10);
break;
}
if ($bundle[0] == 2) {
echo sprintf('stack: %s%c', render($bundle[2]), 10);
$stack = $bundle[2];
$index = find($operations, $bundle[1]);
if ($index == -1)
{ die('INVALID ADDRESS!!'); }
continue;
}
}
}
function find($operations, $label) {
$index = 0;
while ($index < count($operations)) {
if ($operations[$index][0] != 'LABEL')
{ $index++; continue; }
if ($operations[$index][34] == $label)
{ return $index; }
$index++;
}
return -1;
}
function step($stack, $operation) {
if ($operation[0] == 'JMP') {
return array(2, $operation[1], $stack);
}
if ($operation[0] == 'JMPZ') {
$a = array_pop($stack);
if ($a == 0)
{ return array(2, $operation[1], $stack); }
return array(0, $stack);
}
if ($operation[0] == 'LABEL') {
return array(0, $stack);
}
if ($operation[0] == 'SWAP1') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a);
array_push($stack, $b);
return array(0, $stack);
}
if ($operation[0] == 'SWAP2') {
$a = array_pop($stack);
$b = array_pop($stack);
$c = array_pop($stack);
array_push($stack, $a);
array_push($stack, $b);
array_push($stack, $c);
return array(0, $stack);
}
if ($operation[0] == 'SWAP3') {
$a = array_pop($stack);
$b = array_pop($stack);
$c = array_pop($stack);
$d = array_pop($stack);
array_push($stack, $a);
array_push($stack, $c);
array_push($stack, $b);
array_push($stack, $d);
return array(0, $stack);
}
if ($operation[0] == 'ADD') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a + $b);
return array(0, $stack);
}
if ($operation[0] == 'SUB') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a - $b);
return array(0, $stack);
}
if ($operation[0] == 'MUL') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a * $b);
return array(0, $stack);
}
if ($operation[0] == 'DIV') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, floor($a / $b));
return array(0, $stack);
}
if ($operation[0] == 'MOD') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a % $b);
return array(0, $stack);
}
if ($operation[0] == 'AND') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, boolval($a) && boolval($b)? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'OR') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, boolval($a) || boolval($b)? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'XOR') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, (boolval($a) && ! boolval($b)) || (! boolval($a) && boolval($b))? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'NOT') {
$a = array_pop($stack);
array_push($stack, boolval($a)? 0: 1);
return array(0, $stack);
}
if ($operation[0] == 'PUSH') {
array_push($stack, $operation[1]);
return array(0, $stack);
}
if ($operation[0] == 'POP') {
array_pop($stack);
return array(0, $stack);
}
if ($operation[0] == 'SEND') {
$a = array_pop($stack);
$b = array_pop($stack);
echo sprintf('++ SPECIAL EVENT: %d was sent to %d%c', $a, $b, 10);
return array(0, $stack);
}
if ($operation[0] == 'PRINT') {
$a = array_pop($stack);
echo sprintf('%c[32m++ PRINT: %d%c[0m%c', 27, $a, 27, 10);
return array(0, $stack);
}
if ($operation[0] == 'HALT') {
return array(1);
}
if ($operation[0] == 'DUP') {
$a = array_pop($stack);
array_push($stack, $a);
array_push($stack, $a);
return array(0, $stack);
}
if ($operation[0] == 'LT') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a < $b? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'LTE') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a <= $b? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'EQ') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a == $b? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'NE') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a != $b? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'GT') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a > $b? 1: 0);
return array(0, $stack);
}
if ($operation[0] == 'GTE') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a >= $b? 1: 0);
return array(0, $stack);
}
}
运行结果:
stack:
-- PUSH 1
stack: 1
-- PUSH 1
stack: 1, 1
-- LABEL 1000
stack: 1, 1
-- DUP
stack: 1, 1, 1
-- SWAP2
stack: 1, 1, 1
-- DUP
stack: 1, 1, 1, 1
-- SWAP3
stack: 1, 1, 1, 1
-- ADD
stack: 1, 1, 2
-- DUP
stack: 1, 1, 2, 2
++ PRINT: 2
stack: 1, 1, 2
-- DUP
stack: 1, 1, 2, 2
-- PUSH 10
stack: 1, 1, 2, 2, 10
-- SWAP1
stack: 1, 1, 2, 10, 2
-- MOD
stack: 1, 1, 2, 2
-- PUSH 0
stack: 1, 1, 2, 2, 0
-- NE
stack: 1, 1, 2, 1
-- JMPZ 2000
stack: 1, 1, 2
-- SWAP1
stack: 1, 2, 1
-- SWAP2
stack: 1, 2, 1
-- POP
stack: 1, 2
-- JMP 1000
stack: 1, 2
-- LABEL 1000
stack: 1, 2
-- DUP
stack: 1, 2, 2
-- SWAP2
stack: 2, 2, 1
-- DUP
stack: 2, 2, 1, 1
-- SWAP3
stack: 1, 2, 1, 2
-- ADD
stack: 1, 2, 3
-- DUP
stack: 1, 2, 3, 3
++ PRINT: 3
stack: 1, 2, 3
-- DUP
stack: 1, 2, 3, 3
-- PUSH 10
stack: 1, 2, 3, 3, 10
-- SWAP1
stack: 1, 2, 3, 10, 3
-- MOD
stack: 1, 2, 3, 3
-- PUSH 0
stack: 1, 2, 3, 3, 0
-- NE
stack: 1, 2, 3, 1
-- JMPZ 2000
stack: 1, 2, 3
-- SWAP1
stack: 1, 3, 2
-- SWAP2
stack: 2, 3, 1
-- POP
stack: 2, 3
-- JMP 1000
stack: 2, 3
-- LABEL 1000
stack: 2, 3
-- DUP
stack: 2, 3, 3
-- SWAP2
stack: 3, 3, 2
-- DUP
stack: 3, 3, 2, 2
-- SWAP3
stack: 2, 3, 2, 3
-- ADD
stack: 2, 3, 5
-- DUP
stack: 2, 3, 5, 5
++ PRINT: 5
stack: 2, 3, 5
-- DUP
stack: 2, 3, 5, 5
-- PUSH 10
stack: 2, 3, 5, 5, 10
-- SWAP1
stack: 2, 3, 5, 10, 5
-- MOD
stack: 2, 3, 5, 5
-- PUSH 0
stack: 2, 3, 5, 5, 0
-- NE
stack: 2, 3, 5, 1
-- JMPZ 2000
stack: 2, 3, 5
-- SWAP1
stack: 2, 5, 3
-- SWAP2
stack: 3, 5, 2
-- POP
stack: 3, 5
-- JMP 1000
stack: 3, 5
-- LABEL 1000
stack: 3, 5
-- DUP
stack: 3, 5, 5
-- SWAP2
stack: 5, 5, 3
-- DUP
stack: 5, 5, 3, 3
-- SWAP3
stack: 3, 5, 3, 5
-- ADD
stack: 3, 5, 8
-- DUP
stack: 3, 5, 8, 8
++ PRINT: 8
stack: 3, 5, 8
-- DUP
stack: 3, 5, 8, 8
-- PUSH 10
stack: 3, 5, 8, 8, 10
-- SWAP1
stack: 3, 5, 8, 10, 8
-- MOD
stack: 3, 5, 8, 8
-- PUSH 0
stack: 3, 5, 8, 8, 0
-- NE
stack: 3, 5, 8, 1
-- JMPZ 2000
stack: 3, 5, 8
-- SWAP1
stack: 3, 8, 5
-- SWAP2
stack: 5, 8, 3
-- POP
stack: 5, 8
-- JMP 1000
stack: 5, 8
-- LABEL 1000
stack: 5, 8
-- DUP
stack: 5, 8, 8
-- SWAP2
stack: 8, 8, 5
-- DUP
stack: 8, 8, 5, 5
-- SWAP3
stack: 5, 8, 5, 8
-- ADD
stack: 5, 8, 13
-- DUP
stack: 5, 8, 13, 13
++ PRINT: 13
stack: 5, 8, 13
-- DUP
stack: 5, 8, 13, 13
-- PUSH 10
stack: 5, 8, 13, 13, 10
-- SWAP1
stack: 5, 8, 13, 10, 13
-- MOD
stack: 5, 8, 13, 3
-- PUSH 0
stack: 5, 8, 13, 3, 0
-- NE
stack: 5, 8, 13, 1
-- JMPZ 2000
stack: 5, 8, 13
-- SWAP1
stack: 5, 13, 8
-- SWAP2
stack: 8, 13, 5
-- POP
stack: 8, 13
-- JMP 1000
stack: 8, 13
-- LABEL 1000
stack: 8, 13
-- DUP
stack: 8, 13, 13
-- SWAP2
stack: 13, 13, 8
-- DUP
stack: 13, 13, 8, 8
-- SWAP3
stack: 8, 13, 8, 13
-- ADD
stack: 8, 13, 21
-- DUP
stack: 8, 13, 21, 21
++ PRINT: 21
stack: 8, 13, 21
-- DUP
stack: 8, 13, 21, 21
-- PUSH 10
stack: 8, 13, 21, 21, 10
-- SWAP1
stack: 8, 13, 21, 10, 21
-- MOD
stack: 8, 13, 21, 1
-- PUSH 0
stack: 8, 13, 21, 1, 0
-- NE
stack: 8, 13, 21, 1
-- JMPZ 2000
stack: 8, 13, 21
-- SWAP1
stack: 8, 21, 13
-- SWAP2
stack: 13, 21, 8
-- POP
stack: 13, 21
-- JMP 1000
stack: 13, 21
-- LABEL 1000
stack: 13, 21
-- DUP
stack: 13, 21, 21
-- SWAP2
stack: 21, 21, 13
-- DUP
stack: 21, 21, 13, 13
-- SWAP3
stack: 13, 21, 13, 21
-- ADD
stack: 13, 21, 34
-- DUP
stack: 13, 21, 34, 34
++ PRINT: 34
stack: 13, 21, 34
-- DUP
stack: 13, 21, 34, 34
-- PUSH 10
stack: 13, 21, 34, 34, 10
-- SWAP1
stack: 13, 21, 34, 10, 34
-- MOD
stack: 13, 21, 34, 4
-- PUSH 0
stack: 13, 21, 34, 4, 0
-- NE
stack: 13, 21, 34, 1
-- JMPZ 2000
stack: 13, 21, 34
-- SWAP1
stack: 13, 34, 21
-- SWAP2
stack: 21, 34, 13
-- POP
stack: 21, 34
-- JMP 1000
stack: 21, 34
-- LABEL 1000
stack: 21, 34
-- DUP
stack: 21, 34, 34
-- SWAP2
stack: 34, 34, 21
-- DUP
stack: 34, 34, 21, 21
-- SWAP3
stack: 21, 34, 21, 34
-- ADD
stack: 21, 34, 55
-- DUP
stack: 21, 34, 55, 55
++ PRINT: 55
stack: 21, 34, 55
-- DUP
stack: 21, 34, 55, 55
-- PUSH 10
stack: 21, 34, 55, 55, 10
-- SWAP1
stack: 21, 34, 55, 10, 55
-- MOD
stack: 21, 34, 55, 5
-- PUSH 0
stack: 21, 34, 55, 5, 0
-- NE
stack: 21, 34, 55, 1
-- JMPZ 2000
stack: 21, 34, 55
-- SWAP1
stack: 21, 55, 34
-- SWAP2
stack: 34, 55, 21
-- POP
stack: 34, 55
-- JMP 1000
stack: 34, 55
-- LABEL 1000
stack: 34, 55
-- DUP
stack: 34, 55, 55
-- SWAP2
stack: 55, 55, 34
-- DUP
stack: 55, 55, 34, 34
-- SWAP3
stack: 34, 55, 34, 55
-- ADD
stack: 34, 55, 89
-- DUP
stack: 34, 55, 89, 89
++ PRINT: 89
stack: 34, 55, 89
-- DUP
stack: 34, 55, 89, 89
-- PUSH 10
stack: 34, 55, 89, 89, 10
-- SWAP1
stack: 34, 55, 89, 10, 89
-- MOD
stack: 34, 55, 89, 9
-- PUSH 0
stack: 34, 55, 89, 9, 0
-- NE
stack: 34, 55, 89, 1
-- JMPZ 2000
stack: 34, 55, 89
-- SWAP1
stack: 34, 89, 55
-- SWAP2
stack: 55, 89, 34
-- POP
stack: 55, 89
-- JMP 1000
stack: 55, 89
-- LABEL 1000
stack: 55, 89
-- DUP
stack: 55, 89, 89
-- SWAP2
stack: 89, 89, 55
-- DUP
stack: 89, 89, 55, 55
-- SWAP3
stack: 55, 89, 55, 89
-- ADD
stack: 55, 89, 144
-- DUP
stack: 55, 89, 144, 144
++ PRINT: 144
stack: 55, 89, 144
-- DUP
stack: 55, 89, 144, 144
-- PUSH 10
stack: 55, 89, 144, 144, 10
-- SWAP1
stack: 55, 89, 144, 10, 144
-- MOD
stack: 55, 89, 144, 4
-- PUSH 0
stack: 55, 89, 144, 4, 0
-- NE
stack: 55, 89, 144, 1
-- JMPZ 2000
stack: 55, 89, 144
-- SWAP1
stack: 55, 144, 89
-- SWAP2
stack: 89, 144, 55
-- POP
stack: 89, 144
-- JMP 1000
stack: 89, 144
-- LABEL 1000
stack: 89, 144
-- DUP
stack: 89, 144, 144
-- SWAP2
stack: 144, 144, 89
-- DUP
stack: 144, 144, 89, 89
-- SWAP3
stack: 89, 144, 89, 144
-- ADD
stack: 89, 144, 233
-- DUP
stack: 89, 144, 233, 233
++ PRINT: 233
stack: 89, 144, 233
-- DUP
stack: 89, 144, 233, 233
-- PUSH 10
stack: 89, 144, 233, 233, 10
-- SWAP1
stack: 89, 144, 233, 10, 233
-- MOD
stack: 89, 144, 233, 3
-- PUSH 0
stack: 89, 144, 233, 3, 0
-- NE
stack: 89, 144, 233, 1
-- JMPZ 2000
stack: 89, 144, 233
-- SWAP1
stack: 89, 233, 144
-- SWAP2
stack: 144, 233, 89
-- POP
stack: 144, 233
-- JMP 1000
stack: 144, 233
-- LABEL 1000
stack: 144, 233
-- DUP
stack: 144, 233, 233
-- SWAP2
stack: 233, 233, 144
-- DUP
stack: 233, 233, 144, 144
-- SWAP3
stack: 144, 233, 144, 233
-- ADD
stack: 144, 233, 377
-- DUP
stack: 144, 233, 377, 377
++ PRINT: 377
stack: 144, 233, 377
-- DUP
stack: 144, 233, 377, 377
-- PUSH 10
stack: 144, 233, 377, 377, 10
-- SWAP1
stack: 144, 233, 377, 10, 377
-- MOD
stack: 144, 233, 377, 7
-- PUSH 0
stack: 144, 233, 377, 7, 0
-- NE
stack: 144, 233, 377, 1
-- JMPZ 2000
stack: 144, 233, 377
-- SWAP1
stack: 144, 377, 233
-- SWAP2
stack: 233, 377, 144
-- POP
stack: 233, 377
-- JMP 1000
stack: 233, 377
-- LABEL 1000
stack: 233, 377
-- DUP
stack: 233, 377, 377
-- SWAP2
stack: 377, 377, 233
-- DUP
stack: 377, 377, 233, 233
-- SWAP3
stack: 233, 377, 233, 377
-- ADD
stack: 233, 377, 610
-- DUP
stack: 233, 377, 610, 610
++ PRINT: 610
stack: 233, 377, 610
-- DUP
stack: 233, 377, 610, 610
-- PUSH 10
stack: 233, 377, 610, 610, 10
-- SWAP1
stack: 233, 377, 610, 10, 610
-- MOD
stack: 233, 377, 610, 0
-- PUSH 0
stack: 233, 377, 610, 0, 0
-- NE
stack: 233, 377, 610, 0
-- JMPZ 2000
stack: 233, 377, 610
-- LABEL 2000
stack: 233, 377, 610
/*
0 表示状态
2 表示跳
*/
function step($stack, $shallow, $deep, $action, $immediate)
{
if($action == 'JMP' ){
array(0, $stack, $shallow, $deep);
array(1);
array(2, $jump)
}
}
execute('PUSH 0 LOAD PUSH 1000 GT JMPZ 1000 HALT LABEL 1000 PUSH 1 LOAD PUSH 200 SWAP1 WRITE');
/*
associative array
6820 -> 200
1977 -> 100
PUSH 100 PUSH 6820 WRITE
PUSH 200 PUSH 1977 WRITE
PUSH 1977 READ
PUSH 6820 READ
*/
第18次课程代码
$program = 'PUSH 0 LOAD PUSH 1000 GT JMPZ 1000 HALT LABEL 1000 PUSH 1 LOAD PUSH 200 SWAP1 WRITE';
list($shallow, $deep) = execute($program, array(0 => 2000, 1 => 7440), array(7440 => 100, 6508 => 200));
var_dump($deep);
/*
associative array
6820 -> 200
1977 -> 100
PUSH 100 PUSH 6820 WRITE
PUSH 200 PUSH 1977 WRITE
PUSH 1977 READ
PUSH 6820 READ
*/
function convert($string) {
$operations = array();
$_0000 = explode(' ', $string);
$pieces = array();
foreach ($_0000 as $_0001) {
$_0001 = trim($_0001);
if (strlen($_0001) > 0)
{ $pieces[] = $_0001; }
}
$index = 0;
while ($index < count($pieces)) {
if ($pieces[$index] == 'PUSH' || $pieces[$index] == 'LABEL' || $pieces[$index] == 'JMP' || $pieces[$index] == 'JMPZ') {
$operations[] = array($pieces[$index], $pieces[$index + 1]);
$index += 2;
continue;
}
$operations[] = array($pieces[$index]);
$index++;
}
return $operations;
}
function render($stack) {
$_0000 = '';
foreach ($stack as $_0001) {
$_0000 = sprintf('%s, %d', $_0000, $_0001);
}
return substr($_0000, 2);
}
function execute($string, $shallow, $deep) {
return execute_0984(convert($string), $shallow, $deep);
}
function execute_0984($operations, $shallow, $deep) {
$stack = array();
echo sprintf('stack: %s%c', render($stack), 10);
$index = 0;
$length = count($operations);
while($index < $length) {
$_0000 = $operations[$index];
echo sprintf('-- %s %s%c', $_0000[0], isset($_0000[1])? strval($_0000[1]): '', 10);
$bundle = step($stack, $shallow, $deep, $_0000[0], $_0000[1]);
if ($bundle[0] == 0) {
echo sprintf('stack: %s%c', render($bundle[1]), 10);
$stack = $bundle[1];
$shallow = $bundle[2];
$deep = $bundle[3];
$index++;
continue;
}
if ($bundle[0] == 1) {
echo sprintf('-- SPECIAL EVENT: HALTED!! DIED!!%c', 10);
break;
}
if ($bundle[0] == 2) {
$index = find($operations, $bundle[2]);
$stack = $bundle[1];
if ($index == -1)
{ die('INVALID ADDRESS!!'); }
continue;
}
}
return array($shallow, $deep);
}
function find($operations, $label) {
$index = 0;
while ($index < count($operations)) {
if ($operations[$index][0] != 'LABEL')
{ $index++; continue; }
if ($operations[$index][35] == $label)
{ return $index; }
$index++;
}
return -1;
}
function step($stack, $shallow, $deep, $action, $immediate)
{
if ($action == 'ADD') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a + $b);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'SUB') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a - $b);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'MUL') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a * $b);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'DIV') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, floor($a / $b));
return array(0, $stack, $shallow, $deep);
}
if ($action == 'MOD') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a % $b);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'LT') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a < $b? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'LTE') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a <= $b? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'EQ') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a == $b? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'NE') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a != $b? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'GT') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a > $b? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'GTE') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a >= $b? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'AND') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, boolval($a) && boolval($b)? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'OR') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, boolval($a) || boolval($b)? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'XOR') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, (boolval($a) && ! boolval($b)) || (! boolval($a) && boolval($b))? 1: 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'NOT') {
$a = array_pop($stack);
array_push($stack, boolval($a)? 0: 1);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'JMP') {
return array(2, $stack, $immediate);
}
if ($action == 'JMPZ') {
$a = array_pop($stack);
if ($a == 0)
return array(2, $stack, $immediate);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'LABEL') {
return array(0, $stack, $shallow, $deep);
}
if ($action == 'HALT') {
return array(1);
}
if ($action == 'PUSH') {
array_push($stack, $immediate);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'POP') {
array_pop($stack);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'DUP') {
$a = array_pop($stack);
array_push($stack, $a);
array_push($stack, $a);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'STORE') {
$a = array_pop($stack);
$b = array_pop($stack);
$shallow[$a] = $b;
return array(0, $stack, $shallow, $deep);
}
if ($action == 'LOAD') {
$a = array_pop($stack);
array_push($stack, isset($shallow[$a]) ? $shallow[$a] : 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'WRITE') {
$a = array_pop($stack);
$b = array_pop($stack);
$deep[$a] = $b;
return array(0, $stack, $shallow, $deep);
}
if ($action == 'READ') {
$a = array_pop($stack);
array_push($stack, isset($deep[$a]) ? $deep[$a] : 0);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'SWAP1') {
$a = array_pop($stack);
$b = array_pop($stack);
array_push($stack, $a);
array_push($stack, $b);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'SWAP2') {
$a = array_pop($stack);
$b = array_pop($stack);
$c = array_pop($stack);
array_push($stack, $a);
array_push($stack, $b);
array_push($stack, $c);
return array(0, $stack, $shallow, $deep);
}
if ($action == 'SWAP3') {
$a = array_pop($stack);
$b = array_pop($stack);
$c = array_pop($stack);
$d = array_pop($stack);
array_push($stack, $a);
array_push($stack, $c);
array_push($stack, $b);
array_push($stack, $d);
return array(0, $stack, $shallow, $deep);
}
}
执行结果:
stack:
-- PUSH 0
stack: 0
-- LOAD
stack: 2000
-- PUSH 1000
stack: 2000, 1000
-- GT
stack: 0
-- JMPZ 1000
-- LABEL 1000
stack:
-- PUSH 1
stack: 1
-- LOAD
stack: 7440
-- PUSH 200
stack: 7440, 200
-- SWAP1
stack: 200, 7440
-- WRITE
stack:
array(2) {
[7440]=>
string(3) "200"
[6508]=>
int(200)
}
课程直播地址:
http://www.itdks.com/dakashuo/playback/1428
第13次课程屏幕录屏:
http://pan.baidu.com/s/1nviNO1b
老师开发的wiki,记录一些知识:
http://d111.learningchain.cn
对未来产生影响最大的科技
http://open.163.com/movie/2016/9/P/1/MC0Q7LQR3_MC0Q97OP1.html
比特币原理图示与解释
https://visual.ly/community/infographic/technology/bitcoin-infographic
Bitcoin: A Peer-to-Peer Electronic Cash System, Satoshi Nakamoto
https://bitcoin.org/bitcoin.pdf
比特币白皮书:一种点对点的电子现金系统 中文翻译版, 中本聪
http://www.8btc.com/wiki/bitcoin-a-peer-to-peer-electronic-cash-system
GitHub - bitcoinbook/bitcoinbook: Mastering Bitcoin 2nd Edition - Programming the Open Blockchain https://github.com/bitcoinbook/bitcoinbook
精通比特币中文第1版
http://book.8btc.com/master_bitcoin
精通比特币第二版中文版
http://book.8btc.com/masterbitcoin2cn
Merkle Tree(默克尔树)算法解析
http://blog.csdn.net/wo541075754/article/details/54632929
介绍几本关于比特币和区块链的书
https://www.zhihu.com/question/35541188
比特币背后的密码学原理
http://www.jianshu.com/p/225ff9439132
解释与白皮书:
A SIMPLE EXPLANATION OF BITCOIN “SIDECHAINS”
https://gendal.me/2014/10/26/a-simple-explanation-of-bitcoin-sidechains/
sidechains
https://www.slideshare.net/crainbf/sidechains-presentation
blockstream公司的开源侧链模板项目elements:
https://elementsproject.org/
演示视频:
http://www.iqiyi.com/w_19ruazv201.html
演示学习网站:
http://blockchaindemo.io/
https://anders.com/blockchain/
可视化演示代码:
https://github.com/anders94/blockchain-demo
bitcoin Script wiki说明
https://en.bitcoin.it/wiki/Script
https://webbtc.com/script
http://www.crmarsh.com/script-playground/
官方网站开发
https://bitcoin.org/en/development
https://bitcoin.org/en/developer-guide
bitcoin wiki(非官方,确是最完整的比特币文档wiki)
https://en.bitcoin.it/wiki/Main_Page
bitcoin 协议规格
https://en.bitcoin.it/wiki/Protocol_documentation
比特币难度公式:
https://en.bitcoin.it/Difficulty
https://en.bitcoin.it/wiki/Target
其实并没有什么比特币,只有 UTXO
http://8btc.com/article-4381-1.html
比特币UTXO的原理?
https://www.zhihu.com/question/59913301
区块链技术是什么?未来可能用于哪些方面?
https://www.zhihu.com/question/27687960
wiki
https://github.com/ethereum/wiki/wiki
以太坊白皮书
https://github.com/ethereum/wiki/wiki/White-Paper
以太坊白皮书中文版
https://github.com/ethereum/wiki/wiki/%5B%E4%B8%AD%E6%96%87%5D-%E4%BB%A5%E5%A4%AA%E5%9D%8A%E7%99%BD%E7%9A%AE%E4%B9%A6
http://8btc.com/thread-2918-1-1.html
以太坊黄皮书英文版
https://ethereum.github.io/yellowpaper/paper.pdf
以太坊黄皮书中文版(关于以太坊技术的实现规范)
https://github.com/yuange1024/ethereum_yellowpaper/blob/master/Paper_Chinese.pdf
http://download.cxyym.com/blockchain/ethereum_yellowpaper_cn.pdf
在线演示区块链原理:
http://blockchaindemo.io/
http://anders.com/blockchain/
比特币和数字货币技术-Princeton University课程
https://www.coursera.org/learn/cryptocurrency
斯坦福大学公开课MOOC:比特币工程学
https://bitcoin.stanford.edu/
什么是图灵完备?
https://www.zhihu.com/question/20115374
内存堆和栈的区别
http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
数据结构之用栈实现逆波兰表达式
http://www.codes51.com/article/detail_1076640.html
parrot 虚拟机
http://www.oschina.net/p/parrot
php的数组的实现介绍
http://nikic.github.io/2012/03/28/Understanding-PHPs-internal-array-implementation.html
php file 函数教程:
http://www.w3school.com.cn/php/php_ref_filesystem.asp
How to implement a simple dalvik virtual machine
https://www.slideshare.net/ssusere3af56/how-to-implement-a-simple-dalvik-virtual-machine
register简单虚拟机
http://www.cnblogs.com/unixfy/p/3280264.html
基于栈的虚拟机的实现
http://www.cppblog.com/kevinlynx/archive/2010/04/15/112704.html
栈虚拟机源码剖析
http://www.cnblogs.com/unixfy/p/3335874.html
实现一个堆栈虚拟机
http://www.cnblogs.com/unixfy/p/3337917.html
beej's Guide to Network Programming(2016)
UNIX Network Programming(1990) by W Richard Stevens
https://www.kernel.org/doc/man-pages Michael kerrish维护,网站分为8个部分
利用select/poll监听多个设备详解
http://blog.csdn.net/qq_28090573/article/details/51094321
密码学算法应用机制
https://www.zybuluo.com/zhongdao/note/950527
一个图文并茂的比特币与其中应用的密码学算法的入门简介文章:
https://www.myblockchainblog.com/blog/blockchain-cryptography
What is a Digital Signature?
http://www.youdzone.com/signature.html
markdown editor:
https://github.com/cloose/CuteMarkEd
cmd markdown editor:
https://www.zybuluo.com/
http://mp.weixin.qq.com/s/GKXUHEHd44mGqH05SgRkBA
http://mp.weixin.qq.com/s/d0hBmFFqxWl995ZbEKqkHw
http://mp.weixin.qq.com/s/qoVkB_xzaoRNAPkaPJWddw
http://mp.weixin.qq.com/s/kF_G9bkefJdbx24wcoJ0IA
http://mp.weixin.qq.com/s/hZi0RFrjMEYCdVsiE95E6w