- 主题:DOS 写汇编最烦的地方是调函数保存寄存器吧
每调一个函数都需要把自己使用到的寄存器保存到栈上,再调用函数。等函数返回后,还得把寄存器一个个从栈上弹出来。
这个开销挺大的,所以听说以前有个技巧是写超大的 main() 函数. 以减少函数的调用开销?
--
FROM 59.61.197.*
所以当年的程序员写程序一定很累啊。
现在的程序员,应该都不会考虑啥函数调用开销这些破事了哈。
【 在 BigCarrot 的大作中提到: 】
: 定义自己的calling convention
: 用寄存器传餐
--
FROM 59.61.197.*
如果用 inline,那程序容量就上来了。
【 在 BigCarrot 的大作中提到: 】
: 你当inline是摆设啊
--
FROM 47.243.39.*
和现代编译器的寄存器分配算法有啥区别吗?
【 在 blackoil 的大作中提到: 】
: 我看过atof的16位代码实现,每个寄存器都琢磨其用处用法。设计得很精致。
--
FROM 106.122.208.*
今天闲得没事继续想这个寄存器的事情。
不管 DOS 程序使用寄存器传参还是使用栈。在调用其它函数之前,如果不知道被调用函数是否使用寄存器,那调用者最好先把寄存器保存一下。既然是这样,那完全可以多用 fastcall 寄存器传参啊。
神奇的是为啥当年在 DOS 下 c 语言会选择那个 cdecl 调用约定。难道是只是为了实现 printf() ?
那么保存寄存器的时候,用 PUSHA 方便呢?还是一个个 PUSH 比较方便?可惜 PUSHA 是 80186 的指令,8086 不能用。
【 在 hgoldfish 的大作中提到: 】
: 每调一个函数都需要把自己使用到的寄存器保存到栈上,再调用函数。等函数返回后,还得把寄存器一个个从栈上弹出来。
: 这个开销挺大的,所以听说以前有个技巧是写超大的 main() 函数. 以减少函数的调用开销?
--
FROM 110.84.122.*
i386 的一些调用约定 (c, borland register, stdcall) 有要求函数保存 EAX, ECX, EDX. 其它的 EBX, ESI, EDI, EBP, ESP 这几个,如果被调用者要用到的话,需要自行保存。
个人感觉 borland register 的调用约定是比较合理的。其它的调用约定简直是丧心病狂也不知是怎么想出来的。既要求调用者保存 EAX, ECX, EDX 又不拿来传参数。这不是浪费宝贵的字节么。
8086 的话,也是 turbo c 比较合理,使用了 AX, DX, BX 进行传参。
【 在 BigCarrot 的大作中提到: 】
: 没有看过这方面的历史,我猜还是因为当时的指令集对寄存器的使用不够general,很多指令都只能使用特定的寄存器,你用了寄存器传餐了,后面要用的时候不在你期待的寄存器里怎么办,还得挪到特定的寄存器中,有时还需要把某些寄存器先压栈。。。
: 你想说的是vararg吧,用寄存器传参也能实现的,参考现代的调用约定
: 当然用pusha更方便了,但是不是每一个寄存器都需要保存的,取决于你的函数实际用了多少寄存器吧
: ...................
--
修改:hgoldfish FROM 110.84.122.*
FROM 110.84.122.*
都玩 DOS 了,肯定不是冲着实用性去的。
我经常在思考的一个问题。用现在的软件思维在当年受限的硬件上面重写当年的软件能不能做到更快更好?如果不行,那我们的软件工业算是进步了吗?
【 在 BigCarrot 的大作中提到: 】
: 386对寄存器的使用已经非常通用了
: 当时的调用约定你要放在当时的情况下去理解它的合理性
: 不过现在研究这个已经完全没有意义了
: ...................
--
FROM 59.61.197.*
这是硬件设计啊。或许你对 riscv 会感兴趣哈哈。
可惜龙芯的 la64 没有把 mips 的包袱多抛一些。有点不上不下的。
【 在 chaobill 的大作中提到: 】
: 我恰恰相反,如果按现在的应用重新设计机器会怎么样
: 比如现在就缺了复合类型的操作
: 双重指针操作的优化也没有
: ...................
--
FROM 59.61.197.*
riscv 的意思是给你基础指令。额外的,你自己加。这个有很多开源的微构架让你自己改,自己去流片。
【 在 chaobill 的大作中提到: 】
: riscv 过了一下,也没复合数据支持
: 这些指令只能是学校里研究学术用
: 毕竟要改的话太多了
: ...................
--
FROM 59.61.197.*
我得出一个结论是,现代编程语言的大多数函数都应该弄成 inline 函数。除非这个函数被外部调用,或者这个函数是用于启动协程的函数。
函数帧是 c 语言的概念,其它语言没必要跟着这样玩。
【 在 poggy 的大作中提到: 】
: >既要求调用者保存 EAX, ECX, EDX
: 这是权责划分要求吧, 调用者保存, 函数内就不需要再做保存恢复的动作,减少函数书写的繁琐。
: 另外, 函数外面调用, 有时是不在乎这几个寄存器的数据会不会破坏,
: ...................
--
FROM 59.61.197.*