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 [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

.

This book introduces programmers to 64 bit Intel assembly language using the Microsoft Windows operating system. The book also discusses how to use the free integrated development environment, ebe, designed by the author specifically to meet the needs of assembly language programmers. Ebe is a C++ program which uses the Qt library to implement a GUI environment consisting of a source window, a data window, a register window, a floating point register window, a backtrace window, a console window, a terminal window, a project window and a pair of teaching tools called the "Toy Box" and the "Bit Bucket". The source window includes a full-featured text editor with convenient controls for assembling, linking and debugging a program. The project facility allows a program to be built from C source code files and assembly source files. Assembly is performed automatically using the yasm assembler and linking is performed with ld or gcc. Debugging operates by transparently sending commands into the gdb debugger while automatically displaying registers and variables after each debugging step. The Toy Box allows the use to enter variable definitions and expressions in either C++ or Fortran and it builds a program to evaluate the expressions. Then the user can inspect the format of each expression. The Bit Bucket allows the user to explore how the computer stores and manipulates integers and floating point numbers. Additional information about ebe can be found at http://www.rayseyfarth.com. The book is intended as a first assembly language book for programmers experienced in high level programming in a language like C or C++. The assembly programming is performed using the yasm assembler automatically from the ebe IDE under the Linux operating system. The book primarily teaches how to write assembly code compatible with C programs. The reader will learn to call C functions from assembly language and to call assembly functions from C in addition to writing complete programs in assembly language. The gcc compiler is used internally to compile C programs. The book starts early emphasizing using ebe to debug programs. Being able to single-step assembly programs is critical in learning assembly programming. Ebe makes this far easier than using gdb directly. Highlights of the book include doing input/output programming using Windows API functions and the C library, implementing data structures in assembly language and high performance assembly language programming. Early chapters of the book rely on using the debugger to observe program behavior. After a chapter on functions, the user is prepared to use printf and scanf from the C library to perform I/O. The chapter on data structures covers singly linked lists, doubly linked circular lists, hash tables and binary trees. Test programs are presented for all these data structures. There is a chapter on optimization techniques and 3 chapters on specific optimizations. One chapter covers how to efficiently count the 1 bits in an array with the most efficient version using the recently-introduced popcnt instruction. Another chapter covers using SSE instructions to create an efficient implementation of the Sobel filtering algorithm. The final high performance programming chapter discusses computing correlation between data in 2 arrays. There is an AVX implementation which achieves 20.5 GFLOPs on a single core of a Core i7 CPU. A companion web site, http://www.rayseyfarth.com, has a collection of PDF slides which instructors can use for in-class presentations and source code for sample programs.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值