汇编基础

14 篇文章 0 订阅
1 篇文章 0 订阅

一、汇编基础

1.1-程序的本质

装载
1
2
3
控制
硬盘/程序软件
内存
CPU
寄存器/信息存储
运算器/信息处理
控制器
计算机/显示器音响等其他设备

1.2-寄存器与内存

/*
CPU会先将内存中的数据存储到寄存器中,然后再对寄存器中的数据进行运算;

例:
CPU先将数字1放到rax寄存器中:movq 1的内存空间, %rax
然后将rax寄存器与1相加:addq $0x1,%rax
最后赋值给内存空间:movq %rax,新内存空间
*/
内存 CPU 取出数字1 RAX+1=2 赋值给内存空间 内存 CPU

1.3-编程语言

1、机器语言:由01组成,1000100111011000
2、汇编语言:用符号代替01,movw %bx,%ax
3、高级语言:C\C++\JAVA\JavaScript\Python等等,ax=bx
/*
汇编语言和机器语言对应,每一条指令都有对应的汇编指令
汇编语言可以通过编译得到机器语言,机器语言可以通过反编译得到汇编语言
高级语言可以通过编译得到汇编语言\机器语言,但汇编语言\机器语言很难还原成高级语言
*/
编译
编译
反编译
运行
高级语言
汇编语言
机器语言
计算机

1.4-汇编语言的种类

/*
8086汇编(16bit)
x86汇编(32bit)
x64汇编(64bit)
ARM汇编(嵌入式、移动设备)
...

x86、x64根据编译器不同两种书写格式:intel(windows)、at&t(unix)

IOS开发最主要的汇编语言:at&t汇编(ios模拟器)和arm汇编(真机)
*/

1.5-常见的汇编指令

1.寄存器引用 
   引用寄存器要在寄存器号前加百分号%,如“movl %eax, %ebx”。 
    80386有如下寄存器: 
    832-bit寄存器 %eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp; 
    816-bit寄存器 它们事实上是上面832-bit寄存器的低16位:
                   %ax,%bx,%cx,%dx,%di,%si,%bp,%sp; 
    88-bit寄存器  %ah,%al,%bh,%bl,%ch,%cl,%dh,%dl。
                  它们事实上是寄存器%ax,%bx,%cx,%dx的高8位和低8位; 
    6个段寄存器   %cs(code)%ds(data)%ss(stack), %es,%fs,%gs; 
    3个控制寄存器 %cr0,%cr2,%cr3; 
    6个debug寄存器  %db0,%db1,%db2,%db3,%db6,%db7; 
    2个测试寄存器  %tr6,%tr7; 
    8个浮点寄存器栈 %st(0)%st(1)%st(2)%st(3)%st(4)%st(5)%st(6)%st(7)2. 操作数顺序 
    操作数排列是从源(左)到目的(右),如“movl %eax(源), %ebx(目的)” 
3. 立即数 
    使用立即数,要在数前面加符号$
      如“movl $0x04, %ebx” 
         或者: 
         para = 0x04 
         movl $para, %ebx 
    指令执行的结果是将立即数04h装入寄存器ebx。 
4. 符号常数 
    符号常数直接引用 如 
    value: .long 0x12a3f2de 
    movl value , %ebx 
    指令执行的结果是将常数0x12a3f2de装入寄存器ebx。 
    引用符号地址在符号前加符号$, 如“movl $value, % ebx”则是将符号value的地址装入寄存
    器ebx。 
5. 操作数的长度 
        操作数的长度用加在指令后的符号表示b(byte, 8-bit), w(word, 16-bits), l
    (long, 32-bits),如“movb %al, %bl”,“movw %ax, %bx”,“movl %eax, %ebx ”。 
        如果没有指定操作数长度的话,编译器将按照目标操作数的长度来设置。比如指令“mov %
    ax, %bx”,由于目标操作数bx的长度为word,那么编译器将把此指令等同于“movw %ax, %
    bx”。同样道理,指令“mov $4, %ebx”等同于指令“movl $4, %ebx”,“push %al”等同
    于“pushb %al”。对于没有指定操作数长度,但编译器又无法猜测的指令,编译器将会报错,
    比如指令“push $4”。 
6. 符号扩展和零扩展指令 
        绝大多数面向80386AT&T汇编指令与Intel格式的汇编指令都是相同的,符号扩展指令和
    零扩展指令则是仅有的不同格式指令。符号扩展指令和零扩展指令需要指定源操作数长度和目的
    操作数长度,即使在某些指令中这些操作数是隐含的。 
        在AT&T语法中,符号扩展和零扩展指令的格式为,基本部分"movs""movz"(对应Intel语
    法的movsx和movzx),后面跟上源操作数长度和目的操作数长度。movsbl意味着movs (from)
    byte (to)long;movbw意味着movs (from)byte (to)word;movswl意味着
    movs (from)word (to)long。对于movz指令也一样。比如指令“movsbl %al, %edx”意味
    着将al寄存器的内容进行符号扩展后放置到edx寄存器中。 
 
    其它的Intel格式的符号扩展指令还有: 
            cbw -- sign-extend byte in %al to word in %ax; 
            cwde -- sign-extend word in %ax to long in %eax; 
            cwd -- sign-extend word in %ax to long in %dx:%ax; 
            cdq -- sign-extend dword in %eax to quad in %edx:%eax; 
    对应的AT&T语法的指令为cbtw,cwtl,cwtd,cltd7. 调用和跳转指令 
        段内调用和跳转指令为"call""ret""jmp",段间调用和跳转指令为   
    为:"lcall""lret""ljmp"。 
        段间调用和跳转指令的格式为“lcall/ljmp $SECTION, $OFFSET”,而段间返回指令则为
    “lret $STACK-ADJUST”。 
