AT&T汇编与Xcode LLDB调试

2020-01-02  本文已影响0人  迷路的小小

AT&T汇编与Xcode LLDB调试

寄存器

模拟器

通用寄存器

64位寄存器 32位寄存器(低32位) 16位寄存器(低16位) 8位寄存器(低8位) 说明
%rax %eax %ax %ah(高4位) %al(低4位) 函数返回值
%rbx %ebx %bx %bh(高4位) %bl(低4位)
%rcx %ecx %cx %ch(高4位) %cl(低4位) 第4个参数
%rdx %edx %dx %dh(高4位) %dl(低4位) 第3个参数
%rdi %edi %di %dil 第1个参数
%rsi %esi %si %sil 第2个参数
%rbp %ebp %bp %bpl 栈低
%rsp %esp %sp %spl 指向栈顶
%r8 %r8d %r8w %r8b 第5个参数
%r9 %r9d %r9w %r9b 第6个参数
%r10 %r10d %r10w %r10b
%r11 %r11d %r11w %r11b
%r12 %r12d %r12w %r12b
%r13 %r13d %r13w %r13b
%r14 %r14d %r14w %r14b
%r15 %r15d %r15w %r15b
%rip %eip 指令寄存器
%rflags %eflags 状态和控制寄存器
%cs 代码段寄存器
%fs 数据段寄存器
%gs 数据段寄存器

21个64位通用寄存器 rax,rbx, rcx,rdx,rdi,rsi, rbp,rsp, r8,r9, r10, r11, r12,r13,r14, r15,rip,rflags,cs,fs,gs

rflags:状态和控制寄存器rflags低8位eflags

CF (bit 0) —— 进位标识,算术操作进行了进位和借位,则此位被设置

PF (bit 2) —— 奇偶标识,结果包含奇数个1,则设置此位

AF (bit 4) —— 辅助进位标识,结果的第3位像第4位借位,则此位被设置

ZF (bit 6) —— 零标识,结果为零,此位设置

SF (bit 7) —— 符号标识,若为负数则设置此位

TF (bit 8) —— 陷阱标识,设置进程可以被单步调试

IF (bit 9) —— 中断标识,设置能够响应中断请求

DF (bit 10) —— 方向标识,用于标示字符处理过程中指针移动方向。

OF (bit 11) —— 溢出标识,结果像最高位符号位进行借位或者进位,此标志被设置

rip:标志当前进程将要执行指令位置

XMM寄存器(128位)

通过一条指令执行多个数据运算,XMM0-XMM7八个寄存器,64位寄存器新加XMM8-XMM15八个寄存器。

FPU 寄存器和MMX寄存器

  1. MMX是FPU 80位寄存器的低64位,MMX0-MMX7
  2. FPU 80位寄存器用于浮点运算,FPR0-FPR7
  3. 数据寄存器包括 r0 – r7 的8个 80 位寄存器,汇编程序中通过名字 st(x) 引用

真机

指令

格式、与Intel的区别

项目 AT&T Intel 说明
寄存器命名 %eax eax intel的不带%
操作数顺序 movl $eax, %edx mov edx, eax 将eax的值赋值给edx
常熟、立即数 movl $3, %edx mov eax, 3 将三赋值给eax
jmp指令 jmp *%edx jmp edx 在AT&T的jmp地址前面要加“*”
访问内存高度 movl %eax, %edx mov edx, eax
引用全局或静态变量var的值 _var [_var]
引用全局或静态变量var的地址 $_var _var
引用局部变量 基于栈指针(ESP) 基于栈指针(ESP)
内存直接寻址 imm(base, index, indexscale) [base+index*indexscale+imm] imm+base+index*indexscale
立即数变址寻址 -4(%ebp) [ebp - 4]
整数数组寻址 0x4(, %eax, 3) [0x4 + eax * 3]
寄存器变址寻址 0x4(%ebx, %eax, 2) [ebx + eax * 2 + 0x4]
寄存器间接寻址 movw $6, %ds:(%eax) mov word ptr ds:[eax], 6

