氢弹打蚊子……懂吗……我不信有神人能看懂
2026-09-05 11:38:03
发布于:河北
64 位 8MB 内存的汇编虚拟机
我们又注意到,这道题还可以通过手搓一个拥有 8MB 内存、64 位系统、使用类似汇编的语言的虚拟机来完成。
a+b代码实现
Code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned int
#define N 1048576
int memory[N],pos;
string code[N]={
"input 1",
"input 2",
"calc add 1 2 3",
"output int 3",
"exit"
};
string readStr(int x,int y)
{
pos=y;
string ret="";
int len=code[x].length();
while(pos<len && code[x][pos]==' ')
{
++pos;
}
while(pos<len && code[x][pos]!=' ')
{
ret=ret+code[x][pos++];
}
return ret;
}
int readInt(int x,int y)
{
pos=y;
int ret=0, len=code[x].length();
bool f=0;
while(pos<len && !isdigit(code[x][pos]))
{
if(code[x][pos]=='-')
{
f=1;
}
++pos;
}
while(pos<len && isdigit(code[x][pos]))
{
ret=(ret<<3)+(ret<<1)+(code[x][pos++]^48);
}
return f?-ret:ret;
}
signed main()
{
for(int i=0;;i=(i+1)%N)
{
string op=readStr(i,0);
if(op=="input")
{
int x=readInt(i,pos);
cin>>memory[x];
}
else if(op=="output")
{
string mode=readStr(i,pos);
if(mode=="int")
{
int x=readInt(i,pos);
cout<<memory[x];
}
else if(mode=="char")
{
int x=readInt(i,pos);
cout<<char(memory[x]%128);
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
else if(op=="write")
{
int x=readInt(i,pos), y=readInt(i,pos);
memory[x]=y;
}
else if(op=="copy")
{
int x=readInt(i,pos), y=readInt(i,pos);
memory[y]=memory[x];
}
else if(op=="calc")
{
string mode=readStr(i,pos);
int x=readInt(i,pos), y=readInt(i,pos), z=(mode=="not" ? 0 : readInt(i,pos));
x=memory[x], y=memory[y];
if(mode=="and")
{
memory[z]=x&y;
}
else if(mode=="or")
{
memory[z]=x|y;
}
else if(mode=="not")
{
memory[y]=~x;
}
else if(mode=="xor")
{
memory[z]=x^y;
}
else if(mode=="add")
{
memory[z]=x+y;
}
else if(mode=="sub")
{
memory[z]=x-y;
}
else if(mode=="mul")
{
memory[z]=x*y;
}
else if(mode=="div")
{
if(y==0)
{
cout<<"\n\nError: Division by Zero\n\n";
break;
}
memory[z]=x/y;
}
else if(mode=="mod")
{
memory[z]=x%y;
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
else if(op=="goto")
{
int x=readInt(i,pos);
i=x-1;
}
else if(op=="if")
{
string mode=readStr(i,pos);
int x=readInt(i,pos), y=readInt(i,pos), z=readInt(i,pos);
x=memory[x], y=memory[y];
if(mode=="<")
{
if(x<y)
{
i=z-1;
}
}
else if(mode==">")
{
if(x>y)
{
i=z-1;
}
}
else if(mode=="==")
{
if(x==y)
{
i=z-1;
}
}
else if(mode=="<=")
{
if(x<=y)
{
i=z-1;
}
}
else if(mode==">=")
{
if(x>=y)
{
i=z-1;
}
}
else if(mode=="!=")
{
if(x!=y)
{
i=z-1;
}
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
else if(op=="++")
{
int x=readInt(i,pos);
memory[x]++;
}
else if(op=="--")
{
int x=readInt(i,pos);
memory[x]--;
}
else if(op=="exit")
{
break;
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
return 0;
}
虚拟机完整指令教程
基础说明
code[]数组每一行是一条指令;code[0]= 第 1 行,code[1]= 第 2 行。goto、if跳转写的是行号(从 1 开始计数),不是数组下标。跳转到第 L 行,虚拟机内部执行i = L‑1。memory[]:虚拟机内存,下标叫内存地址,存 long long 整数。地址随便用,0、1、2、100 都可以。- 每条指令空格分隔参数。
- 程序遇到
exit结束。
📋全部指令列表
1. input 地址
作用:从控制台读一个整数,存入指定内存地址
示例:
input 5
读取数字,放到 memory [5]
2. output int 地址
作用:输出内存地址里的数字
output int 5
打印 memory [5] 的数值
3. output char 地址
作用:将内存的值对 128 取模,当做 ASCII 字符输出
output char 10
memory [10]=65 → 输出字符
A
4. write 地址 常数
作用:把固定数字写入内存地址
write 2 100
memory[2]=100
5. copy 源地址 目标地址
作用:把源内存的值复制到目标内存
copy 3 7
memory[7] = memory[3]
6. calc 运算名 A B C
通用运算指令:
memory[C] = memory[A] 运算 memory[B]
支持运算:
add加法sub减法mul乘法div除法(除零报错终止)mod取模and按位与or按位或xor按位异或
示例:
calc add 1 2 3
memory[3]=memory[1]+memory[2]
特殊:calc not A B 按位取反
只有两个参数!memory[B]= ~ memory[A]
calc not 4 5
7. ++ 地址
内存自增:memory[x] +=1
++ 6
8. -- 地址
内存自减:memory[x] -=1
-- 6
9. goto 行号
无条件跳转到指定行号(从 1 开始)
goto 3
直接运行第 3 行指令
10. if 比较符 A B 行号
条件跳转:如果 memory[A] 比较 memory[B] 条件成立,则跳转到指定行号;不成立就往下执行下一行。
可用比较符:< > == <= >= !=
示例:
if < 1 2 5
如果 memory [1] < memory [2],跳到第 5 行;否则顺序执行。
11. exit
结束虚拟机运行。无参数。
exit
🧪小案例实操
案例 1:a+b
string code[N]={
"input 1",
"input 2",
"calc add 1 2 3",
"output int 3",
"exit"
};
流程:
- 读入第一个数到地址 1
- 读入第二个数到地址 2
- 相加存入地址 3
- 输出地址 3
- 退出
案例 2:循环输出 1~10
虚拟机指令(一共 6 行)
string code[N]={
"write 1 1", //第1行 mem[1]=1
"if > 1 10 6", //第2行 如果mem[1]>10 跳转到第6行exit
"output int 1", //第3行 输出i
"++ 1", //第4行 i++
"goto 2", //第5行 回到第2行判断
"exit" //第6行
};
⚠️ goto/if 后面数字是行号,不是数组下标!第 6 行对应
code[5]。
案例 3:判断大小,输出较大数
string code[N]={
"input 1",
"input 2",
"if > 1 2 5", // 如果mem1>mem2 →跳到第5行输出1
"copy 2 3", // 否则把mem2复制给mem3
"goto 6",
"copy 1 3",
"output int 3",
"exit"
};
⚠️高频踩坑清单
- goto、if 后面是行号从 1 开始,不是数组下标!
goto 1代表执行code[0]。 calc not只有两个参数,不要写第三个寄存器。
错误:calc not 1 2 3
正确:calc not 1 2write第二个是常数数字,不是内存地址;要复制内存值用copy。
write 5 10✔ mem[5]=10write 5 3❗是把数字 3 写入 5,不是 mem [3] 的值;mem [3] 的值要复制请用copy 3 5
- 除法
div除数为 0 直接程序终止报错。 - 不要漏写
exit;如果没有 exit,i 会(i+1)%N无限循环跑满整个 code 数组。 readInt读负数支持-123。output char自动模 128,超出 ASCII 范围也不会崩溃。
📝练习题(你可以自己写 code 跑)
- 输入 a,b,输出 a‑b
- 输入 a,b,输出 a*b
- 循环:不停输入数字,遇到 0 就 exit 退出
提示:指令要写在code字符串里面!
没有神人盐瞎吧
无指令版:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned int
#define N 1048576
int memory[N],pos;
string code[N]={
};
string readStr(int x,int y) // 从 code[x][y] 开始读取一个字符串, 读到空格为止
{
pos=y;
string ret="";
int len=code[x].length();
while(pos<len && code[x][pos]==' ')
{
++pos;
}
while(pos<len && code[x][pos]!=' ')
{
ret=ret+code[x][pos++];
}
return ret;
}
int readInt(int x,int y) // 从 code[x][y] 开始读取一个整数, 读到非数字为止
{
pos=y;
int ret=0, len=code[x].length();
bool f=0;
while(pos<len && !isdigit(code[x][pos]))
{
if(code[x][pos]=='-')
{
f=1;
}
++pos;
}
while(pos<len && isdigit(code[x][pos]))
{
ret=(ret<<3)+(ret<<1)+(code[x][pos++]^48);
}
return f?-ret:ret;
}
signed main()
{
for(int i=0;;i=(i+1)%N)
{
string op=readStr(i,0);
if(op=="input")
{
int x=readInt(i,pos);
cin>>memory[x];
}
else if(op=="output")
{
string mode=readStr(i,pos);
if(mode=="int")
{
int x=readInt(i,pos);
cout<<memory[x];
}
else if(mode=="char")
{
int x=readInt(i,pos);
cout<<char(memory[x]%128);
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
else if(op=="write")
{
int x=readInt(i,pos), y=readInt(i,pos);
memory[x]=y;
}
else if(op=="copy")
{
int x=readInt(i,pos), y=readInt(i,pos);
memory[y]=memory[x];
}
else if(op=="calc") // and or not xor add sub mul div mod
{
string mode=readStr(i,pos);
int x=readInt(i,pos), y=readInt(i,pos), z=(mode=="not" ? 0 : readInt(i,pos));
x=memory[x], y=memory[y];
if(mode=="and")
{
memory[z]=x&y;
}
else if(mode=="or")
{
memory[z]=x|y;
}
else if(mode=="not")
{
memory[y]=~x;
}
else if(mode=="xor")
{
memory[z]=x^y;
}
else if(mode=="add")
{
memory[z]=x+y;
}
else if(mode=="sub")
{
memory[z]=x-y;
}
else if(mode=="mul")
{
memory[z]=x*y;
}
else if(mode=="div")
{
if(y==0)
{
cout<<"\n\nError: Division by Zero\n\n";
break;
}
memory[z]=x/y;
}
else if(mode=="mod")
{
memory[z]=x%y;
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
else if(op=="goto")
{
int x=readInt(i,pos);
i=x-1;
}
else if(op=="if") // < > == <= >= !=
{
string mode=readStr(i,pos);
int x=readInt(i,pos), y=readInt(i,pos), z=readInt(i,pos);
x=memory[x], y=memory[y];
if(mode=="<")
{
if(x<y)
{
i=z-1;
}
}
else if(mode==">")
{
if(x>y)
{
i=z-1;
}
}
else if(mode=="==")
{
if(x==y)
{
i=z-1;
}
}
else if(mode=="<=")
{
if(x<=y)
{
i=z-1;
}
}
else if(mode==">=")
{
if(x>=y)
{
i=z-1;
}
}
else if(mode=="!=")
{
if(x!=y)
{
i=z-1;
}
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
else if(op=="++")
{
int x=readInt(i,pos);
memory[x]++;
}
else if(op=="--")
{
int x=readInt(i,pos);
memory[x]--;
}
else if(op=="exit")
{
break;
}
else
{
cout<<"\n\nError: Invalid Code at i = "<<i<<"\n\n";
break;
}
}
return 0;
}
程序解释
对其中每种指令的介绍({} 表示必选参数,[] 表示可选参数):
input {x}:输入一个整数(范围:[−2
63
,2
63
)),并将其存放于内存的 x 号位置。
output {mode} {x}:以 mode 形式(int 或 char,其中 char 形式是按照 ASCII 码输出)输出内存的 x 号位置中的数据。
write {x} {y}:将内存的 x 号位置的数据设为 y。
copy {x} {y}:将内存的 x 号位置的数据拷贝至内存的 y 号位置。
calc {mode} {x} {y} [z](当 mode 为 not 时无需 z):将内存的 x 号位置的数据与内存的 y 号位置的数据进行 mode 运算(and、or、xor、add、sub、mul、div 或 mod,其中 div 操作在除数为 0 时会提示 Error: Division by Zero 并退出程序),并将结果存放在内存的 z 号位置。
注:当 mode 为 not 时,其效果为将内存的 x 号位置的数据按位取反的结果存放在内存的 y 号位置;此处的 and、or、xor 和 not 均为位运算,逻辑运算是可以通过这个实现的,故没有单独制作。
goto {x}:跳转至第 x 行(从 0 开始)代码。
if {mode} {x} {y} {z}:如果内存的 x,y 号位置的数据满足 mode 这一关系(mode 可在 <、>、==、<=、>= 和 != 中选择),则跳转至第 z 行(从 0 开始)代码。
++ {x}:将内存的 x 号位置的数据加 1。
-- {x}:将内存的 x 号位置的数据减 1。
exit:退出程序。
此外,如果在运行过程中发现了无效的代码,则会提示 Error: Invalid Code 并直接退出程序。
将 code 数组设为 "input 0", "input 1", "calc add 0 1 2", "output int 2", "exit" 即可实现 A+B Problem 的要求。
附赠若干程序(将其复制进程序的第 8 行即可):
Hello world:
"write 0 72", "output char 0",
"write 0 101", "output char 0",
"write 0 108", "output char 0",
"write 0 108", "output char 0",
"write 0 111", "output char 0",
"write 0 44", "output char 0",
"write 0 32", "output char 0",
"write 0 119", "output char 0",
"write 0 111", "output char 0",
"write 0 114", "output char 0",
"write 0 108", "output char 0",
"write 0 100", "output char 0",
"write 0 33", "output char 0",
"exit"
解析:显然。
输出 0∼n−1:
"input 0",
"write 2 32",
"if == 0 1 7",
"output int 1",
"output char 2",
"++ 1",
"goto 2",
"exit"
逐行解析:
input 0:输入一个整数,将其存放于内存的 0 号位置;
write 2 32:将内存 2 号位置的值设为 32(即空格的 ASCII 码);
if == 0 1 7:如果内存的 0,1 号位置的值相等,则跳转至第 7 行代码(即 exit);
output int 1:以数字形式输出内存 1 号位置的值;
output char 2:以字符形式输出内存 2 号位置的值;
++ 1:将 1 号位置的值加 1;
goto 2:跳转至第 2 行代码(即 if == 0 1 7);
exit:退出程序。
P1226 【模板】快速幂(AC 记录:link):
// 输入 & 预处理
"input 0", "input 1",
"input 2", "write 3 1",
"copy 0 4", "copy 1 5",
"write 7 1", "write 8 2",
// 计算
"if == 5 6 17", "calc and 5 7 9",
"if == 9 6 13", "calc mul 3 4 3",
"calc mod 3 2 3", "calc div 5 8 5",
"calc mul 4 4 4", "calc mod 4 2 4",
"goto 8",
// 输出
"output int 0", "write 10 94",
"output char 10", "output int 1",
"write 11 32", "output char 11",
"write 10 109", "output char 10",
"write 10 111", "output char 10",
"write 10 100", "output char 10",
"output char 11", "output int 2",
"write 10 61", "output char 10",
"output int 3", "exit"
解析:基本相当于这段代码 (绝对不是我懒得对这么长的代码写逐行解析了):
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b,tmp,mod,ans=1,cnt=0,p;
int main()
{
cin>>a>>b>>mod;
p=a;
tmp=b;
while(tmp)
{
if(tmp&1)
{
ans*=p;
ans%=mod;
}
tmp/=2;
p*=p;
p%=mod;
}
cout<<a<<"^"<<b<<" mod "<<mod<<"="<<ans;
return 0;
}
欢迎各位大佬在评论区批评指正。
全部评论 3
代码数组 code[N] 开了一百万行
N = 1048576(即 2^20),定义了 100 多万条指令的字符串数组。
实际只用了 5 条指令(input、input、calc add、output、exit),却开了一百万的数组,99.9995% 的空间全在吃灰。
2026-09-22 来自 河北
0cpu烧了!
2026-09-05 来自 广东
0是就得了!对了,我给这个虚拟机写了个OS,在洛谷搜“在A+B题解中发掘的灵感,干了亿点东西……”
呵呵,忘了说了,这是在洛谷抄袭搬运的,怕你们没有洛谷账号……2026-09-05 来自 河北
0

2026-09-05 来自 河北
0










有帮助,赞一个