寻址方式 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 [buff­1+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

.

Ubuntu x86-64汇编(6)的更多相关文章

  1. Ubuntu x86 64 settup nginx rtmp server

    常常搭建nginxserver,可是好像每次的情况都不同,这次具体记录这个过程: 平台:unbutu 10.04 内核:2.6.32-33-generic 1, 编译环境搭建. sudo apt-ge ...

  2. < IOS > X-code 5.1 x86 - 64 编译问题

    关于xcode 5.1   x86 - 64 编译问题   坐等了N久,终于IOS 7.1 发布了,作为一个果粉,忍不住第一时间升级了.结果用设备测试的时候,出问题了,一直检测不到设备,哈哈,纠结了半 ...

  3. Ubuntu Linux14 64位下在Android studio下用gradle编译Andrid项目时发生libz.so.1共享库找不到的解决方法。

    ---恢复内容开始--- 我在Ubuntu14 64为下安装了AS,但在用Gradle编译项目时总是报找不到 libz.so.1的错误. error while loading shared libr ...

  4. 一段简单c程序的汇编语言学习(ubuntu+x86)

    c程序代码: #include <stdio.h> int main(void) { int i=0, j=0; for(i=0; i<8; i++) j=j+1; return 0 ...

  5. ubuntu 32/64 bit

    https://askubuntu.com/questions/454253/how-to-run-32-bit-app-in-ubuntu-64-bit how to run 32-bit app ...

  6. Ubuntu上64位adv无法创建问题

    Ubuntu上安装android开发环境,前面都成功了,但到了最后创建adv的时候却总是失败. 出现了这个问题.最后,上网找了这个教程http://blog.sina.com.cn/s/blog_66 ...

  7. centos(x86 64位系统)使用boost

    1. 安装gcc,g++,make等开发环境 yum groupinstall "Development Tools" 2. 安装boost yum install boost b ...

  8. ubuntu 12 64 桌面版Oracle11g 安装

    1.Creating the Oracle Inventory Group sudo groupadd oinstall sudo groupadd dba sudo groupadd oper su ...

  9. Openfiler能把标准x86/64架构的系统变成一个强大的NAS、SAN存储和IP存储网关

    http://www.linuxprob.com/vmware-openfiler.html

  10. ubuntu 16 64位编译安装php

    ./configure \ --prefix=/usr/local/php7 \ --exec-prefix=/usr/local/php7 \ --with-config-file-path=/us ...

随机推荐

  1. oracle 索引的(创建、简介、技巧、怎样查看)

    一.索引简介1.索引相当于目录2.索引是通过一组排序后的索引键来取代默认的全表扫描检索方式,从而提高检索效率.3.索引的创建要适度,多了会影响增删改的效率,少了会影响查询的效率,索引最好创建在取值分散 ...

  2. 在Win7 Hyper-v虚拟机中挂接真实机的声卡

    最近在测试Lync的语音功能,环境已在虚拟机中搭建好,但Hyper-V中不支持声卡,一直未测试成功,经过一番尝试后终于成功,细节如下: 1.真机为Win7 企业版,虚拟机也是Win7的企业版.(虚拟机 ...

  3. Flyweight 享元模式 MD

    享元模式 简介 在JAVA语言中,String类型就是使用了享元模式,JAVA中的字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝,避免了在创建N多相同对象时所产生的不 ...

  4. Laravel Composer 脚本

    composer update --no-scripts 执行静态文件 composer dump-autoload 文件映射

  5. MongoDB 通过配置文件启动

    mongod启动命令需指定一些参数启动服务,我们通过配置文件的方式配置这些参数加载配置. ./bin/mongod --config ./conf/mongodb.conf(或./bin/mongod ...

  6. (转)Unity3D研究院之手游开发中所有特殊的文件夹(assetbundle与Application.persistentDataPath)

    这里列举出手游开发中用到了所有特殊文件夹. 1.Editor Editor文件夹可以在根目录下,也可以在子目录里,只要名子叫Editor就可以.比如目录:/xxx/xxx/Editor  和 /Edi ...

  7. .NET 服务器定位模式(Service Locator Pattern)——Common Service Locator

    本文内容 场景 目标 解决方案 实现细节 思考 相关模式 更多信息 参考资料 Common Service Locator 代码很简单,它一般不会单独使用,而是作为一个单件模式,与像 .net Uni ...

  8. CXF实战之拦截器Interceptor(四)

    拦截器(Interceptor)是CXF功能最基本的扩展点,能够在不正确核心模块进行改动的情况下.动态加入非常多功能.拦截器和JAX-WS Handler.Filter的功能相似,当服务被调用时.就会 ...

  9. 搭建持续集成单元测试平台(Jenkins+Ant+Java+Junit+SVN)

    一.环境准备 Jenkins: 到官网下载jenkins.war包:http://jenkins-ci.org/ 安装方法有两种: 把下载下来的jenkins.war包放到文件夹下,如C:\jenki ...

  10. 微信小程序 - 步骤条组件

    <!-- 未激活颜色: uncolor:'#ccc' 激活 active:0 数据源 data:[{},{}] 步骤条类型:type basic detail num more --> & ...