操作数长度:

b = byte 8bit

s = short (integer 16bit, floating point 64bit)

w = word 16bit

l = long(integer 32, floating point 64bit)

q = quad 64bit

t = ten bytes(floating point 80bit)

数据传送

指令 例子 效果 描述
mov movl S,D D = S S入D
movsb movsbl S,D D <--符号扩展S 符号位填充(字节->双字)
movzb movzbl S,D D <-- 零扩展S 零填充(字节->双字)
push pushl S 入栈
pop popl D 出栈

算数和逻辑操作地址

指令 例子 效果 描述
lea leal S,D D = &S S地址入D,D仅能是寄存器
add addl S,D D = D + S
inc addl D D++ 加1
sub subl S,D D = D – S
dec decl D D-- 减1
neg negl D D = -D 取负
not notl D D = ~D 取反
imul imull s,D D = D*S
xor xorl S,D D = D ^ S 异或
or orl S,D D = D | S
and andl S,D D = D & S
sal sall k,D D = D << k 左移
shl shll k,D D = D << k 左移
sar sarl k,D D = D >> k 算数右移(符号为一起右移)
shr shrl k,D D = D >> k 逻辑右移

比较

指令 实例 基于 描述
cmp cmpb S2,S1 S1 – S2 比较字节,差关系
test testb S2,S1 S1 & S2 测试字节,与关系

访问条件码指令

指令 同义名 效果 设置条件
sete D setz D = ZF 相等/零
setne D setnz D = ~ZF 不等/非零
sets D D = SF 负数
setns D D = ~SF 非负数
setg D setnle D = ~(SF ^OF) & ZF 大于(有符号>)
setge D setnl D = ~(SF ^OF) 小于等于(有符号>=)
setl D setnge D = SF ^ OF 小于(有符号<)
setle D setng D = (SF ^ OF) | ZF 小于等于(有符号<=)
seta D setnbe D = ~CF & ~ZF 超过(无符号>)
setae D setnb D = ~CF 超过或等于(无符号>=)
setb D setnae D = CF 低于(无符号<)
setbe D setna D = CF | ZF 低于或等于(无符号<=)

JCC

指令 实例 描述
jmp jmp 0x10, jmp *0x10 直接跳转,间接跳转
je, jz je 0x10 等于/零
jne, jnz jne 0x10 不等/非零
js js 0x10 负数
jns jns 0x10 非负数
jb, jnae jb 0x10 小于(无符号数)
jbe, jna jbe 0x10 小于等于(无符号数)
jnbe, ja jnbe 0x10 大于(无符号数)
jnb, jae jnb 0x10 大于等于 (无符号数)
jl, jnge jl 0x10 小于 (有符号数)
jle, jng jle 0x10 小于等于 (有符号数)
jnle, jg jnle 0x10 大于(有符号数)
jnl, jge jnl 0x10 大于等于 (有符号数)
jp, jpe jpe 0x10 结果中1的个数为偶数
jnp, jpo jpo 0x10 结果中1的个数为偶数
jo jo 0x10 溢出
jno jno 0x10 没有溢出

转移控制指令(函数调用)

指令 描述
call Label 过程调用,返回地址入栈,跳转到调用过程起始处,返回地址是call后面那条指令的地址
call *Operand
leave 为返回准备好栈,为ret准备好栈,主要是弹出函数内的栈使用及%ebp

