64位汇编语言简介
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
x86-64位汇编语言简介
一、x86-64的寄存器
x86-64较x86-32多了8个通用寄存器,而且,每个通用寄存器都是64位宽,它们是:
rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp
r8,r9,r10,r11,r12,r13,r14,r15
同时,x86-64全面支持x86-32和x86-16的通用寄存器:
eax,ax,al,ah,
ebx,bx,bl,bh,
....
而且,还对传统的edi,esi做了改进:
edi ,32位
di,16位
dil ,8位,在传统的x86机器中,di是不可按照8位来访问的,但在x86-64下可以。
同样esi也可以按照8位来访问。一个很特别的寄存器rip,相当于x86-32的eip.在x86-32是不可直接访问的,如mov eax,eip是错的,但在x86-64位下却可以,如mov,rax,qword ptr [rip+100]是对的。而且,它除了是个程序计数器外,也是个“数据基地址”,有此可见,它现在是身兼两职!为什么在x86-64位下要用rip做访问数据的基地址呢?因为,在x86-64下,DS,ES,CS,SS都没有实际意义了,也就是说,它们不再参与地址计算,只是为了兼容x86-32。FS,GS还是参与地址计算,它们两个和x86-32的意义相同。
二、x86-64的汇编
x86-64的汇编和x86-32的没有多大的区别。添加了新寄存器和指令。
写64位汇编代码时,可以用8、16、32、64位寄存器,如:
push rdi
sub rsp, 48 ;
mov r10, rcx
; Line 36
mov rdi, rdx
xor eax, eax
mov ecx, 512
rep stosb
; Line 43
movsxd r8, DWORD PTR [r10+16]
mov QWORD PTR [rsp+32], rdx
mov r9, QWORD PTR [r10+648]
mov rdx, QWORD PTR [r10+52]
mov rcx, QWORD PTR [r10+44]
call fs_read_disk
; Line 47
mov ecx, 1
cmp eax, ecx
cmovne ecx, eax
mov eax, ecx
; Line 52
add rsp, 48
pop rdi
ret 0
再如:
$L1818:
; Line 2398
mov al, BYTE PTR [rdx+rbx]
cmp al, 32
jne SHORT $L1819
mov BYTE PTR [rdx+rbx], 0
$L1819:
add r8d, 1
movsxd rdx, r8d
xor eax, eax
mov rcx, r12
mov rdi, rbx
repne scasb
not rcx
sub rcx, 1
cmp rdx, rcx
jb SHORT $L1818
但,有点值得注意,当操作传统的32位寄存器时,那么,整个64位寄存器都会受到影响,如:
mov eax,0ah
那么,rax也等于000000000000000ah
再如:
mov rcx,0aaaaaaaaaaaaaaaah
(此时ecx等于0aaaaaaaah)
mov ecx,0ddddddddh
(此时,rcx等于00000000ddddddddh,高32位受到了影响).
规则:
Example 1: 64-bit Add:
Before:RAX =0002_0001_8000_2201
RBX =0002_0002_0123_3301
ADD RBX,RAX ;48 is a REX prefix for size.
Result:RBX = 0004_0003_8123_5502
Example 2: 32-bit Add:
Before:RAX = 0002_0001_8000_2201
RBX = 0002_0002_0123_3301
ADD EBX,EAX ;32-bit add
Result:RBX = 0000_0000_8123_5502
(32-bit result is zero extended)
Example 3: 16-bit Add:
Before:RAX = 0002_0001_8000_2201
RBX = 0002_0002_0123_3301
ADD BX,AX ;66 is 16-bit size override
Result:RBX = 0002_0002_0123_5502
(bits 63:16 are preserved)
Example 4: 8-bit Add:
Before:RAX = 0002_0001_8000_2201
RBX = 0002_0002_0123_3301
ADD BL,AL ;8-bit add
Result:RBX = 0002_0002_0123_3302
(bits 63:08 are preserved)
三、指令集变化小结:
当然,这里说的都是最基本的东西,是针对通用寄存器言的。其实,x86-64对FPU(数学处理单元)和MMX,SSE,SSE2都做了很大的改进。然而,对写OS来说,我们最关心的还是通用寄存器
1.地址宽度和操作数宽度前缀
64位模式中,缺省的地址宽度是64位,缺省的操作数宽度是32位。地址宽度和操作数宽度前缀允许32位和64位数据和地址在指令序列中混用。下表(1-7)显示了在IA-32e 模式下需要指令前缀地址宽度。注意,在64位模式下不支持16位地址。在敬爱内容和传统模式下,地址宽度函数的功能和在IA-32传动架构中一样。
下表(1-8)显示了66H指令前缀和REX.W前缀的有效组合来指定IA-32e操作模式下的操作数宽度问题。
在64位模式下,缺省的操作数宽度是32位,REX前缀包括4位域来指定16个不同的值。REX前缀的W位域指定为REX.W。REX.W=1时前缀表明操作数位64为操作数。注意,软件依然能使用操作数宽度66H前缀来切换到16位操作宽度。然而如果同时用REX.W和66H 前缀,REX.W的优先权要高。
在SSE/SSE2/SSE3 SIMD指令的情况下,66H, F2H和F3H前缀作为操作码扩展,并被认为是指令的一部分。在这些情况下,有效的REX.W前缀和66H代码扩展前缀之间没有相互关系。
2.REX前缀
REX前缀是64位模式下引入的新的指令前缀字节,他作以下工作:
•指定新的GPRs和SSE寄存器