美文网首页
Swift:07-汇编

Swift:07-汇编

作者: DoBetter1 | 来源:发表于2023-03-17 10:26 被阅读0次
image.png image.png

这里注意:addq $0x1, %rax 的意思是,把1与%rax相加,然后结果存储到%rax寄存器中

image.png image.png
image.png
image.png

这里有个注意点:

// 这里小括号一般代表的是内存地址
//整个代码的意思:把内存地址%rbp-0x1中存储的内容取出来赋值给寄存器%rax
movq -0x18(%rbp),%rax 

//这句汇编的意思是把 %rbp - 0x18这个地址的值赋值给%rax
//%rax寄存器中存储的是地址值
leaq -0x18(%rbp), %rax

从上图可以看出,每一条汇编指令占4个字节,0x100001633~0x100001637

jum指令:cpu跳转到对应内存地址,去执行代码,jum还支持跳转到寄存器中存储的地址值去

jum 0x4001002 //cpu跳转到0x4001002内存地址,去执行汇编指令
//intel
jum rdx
//AT&T
jum *%rdx

jum和callq的区别:

//call后面一般会放函数地址
call 0x100001666 

测试一段汇编代码:


image.png

[图片上传中...(image.png-c742aa-1678592313947-0)]

image.png

汇编显示:callq 0x100002fe0
首先会跳转到 0x100002fe0 这个内存地址
执行下lldb命令 si(单步执行汇编指令)命令 会跳到0x100002fe0这个内存地址,所以0x100002fe0就是函数地址,所以callq后面跟着基本就是函数地址,这里和jum区别是,callq一般都会和retq配合使用


image.png

后面单步执行si,直接回车就好了,因为之前执行过si ,一直执行到最后一步retq,然后再执行一次si


test函数的最后一条汇编指令 最终回到了执行callq指令到后一条汇编指令 image.png

这里注意下:
rax “r”开头的寄存器都是64位8个字节的寄存器
eax “e”开头的是32位4字节的寄存器

64位寄存器是可以兼容32位寄存器的:如下图
64位寄存器%rax,会拿出低地址的4个字节来存储32寄存器的4个字节,当作%eax来使用,同理拿出低2个字节来当作16位寄存器来使用%ax,%ax寄存器又可以拆分成低%ah与%al 两种8位寄存器


image.png

小结:
r开头:64bit,8字节
e开头:43bit,4字节
ax, bx, cx : 16bit, 2字节
ah al:8bit,1字节(带h或者l的是1个字节)
bh bl

因为共用寄存器存储空间,把值放到寄存器的不同位,所以会间接的改变rax,eax的寄存器值
movq $0xa, %rax  //把值0xa存储到%rax寄存器中
movl $0xa, %eax 

lldb常用指令:


image.png
(lldb) register read rax. //读寄存器
rax = 0x000000008327a7fb

(lldb) register read rax
     rax = 0x000000008327a7fb
(lldb) register write rax 0x1  //写寄存器 
(lldb) register read rax
     rax = 0x0000000000000001
(lldb) 

(lldb) register read //打印所有寄存器
General Purpose Registers:
       rax = 0x0000000000000001
       rbx = 0x00000001000d8060
       rcx = 0x000000008327a7fb
       rdx = 0x000000008347a80b
       rdi = 0x00000000000007fb
       rsi = 0x0000600001700280
       rbp = 0x00007ff7bfeff420
       rsp = 0x00007ff7bfeff300
        r8 = 0x0000000000000280
        r9 = 0x0000000000000040
       r10 = 0x00000000000007fb
       r11 = 0x00000000000000ff
       r12 = 0x00000001000a03a0  dyld`_NSConcreteStackBlock
       r13 = 0x00007ff7bfeff4d8
       r14 = 0x0000000100002990  TestSwift`main at main.swift
       r15 = 0x000000010008c010  dyld`dyld4::sConfigBuffer
       rip = 0x0000000100002def  TestSwift`main + 1119 at main.swift:115:1
    rflags = 0x0000000000000206
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000

(lldb) x 0x00000001000d8060 //打印内存地址
0x1000d8060: 58 dd 08 00 01 00 00 00 10 c0 08 00 01 00 00 00  X...............
0x1000d8070: 10 80 0d 00 01 00 00 00 f0 8b 0d 00 01 00 00 00  ................

(lldb) x/3xw 0x00000001000d8060  //3xw的意思是,“3”打印三组内存读取内容,“x”按照16进制打印,“w“意思是4个字节位一组
0x1000d8060: 0x0008dd58 0x00000001 0x0008c010
0x1000d8060: 58 dd 08 00 小端模式,低字节位放到低地址位,高字节位放到高内存位,刚好可以和前面0x0008dd58对应起来
image.png
n 单步执行,遇到函数会跳过
s 遇到函数会进入
n和s都是针对源码级别的调试,所以如果实在汇编代码的情况下执行n或者s,或自动跳转到源码对应的汇编代码位置,不会按照汇编指令挨个挨条执行

如下图:在执行到test()函数,执行“s”命令


image.png

会直接跳转到源码test函数中第一句源码对应的汇编代码,并不是从test函数第一行汇编代码开始执行

func test() {
    var a = 3
    var b = a+1
}
test()
movq $0x3, -0x8(%rbp) 刚好对应 var a = 3 这句源码
  • 相对应的si和ni就对应汇编代码的单条执行
  • finish和放开断点的意思相同,如果是在函数内部,执行finish会直接执行到当前函数最后一行
  • 汇编中打断点和源码中打断点式分开的,都会记录
image.png
//接下来看一段汇编代码,$是立即数的全称,立即数就是常数
movq   $0x3, -0x8(%rbp) //将3 赋值到%rbp+-0x8这个内存空间中,%rbp是寄存器中存储的值,然后减去0x8,movq中q的意思是用8个字节来存储值,movb中b的意思是用1个字节来存储,一般用于枚举变量的成员值
//如果想查看寄存器中存储的值可以使用命令:
(lldb) register read rbp
 rbp = 0x0000000100002ff4 
//xorl 位或运算
xorl %ecx,%ecx
image.png
注意:这里手动计算下rip-0x8 ,rip是 0x00007ff7bfeff2f0 减去 0x8 为0x7FF7BFEFF2E8

我们查找内存中 0x7FF7BFEFF2E8 地址对应的内存看下,确实把3存储到了 0x7FF7BFEFF2E8 地址


rip寄存器存储的是指令的地址
cpu要执行的下一条指令地址就存储在rip中

这里+8的意思是,相对于函数起始地址,偏移增加的地址量

相关文章

网友评论

      本文标题:Swift:07-汇编

      本文链接:https://www.haomeiwen.com/subject/wtsnldtx.html