LLDB调试

  1. po <expr>:你可以使用po命令打印出来一个继承与NSObject的类
  2. p <expr>:打印出来一些值
  3. expr/expression <expr>:可以在调试时动态的制定制定的表达式
  4. thread <expr>:打印调用的堆栈
    • thread list:用于列出所有线程,其中星号(*)表示thread#1为当前线程。
  1. br l:打印出现在项目中已经打得断点
  2. image <expr>
    • image list:查看工程中使用的库
    • image lookup --address 0x0000010:查找可执行文件或共享库的原始地址,当遇到程序崩溃时,可以使用这条命令来根据崩溃日志的原始地址查找崩溃所在的具体位置
  3. frame variable 默认输出当前帧所有参数和所有局部变量
  4. 流程控制
    • continue : 继续执行下去到达下一个断点(process continue),或者使用缩写 c;
    • next : 单步执行到下一个语句(process step-over),缩写 n;
    • step : 跳进一个函数调试(process step-into),缩写 s;
    • finish : 继续执行到下一个断点或返回语句,然后再次停止(process step-out)。
  5. help:可以列出所有可以用于调试代码的命令及功能说明
    • help <command>:列出某个命令更多的细节
  6. apropos <command>:查看LLDB有哪些功能
  7. register:读写寄存器的值:
    • register read <expr>, 这里x 指 16进制格式, 还有 f 浮点数, d 十进制数
    • register write <address> <value>
  8. memory
    • memory read <address>
    • memory read 读出所有寄存器
    • memory write <address> <value>:修改内存中的值
  9. x
    • x <address>:读取内存中的值
    • x/<num><style><size> <address>:读取内存中的值

实例

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let str0 = "1"
        let str1 = "2"
        let str2 = "7"
        let str3 = "4"
        let str4 = "5"
        let str5 = "6"
        
        funtion(p0: str0, p1: str1, p2: str2, p3: str3, p4: str4, p5: str5)
        // Do any additional setup after loading the view.
    }

    func funtion(p0: String, p1: String, p2: String, p3: String, p4: String, p5: String) -> Void {
        print(p0+p1+p2+p3+p4+p5)
    }
}
0x1044d67b1 <+145>: leaq   0x32e8(%rip), %rdi        ; "'1'"
0x1044d67b8 <+152>: movl   $0x1, %eax
0x1044d67bd <+157>: movl   $0x1, %ecx
0x1044d67c2 <+162>: movq   %rax, %rsi
0x1044d67c5 <+165>: movl   %ecx, %edx
0x1044d67c7 <+167>: movq   %rax, -0xb0(%rbp)
0x1044d67ce <+174>: movl   %ecx, -0xb4(%rbp)
0x1044d67d4 <+180>: callq  0x1044d8bae               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
0x1044d67d9 <+185>: movq   %rax, -0x40(%rbp)
0x1044d67dd <+189>: movq   %rdx, -0x38(%rbp)
0x1044d67e1 <+193>: leaq   0x32ba(%rip), %rdi        ; "'2'"
0x1044d67e8 <+200>: movq   -0xb0(%rbp), %rsi
0x1044d67ef <+207>: movl   -0xb4(%rbp), %ecx
0x1044d67f5 <+213>: movq   %rdx, -0xc0(%rbp)
0x1044d67fc <+220>: movl   %ecx, %edx
0x1044d67fe <+222>: movq   %rax, -0xc8(%rbp)
0x1044d6805 <+229>: callq  0x1044d8bae               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
0x1044d680a <+234>: movq   %rax, -0x50(%rbp)
0x1044d680e <+238>: movq   %rdx, -0x48(%rbp)

register

(lldb) register read 
General Purpose Registers:
       rax = 0x000000000000003c
       rbx = 0x00007f9c99908bd0
       rcx = 0x0000000000000000
       rdx = 0x0000000000000000
       rdi = 0x00007f9c99908bd0
       rsi = 0x00007fff5271f36a
       rbp = 0x00007ffeeb727200
       rsp = 0x00007ffeeb7270b0
        r8 = 0x00007fff89eada30  libsystem_pthread.dylib`_pthread_keys
        r9 = 0x000000000000001f
       r10 = 0x00000001044dda28  (void *)0x00000001044ddbb0: _TtC3ATT14ViewController
       r11 = 0x00007fff47a42e67  UIKitCore`-[UIViewController(UIKitManual) release]
       r12 = 0x0000000000000270
       r13 = 0x00007f9c99908bd0
       r14 = 0x0000000000000000
       r15 = 0x00007fff513f7780  libobjc.A.dylib`objc_msgSend
       rip = 0x00000001044d67b1  ATT`ATT.ViewController.viewDidLoad() -> () + 145 at ViewController.swift:16:20
    rflags = 0x0000000000000206
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000
(lldb) register read $rsp
     rsp = 0x00007ffeeb7270b0

