找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 7221|回复: 6

【VS2012】VS2012与NASM联合进行64位编程

[复制链接]

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24261 个
贡献
46222 次
宅之契约
0 份
在线时间
2298 小时
注册时间
2014-1-26
发表于 2014-5-14 18:40:12 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
很多人都发现好像VS2012不允许x64平台使用_asm语句进行内联汇编。没错,事实就是这样。那么有没有代替的解决方法呢?有。
那就是用NASM编译汇编的文件,然后把它和你的C文件一起链接就行啦。

因为是用NASM做汇编器,所以你必须有NASM汇编器才能编译。
NASM下载地址在此。
顺带请把NASM.EXE放到C:\Windows文件夹。

新建工程
20141119222654.png
这里要选择空项目,免得预编译头出来烦人。
20141119222750.png
然后一个工程就弄好了。
20141119222756.png
先照例新建一个文件:Entry.c
20141119223012.png
写一些简单的代码。
20141119223121.png
然后再新建一个文件,用作我们写汇编的文件。取名为123.ASM。其实可以是其它的名字的,这里只是以123.asm为例子。
20141119223227.png
右键选择该文件,属性,把“项类型”设置为“自定义生成工具”
NASM.png
20141119223352.png
点右上角配置管理器,新建一个x64的编译目标。
20141119223432.png
20141119223635.png
之后设置针对x64目标的编译命令。首先在“平台”那里选“x64”,然后将编译命令设置为
nasm -f win64 "%(FullPath)" -o "$(TargetDir)%(Filename).obj"
再将输出设置为$(TargetDir)%(Filename).obj
“将输出视为内容”选“是”
20141119224412.png
转到123.asm
写一些简单的代码。
20141119224201.png
然后再在Entry.c里面添加一些代码。
20141119224525.png
然后运行。
20141119224533.png
好啦。这就算配置完了。

那么我们就可以欢快地让NASM的64位汇编与VS2012的64位C语言合体啦~~

接下来是详细的编程方面的教程。

NASM用global语句公开一个符号。我这里示范一下,C语言的int foo=123;是怎么翻译成NASM汇编的。
  1. global foo      ;公开符号,注意VS2012的C语言编译器不会在符号前加下划线,但是VC6会,MinGW的GCC、G++也会,切记。

  2. segment .data   ;数据放到数据段。
  3. foo dd  123     ;int foo=123;
复制代码
这个时候对于C语言来说,引用它的方法如下:
  1. extern int foo;//外部符号
复制代码
然后就可以使用了。而C++是这样引用的:
  1. extern"C" int foo;//外部符号
复制代码
请记住区别。

NASM编写函数,举个例子是这样的:
  1. global foo      ;公开符号。函数原型:void foo(void);功能:什么也不做。

  2. segment .text   ;代码放在代码段
  3. foo:            ;函数入口
  4. ret             ;什么也不做,直接返回
复制代码
那么C语言怎么引用它呢?很简单。只需提供这个函数的声明就可以使用它了。举例如下:
  1. #include<stdio.h>

  2. void foo(void);

  3. int main(void)
  4. {
  5.     foo();
  6.     printf("OK.\n");
  7.     return 0;
  8. }
复制代码
x64编程需要注意的详细的事项:
1、x64默认函数调用约定是__fastcall,第一个参数用rcx寄存器传递,第二个参数用rdx寄存器传递,第三个参数用r8寄存器传递,第四个参数用r9寄存器传递,剩下的参数都用栈传递,而且是逆顺序压栈。
2、调用者维护栈。因此被调用者只需用ret返回即可。请勿使用ret XXXX指令返回,请务必使用ret指令返回。

最后,我会放出已经配置好的工程的下载地址。
SRC下载: Win64ASM.7z (4.59 KB, 下载次数: 6, 售价: 10 个宅币)
回复

使用道具 举报

0

主题

1

回帖

15

积分

用户组: 初·技术宅

UID
290
精华
0
威望
1 点
宅币
12 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-5-14
发表于 2014-5-14 21:01:52 | 显示全部楼层
看起来好复杂
回复 赞! 靠!

使用道具 举报

55

主题

275

回帖

9358

积分

用户组: 管理员

UID
77
精华
16
威望
237 点
宅币
8223 个
贡献
251 次
宅之契约
0 份
在线时间
255 小时
注册时间
2014-2-22
发表于 2014-5-14 22:31:54 | 显示全部楼层
不顶行不行?
回复 赞! 靠!

使用道具 举报

0

主题

31

回帖

109

积分

用户组: 小·技术宅

UID
141
精华
0
威望
2 点
宅币
74 个
贡献
0 次
宅之契约
0 份
在线时间
10 小时
注册时间
2014-3-23
发表于 2014-5-15 17:27:15 | 显示全部楼层
本帖最后由 我晕 于 2014-5-15 17:49 编辑

x64asm的话...
还要注意堆栈需保持16字节对齐
堆栈由调用方分配 调用方收回 最少分配 4*8字节的空间 即无参函数也需要分配空间
在函数中 一般会把寄存器中的前4个参数再放入堆栈中 第1个参数的位置是[rsp + 8] 因为返回地址已经在堆栈中了 第二个参数在[rsp + 16] 第五个参数是[rsp + 40]
前4个参数由rcx rdx r8 r9传递 其余的走堆栈
浮点参数是 xmm0 xmm1 xmm2 xmm3 其余走堆栈
返回值是 rax 或 xmm0
调用win api时的struct成员需要自身长度对齐
额...
回复 赞! 靠!

使用道具 举报

1

主题

19

回帖

59

积分

用户组: 小·技术宅

UID
375
精华
0
威望
1 点
宅币
37 个
贡献
0 次
宅之契约
0 份
在线时间
1 小时
注册时间
2014-7-7
发表于 2014-7-7 13:15:39 | 显示全部楼层
我以为是64汇编语言!
回复 赞! 靠!

使用道具 举报

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24261 个
贡献
46222 次
宅之契约
0 份
在线时间
2298 小时
注册时间
2014-1-26
 楼主| 发表于 2014-7-7 13:35:32 | 显示全部楼层
fsjaky 发表于 2014-7-7 05:15
我以为是64汇编语言!

NASM同时支持16位、32位、64位。
回复 赞! 靠!

使用道具 举报

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24261 个
贡献
46222 次
宅之契约
0 份
在线时间
2298 小时
注册时间
2014-1-26
 楼主| 发表于 2014-11-19 23:10:27 | 显示全部楼层
内容已经更新,那个愚蠢的BUG是升级旧版VS工程导致的。
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-29 23:51 , Processed in 0.051517 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表