Ubuntu x86-64汇编(6)
寻址方式 Addressing Modes
地址和值 Addresses vs Values
在64bit架构中, 地址是64bit. 访问内存内容的唯一方式就是通过方括号, 不加方括号读取的只是地址, 例如
mov rax, qword [var1] ; value of var1 in rax mov rax, var1 ; address of var1 in rax
寻址方式 Addressing Modes
在访问内存时, 大多数情况下尺寸是明确的, 例如下面的尺寸是double word
mov eax, [rbx]
但是有一些情况是不明确的, 例如
inc [rbx] ; error
这时候需要显式标明其尺寸, 例如
inc byte [rbx] inc word [rbx] inc dword [rbx]
寄存器寻址 Register Mode Addressing
寄存器寻址表明运算数是一个CPU寄存器(eax, ebx, etc.), 例如下面的eax, ebx都是寄存器寻址
mov eax, ebx
立即数寻址 Immediate Mode Addressing
这种模式下运算数为立即数, 例如下面的123就是立即数寻址
mov eax, 123
内存寻址 Memory Mode Addressing
这种模式下运算数为内存地址, 可以是间接或引用, 例如如下指令将会从内存中找到变量qNum的地址并读出其中的qword尺寸的值
mov rax, qword [qNum]
相比寄存器寻址和立即数寻址, 这个操作CPU需要等待更多的时间等待内容读取完成, 当读取数组时, 有更通用的方法, 地址可以放在寄存器中, 例如
lst dd 101, 103, 105, 107
数组第一个元素可以通过如下指令读取
mov eax, dword [list] ; 以及这个方法, 将开始的地址放到rbx mov rbx, list mov eax, dword [rbx]
读取列表中其他元素, 可以通过
mov rbx, list mov rsi, 8
因为地址的增长是以byte为单位的, 此数组每个元素的尺寸为double word = 4byte, 下面的每个指令, 都能通过开始地址偏移8(8个byte)后, 读取到数组中的第三个元素 105
mov eax, dword [list+8] mov eax, dword [rbx+8] mov eax, dword [rbx+rsi]
一个通用的寻址计算公式为
[ baseAddr + (indexReg * scaleValue ) + displacement ]
baseAddr 为寄存器或变量名
indexReg 必须为寄存器
scaleValue 是一个立即数, 值为1, 2, 4, 8, (1是合法的但是没有意义)
displacement 是一个立即数,
以上合起来表示一个64bit地址
一些寻址的例子
mov eax, dword [var1] mov rax, qword [rbx+rsi] mov ax, word [lst+4] mov bx, word [lst+rdx+2] mov rcx, qword [lst+(rsi*8)] mov al, byte [buff1+rcx] mov eax, dword [rbx+(rsi*4)+16] mov rsi, 2 ; index=2 mov eax, dword [list+rsi*4] ; get lst[2]
计算数组之和的代码例子
; Simple example to the sum and average for ; a list of numbers. ; ***************************************************** ; Data declarations section .data ; ---- ; Define constants EXIT_SUCCESS equ 0 ; successful operation SYS_exit equ 60 ; call code for terminate ; ---- ; Define Data. section .data lst dd 1002, 1004, 1006, 1008, 10010 len dd 5 sum dd 0 ; ******************************************************** section .text global _start _start: ; ---- ; Summation loop. mov ecx, dword [len] ; get length value mov rsi, 0 ; index=0 sumLoop: mov eax, dword [lst+(rsi*4)] ; get lst[rsi] add dword [sum], eax ; update sum inc rsi ; next item loop sumLoop ; ---- ; Done, terminate program. last: mov rax, SYS_exit ; call code for exit mov rdi, EXIT_SUCCESS ; exit with success syscall
栈操作
push <op64>
将64bit的运算数加入堆栈: 先将rsp-8, 然后将运算数复制到[rsp] (rsp指向的地址), 例子
push rax push qword [qVal] ; value push qVal ; address
pop <op64>
将64bit的栈顶内容复制到运算数. 然后将rsp+8, 例子
pop rax pop qword [qVal] pop rsi
堆栈布局 Stack Layout
堆(heap)用于为数据动态申请内存空间, 例如在C++中的new或C中的malloc(). 申请内存时, 堆地址是往上长的. 而栈地址是从高地址位往下长. 如果堆地址和栈地址相交则程序将崩溃.
代码例子, 用栈将一个数组倒序
; Simple example demonstrating basic stack operations. ; Reverse a list of numbers in place. ; Method: Put each number on stack, the pop each number ; back off, and then put back into memory. ; ***************************************************** ; Data declarations section .data ; ---- ; Define constants EXIT_SUCCESS equ 0 ; successful operation SYS_exit equ 60 ; call code for terminate ; ---- ; Define Data. numbers dq 121, 122, 123, 124, 125 len dq 5 ; **************************************************** section .text global _start _start: ; Loop to put numbers on stack. mov rcx, qword [len] mov rbx, numbers mov r12, 0 mov rax, 0 pushLoop: push qword [rbx+r12*8] inc r12 loop pushLoop ; --- ; All the numbers are on stack (in reverse order). ; Loop to get them back off. Put them back into ; the original list... mov rcx, qword [len] mov rbx, numbers mov r12, 0 popLoop: pop rax mov qword [rbx+r12*8], rax inc r12 loop popLoop ; ---- ; Done, terminate program. last: mov rax, SYS_exit ; call code for exit mov rdi, EXIT_SUCCESS ; exit with success syscall
.
相关文章
- Amazon Comprehend Medical 批处理模式处理简介
- 以云为助的下一代银行
- java.lang.UnsupportedClassVersionError
- 搭建云上日志收集分析系统 (EKK Amazon Elasticsearch Service, Amazon Kinesis, and Kibana)
- 企业备份&灾备专题
- 企业备份&容灾系列 – 其他云服务商 to AWS Cold Backup 容灾解决方案
- 企业备份&容灾系列 — 使用AWS为本地数据中心实现Cold backup & Pilot light容灾解决方案
- 企业备份&容灾系列 – AWS 多区域 Pilot Light 容灾设计
- 现已推出 8211 配有 NVIDIA T4 Tensor Core GPU 的 EC2 实例 (G4)
- 新增功能 – Step Functions 支持动态并行性
- 如何测试 Amazon Elastic File System
- Python Socket 网络编程
- python threading 学习笔记
- AWS数据纵深防御篇-如何配置EBS整合KMS的静态加密
- 了解 AWS 服务和 & 解决方案 – AWS 9 月在线技术讲座
- Python3 : pdb调试
- AWS 为什么要为开源做贡献? 以 Firecracker 为例
- 适用于 EBS CSI 驱动程序的 EKS 支持
- 介绍最新的 AWS 精英 – 2019 年 9 月
- 介绍服务账户的精细 IAM 角色