#P51796. 「LOJ」 模拟

「LOJ」 模拟

题目描述

小 X 迷上了一部没有汉化的 Galgame,他决心为这部游戏的汉化尽自己的一份力量。于是,他反汇编了这部游戏,想从汇编代码里找一些线索。然而,由于小 X 太弱,不能人脑汇编,所以他找到了你,要你帮助他进行汇编模拟。也就是说,小 X 讲给你一段 X86_64 汇编代码,请你帮他输出运行后寄存器的内容和内存内容。

小 X 在程序中发现的汇编只是 X86_64 汇编的一个子集。为了简化题目,本题部分细节与 X86_64 汇编不同,请仔细阅读题面叙述。

约定:我们使用 ATT 格式的汇编代码,同时认为内存寻址操作与栈操作相互独立。同时,程序保证仅包含迭代,不包含递归调用。

你需要的前置技能:补码及其运算,否则符号位会让你崩溃。

一、寄存器

指令 说明
[r/e/_/_]a[x/x/x/l]
[r/e/_/_]b[x/x/x/l]
[r/e/_/_]c[x/x/x/l]
[r/e/_/_]d[x/x/x/l]
[r/e/_/_]si[_/_/_/l]
[r/e/_/_]di[_/_/_/l]
[r/e/_/_]bp[_/_/_/l]
[r/e/_/_]sp[_/_/_/l]
_ 表示为空。括号中从前到后四个选项分别代表对低 64 位,低 32 位,低 16 位,低 8 位进行操作所需的指令。

二、数据传送

1. 表达式 (Expression)

指令 说明
表达式:立即数 X
$X
我们约定 x 均为无符号十进制整数,立即数不会被作为目标表达式。
表达式:一个寄存器
%Register_Name
表达式:对内存进行寻址
x=0(Rb=0,Ri=0,s=1)
其中 x s 为两个立即数,Rb Ri 为两个通用寄存器名称,等号后的值为未列出时的默认值。
括号内的填充顺序为:RbRi。如果没有 Rb 而单独使用 Ri,则应留出前面的逗号:x(,Ri,s)
在此,我们假设内存以 8B8\:\texttt{B}64bit64\:\texttt{bit} 为一个数据块。每次读取一整个块。

2. 数据传送指令

指令 说明
基本数据传送
mov[q/l/w/b] (:Expression1),(:Expression2)
表示把 Expression1 处的数据传送到 Expression2 处。
[q/l/w/b] 从左到右分别代表传送低 64 位,低 32 位,低 16 位,低 8 位。
在操作寄存器低位时,高位保持不变。
拓展数据传送
mov[z/s][q/l/w/b][q/l/w/b] (:Expression1),(:Expression2)
在数据传送的基础上对中的 Expression2 处的数据进行拓展。
第一个 [q/l/w/b] 表示 Expression1 处的数据大小,第二个表示 Expression2 处的数据大小。
[q/l/w/b] 从左到右分别代表传送低 64 位,低 32 位,低 16 位,低 8 位。
z 表示对无符号数进行零拓展,s 表示对有符号数进行符号拓展。
本题目限定判定符号正负无脑判定首位即可。
地址传送
leaq (:Expression) (:Register)
Expression 的地址加载到 Register 中。注意 X86_64 的指针都是 64 位的,所以长度码只能为 q

三、算术指令

1. 一元运算

指令 说明
inc[q/l/w/b] (:Expression)
dec[q/l/w/b] (:Expression)
自增 Expression
自减 Expression
neg[q/l/w/b] (:Expression) Expression 变为其相反数。
not[q/l/w/b] (:Expression) Expression 按位取反。

2. 二元运算

指令 说明
add[q/l/w/b] (:Expression1),(:Expression2)
sub[q/l/w/b] (:Expression1),(:Expression2)
imul[q/l/w/b] (:Expression1),(:Expression2)
Expression1Expression2 相加存入 Expression2 中。
Expression2Expression1 作差存入 Expression2 中。
Expression1Expression2 相乘存入 Expression2 中。
xor[q/l/w/b] (:Expression1),(:Expression2)
or[q/l/w/b] (:Expression1),(:Expression2)
and[q/l/w/b] (:Expression1),(:Expression2)
Expression1Expression2 按位异或存入 Expression2 中。
Expression1Expression2 按位或存入 Expression2 中。
Expression1Expression2 按位与存入 Expression2 中。
[sal/shl][q/l/w/b] (:Expression1),(:Expression2)
sar[q/l/w/b] (:Expression1),(:Expression2)
shr[q/l/w/b] (:Expression1),(:Expression2)
Expression2 左移 Expression1 位存入 Expression2 中。
Expression2 算术右移(填上符号位)Expression1 位,存入 Expression2 中。
Expression2 逻辑右移(左边补零)Expression1 位,存入 Expression2 中。

本来这道题还应该有比较和跳转的,只是因为出题人太弱写不动,放弃了......

输入格式

第一行一个整数 nn,代表输入代码的行数。

接下来 nn 行,每行一条汇编代码,代表你需要执行的语句。

输出格式

第一行 77 个整数,代表除 %rsp 外所有寄存器的值。规定以 64 位无符号整数格式输出。

接下来数行,每行两个64位无符号整数,代表内存中元素的地址和数值。

样例 1

3
movq $1,%rax
movq $18446744073709551615,%rbx
movb %al,%bl
1 18446744073709551361 0 0 0 0 0
6
movq $1,%rax
subq $3,%rax
movq $2147483647,%rbx
movq %rbx,%rcx
movl %eax,%ebx
movsbq %ax,%rcx
18446744073709551614 4294967294 18446744073709551614 0 0 0 0
2
movb $2,%al
leaq (%rax,%rax,4),%rax
10 0 0 0 0 0 0

数据范围与提示

所有输入数据都是手造的,std 也是人写的。
保证 n50n \le 50,每一行长度 100\le 100
真·良心题目。基本上写出来就给过。当然写 WA 了除外 2333。