CMU 15213:machine-level programming课程笔记和bomb实验

本文详细记录了CMU 15213课程的机器级编程笔记,涵盖汇编语言、C语言、Linux汇编模式、寻址方式等内容,并深入剖析了Bomb实验的六个阶段,包括字符串匹配、整数序列计算、switch case逻辑等,强调了汇编、程序ABI和调试技巧的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 笔记

本章的主要讲了编程语法,包括:汇编和C语言。

1.1 basics

1.介绍了intel x86 processors的发展历史(AMD和ARM);

2.指令集大的分类:cisc和risc;

3.c代码到可执行代码的过程:

  • c代码;
  • 汇编代码(gcc -og -S);
  • 二进制文件(gcc);
  • 二进制文件(链接了其他的静态库)(gcc 或者 ld);

4.Objdump(将二进制代码转换成汇编代码);

5.gdb调试时使用disassemble命令,也可以获取汇编代码;

6.x86-64寄存器:rax、rbx、rcx、rdx、rsi、rdi、rsp、rb和 r8-r15;

  • rax表示是64bit;
  • eax表示32bit;
  • ax表示16bit;
  • ah表示高8bit;
  • al表示低8bit;

7.Operation:

在这里插入图片描述

8.寻址方式(三种模式):

  • movq (%rcx),%rax:将rcx寄存器指向的地址数据移动到rax
  • movq 8(%rbp),%rdx:将[rbp]+8地址的数据移动到rdx
  • Mem[Reg[Rb]+S*Reg[Ri]+ D](D只能是1、2、4和8)

假设rdx=0xf000 rcx=0x0100,则计算地址的结果如下:

在这里插入图片描述
9. 地址计算指令leaq,它主要有两个用途:

  • 计算地址(而不会将该地址的数据存放到dest);
  • 计算算术表达式,形如x+k*y(k是1、2、4或者8)(和取址指令一样)(要比普通的加法和乘法快一些)

1.2 control

一般采用linux类型的汇编模式,而不是Intel模式的;它们之间差别还是很大的

1.X86-64单bit的寄存器:CF、SF、ZF、OF

  • cf:下图是cf的置1的情况,分别是:进位(unsigned溢出)和借位;
    在这里插入图片描述
  • sf:下图是sf置1的情况,根据符号位是否为1来判断;
    在这里插入图片描述
  • zf:当数据全为0时,zf置1;
    在这里插入图片描述
  • of:当两个数(符号位一致)相加,得到结果的符号位同原数据的符号位不一致;
    在这里插入图片描述

2.Comq src2,src1指令:类似于src1-src2,影响PSW;

3.Testq src2,src1指令:类似于计算src1&src2;(经常用于判断一个寄存器里面得值是否为0)

  • Zf set:src1&src2 == 0;
  • Sf set:src1&src2 < 0;

4.Set dest指令:用于判断PSW的值,当条件成立时将1写入dest;

在这里插入图片描述

  • 下图时setl成立的示意图:
    在这里插入图片描述

5.Movzbl:高位填充为0;

6.jx指令:
在这里插入图片描述
7.c语言goto;

8.c语言条件语句:if、a?b:c(注意b和c如果是表达式都会被计算,所以会增加复杂度);

9.循环语句:do-while、while、for;

10.Switch:编译成汇编后,会结合jump table和rdi(index)找到对应的跳转入口;

1.3 Procedures

1.ABI:机器程序级别的接口(windows linux ios都有自己的abi,大致相同,细节不同)。它包括:passing control、passing data、memory management等机制;

  • 比如一个编译好的二进制程序,如果放在ABI修改后的机器上运行会导致程序出现无法预计的错误;

2.Stack:向低地址增长

  • Pushq src:修改(减少8bytes)%rsp;将src写入stack
  • Popq dest:将栈顶的数据放入dest;修改(增加8bytes)%rsp

