VS使用NASM编译汇编文件

时间:2024-05-30 18:40:12

注意下面第一个方法用到的配置文件只能编译win32格式的汇编,要是有其他需求自己改配置文件

 

@1:

下载nasm后安装,在环境变量path中添加其安装目录,下载地址http://www.nasm.us/

将下载的三个配置文件放到C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations文件夹下,ok。下载地址http://download.****.net/detail/x356982611/9504205

 

@2:

下面就说下怎么在vs工程中使用:

工程目录右击->"工程依赖项"->"生成自定义",然后勾选nasm这一项

VS2019使用NASM编译汇编文件

在添加的.asm文件上右击打开属性

VS2019使用NASM编译汇编文件

VS2019使用NASM编译汇编文件

VS2019使用NASM编译汇编文件

这样就可以了,F7编译 -------》通过

另一个要注意的点是,如果是c++工程,一定要用extern “c” 去导入函数

参考文献 http://www.codeproject.com/Articles/410776/Integrating-a-compiler-assembler-in-VS-Using-NASM


————————————————

原文链接:https://blog.****.net/x356982611/article/details/51260841

 

 

 

参考了以下两个博客文章

http://blog.****.net/x356982611/article/details/51260841

http://www.cnblogs.com/antoniozhou/archive/2008/10/23/1318287.html

首先到CodeProject下载NASM的VS配置文件

https://www.codeproject.com/Articles/410776/Integrating-a-compiler-assembler-in-VS-Using-NASM

解压3个配置文件到

C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations

也就是和masm的配置文件相同的位置

然后把NASM加入到系统环境变量

D:\nasm-2.13.01

新建一个控制台空工程,同之前MASM的一样,只不过这次选NASM

http://www.cnblogs.com/kileyi/p/7257852.html

VS2019使用NASM编译汇编文件

建立1个cpp和1个asm文件

cpp01.cpp

 
  1. #include <iostream>
  2.  
  3. extern "C" void nasm_function(void);
  4.  
  5. void main()
  6. {
  7. nasm_function();
  8.  
  9. system("pause");
  10. }

asm01.asm

 
  1. segment .text
  2.  
  3. global _nasm_function
  4.  
  5. _nasm_function:
  6. mov eax, 1234h
  7. ret

asm文件上,鼠标右键属性设置

VS2019使用NASM编译汇编文件

VS2019使用NASM编译汇编文件

需要注意的一点是,cpp和asm文件要放到NASMTest.vcxproj与.vcproj相同的目录下才能编译,不像MASM可以放在任意目录下,只要把文件添加到

工程就可以编译,NASM的不行,似乎只能放到根目录下才有效,原因不明,说不定可以设置,但是我没找到。

编译应该就能通过了。

有趣的是MASM可以在ASM汇编代码上下断点,而NASM的却不行。不太清楚怎么回事,不过反正可以在cpp函数前下断点,也差不了太多。

在cpp中的nasm_function函数处下断点,单步就能在寄存器中看到eax变成1234了

接下来搞个纯ASM的测试

pure01.asm

 

 
  1. ;filename: sayhellon.asm
  2.  
  3. ;cmd> nasm -fcoff -Xvc sayhellon.asm
  4. ;cmd> link sayhellon.obj
  5.  
  6. extern [email protected] ;in user32.dll
  7. extern [email protected] ;in kernel32.dll
  8.  
  9. global SayHello
  10. global _WinMain
  11.  
  12. [SECTION .drectve info align=8]
  13. db " /subsystem:windows"
  14. db " /out:sayhellon.exe"
  15. db " /defaultlib:kernel32.lib"
  16. db " /defaultlib:user32.lib"
  17. db " /export:SayHello"
  18. db " /entry:WinMain"
  19. db " /merge:.rdata=.text",0
  20.  
  21. [SECTION .text USE32 align=16]
  22. szTitle:
  23. db "SayHello",0
  24. szMsg:
  25. db "Hello World!", 0
  26.  
  27. SayHello:
  28. push 0 ;uType
  29. push dword szTitle ;lpCaption
  30. push dword szMsg ;lpText
  31. push 0 ;hWnd
  32. call [email protected]
  33.  
  34. ret 16
  35.  
  36. _WinMain:
  37. call SayHello
  38. push 0
  39. call [email protected]

