【读书笔记】汇编语言程序设计

本文作为《汇编语言程序设计》的读书笔记,详细介绍了汇编的基础知识,包括基础指令、通用寄存器、开发工具、操作码语法、汇编程序的创建、调试和函数调用等。重点讲解了汇编语言在游戏服务器宕机问题排查中的作用,通过实例演示了如何使用gdb进行调试,并强调了汇编语言在理解和分析程序执行过程中的重要性。此外,还探讨了内联汇编在C/C++中的应用,以及如何通过strace跟踪系统调用。
摘要由CSDN通过智能技术生成

这里写图片描述

零.阅读目的

C++开发的游戏服务器避免不了偶尔出现的宕机问题,在查找宕机问题时,一般都会分析dump,但由于编译器优化问题和64位dump调试的不方便,能看懂汇编可以起到事半功倍的效果,通常可以通过反汇编查找空指针或者程序的执行过程,所以阅读本书的目标是:看懂汇编,并不深究

一.汇编基础

1.基础指令汇总
  • mov //传送指令
  • cmov //条件传送指令
  • xchg //交换指令
  • push //压栈
  • pop //出栈
  • pusha/popa //压入/弹出所有16位通用寄存器
  • pushad/popad //压入/弹出所有32位通用寄存器
  • add //加法
  • sub //减法
  • inc //自增
  • dec //递减
  • mul //无符号乘
  • imul //带符号乘
  • div //无符号除
  • idiv //带符号除
  • sal //向左移位,右边补0
  • shr //无符号,向右移位,左边补0
  • sar //带符号,向右移位,左边补1
  • lea //赋值地址
  • xor //异或,可用来清零 ^
  • or //或者 ||
  • not //非 !
  • and //并且 &&
  • nop //空指令
  • test //位判断
  • je //j开头的均为条件跳转指令,带n的为反义
  • call //调用函数
  • enter //替代函数操作esp,pushl %ebp movl %esp, %ebp
  • leave //替代函数操作esp,movl %ebp, %esp popl %ebp
  • ret //函数返回指令
  • jmp //跳转到某个地址
  • int //中断
  • rep //重复执行某个操作,知道ecx为0
  • loop //循环直到ecx寄存器为0

以上列举了一些非常常见的汇编指令,在调试过程中,这些指令无处不在,也是必须要掌握的基本指令。

2.数据类型
  • AT&T语法
    使用L,W,B来表示数据大小,分别代表四位long,两位word,一位byte;
  • intel语法
    byte(字节)、word(字)、dword(双字)、qword(四字)、tbyte(十字节),可以放在ptr前面

二.通用寄存器

1.32位寄存器
  • EAX 用于操作数和结果数据的累加器
  • EBX 指向数据内存段中的数据的指针
  • ECX 字符串和循环操作的计数器
  • EDX I/O指针
  • EDI 用于字符串操作的目标的数据指针
  • ESI 用于字符串操作的源的数据指针
  • ESP 堆栈指针
  • EBP 堆栈数据指针
2.64位寄存器
  • RAX
  • RBX
  • RCX
  • RDX
  • RDI
  • RSI
  • RSP
  • RBP
3.系统寄存器
  • EIP 系统寄存器,用来记录CPU要执行的指令地址
4.寄存器的特定使用

linux程序中,程序的退出的状态码保存在%ebx寄存器中
movl $8, %ebx
echo $? //可以显示上一个程序的退出码,也就是ebx寄存器的值
linux平台可以使用echo $?查看程序返回值,若使用汇编变成,那么可以将返回值传送到ebx寄存器

5.8位、16位、32位寄存器
位数 寄存器 寄存器 寄存器 寄存器
32位 EAX EBX ECX EDX
16位 AX BX CX DX
8位 AH/AL BH/BL CH/CL DH/DL

三.开发工具

1.汇编器

MASM 微软开发的 http://www.masm32.com/
NASM
GAS GNU系列,另外有gcc、g++
HLA

2.连接器

ld:把汇编语言目标代码和其他库连接在一起,生成操作系统可执行文件

3.调试器

gdb:停止程序、检查修改数据

4.编译器

as:把高级语言转换为处理器能够执行的指令码

5.目标代码反汇编器

objdump:将可执行文件或者目标代码文件转换成汇编语言

6.简档器

gprof:跟踪每个函数在程序执行过程中被使用时花费了多长处理器时间

7.一些需要用到的工具

gdb
kdbg 图形化调试工具
objdump 查看反汇编
gprof 性能分析工具:可以查看函数被调用多少次多少时间
gcc -o demo demo.c -pg
./demo
gprof demo > gprof.txt

gcc过程:
gcc -S ctest.c //生成ctest.s
as ctest.s -o ctest.o
ld ctest.o -o ctest //这一步如果涉及到调用C库函数,那么就得带其他参数

四.操作码语法(Intel和AT&T的语法不同)

AT&T和intel汇编语法,比较明显的是操作数顺序相反,主要区别有以下几点:

编号 Intel AT&T AT&T说明
1 4 $4 AT&T使用$表示立即操作数
2 eax %eax AT&T在寄存器名称前面加上前缀%
3 mov eax, 4 movl $4, %eax 处理源和目标使用相反的顺序
4 mov eax, dword ptr test movl $test, %eax AT&T不用指定数据长度,但mov后面要指定L,W,B
5 jmp section:offset ljmp section, offset 长调用和跳转使用不同语法定义段和偏移值
6 -4(%ebp) [ebp-4] 间接寻址
7 foo(,%eax,4) [foo + eax*4] 间接寻址

这里只是列举了几个常见并且比较基本的区别,太复杂的语法没有深究。

五.汇编程序

1.基本模板
#注释
.section .data
.section .bss
.section .text
.globl _start
_start:
    movl $0, %eax
2.编译
as cpuid.s -o cpuid.o  (-gstabs 添加调试信息)
ld cpuid.o -o cpuid
3.调试(几个gdb常用调试命令)
  • break * label + offset 下断点,指定行数也行
  • next 下一行
  • step 下一步,若有函数,则进入函数
  • continue
  • run
  • info registers 查看寄存器
  • print /x $ebx 查看寄存器十六进制值
  • layout asm 切到反汇编
  • x/nyz: 显示内存位置
    • n是字段数: 个数
    • y是输出格式 c字符 d十进制 x十六进制
    • z是显示字段长度 b字节 h半字 w32位字
    • 例子:x/42cb &output 查看该变量42位字符
4.测试程序
#cpuid2.s
.section .data
output:
    .asciz "The processor Vendor ID is '%s'\n"
.section .bss
    .lcomm buffer, 12
.section .text
.globl _start
_start:
    movl $0, %eax
    cpuid
    movl $buffer, %edi
    movl %ebx, (%edi)
    movl %edx, 4(%edi)
    movl %ecx, 8(%edi)
    pushl $buffer
    pushl $output
    call printf
    addl $8, %esp
    pushl $0
    call exit

编译运行

gzshun@gzshun-vm:~/c$ as cpuid2.s -o cpuid2.o
gzshun@gzshun-vm:~/c$ ld cpuid2.o 
  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值