x64/x86-64/AMD64/ml64入门解惑

这张图已经写得比较清楚了,下面三哥哥再解说一下
对于微软Windows系统在x64架构CPU下的运作规则是怎么样的,这里指的是平台系统x64 ABI规则。
系统ABI(应用程序二进制接口)规则包括哪些方面,这是大家需要自己去了解的内容,这里仅提供一条学习指引。

x64/x86-64/AMD64/ml64入门解惑_第1张图片

无论是系统API函数或者是自建函数,它们之间的调用都必须遵守相应的约定。ml64汇编编译器必须且一定是对应实现了操作系统这套约定了的,这样我们的程序才会正常工作。

什么是调用约定指函数间约定待传参数存放顺序及存放在哪里和取参数顺序及到哪里取、哪些寄存器要保护及由谁来做、栈平衡回收是由调用方还是被调用方来做。(思考并拿笔画一画图)

简单说下,x64函数体内的栈空间需要16字节对齐。这个对齐的意思不仅体现了栈空间大小是16的倍数,而且最低的栈地址即rsp指向位置也是16字节对齐的,一个说的是空间大小,一个说的是地址对齐,但两者一定联动。

对齐的栈地址结尾数字必然为0,可以推断出当函数A调用函数B,返回地址被压入栈空间那一刻,栈地址就不是16字节对齐了(结尾数字为8),后续就是考虑函数调用约定,凑出B函数栈空间需要开辟多少字节才能满足B函数体内的16字节对齐要求。

有人总结了16n+8公式体,16n是n个变量的16倍怎么都是对齐的,多出这个8字节为的是跟压入栈的返回地址一起凑成16字节(保护非易变寄存器的压栈数这部分也要算进去)。当然还可以以别的视角去看待对齐,每个人的思考都会不同,用心去研究不要被既有局限了认知。

说说函数的栈空间布局问题,示意图已经展示的非常清晰了,作者在这里想提到的一个重点中的重点还是让大家自己学会独立思考问题,可以看下作者写过的 “如何理解计算机编程并把它学好呢?” 认知篇、思想篇、棒喝篇,为什么在这里要说这事情,模型的概念,建模的概念,思考具现化构建出实体对于更好的理解和解决问题非常非常重要,脑子里没有思考模型,就是没有印象!连印象都建立不起来 你说我懂了,懂毛啊,无知+幼稚!经不起别人的一点点反问,我曹 尬了。。

翟山鹰说过,为什么我不是科班出身一天金融没学过,但是全国最顶尖院校用的金融书都是我编的,是我厉害吗,不,是这个圈里没人愿意认认真真能踏实的做研究!我骂他教授他敢回嘴吗,有人敢顶嘴的吗,他们不敢。三哥哥想用这个案例让所有看到这篇文章的小伙伴清楚明白一个道理,实力到了你就是权威,游刃有余应对自如,何必学完还有种战战兢兢心里不踏实的感觉呢,好像都懂了但为毛又有点不是很踏实的赶脚,三哥哥建议你找出这种不安原因,干掉它,当然如果你对自己学习能力和已验证过的实力非常自信,可以略过。

说这些,因为作者经历所有学习者经历过的所有,或者更曲折,花费的时间更漫长,今天你看到这篇文章,是无数岁月里无数次的迷茫求知和折磨才有了属于今天自己学习和认知上的积淀,时间它贵吗?三哥哥希望大家能少走学习弯路,早点认清找到自己问题 找到正确的学习路径和学习方法

问自己一句:为什么别人知道的我不知道,他是怎么知道这些内容的?我们好像年龄都差不多大,为什么差距这么大,我要多久能赶上他?今天反思自己了吗,我到底比别人差在哪儿?是我不够热爱编程吗?是我没有认真思考问题吗?是我理解力有问题吗? 是我知识储备不足吗?是我实践的少只顾着群里嗨聊浪费时间了?是我不懂得怎么get到知识源头吗?为什么没人告诉回答我,是问题太难了没人懂还是太简单被鄙视了?我要不要放弃换种语言继续学呢?


x64调用约定:
1 . 从左到右,整形参数前4个在RCX RDX R8 R9寄存器里传递,从第5个参数开始放入它在主调函数对应的栈参数位置;浮点参数前4个依次在XMM0-XMM3 中保存。
2.无论参数个数,主调函数的栈空间必须预留出前4个寄存器参数位置(该空间可以被重复利用)
3.RBX RBP RSI RDI R12-R15,XMM6-XMM15为非易变寄存器,必须由被调函数保存;R10 R11,XMM4 XMM5 必须根据需要由主调方保存。
4.返回值放置在RAX中

浮点相关内容仅简单列举,不全的地方小伙伴自行了解。

进入被调用函数内部,首先push 保存将要用到的非易变寄存器,然后一次性sub rsp拉到栈底来分配足够大的栈空间,而栈底位置就是RCX参数存放位置,到此rsp 不再变化 其地址为16字节对齐。

拿出纸笔画一画,发现自己的不足就是进步


头参RCX在栈里的地址必须16字节对齐!

动不动就崩溃的问题关键就在这

写个简单基础程序,自己可以使用x64dbg观察栈区分配变化加深理解

基础提示:16字节对齐的栈地址同时也是8字节对齐的,反过来讲就是错的;8字节对齐的栈地址后4bit位是1000B,16字节对齐的栈地址后4bit位是0000B

经过对本篇文章的分析思考,只要小伙伴们提取出了栈对齐这个本质,随便怎么玩!
三哥哥再拿出一个从另一个角度的观察,这里不看16n+8,看看你自己有没有意识到它:只要调用系统API函数时栈是对齐的,就不会崩。

当然了,在作者看来这只是基础理论层面,懂归懂,熟归熟,上手写代码思路卡不卡壳只有自己知道,这仅仅是够资格写x64程序的起点而已,把熟练手撸ml64当目标 加油。

你可能感兴趣的:(基础知识学习,经验话题分享,汇编,assembler,ml,反汇编)