3.passing control

  • 使用stack;
  • 执行call label语句时:将return address压入栈;跳转到label执行;
  • Return address:当前call label语句的下一条语句的地址;
  • 执行ret语句时:pop出栈的return address;跳转到该处运行;

4.Passing data

  • 参数传递:前6个参数通过寄存器:%rdi、%rsi、%rdx、%rcx、%r8、%r9;剩余的参数通过stack传递;(浮点数参数有单独的寄存器);
  • 返回值:%rax

5.Stack frames:

  • Contents:返回地址;局部变量空间;临时空间
  • Management:stack分配空间(call)和释放空间的时机(return);

在这里插入图片描述

call的时候是否压入%rbp是可选的

6.Linux stack frame

在这里插入图片描述

7.Register saving conventions

  • “Caller Saved”:Caller saves temporary values in its frame before the call;
  • “Callee Saved”:Callee saves temporary values in its frame before using;Callee restores them before returning to caller;

Caller-saved registers (AKA volatile registers, or call-clobbered) are used to hold temporary quantities that need not be preserved across calls. caller如果在callee返回之后需要使用这些寄存器,则应该在callee之前保存它们。
在这里插入图片描述

Callee-saved registers (AKA non-volatile registers, or call-preserved) are used to hold long-lived values that should be preserved across calls. 说明这些寄存器在callee返回时会被恢复,所以caller可以不用保存这些寄存器,即使后面需要使用也不需要保存(因为Callee返回时会恢复)。
在这里插入图片描述

2. bomb lab

本实验主要考察了汇编、程序ABI的了解、gdb调试等基础知识。实验提供了一个二进制文件:bomb和一个c语言文件:bomb.c。

2.1 phase 1

Phase 1的函数汇编代码如下:

0000000000400ee0 <phase_1>:
  400ee0:	48 83 ec 08          	sub    $0x8,%rsp
  400ee4:	be 00 24 40 00       	mov    $0x402400,%esi
  400ee9:	e8 4a 04 00 00       	callq  401338 <strings_not_equal>
  400eee:	85 c0                	test   %eax,%eax
  400ef0:	74 05                	je     400ef7 <phase_1+0x17>
  400ef2:	e8 43 05 00 00       	callq  40143a <explode_bomb>
  400ef7:	48 83 c4 08          	add    $0x8,%rsp
  400efb:	c3                   	retq   

很显然phase 1函数将我们的输入同bomb程序预先存储的字符串进行匹配,如果不一致的话则会引爆炸弹。

我们知道%rdi和%rsi可以用来传递参数,%rdi当前指向我们输入的字符串的地址,那么%esi就指向密钥。从汇编mov $0x402400,%esi可知,该密钥存储在0x402400内存地址上。

用gdb查看该地址存放的字符串的命令是:x/s 0x402400。得到输出结果:Border relations with Canada have never been better.

2.2 phase 2

Phase 2的汇编代码如下:

0000000000400efc <phase_2>:
  400efc:	55                   	push   %rbp
  400efd:	53                   	push   %rbx
  400efe:	48 83 ec 28          	sub    $0x28,%rsp
  400f02:	48 89 e6             	mov    %rsp,%rsi
  400f05:	e8 52 05 00 00       	callq  40145c <read_six_numbers>
  400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)
  400f0e:	74 20                	je     400f30 <phase_2+0x34>
  400f10:	e8 25 05 00 00       	callq  40143a <explode_bomb>
  400f15:	eb 19                	jmp    400f30 <phase_2+0x34>
  400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax
  400f1a:	01 c0                	add    %eax,%eax
  400f1c:	39 03                	cmp    %eax,(%rbx)
  400f1e:	74 05                	je     400f25 <phase_2+0x29>
  400f20:	e8 15 05 00 00       	callq  40143a <explode_bomb>
  400f25:	48 83 c3 04          	add    $0x4,%rbx
  400f29:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值