理解程序的本质
程序的本质
装载进内存的的程序都不是代码层级了,都是01011这种二进制数据
image.png
编程语言的发展
image.png汇编语言的种类
image.pngmovq 0x18(%rbp),%rax // 将rbp+0x18的地址值对应的存储空间的值赋值给rax
leaq 0x18(%rbp),%rax// 将rbp+0x18的地址值赋值给rax
常见的汇编指令
image.png注意点:
1.jmp是跳转到那个地址(而且从不回头)
2.call 后面是函数地址,一般跟ret(返回)一起使用,可以回头
call 0x100001666 是跳转到此地址
call *%rax 是跳转到rax存储的地址值
3.movq movl后面的 q是指64bit也就是8字节 l是32bit 4字节是单位 要移动的值对应的要占用多少内存
寄存器 和寄存器的兼容性
image.png注意点:寄存器既然是拿来存储数据的,就会有空间,它多大取决于电脑是32位X86汇编(32bit),也就是4个字节,X64汇编(64bit),也就是8个字节,随着时代的发展,越来越多的X64汇编,但是对X86(32bit)做了兼容
r开头:64bit 8字节 (拿出自己的一半,从31往前的低位存储eax)
e开头:32bit 4字节 (拿出自己的一半,从15往前的低位存储ax)
ax bx cx ...:16bit 2字节(拿出自己的一半,存储ah,al)
ah al bh bl...:8bit 1字节
image.png
lldb常用指令
image.png注意点:
x/数量 格式 字节大小 内存地址
x/4xg 0x0000010
//勾选如下按钮,可以查看汇编断点
注意点:汇编断点如果想快速过掉函数
方法一:断点打到retq,然后敲si
方法二:直接敲finish
查看汇编代码
enum TestEnum {
case test1(Int, Int, Int)//24
case test2(Int, Int)//16
case test3(Int)//8
case test4(Bool)//1
case test5
}
// 0x100005469 <+249>: movq $0x2, 0x3334(%rip) // 0x3334 + 0x100005474 = 0x1000087A8
//-> 0x100005474 <+260>: movq $0x3, 0x3331(%rip) // 0x3331 + 0x10000547f = 0x1000087B0 和第一条比相差8个字节证明他们内存是连续的
// 0x10000547f <+271>: movq $0x4, 0x332e(%rip) // 0x1000087B8
// 0x10000548a <+282>: movb $0x0, 0x332f(%rip) // 0x1000087C0 movb 是一个字节 是枚举的成员值
var t1 = TestEnum.test1(2, 3, 4)
0x3334 + 0x100005474 // 用编程计算器可得出一个地址 // 0x1000087A8
刚好是枚举变量t1所在的内存地址 ,此时查看内存地址的内容,已经把2赋之子给了前8个字节,如图所示:
注意点:rip存储的是指令要执行的地址
1.CPU要执行的下一条指令就存储在rip中
举例:如果当前rip = 0x00 那么cpu运行到这个地址时会做一个操作,rip += 正在执行指令的长度,所以要取得rip的地址值,是下一条指令的地址
2.movq是8个字节,内存地址是连续的
3.movb是一个字节,为枚举成员变量
网友评论