在64bit架构中, 地址是64bit. 访问内存内容的唯一方式就是通过方括号, 不加方括号读取的只是地址, 例如
mov rax, qword [var1] ; value of var1 in rax mov rax, var1 ; address of var1 in rax
在访问内存时, 大多数情况下尺寸是明确的, 例如下面的尺寸是double word
mov eax, [rbx]
但是有一些情况是不明确的, 例如
inc [rbx] ; error
这时候需要显式标明其尺寸, 例如
inc byte [rbx] inc word [rbx] inc dword [rbx]
寄存器寻址表明运算数是一个CPU寄存器(eax, ebx, etc.), 例如下面的eax, ebx都是寄存器寻址
mov eax, ebx
这种模式下运算数为立即数, 例如下面的123就是立即数寻址
mov eax, 123
这种模式下运算数为内存地址, 可以是间接或引用, 例如如下指令将会从内存中找到变量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 declarationssection .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
堆(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 declarationssection .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, 0pushLoop: 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 mov rcx, qword [len] mov rbx, numbers mov r12, 0popLoop: 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
.
本文发布于:2024-01-28 10:17:30,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064082536716.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |