Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

汇编语言学习笔记

4
Feb
2004

汇编语言学习笔记

By Alex
/ in Assembly
0 Comments
X84-64

x86-64(也叫x64或amd64)是x86/IA32指令集的64-bit版本。

编译器

可以使用NASM,它针对x86系列处理器:

Shell
1
sudo apt-get install nasm
常用指令

很多指令会带有b w l q后缀,分别表示操作寄存器的1 2 4 8字节。

指令 C助记符 说明
赋值操作
mov src, dst dst = src 

从源复制值到目标,源可以是一个直接量、寄存器、内存地址,目标可以是寄存器或内存地址。源/目标不能同时是内存地址

movb movw movl movq分别表示移动1 2 4 8字节(整数的低位)

Assembly
1
2
3
mov $0, %eax              ; %eax = 0
movb %al, 0x409892        ; write to address 0x409892 low-byte of %eax
mov 8(%rsp), %eax         ; %eax = value read from address %rsp + 8
movs  

mov时,如果是位宽小的数据拷贝到位宽大的目标,则使用sign-extend填充额外字节

Assembly
1
movsbl %al, %edx    ; copy 1-byte %al, sign-extend into 4-byte %edx 
cltq   专门操作%rax,等价于 movslq %eax,%rax
movz   mov时,如果是位宽小的数据拷贝到位宽大的目标,则使用zero填充额外字节
Assembly
1
movzbl %al, %edx    ; copy 1-byte %al, zero-extend into 4-byte %edx

需要注意:用mov将32bit值拷贝到寄存器时,高32bit自动清零,相当于自动movz。下面的指令: 

Assembly
1
mov %ebx, %ebx

看似无意义,实际上会将高32bit清零 

lea src, dst dst = src 即load effective address指令,源是一个内存地址,将计算得到的地址(不是数据)拷贝到目标:
Assembly
1
2
lea 0x20(%rsp), %rdi      ; %rdi = %rsp + 0x20 (no dereference!)
lea (%rdi,%rdx,1), %rax   ; %rax = %rdi + %rdx

该指定不会对源地址进行解引用操作 

算术操作
add src, dst dst += src  
sub src, dst dst -= src  
imul src, dst   dst *= src imul src这种特殊用法,假设乘法的另外一个操作数位于%rax,计算得到128bit结果,高64bit存放到%rdx
neg dst dst = -dst  
 and src, dst dst &= src  
or src, dst dst |= src  
xor src, dst dst ^= src 按位异或
not dst dst = ~dst 按位取反
shl count, dst dst <<= count 左移,同义词sal
sar count, dst dst >>= coun 算术右移
shr count, dst dst >>= coun 逻辑右移
条件分支
cmp op2, op1 result = op1 - op2

属于算术指令,计算结果丢弃,在%eflags中设置条件代码(结果为0也就是操作数相等则ZF置1)。操作数可以是直接量、内存地址(最多一个操作数)、寄存器

test op2, op1 result = op1 & op2 属于逻辑指令,计算结果丢弃,在%eflags中设置条件代码(结果为0则ZF置1)。操作数可以是直接量、内存地址(最多一个操作数)、寄存器
jmp target   无条件跳转
je target if (ZF=1) goto 如果相等,则跳转
jne target if (ZF=0) goto 如果不等,则跳转
jl target if (SF!=OF) goto 如果小于,则跳转
jle target if (ZF=0 || SF!=OF) goto 如果小于等于,则跳转
jg target if (ZF=0 and SF=O) goto 如果大于,则跳转
jge target if (SF=OF) goto 如果大于等于,则跳转
js if (SF=1) goto  
jns if (SF=0) goto  
sete dst   如果ZF=1,则将dst寄存器的值设置为1
setge dst   如果大于等于,则将dst寄存器的值设置为1
函数调用栈
push dst  

将直接量、寄存器或者内存地址压入栈中,操作数变成新的栈顶,%rsp寄存器的值因而递减

Assembly
1
2
3
push %rbx         ; 将%rbx的值压栈
pushq $0x3        ; 将直接量3压栈
sub $0x10, %rsp   ; 调整栈指针,增加10字节
pop dst  

弹出栈顶的值,存入目标寄存器,%rsp寄存器的值因而递增

Assembly
1
2
pop %rax          ; 将栈顶的值存放到%rax
add $0x10, %rsp   ; 从栈顶移除16字节
callq funcaddr funcaddr() 通过地址调用指定的函数。它指令将返回地址(当前函数下一条指令的地址)压栈(%rip),然后跳转到目标函数上继续运行
retq  return 弹出栈顶作为%rip的值,导致当前函数调用返回
寄存器