8. 前缀 
    操作码前缀被用在下列的情况: 
        字符串重复操作指令(rep,repne); 
        指定被操作的段(cs,ds,ss,es,fs,gs); 
        进行总线加锁(lock); 
        指定地址和操作的大小(data16,addr16); 
    在AT&T汇编语法中,操作码前缀通常被单独放在一行,后面不跟任何操作数。例如,对于重复
    scas指令,其写法为: 
             repne 
             scas 
    上述操作码前缀的意义和用法如下: 
        指定被操作的段前缀为cs,ds,ss,es,fs,和gs。在AT&T语法中,只需要按照
    section:memory-operand的格式就指定了相应的段前缀。比如:lcall %:realmode_swtch
    操作数/地址大小
        前缀是“data16”和"addr16",它们被用来在32-bit操作数/地址代码中指定16-bit的操
    作数/地址。 
        总线加锁前缀“lock”,它是为了在多处理器环境中,保证在当前指令执行期间禁止一切中
    断。这个前缀仅仅对ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG,DEC, INC, NEG, NOT, 
    OR, SBB, SUB, XOR, XADD,XCHG指令有效,如果将Lock前缀用在其它指令之前,将会引起异
    常。 
        字符串重复操作前缀"rep","repe","repne"用来让字符串操作重复“%ecx”次。 
9. 内存引用 
    Intel语法的间接内存引用的格式为: 
        section:[base+index*scale+displacement] 
    而在AT&T语法中对应的形式为: 
        section:displacement(base,index,scale) 
    其中,base和index是任意的32-bit base和index寄存器。scale可以取值1248。如果不
    指定scale值,则默认值为1。section可以指定任意的段寄存器作为段前缀,默认的段寄存器在
    不同的情况下不一样。如果你在指令中指定了默认的段前缀,则编译器在目标代码中不会产生此
    段前缀代码。 
如果call和jump操作在操作数前指定前缀“*”,则表示是一个绝对地址调用/跳转,也就是说jmp/call指令指定的是一个绝对地址。如果没有指定"*",则操作数是一个相对地址。 
任何指令如果其操作数是一个内存操作,则指令必须指定它的操作尺寸(byte,word,long),也就是说必须带有指令后缀(b,w,l)

1.6-寄存器

16个常用寄存器:rax\rbx\rcx\rdx\rsi\rdi\rbp\rsp\
             r8\r9\r10\r11\r12\r13\r14\r15

寄存器用途:
rax、rdx常做为函数返回值用
rdi、rsi、rdx、rcx、r8、r9等寄存器常用于存放函数参数
rsp、rbp用于栈操作
rip做为指令指针
	存粗cpu下一条要执行指令的地址
	一旦cpu读取一条指令,rip会自动指向下一条指令(%rip存储下一条指令的地址)
	

1.7 lldb常用指令

1、读取寄存器的值
	register read/格式
	register read/x
2、修改寄存器的值
	register write 寄存器名称 数值
	register write rax 0
3、读取内存中的值
	x/数量-格式-字节大小 内存地址
	x/3xw 0x00000010
4、修改内存中的值
	memory write 内存地址 数值
	memery write 0x00000010 10
5、格式
	表示	    进制
	x		16
	f		浮点
	d		10
6、字节大小
	表示     大小		字节
	b		byte 		1
	h		half word 	2
	w		word 		4
	g		giant word 	8
7、expression表达式
	expr
	expression $rax
	expression $rax=1
8、po表达式print表达式
	po/x $rax
	po (int)$rax
9、单步运行,把子函数当作整体一步执行
	(源码级别)thread step-over->缩写next->缩写n
	 (汇编级别)thread step-inst-over->缩写nexti->缩写ni
10、单步运行,遇到子函数进入子函数
	(源码级别)thread step-in->缩写step->缩写s
	 (汇编级别)thread step-inst-in->缩写stepi->缩写si
11、直接执行完当前函数的所有代码,返回到上一个函数,遇到断电卡住
	thread step-out->缩写finish

1.8-常见规律

1、内存地址格式为:0x4bdc(%rip)一般是全局变量、全局区、数据段
2、内存地址格式为:-0x78%rbp)一般为局部变量、函数内、栈空间
3、内存地址格式为:0x10(%rax)一般为堆空间、类
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值