局部变量

&str0 = 0x7ffeeb7271c0
&str1 = 0x7ffeeb7271b0
&str2 = 0x7ffeeb7271a0
&str3 = 0x7ffeeb727190
&str4 = 0x7ffeeb727180
&str5 = 0x7ffeeb727170
/// 内存位于栈内,栈顶rsp:栈低rbp

方法参数

0x1044d6a84 <+20>:  movq   0x38(%rbp), %rax
0x1044d6a88 <+24>:  movq   0x30(%rbp), %r10
0x1044d6a8c <+28>:  movq   0x28(%rbp), %r11
0x1044d6a90 <+32>:  movq   0x20(%rbp), %rbx
0x1044d6a94 <+36>:  movq   0x18(%rbp), %r14
0x1044d6a98 <+40>:  movq   0x10(%rbp), %r15
0x1044d6a9c <+44>:  xorps  %xmm0, %xmm0
0x1044d6a9f <+47>:  movaps %xmm0, -0x40(%rbp)
0x1044d6aa3 <+51>:  movaps %xmm0, -0x50(%rbp)
0x1044d6aa7 <+55>:  movaps %xmm0, -0x60(%rbp)
0x1044d6aab <+59>:  movaps %xmm0, -0x70(%rbp)
0x1044d6aaf <+63>:  movaps %xmm0, -0x80(%rbp)
0x1044d6ab3 <+67>:  movaps %xmm0, -0x90(%rbp)
0x1044d6aba <+74>:  movq   $0x0, -0x98(%rbp)
0x1044d6ac5 <+85>:  movq   %rdi, -0x40(%rbp)
0x1044d6ac9 <+89>:  movq   %rsi, -0x38(%rbp)
0x1044d6acd <+93>:  movq   %rdx, -0x50(%rbp)
0x1044d6ad1 <+97>:  movq   %rcx, -0x48(%rbp)
0x1044d6ad5 <+101>: movq   %r8, -0x60(%rbp)
0x1044d6ad9 <+105>: movq   %r9, -0x58(%rbp)
0x1044d6add <+109>: movq   %r15, -0x70(%rbp)
0x1044d6ae1 <+113>: movq   %r14, -0x68(%rbp)
0x1044d6ae5 <+117>: movq   %rbx, -0x80(%rbp)
0x1044d6ae9 <+121>: movq   %r11, -0x78(%rbp)
0x1044d6aed <+125>: movq   %r10, -0x90(%rbp)
0x1044d6af4 <+132>: movq   %rax, -0x88(%rbp)
/// rdi=1, rsi=0xe100000000000000
/// rdx=2, rcx=0xe100000000000000
/// r8=7, r9=0xe100000000000000
/// r15=4, r14=0xe100000000000000
/// rbx=5, r11=0xe100000000000000
/// r10=6
/// rax=0xe100000000000000 返回值

x指令

%rbp-0x2fdb = %rax(0x0000007473726946="tsriF")

%rbp-0x30 = %rax(0x0000646e6f636553="dnoceS")

(lldb) x/xw 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: 0x6f636553
(lldb) x/bw 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: 0x6f636553
(lldb) x/uw 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: 1868784979
(lldb) x/cw 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: Seco
(lldb) x/cg 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: Second\0\0
(lldb) x/ct 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: 0b0000000000000000011001000110111001101111011000110110010101010011
(lldb) x/cs 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: "Second"
(lldb) x/cb 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: 'S'
(lldb) x/3cs 0x00007ffedfe2d1c0
0x7ffedfe2d1c0: "Second"
0x7ffedfe2d1c7: ""
0x7ffedfe2d1c8: ""
上一篇下一篇

猜你喜欢

热点阅读