#L6366. 模拟

模拟

题目描述

小 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] 下划线 _ 表示为空。括号中从前到后四个选项分别代表对低 6464 位,低 3232 位,低 1616 位,低 88 位进行操作所需的指令。

二、数据传送

1. 表达式 (Expression)

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

2. 数据传送指令

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

三、算术指令

1. 一元运算

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

2. 二元运算

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

输入格式

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

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


输出格式

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

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


样例 1

输入

3
movq $1,%rax
movq $18446744073709551615,%rbx
movb %al,%bl

输出

1 18446744073709551361 0 0 0 0 0

样例 2

输入

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

样例 3

输入

2
movb $2,%al
leaq (%rax,%rax,4),%rax

输出

10 0 0 0 0 0 0

数据范围与提示

所有输入数据都是手造的,std 也是人写的。

保证 n50n \le 50,每一行长度 100\le 100