asm 32 /64
我使用NASM编写的,运行在32位windows和linux主机上,但后来需求增加了,需要在64位windows和linux上运行,windows自身有个wow(windows on windows)机制,32位程序根本不用移植就能在64位机器上跑,而linux虽然没有LOL机制(是Linux on linux,不是laugth out loud哈,呵呵 ~),但linux 可以安装ia-libs库(ia 应该是 Intel x86 Archive的简写)达到LOL效果,不过,编译ELF64和WIN64OBJ也是我比较感兴趣的,所以我要移植程序!
首先是了解CPU,寄存器,基本上所有的32位寄存器都升级了,eax变成了rax,ebx变成了rbx,等等,它们带宽变长了,用起来自然也爽了,一次处理 8个字节,一步可以做很多以前需要几步的操作了。寄存器增加了r8,r9,r10,r11,r12,r13,r14,r15,这么多寄存器,又要少用多 少内存做中间变量,效率又高了,可以自己保存使用的是r12-r15,以前一般只有esi,edi,ebx三个寄存器用作自己保存,现在可好了,有 r12-r15,rbx,一共有5个!为什么没有rsi和rdi?问得好,在Linux系统里,这两个寄存器在64位CPU上用作参数传递,所以它们一般不用作保存了,但 是,rsi,rdi这两个寄存器还是很重要的,lodsb,stosb之类的指令还是得用rsi,rdi保存源地址和目的地址。这点,我觉得做得很不好, 为什么不拿新加的寄存器来传参数,偏要用到我心爱的rsi和rdi寄存器呢。。。我不会做CPU,我还不能抱怨啊!抱怨归抱怨,这种情况下,要方便移植,最好就是不要用lodsb之类的指令,而是直接用基址加变址的方式访问内存。
接下来是函数调用,Unix 64 ABI规定使用rdi,rsi,rdx,rcx,r8,r9来传递前6个参数,少于6个的,按上面的顺 序,要几个就用几个,超过6个的,前6个按上面的顺序放入寄存器,剩下的从后向前压入堆栈,然后,设置rax=0,最后使用call指令调用函数,如果超 过6个参数,函数返回后需要修复堆栈,你以前压入了几个参数,就把栈顶指针回移 几*8 个字节,以平衡堆栈。注意的是Windows的ABI规定又不一样了!
另外64位CPU不支持将32位寄存器直接入栈,所以,不好意思,你的push eax 不能用了,使用push rax,pop rax。不过,直接操作堆栈指针rsp/esp是一种可同时在32位和64位CPU上编译通过,且不会出问题的方式,而且要连续push多个数值时(比如函数调用),往往一次性减掉esp/rsp,再用基址加变址的形式存参数,会比一个一个push参数的效率高!GCC进行API调用的时候就是这么实现的,所以其实写汇编是不如用gcc的,一不注意,GCC编译的C程序都会比汇编写的程序效率还高。我一般正式的项目都是用C语言的,但NASM可以让我了解得更深,这点是无话可说的!!
而自己实现的函数,还是可以用以前的c-call方式,如下:
1
2
3
4
5
6
7
8
9
10
|
Function: %define param1 rbp+16 %define param2 rbp+24 %define param3 rbp+32 enter 16,0 %define local1 rbp-8 %define local2 rbp-16 ;..... leave ret |
最后,就是在移植时困扰了我的问题,就是C函数的返回值,64位CPU中C函数的返回值不是在rax中,而是在edx:eax中。其实大多数函数都没问题, 一般在返回-1的时候,这个问题就出来了,edx:eax是-1,但是rax不是-1,高32位全是0.低32位全是1。。
现在时间不多,下次再写一篇文章详细讨论。
结束之前,引用C语言的部分文档。
==========================================
Interfacing HLL code with asm
C calling convention – standard stack frame
Arguments passed to a C function are pushed onto the stack, right to left, before the function is called. The first thing the called function does is push the (E)BP register, then copy (E)SP into it. This creates a data structure called the standard C stack frame.
32-bit code | 16-bit code, TINY, SMALL, or COMPACT memory models | 16-bit code, MEDIUM, LARGE, or HUGE memory models | |
Create standard stack frame, allocate 16 bytes for local variables, save registers | push ebp
mov ebp,esp sub esp,16 push edi push esi … |
push bp
mov bp,sp sub sp,16 push di push si … |
push bp
mov bp,sp sub sp,16 push di push si … |
Restore registers, destroy stack frame, and return | …
pop esi pop edi mov esp,ebp pop ebp ret |
…
pop si pop di mov sp,bp pop bp ret |
…
pop si pop di mov sp,bp pop bp retf |
Size of ‘slots’ in stack frame, i.e. stack width | 32 bits | 16 bits | 16 bits |
Location of stack frame ‘slots’ | [ebp + 8] [ebp + 12] [ebp + 16]… |
[bp + 4] [bp + 6] [bp + 8]… |
[bp + 6] [bp + 8] [bp + 10]… |
If an argument passed to a function is wider than the stack, it will occupy more than one ‘slot’ in the stack frame. A 64-bit value passed to a function (long long or double) will occupy 2 stack slots in 32-bit code or 4 stack slots in 16-bit code.
Function arguments are accessed with positive offsets from the BP or EBP registers. Local variables are accessed with negative offsets. The previous value of BP or EBP is stored at [bp + 0] or [ebp + 0]. The return address (IP or EIP) is stored at [bp + 2] or [ebp + 4].
C calling convention – return values
A C function usually stores its return value in one or more registers.
32-bit code | 16-bit code, all memory models | |
8-bit return value | AL | AL |
16-bit return value | AX | AX |
32-bit return value | EAX | DX:AX |
64-bit return value | EDX:EAX | space for the return value is allocated on the stack of the calling function, and a ‘hidden’ pointer to this space is passed to the called function |
128-bit return value | hidden pointer | hidden pointer |
C calling convention – saving registers
GCC expects functions to preserve the callee-save registers:
EBX, EDI, ESI, EBP, DS, ES, SS
You need not save these registers:
EAX, ECX, EDX, FS, GS, EFLAGS, floating point registers
In some OSes, FS or GS may be used as a pointer to thread local storage (TLS), and must be saved if you modify it.
C calling convention – leading underscores
Some C compilers (those for DOS and Windows, and those with COFF output) prepend an underscore to the names of C functions and global variables. If a C global variable, e.g. conv_mem_size, is accessed by asm code, it should be declared with a leading underscore in the asm code:
EXTERN _conv_mem_size ; NASM syntax
mov [_conv_mem_size],ax
Linux ELF does NOT use underscores. Watcom C uses trailing underscores for function names, and leading underscores for global variables.
If your GCC supports it, leading underscores can be turned off with the compiler option -fno-leading-underscore
Pascal calling conventions
Function arguments are pushed onto the stack from left to right before the function is called. C-style variable-length argument lists are not possible in Pascal. (Look in file STDARG.H and think about it.)
In C, the calling function must ‘clean up the stack’ (remove function arguments from the stack after the called function returns). In Pascal, the called function must do this, before returning.
Pascal identifiers are case-insensitive. MyKewlProc() will be stored in the object code file as MYKEWLPROC
Other calling conventions
The __stdcall calling convention, used by Windows, is a hybrid of the C and Pascal calling conventions. Like C, function arguments are pushed right-to-left. Like Pascal, the called function must clean up the stack. Exception: the caller must clean up the stack for functions that accept a variable number of arguments, e.g. printf(const char *format, …);
Watcom C uses a register-based calling convention. See sections 7.4, 7.5, 10.4, and 10.5 in cuserguide.pdf in the Watcom documentation. Individual functions can be declared to use the normal, stack-based calling convention.
GCC can be made to use a register calling convention by compiling with gcc -mregparm=NNN …
See the GCC documentation for details.
asm 32 /64的更多相关文章
- bit 32/64
[asm]64位编译32位汇编需要注意的 汇编语言在32位和64位下有区别 32位的汇编在代码前增加.code32 as可以通过--32指定生成32位汇编 在64位系统下ld链接生成3 ...
- windows 7(32/64位)GHO安装指南(序篇)~
大家好,本人是高三刚毕业,即将踏入校园的程序猿~我写这篇文章呢,主要是想巩固一下之前对于电脑的基础知识理论,也希望能帮助没有电脑基础的同学能维护一下自己的电脑,要是能帮助女生修电脑那就是更好啦~~哈哈 ...
- API Monitor v2.0 Alpha-r13 (32+64) 汉化版
API Monitor v2.0 Alpha-r13 (32+64) 汉化版: 链接: https://pan.baidu.com/s/1jIx5znC 密码: 4538 本软件已最大化汉化,已经趋于 ...
- win7(32/64)+apache2.4+php5.5+mysql5.6 环境搭建配置
引用自:http://blog.csdn.net/z_cf1985/article/details/22454749 环境:win7 32.(64位的同理,下载相关软件必须是对应的64位版本) ...
- VRay 2.0 SP1 2.10.01 for 3ds max 9/2008/2009/2010/2011/2012 32/64位 顶渲简体中文版+英文版[中国室内设计论坛-室内人]
VRay 2.0 SP1 2.10.01 for 3ds max 9/2008/2009/2010/2011/2012 32/64位 顶渲简体中文版+英文版[中国室内设计论坛-室内人] 对最新版本的V ...
- 【Win7激活工具2013版下载】适用于旗舰版、家庭高级版等所有版本32/64位 OEM激活
虽然现在Win8已经发布了,但是身边总是还有一些朋友在用着Win7系统,而近期微软频繁的推送补丁包,导致之前的那些激活都失效了.找了网络上很多工具,之前的那些有的已经不能用了,激活不了,今天就推荐一些 ...
- 检测dll是32/64位 ?
检测dll是32/64位 ? void CCheck32Or64Dlg::OnButton2() { CString fileName = ""; CFileDialog *fil ...
- 开源一个IE下获取XPath小工具,支持32/64位
背景是曾经友情支持了测试组一小段时间,发现他们使用selenium做页面的自动化测试,需要用到XPath,但IE下没有获取XPath的工具,只能在Firefox和chrome下获取,步骤还比较麻烦.而 ...
- IE下获取XPATH小工具,支持32/64位
背景是曾经友情支持了测试组一小段时间,发现他们使用selenium做页面的自动化测试,需要用到XPath,但IE下没有获取XPath的工具,只能在Firefox和chrome下获取,步骤还比较麻烦.而 ...
随机推荐
- Docker应用之容器
容器是独立运行的一个或一组应用,以及他们的运行态环境 1.启动容器(基于镜像新建一个容器并启动或将终止状态的容器重新启动) run后面添加--name参数可以指定容器的名称,否则系统默认会给名称:使用 ...
- WAF Bypass数据库特性(Access探索篇)
0x01 背景 无聊,测试了一下access特性 0x02 测试 常见有5个位置即:select * from admin where id=1[位置一]union[位置二]select[位置三]1, ...
- 【RF库Collections测试】Keep In Dictionary
Name:Keep In DictionarySource:Collections <test library>Arguments:[ dictionary | *keys ]Keeps ...
- [Shell] Shell 中的算术
Shell 脚本变量默认是作为字符串处理,而不是数字,这使得在 Shell 脚本做数学运算显得较为复杂.在保持脚本编程规范和更好的算术支持方便,Perl 和 Python 会是更好的选择.但是你仍然可 ...
- pip导出安装包及批量安装
python导出安装包及版本 pip freeze > requirements.txt 批量安装pip install -r requirements.txt
- iOS10个实用小技巧(总有你不知道的和你会用到的)
本文转载至 http://www.jianshu.com/p/a3156826c27c 在开发过程中我们总会遇到各种各样的小问题,有些小问题并不是十分容易解决.在此我就总结一下,我在开发中遇到的各种小 ...
- C语言预处理命令详解
一 前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置. 预处理是C语言的一个重要功能 ...
- STL 迭代器 iterator const
STL迭代器很多时候可以当成指针来使用. 但是指针一般可以用const来控制访问. 那迭代器呢. #include <iostream> #include <vector> u ...
- jade(pug)学习笔记(待填充.......)
深刻认识到总结知识点的重要性,不然遇到似曾相识的问题,要翻老半天的百度才能解决.20171018 pug——文字内部嵌入结构 比如: <a class = "href"> ...
- laravel部署常用命令
php composer install composer dump-autoload php artisan key:generate .env 及 config/database.php里的数据库 ...