编译应该就能通过,如果不行,手动设置下工程属性中的入口函数

VS2019使用NASM编译汇编文件

============================================================

试了下x64不能编译,google了一阵发现是命令行参数的问题。要手动修改一下。

参考了以下例子

http://www.davidgrantham.com/

http://www.davidgrantham.com/nasm-console64/

64位命令行是类似这样调用的

nasm -f win64 ConsoleMessage64.asm -o ConsoleMessage64.obj

打开nasm.xml文件

搜索

Object File

字符串

把原fwin修改为

 
  1. <EnumValue
  2. Name="0"
  3. DisplayName="Object File 32"
  4. Switch="-f win32" />
  5. <EnumValue
  6. Name="1"
  7. DisplayName="Object File 64"
  8. Switch="-f win64" />
  9. <EnumValue
  10. Name="2"
  11. DisplayName="LINUX ELF FORMAT"
  12. Switch="-f elf" />
  13. <EnumValue
  14. Name="3"
  15. DisplayName="FLAT BINARY"
  16. Switch="-f bin" />

这样在asm文件上右键属性就可以选64位的参数来编译链接了

VS2019使用NASM编译汇编文件

VS2019使用NASM编译汇编文件

新的CPP中调用ASM方法如下

CPP部分不变

 
  1. #include <iostream>
  2.  
  3. extern "C" void nasm_function(void);
  4.  
  5. void main()
  6. {
  7. nasm_function();
  8.  
  9. system("pause");
  10. }

ASM去掉前面的下划线就行了

 
  1. segment .text
  2.  
  3. global nasm_function
  4.  
  5. nasm_function:
  6. mov eax, 1234h
  7. ret

纯ASM如下

 
  1. [SECTION .drectve info align=8]
  2. db " /subsystem:console"
  3. db " /defaultlib:kernel32.lib"
  4. db " /defaultlib:user32.lib"
  5. db " /entry:main"
  6. db " /merge:.rdata=.text",0
  7.  
  8. NULL EQU 0 ; Constants
  9. STD_OUTPUT_HANDLE EQU -11
  10.  
  11. extern GetStdHandle ; Import external symbols
  12. extern WriteFile ; Windows API functions, not decorated
  13. extern ExitProcess
  14.  
  15. global main ; Export symbols. The entry point
  16.  
  17. section .data ; Initialized data segment
  18. Message db "Console Message 64", 0Dh, 0Ah, 0
  19.  
  20. section .bss ; Uninitialized data segment
  21. alignb 8
  22. StandardHandle resq 1
  23. Written resq 1
  24.  
  25. section .text ; Code segment
  26. main:
  27. and RSP, 0FFFFFFFFFFFFFFF0h ; Align the stack to a multiple of 16 bytes
  28.  
  29. sub RSP, 32 ; 32 bytes of shadow space
  30. mov RCX, STD_OUTPUT_HANDLE
  31. call GetStdHandle
  32. mov qword [REL StandardHandle], RAX
  33. add RSP, 32 ; Remove the 32 bytes
  34.  
  35. lea RSI, [REL Message]
  36. xor RDI, RDI
  37.  
  38. .LengthLoop: ; Find the string length by searching for
  39. cmp byte [RSI + RDI], 0 ; the null terminator
  40. je .LengthDone
  41.  
  42. add RDI, 1 ; Maximum length, prevents buffer overrun
  43. cmp RDI, 21 ; if there is no null terminator
  44. jne .LengthLoop
  45.  
  46. .LengthDone:
  47. sub RSP, 32 + 8 + 8 ; Shadow space + 5th parameter + align stack
  48. ; to a multiple of 16 bytes
  49. mov RCX, qword [REL StandardHandle] ; 1st parameter
  50. lea RDX, [REL Message] ; 2nd parameter
  51. mov R8, RDI ; 3rd parameter
  52. lea R9, [REL Written] ; 4th parameter
  53. mov qword [RSP + 4 * 8], NULL ; 5th parameter
  54. call WriteFile ; Output can be redirect to a file using >
  55. add RSP, 48 ; Remove the 48 bytes
  56.  
  57. xor RCX, RCX
  58. call ExitProcess