Lab2 CSAPP: BombLab环境+思路+全注释
为了深入理解并解决BOMBLAB环境中的问题,首先需要搭建开发环境。建议创建一个名为“lab2bomblab”的文件夹,并通过运行以下命令下载实验室的所有最新信息和中文版pdf翻译: 接下来,进入“bomb”目录并执行反汇编过程的第一步。
为了更方便的调试,可以安装cgdb工具,它结合了gdb和vim在查看命令执行位置时的优点。
在Ubuntu下,通过脚本安装最新版本的cgdb,只需运行特定的脚本即可。
安装后使用命令“cgdb./bomb”启动调试界面,查看编译指令,支持断点操作、单步执行。
解决问题首先需要在Bomb.s文件中搜索“read_line”找到调用规则。
%rax的返回值是分配给%rdi的输入字符串,这表明%rdi传递给stage的字符串是用户输入的。
对于Phase_1,找到这个函数,得知它是否返回成功取决于%rsi和%rdi指向的字符串是否相同。
因此,0x402400表示的字符串就是答案。
在gdb中,通过命令print(char*)0x402400得到答案,先运行程序,然后使用ctrl+z暂停并打印结果。
跳过此步骤可能会导致丢失重要信息。
在phase_2中,答案在于字符串格式要求。
星号 (*) 表示可以是任何字符,包括数字,但不能超过 6 个,且不包含引号。
清晰的思路可以从代码注释中看出,使用sscanf通过read_six_numbers函数从输入字符串中读取六个数字。
Phase_3 的解决方案基于特定模式,例如 [0,7] 的第一个整数后跟相应的数字。
此解法与书中的例题类似,请阅读相关章节加深理解。
使用cgdb或者直接在代码中设置断点可以帮助解决问题。
第4阶段的解决方案涉及计算和验证特定条件,答案由一组满足要求的1和0组成。
列出了四个正确答案,通过将解方程转换为 C 可以获得详细的代码。
注释提供了进一步的指导。
Phase_5的答案是需要截取输入字符串中每个字符的后四位,得到与0x4024b0[rdx]匹配的字符,最终形成一个“传单”。
通过cgdb跟踪输出,您可以轻松确定问题出在哪里? 注释代码中的%fs:0x28是堆栈保护值,不影响答案。
Phase_6涉及链表结构,汇编代码分析比较复杂。
通过cgdb的标准分析和调试,可以确定链表的结构。
链表项的序列按降序排列,计算隐藏答案。
详细的分析和代码注释提供了解决方案。
最后搜索“fun7”找到连接关系,然后指定开启隐藏关卡的条件。
只需确保输入的第四个答案正确分为“%d%d%s”并等于“DrEvil”即可解锁第六关中的隐藏关卡。
隐藏层解决方案涉及二叉搜索树规则,可以通过合理的路径选择来解决问题。
在BOMBLAB环境下解决问题的整个过程需要深入理解汇编代码并使用调试和逻辑分析工具,最终获得完整的答案。
Bomb.s 文件中提供了详细的代码和注释,包括各个阶段的解决方案和步骤。
请教8051汇编指令
MCS-51 数据传输指令 共有 29 条到源操作数的数据传输指令。如果希望数据传输过程中不丢失目的操作数,则不能使用直接传输指令,而是使用交换型数据传输指令,但不影响C、AC和OV。
它可能会影响奇偶校验标志。
[1] 以累加器 A 作为目标操作数的指令 (4)。
直接、加速、寄存器和寄存器间接寻址模式:MOVA、数据; (data) → (A) 将直接单元地址的存储到AMOVA,#data; MOVA,累加器A中的Rn; (Rn) → (A) Rn 将累加器 A 的发送给 MOVA,@Ri 到 MOVA,@Ri; ((Ri)) → (A) 将 Ri 的所指示的地址的发送到寄存器 Rn 中的存储 A[2],作为目的操作数 (3) 这 3 条指令的作用是发送源操作符指定的到所选工作寄存器Rn。
有直接地址、立即地址、寄存器地址:MOVRn、数据; (data)→(Rn)直接地址到Rn的 MOVRn,#data; #data→(Rn)直接发送到Rn中的寄存器MO VRn,A; (A)→(Rn) 将累加器A 的送至寄存器Rn[3]指令作为目的操作数。
(5) 该指令组的作用是指定来源和。
地址数据直接发送到选定的片内RAM。
有直接、立即数、寄存器和间接寄存器四种寻址方式:MOVdata、data; (data)→(data)将直接地址段的发送到MOVdata的直接地址,#data; ) 发送立即数据到直接地址MOVdata,A; (A)→(Data)将累加器A的送至直接寻址单元MOVda ta、Rn; (Rn) → (data) 寄存器中的到直接地址部分 MOVdata,@Ri; ((Ri)) → (数据) 将寄存器指定的数据发送到直接地址部分[4]。
重新作为地址。
有直接、立即、寄存器三种寻址方式:MOV@Ri、数据; (data) → ((Ri)) 直接地址部分的与 Ri 的一起发送到 RAM 单元 MOV@Ri,#。
根据地址;#data→((Ri i))将立即数据发送到RAM单元MOV@Ri,A,其根据地址(A)→((Ri))存储的为与一起发送到 RAM 单元。
根据Ri中的地址[5]表查找指令 (2) 本组指令的功能是对程序存储器中的数据表进行存储、查找和传送,采用指针方式:MOVCA、@A+DPTR; ((A) MOVCA,@A+PC;((PC) )+1→(A),((A))+(PC)→(A)将表地址部分的传送到累加器A和片外数据存储器RAM 传送指令(第4段) 这4条指令的作用是在累加器A和片外RAM之间传送数据。
使用寄存器地址:MOVX@DPTR,A; (A)→((DPTR))将存储的送至数据指针MOVXA,@DPTR; (a) 数据指针指向片外RAM地址的并进入缓冲器A。
MOVXA,@Ri; ((Ri)) →(A) 寄存器被发送到芯片。
MOVX@Ri, A ; 将外部 RAM 地址中的发送到缓冲器 A。
(A)→((Ri))将缓冲区的发送到寄存器Ri片外RAM地址[7]]。
直接向相关部门反映。
这样的指令只有两条,下面的第一个通常称为入栈操作指令,第二个称为出栈操作指令。
需要指出的是,单片机上电重启后(SP)会默认为07H,但一般需要重新赋值以设置新的SP起始地址。
第一个入栈的数据必须存放在SP+1指向的存储单元中,所以栈的实际栈底就是SP+1指向的存储单元。
PUSHdata;(SP)+1→(SP),(data)(SP) 堆栈指针先加1,将直接引用段中的数据添加到堆栈指针中(SP→(data) (SP)-1→SP),将堆栈指针SP指向的单元的数据发送到直接地址,堆栈指针SP减1 [8] Swap指令 (5) 这5条指令的作用是比较商店A的。
指与源操作数的相互数据交换。
XCHA,Rn; (A)←→(Rn)汇编件与工作寄存器Rn的交换直接地址部分Ri的; (A3-0)←→((Ri)3-0)累加器交换Ri SWAPA指定的的低四位; (A3-0) ) 存储器的以高半字节和低半字节交替[9]。
MOVDPTR,#data16;#dataH→(DPH),#dataL →(DPL) 16 位常数的高 8 位发送到 DPH,低 8 位发送到 DPLMCS-51 算术运算指令 24 种基本算术运算加法、减法、乘法和执行分段运算。
另外,MCS-51学习系统的关键部分进行加法和减法运算,BCD码的运算和修正都属于算术指令。
虽然MCS-51微控制器的算术逻辑单元ALU以8位进行运算虽然它只能对无符号整数执行操作,但进位标志 C 可以对多字节无符号整数执行操作。
同时,您可以使用溢出标志对有符号数执行补码运算。
1 需要注意的是,除加法和减法指令外,大多数指令都会影响 PSW(程序状态字)。
使用时应特别注意这一点。
[1] 加法指令 (4) 这4条指令的作用是将存储器A的与即时数据、直接地址、工作寄存器和间接地址相加,运算结果存放到A中。
通过存储ADDA,#data;(A)+#data →(A),A的立即与#data相加,结果存储在A中。
ADDA,data;(A)+(data)→(一个)。
) 累加器 A 的直接与地址段的相加,结果存入 ADDA, Rn in A (A) + (Rn) → (A) 累加器 A 的 累加器 A 的为将工作寄存器 Rn 中存储的相加,结果为 ADDA,@Ri by A; 将工作寄存器 Ri 指定的地址段的 Add 并将结果存入 A [2] 加法指令除了进位 (4) [1] 这 4 条指令除了具有相同的功能外,还需要考虑执行加法操作时的手提箱。
ADDCA,data;(A)+(data)+(C)→(A) 将累加器 A 的与带进位的直接寻址单元的相加,结果存入 ADDCA,#data;( A)+ #data+ (C)→(A) 将累加器 A 中的与进位位立即数相加,得到 ADDCA, Rn (A)+Rn+(C)→(A) 将累加器 A 的与 n 中工作寄存器 R 的进位位相加,结果为 ADDCA,@Ri (A) + ((Ri)) + ( C ) → (A) 的存储在累加器 A 和工作寄存器中。
对地址单元的,加上 表示的进位位,结果存入 A [3] 信用位减法指令 (4) 本组指令包括快速数减法、直接地址减法、间接地址减法来自累加器 A 的地址和工作寄存器及其。
信用位 C. 结果存储在a中。
这里解释一下借位位C的状态。
在减法过程中,CY=1表示有借位,CY=0表示没有借位。
OV=1 声明有符号数相减时的错误条件,即正数减去负数时的结果它是负数,或者说当你用负数减去正数时,结果是正数。
在执行减法操作之前,如果借位标志C的状态未知,则必须先将CY清零。
SUBBA,data;(A)-(data)-(C)→(A) 将直接地址段的与进位位相减累加器 A 的,结果为 A。
存储在SUBBA中。
,#data;(A)-#data-(C)→(A) 累加器 A 的随着下一个进位位递减,结果为 SUBBA, Rn in A (A) - (Rn) - (C) → (A) 将存储的 A 和工作寄存器的与借位位相减,结果为 A SUBBA,@Ri; (A)-((Ri)) 存入C) → (A) 将工作寄存器 Ri 地址指定的减去累加器 A 的,结果存入 A [4] 乘法指令(1) 该指令的功能 将一个 8 位无符号数相乘并存储到累加器 A b 中。
结果是一个 16 位乘积,低 8 位存储在累加器 A 中,高 8 位存储在寄存器 B 中。
如果OV=1,则表示乘积大于FFH,否则OV=0,但进位标志CY始终等于0。
穆拉布; (A) × (B) → (A) 和 (B) 累加器 A 的与寄存器 B 的相乘,结果存储在 A 和 B 中。
(1) 功能 累加器中的 8 位无符号整数A除以8位就是除以寄存器B中的无符号整数。
结果存储在寄存器A中,余数存储在寄存器B中。
除法运算始终将 OV 和保持标志 CY 设置为 0。
如果OV=1,则表示寄存器B中的为00H,则执行结果为不确定值,表示除法已飞走。
迪瓦布; (A) ÷ (B) → (A) 和 (B) 累加器 A 的除以寄存器 B 的。
[6] 加1指令 (5) 这5条指令的作用是将主寄存器的加1,并将结果发送到主寄存器。
如上所述,加1指令不触及任何标志,如果原寄存器的是FFH,则加1后输出将为00H。
该指令集列出了间接寻址和其他寻址方法:INCA; + 1 → (数据)直接地址段加1,结果发送到原地址处的INC@Ri; ((Ri))+1→((Ri)) 寄存器指示的地址部分加1,结果送回主地址部分IN RETURN CRn ; (Rn) + 1 → (Rn) 寄存器Rn加1,结果发送到第一个地址段(DPTR)+1→(DPTR)加1,结果返回给数据指针。
INCdata指令中,如果直接地址是I/O,功能是先读取I/O锁存器的,然后给CPU加1,然后输出到I/O。
- 与加1指令相同; (A) -1 → 将累加器A的减1,并将结果加到累加器A。
返回 ;减1,结果发送到直接地址 ((Ri)) → ((Ri)) 地址段减1,结果发送到原地址 (Rn )-1 →(Rn) 将寄存器中的减 1,并将结果送回寄存器 Rn[8],小数调整指令 (1) 该指令总是跟在 ADD 或 ADDC 指令之后,且 其功能是对存储在累加器A中的DAAMCS-51逻辑运算和移位指令AND、OR、XOR、求反、左右移位、清0等逻辑运算以及直接、寄存器和地址的结果进行调整和调整。
寻址方式下有25种逻辑运算,包括移位指令和其他逻辑运算。
此类指令一般不会影响程序状态字(PSW)标志。
[1] 移位指令 (4) 这四个指令的功能是将缓冲区的向左或向右移动一位。
RLA; 累加器A的右移一位RRA; 位RRCA; 累加器 A 中的随进位位 RRCA 左移 CY 位右移一位 (1) 该指令将的高、低四位移位。
在上一节介绍的集合中。
西瓦帕; 交换组件中的顶部和底部表面 [3]。
中国人民解放军; 存储库中的有些重复。
CLRA; 0 → (A)、累加 将装置清零[5]。
如果直接地址是I/O地址,则为“读-修改-写”操作。
ANLA,data;累加器A中的与地址单元中的进行AND逻辑运算。
结果存储在寄存器A中。
ANLData,#Data 对和地址单元执行快速数据操作。
结果很直接它们存储在地址中。
ANLA,#数据; 累加器A的及其立即数信息并执行逻辑运算。
结果存储在累加器 A 中。
ANLA,Rn;累加器A的和寄存器Rn的执行AND逻辑运算。
结果存储在累加器 A 中。
ANLData,A;直接对地址进行寻址,存储A。
结果存储在直接地址中。
ANLA,@Ri;累加器A的与工作寄存器指向的地址段的进行AND逻辑运算。
结果存储在累加器 A 中。
[6]逻辑或运算指令(6条) 该指令集的功能是对两个单元的进行逻辑或运算。
如果直接地址是I/O地址,则为“读-修改-写”功能。
ORLA,数据;累加器A中的与立即地址部分的进行逻辑或运算。
结果存储在寄存器A中。
ORLdata,#data;直接地址类中的和立即数进行逻辑或运算。
结果存储在直接地址中。
ORLA,#data;累加器A的与其立即数进行逻辑或运算。
结果存储在累加器 A 中。
奥尔拉,Rn; 结果存储在累加器 A 中。
ORLdata,A;将直接寻址单元的与数组的进行逻辑或运算。
结果存储在直接地址中。
奥尔拉,@Ri; 累加器A和地址部分的在工作寄存器中指示并执行逻辑或运算。
结果存储在累加器 A 中。
[7]逻辑异或运算指令(6条) 该指令集的功能是对两个分量的进行逻辑异或运算。
如果直接地址是I/O地址,则为“读-修改-写”功能。
XRLA,data;累加器A中的与地址单元中的进行逻辑异操作。
结果存储在寄存器A中。
XRLdata,#data;直接地址段的和立即数进行逻辑异或运算。
结果存储在直接地址中。
XRLA,#data;存储A的与其立即数进行逻辑互斥操作。
结果存储在累加器 A 中。
XRLA,Rn; 累加器A的和寄存器Rn的执行逻辑特殊运算。
结果在累加器 A 中它被存储。
XRLdata,A;直接地址部分的和数组A的执行逻辑上不同的操作。
结果存储在直接地址中。
XRLA,@Ri; 累加器 A 和地址部分的在工作寄存器中指示,并执行逻辑互斥操作。
结果存储在累加器 A 中。
MCS-51 控制传输指令 控制传输指令用于控制程序流程,可访问 64kB 程序空间地址段,调用和长传输指令,可访问 2 kbyte 的绝对调用和绝对传输指令,以及页中的短相对范围传输和其他传输指令一般是影响标志位的指令。
[1]。
长传送指令访问的程序存储器位置具有64KB的16位地址,而绝对传送指令访问的程序存储器位置具有2KB的11位地址。
LJMPaddr16; addr16→(PC),给程序计数器(16位地址)赋值 AJMPaddr11,(PC)+2→(PC),addr11→(PC10-0) 给程序计数器(11-0)赋值位地址),(PC15 -11)不要更改SJMPrel; (PC) +2+rel → (PC) 在当前程序计数器的开头加 2,并将新值赋给程序计数器 JMP@A+DPTR ; (A)+(DPTR)→(PC) 将累加器指向的地址段的值通过数据指针交给程序。
它被连接起来,从而控制程序的方向。
JZel;A = 0, (PC) + 2 + rel → (PC),如果存储中的为0,则将偏移量转移到指定地址,否则程序继续执行 JNZrel A≠0 , (PC) +2+rel→(PC),存储中不为0,则前往偏移指定的地址,否则程序CJNEA,data,rel; A≠(data),(pc)+3+rel→(pc)执行,存储中的不等于直接地址。
单元,然后按偏移量传送到指定地址,否则程序按偏移量执行 CJNEA,#data,rel;A≠#data,(PC)+3+rel→(PC) by offset,rel;A≠#data,( PC)+3+rel→(PC),如果工作寄存器Rn中的不等于下一个值,则转移到偏移指定的地址,否则程序 CJNE@Ri,#data,rel;A≠#data, (pc) + 3+ rel → (pc),如果工作寄存器中指定的地址部分不等于立即数,则传送按偏移量到指定地址,否则程序将被执行。
DJNZRn,相对; (Rn)- 1→(Rn),(Rn)≠0, (pc)+2+rel→(PC)工作寄存器Rn减1不等于0,则转移到偏移表示的地址,否则程序 DJNZdata,rel;(Rn)-1→(Rn),( Rn ) ≠0,(PC)+2+rel→(PC) 如果直接地址部分减1的不等于0,则偏移到指定地址。
被传输,否则程序将继续执行[3]。
为了方便编程,减少需要频繁执行的程序数量,它们占用过多的地址空间,并在程序段中引入。
因此,我们就有了主程序和子程序的概念,对于一些需要重复执行的程序,我们在编程的时候,一般都是用call命令来让程序运行起来。
LALLaddr16; 长调用指令、子程序可在64kB空间内调用。
此时(PC)+3→(PC)、(SP)+1→(SP)、(PC7-0)→(SP)、(SP)+1→(SP)、(PC15-8)SP) ,addr16→(PC),即当调用返回地址ACALLaddr11时,压入的子程序从堆栈中弹出。
此时完美召唤指令为(PC)+2→(PC)、(SP)+1→(SP)、(PC7-0)→(SP)、(SP)+1(SP)、(PC15- 8)→(SP),addr11→(PC10-0)RET; 此时(SP)→(PC15-8)、(SP)-1→(SP)、(SP)→(PC7-0)、(SP)-1→(SP)RETI; 除RET 外的中断返回指令除了RETI 指令的功能外,还具有恢复中断逻辑的功能,不能用RET 代替 (1) 该指令清除缓冲区的。
0.NOP; 该指令除了将 PC 加 1 并使用一个机器周期外,不执行任何操作。
短延时MCS-51布尔变量操作指令 布尔处理功能是MCS-51系列单片机的基本功能,它是针对实际应用的需要而设计的。
布尔变量也是以位为单位的转换变量。
从物理结构上看,MCS-51单片机有一个布尔处理器,采用进位标志作为存储位,采用128地址的内部RAM作为存储位。
因为有布尔处理器函数,所以也有相应的布尔运算指令集,下面我们单独讨论。
[1] 位传送指令 (2) 位传送指令是地址位和累加位CY 之间的传送。
MOVC,bit;bit→CY,某些位数据到CYMOVbit,C;CY→bit发送后,CY 数据发送到某个位 [2] 复位位的指令一共有 4 条。
CLRC; 0→CY,清除CYCLR位; 0 → 位、某个位 SETBC、1 → 设置位、某个位 运算(6)都是逻辑运算,有 AND、OR、AND NOT 三种指令,共 6 条指令。
ANLC,bit;(CY)∧(bit)→CyanLC,/bit;(CY)∧() ()→CI CPLbit;()→Bir[4] 位控制传送指令 (5) 位控制指令程序 使用位状态实现传输,(PC)+2+rel→PC,否则程序继续执行OK,(PC)+2→PC。
JNCrel;(CY)=0传送,(PC)+2+rel→PC,否则程序继续执行,(PC)+2→PC。
JBbit,相对; 位状态转为 1。
JNBbit,相对; 位状态转为 0。
JBCbit,相对; 它将位状态转换为 1 并将该位清除为“0”。
如果满足所有条件,最后三个指令是 (pc) + 3+ rel → pc (pc) + 3 → pc。
51单片机使用汇编语言循环延迟时间怎么算?
时间精确的延迟程序是用汇编语言编写的。要计算延迟时间,需要查询每个程序的执行周期数,然后将它们相加。
在12m晶体振荡器系统中,机器的每个周期持续1微秒。
举例说明:delay:movr0,#10;1(循环)delay1:movr1,#100;1djnzr1,$;2djnzr0,d。
elay1;2ret;2 周期数 = 1 + ((1 + (2*100) + 2) * 10) + 2 = 2033 延迟时间 = 2033 个周期 * 1 微秒 = 2033 微秒(从程序开始到返回)被调用的程序持续了2033微秒
怎样将Y-86 变为 X-86汇编代码?
在这种情况下,您可以通过将每个命令替换为执行相同操作的短序列 y86 命令来进行更改。y86 是图灵完备的,但非常蹩脚,所以切换并不总是那么容易。
某些 x86 指令可能需要完整循环或长函数才能执行,但任何指令都不会出现这种情况。
它们中的每一个都可以翻译成一条或多条y86指令。
(有些可能需要暂存器;我忘记 y86 是立即比较还是仅立即比较。
)您的代码没有任何乘法或移位或 bsf 或浮点数或 y86 没有的任何其他(并且需要一个循环来模拟)。
在指令集参考手册中查找每条 x86 指令(例如此在线版本或此较旧的版本,其中没有 AVX/AVX2 指令,以节省您的麻烦)。
请参阅 x86 Marker Wiki,获取 Intel 和 AMD 的 PDF 链接。
请参阅“操作”部分,其中伪代码描述了指令对体系结构状态的确切影响。
这是您想要使用 y86 命令实现的行为。
例如,我忘记了 y86 是否具有推送/弹出功能,但如果没有,您始终可以直接操作 rsp 并加载/保存。
例如,sub$8,%rsp;movrm%rbx,(rsp) 是push(除非x86 push 不在这里,否则会被设置)。