常用的寄存器包括16个通用寄存器,两个特殊用途寄存器。每个寄存器都是64bit大小,通过一个伪名,可以饮用低32/16/8位部分。

下表列出这些寄存器的惯用法。-owned标注出所有者,所有者(函数调用时)可以自由使用寄存器,覆盖它的值,非所有者则必须复制值到其它地方才能安全使用

寄存器 惯例用法 低32位 低16位 低8位
%rax 用于返回值,被调用者拥有 %eax %ax %al
%rdi 1st argument, callee-owned %edi %di %dil
%rsi 2nd argument, callee-owned %esi %si %sil
%rdx 3rd argument, callee-owned %edx %dx %dl
%rcx 4th argument, callee-owned %ecx %cx %cl
%r8 5th argument, callee-owned %r8d %r8w %r8b
%r9 6th argument, callee-owned %r9d %r9w %r9b
%r10 Scratch/temporary, callee-owned %r10d %r10w %r10b
%r11 Scratch/temporary, callee-owned %r11d %r11w %r11b
%rsp

用于栈指针,调用者拥有。push/pop指令添加/删除栈的元素

直接操作该寄存器,可以实现添加、删除一系列变量

注意:栈是向下增长的,也就是向低地址方向增长

%esp %sp %spl
%rbx Local variable, caller-owned %ebx %bx %bl
%rbp Local variable, caller-owned %ebp %bp %bpl
%r12 Local variable, caller-owned %r12d %r12w %r12b
%r13 Local variable, caller-owned %r13d %r13w %r13b
%r14 Local variable, caller-owned %r14d %r14w %r14b
%r15 Local variable, caller-owned %r15d %r15w %r15b
%rip

指令寄存器,指向下一条需要执行的指令地址

调用函数时,该寄存器的值被压栈,以便函数调用完毕后能够返回

     
%eflags

Status/condition code bits

这个特殊的寄存器,用于存放一系列的boolean标记位 —— 条件代码(condition codes),大部分算术运算符都会更新这些代码

条件跳转(conditional jump)指令会读取条件代码,来确定是否跳转到某个分支

条件代码包括:

ZF 零标记,如果上一次比较/算术操作符产生“相等”或零,则设置为1
SF 正负标记
OF 溢出标记,有符号
CF carry标记,无符号

     
地址模式

由于CISC的特性,x86-64支持多种不同的地址模式。地址模式用于计算内存地址,以便读写之。下面的汇编指令说明了如何向各种地址模式写入数据:

Assembly
1
2
3
4
5
6
7
8
9
10
11
12
movl $1, 0x604892         ; 直接地址,地址是常量
movl $1, (%rax)           ; 间接地址,地址存放在寄存器中
 
movl $1, -24(%rbp)        ; 直接地址+置换  base %rbp + displacement -24
 
movl $1, 8(%rsp, %rdi, 4) ;  indirect with displacement and scaled-index (address = base %rsp + displ 8 + index %rdi * scale 4)
 
movl $1, (%rax, %rcx, 8)  ; (special case scaled-index, displ assumed 0)
 
movl $1, 0x8(, %rdx, 4)   ; (special case scaled-index, base assumed 0)
 
movl $1, 0x4(%rax, %rcx)  ; (special case scaled-index, scale assumed 1)
函数调用

通过callq指令可以发起函数调用,被调用函数中使用retq指令来返回。

调用者必须将前6个参数存入%rdi, %rsi, %rdx, %rcx, %r8, %r9这些寄存器中。如果参数超过6个,额外的参数压栈。

Assembly
1
2
3
mov $0x3, %rdi    ; 第一个参数存入 %rdi
mov $0x7, %rsi    ; 第二个参数存入 %rsi
callq binky       ; 移交控制权给binky函数

被调用函数运行结束后,它应该将返回值写入到%rax,并清理掉栈,最后使用retq指令:

Assembly
1
2
3
mov $0x0, %eax    ; 设置返回值
add $0x10, %rsp   ; 解除栈分配
retq              ; 从当前函数返回,回到caller继续执行
跳转执行

条件分支、静态跳转、函数调用,都会导致跳转执行。

跳转执行的目标,通常是在编译阶段就确定下来的绝对地址。 但是,很多情况下,目标仅到运行时才能知道,这种情况下目标地址被编译器存放在寄存器中。

← HTML知识集锦
MS-DOS批处理学习笔记 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

No related posts.

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2