X86-64 汇编学习1

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了X86-64 汇编学习1相关的知识,希望对你有一定的参考价值。

前言

熟悉一些关键字可以更方便看懂官方的手册:
IA-32(Intel architecture -32): 指代因特尔32位处理器架构。
X86-64:64位处理器架构
compatibility(兼容模式):在64位下运行IA-32程序或者模式

内存范围

我们知道我们的32位程序寻址范围为2^32=4G内存即 0000 0000-FFFF FFFF

具体内存寻址如下图所示:

64位处理器寻址范围为2^64但是实际上指令集架构设计和处理器都没有完全实现这么大的范围。
AMD在地址线实现了52根,但是实际往往只使用48位而已。因此64位系统往往实际只使用48位内存寻址范围,
前16位用于预留扩展。

我们利用x64Dbg调试相关用户程序,你会发现所有的地址前16位都是0,即16进制的四个0。

寄存器

这块建议参阅Intel手册卷1部分内容,这里贴出部分节选:

通用寄存器32位下有8位,64位有16个。

如果你需要访问特定大小的寄存器可以按照如下官方表格进行操作。比如 1字节R8可以使用R8B等

微软文档关于64寄存器说明

限制:

(1) 所有32位寄存器的修改,会将对应的64位寄存器的前32位用0填充(8,16位的赋值不会有影响)。

举例如下:

(1) 所有高8位寄存器访问不能与新的寄存器同时访问(r8-r15等)


Win64 调用约定

这可直接参阅官方文档:

调用约定文档

举例环节:

#include<stdio.h>

float subIntFloat(int i1, float i2, int i3, float i4) 
    printf("hello test %d %f %d %f \\r\\n", i1, i2, i3, i4);
    return i1 + i2 + i3 + i4;


int addNumber4(int i1,int i2,int i3,int i4) 
    printf("hello test %d %d %d %d \\r\\n",i1,i2,i3,i4);
    float fRet= subIntFloat(1,2.0,3,3.0);
    printf("subIntFloat fRet %f \\r\\n", fRet);
    return i1 + i2 + i3 + i4;

int main()

  
   int ret= addNumber4(1, 2, 3, 4);
   printf("addNumber4 ret %d \\r\\n", ret);

   return 0;


我们首先关注addNumber4传参和结果返还。


栈进行128位对齐

在64位系统下很多指令要求内存进行128对齐,比如MOVAPS指令
因此很多函数在开头对RSP进行栈对齐(一般末尾补8h).



相对RIP进行寻址

x86-64额外多出一个寻址方式,
在x32我们想得到EIP的地址往往需要跳一个空函数得到,而在x86-64我们可以写出如下图汇编指令:

x32下相关操作是不被支持的:

参考

wikipedia 64-bit computing 内存说明
stackoverflow 中64-bit 内存讨论
微软文档关于64寄存器说明
intel 手册

以上是关于X86-64 汇编学习1的主要内容,如果未能解决你的问题,请参考以下文章

X86-64 汇编学习1

x86_64 ABI:反汇编问题

汇编语言-X86处理器架构-64位x86处理器

X.86 X64 汇编器中的正确堆栈操作

20155317 第八周课下作业

如何在 x86-64 汇编中使用堆栈?