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寄存器
- MMX是FPU 80位寄存器的低64位,MMX0-MMX7
- FPU 80位寄存器用于浮点运算,FPR0-FPR7
- 数据寄存器包括 r0 – r7 的8个 80 位寄存器,汇编程序中通过名字 st(x) 引用
真机
- x0,x1,x2,x3,x4,x5,x6,x7用来保存参数
objc_msgSend会有两个默认参数,x0=self x1=_cmd - fp=frame point, lr=link point
指令
格式、与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调试
- po <expr>:你可以使用po命令打印出来一个继承与NSObject的类
- p <expr>:打印出来一些值
- expr/expression <expr>:可以在调试时动态的制定制定的表达式
- thread <expr>:打印调用的堆栈
- thread list:用于列出所有线程,其中星号(*)表示thread#1为当前线程。
- thread backtrace / bt
- bt all:打印出所有的thread的堆栈
- thread return 跳出当前方法的执行;thread return 10 直接跳过方法执行,返回10
- br l:打印出现在项目中已经打得断点
- image <expr>
- image list:查看工程中使用的库
- image lookup --address 0x0000010:查找可执行文件或共享库的原始地址,当遇到程序崩溃时,可以使用这条命令来根据崩溃日志的原始地址查找崩溃所在的具体位置
- frame variable 默认输出当前帧所有参数和所有局部变量
- 流程控制
- continue : 继续执行下去到达下一个断点(process continue),或者使用缩写 c;
- next : 单步执行到下一个语句(process step-over),缩写 n;
- step : 跳进一个函数调试(process step-into),缩写 s;
- finish : 继续执行到下一个断点或返回语句,然后再次停止(process step-out)。
- help:可以列出所有可以用于调试代码的命令及功能说明
- help <command>:列出某个命令更多的细节
- apropos <command>:查看LLDB有哪些功能
- register:读写寄存器的值:
- register read <expr>, 这里x 指 16进制格式, 还有 f 浮点数, d 十进制数
- register write <address> <value>
- memory
- memory read <address>
- memory read 读出所有寄存器
- memory write <address> <value>:修改内存中的值
- 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: ""
网友评论