玩好.NET高级调试,你也要会写点汇编
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩好.NET高级调试,你也要会写点汇编相关的知识,希望对你有一定的参考价值。
一:背景
1. 简介
.NET 高级调试要想玩的好,看懂汇编是基本功,但看懂汇编和能写点汇编又完全是两回事,所以有时候看的多,总手痒痒想写一点,在 Windows 平台上搭建汇编环境不是那么容易,大多还是用微软的 MASM + DosBox
搭一个 8086 的环境,这玩意距今快 50 年了。
在以前想快捷的写一点汇编,借助的是 VC 编译器的 __asm
在 C/C++ 代码中内嵌一点,比如下面这样。
int main()
int num = 10;
__asm
mov[num], 20
printf("num=%d", num);
便捷是便捷,但只能玩个局部,还是不够爽,所以本篇我们借助 nasm
来搭建一个 32bit 的汇编环境,当然 64bit 也是可以的, nasm
在 Linux 社区中非常有名。
二:搭建 x86 汇编环境
1. 前置基础构件
nasm 下载
nasm 是一个非常有名的汇编器,官方网址:https://nasm.us/
目前稳定版是 2.15.05
。
gcc
大家都知道,源代码要变成可执行程序,步骤一般是: asm -> obj -> exe
,前半部分由 nasm 负责,后半部分由 gcc 负责, gcc 是 Linux 上的刚需产品,在 Windows 上可以用 MinGW
。
下载网址:https://sourceforge.net/projects/mingw/files/MinGW
下载完之后,将下图中的 五项
全部勾选上进行安装。
把 bin, include,lib
全部配到环境变量的 PATH 中,然后打开控制台键入 gcc -v
看一下有没有配好。
PS C:\\Users\\Administrator\\Desktop> gcc -v
Using built-in specs.
COLLECT_GCC=C:\\MinGW\\bin\\gcc.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/6.3.0/lto-wrapper.exe
Target: mingw32
Configured with: ../src/gcc-6.3.0/configure --build=x86_64-pc-linux-gnu --host=mingw32 --target=mingw32 --with-gmp=/mingw --with-mpfr --with-mpc=/mingw --with-isl=/mingw --prefix=/mingw --disable-win32-registry --with-arch=i586 --with-tune=generic --enable-languages=c,c++,objc,obj-c++,fortran,ada --with-pkgversion='MinGW.org GCC-6.3.0-1' --enable-static --enable-shared --enable-threads --with-dwarf2 --disable-sjlj-exceptions --enable-version-specific-runtime-libs --with-libiconv-prefix=/mingw --with-libintl-prefix=/mingw --enable-libstdcxx-debug --enable-libgomp --disable-libvtv --enable-nls
Thread model: win32
gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
PS C:\\Users\\Administrator\\Desktop>
vscode 插件
这里我准备用 vscode
来写汇编代码,主要安装两个插件。
The Netwide Assembler (NASM)
这个 nasm 官方提供的 语法高亮 插件。
GDB Debug
gdb 已经内嵌到了 gcc 中,方便于 code 调试。
2. vscode 自动化构建
玩过 vscode 的朋友应该知道,自动化构建需要自己写 tasks.json
,这里我简单写了一个。
"version": "2.0.0",
"tasks": [
"label": "win86",
"type": "shell",
"command": "nasm.exe -f win32 -g -F cv8 -l app.lst app.asm; gcc app.obj -o app.exe",
"problemMatcher":
"pattern":
"regexp": "error"
,
"group": "build",
"presentation":
"focus": true,
"panel": "dedicated",
"reveal": "silent",
"clear": true
]
然后就是配置启动 launch.json
,代码如下:
"version": "0.2.0",
"configurations": [
"type": "gdb",
"request": "launch",
"name": "GDB32",
"program": "$workspaceFolder/app.exe",
"stopOnEntry": true,
"preLaunchTask": "win86"
,
"type": "gdb",
"request": "launch",
"name": "GDB64",
"program": "$workspaceFolder/app.exe",
"stopOnEntry": true,
"preLaunchTask": "win64"
]
到这里基础设施就全部搭建完成了,然后就是写一个简单的汇编程序,实现三个 printf
的打印,代码如下:
extern _printf
SECTION .data
msg db 'Hello World!', 0Ah , 0h;
num1 dd 100;
num1_int_fmt db 'num1=%d', 0Ah, 0h;
num2 dq 3.14;
num2_flt_fmt db 'num2=%lf', 0Ah, 0h;
SECTION .text
global _main
_main:
push ebp
mov ebp , esp
; printf("Hello World\\n");
mov eax , msg
push eax
call _printf
add esp, 4
; printf("num1=%d",num1)
mov eax , [num1]
push eax
mov ebx , num1_int_fmt
push ebx ,
call _printf
add esp , 4
; printf("num2=%lf",num2)
movq xmm0 , [num2]
sub esp , 0x8
movsd [esp] , xmm0
mov ebx , num2_flt_fmt
push ebx
call _printf
add esp , 0xc
mov esp , ebp
pop ebp
ret
输出结果如下:
从上面的代码看,我需要自己协调栈平衡,自己去管理寄存器和内存的使用,真的是太爽了。
二:总结
汇编看多了,总想自己动手试试,如果你也有这种想法,可以搭建一下玩玩,有一点遗憾的是,在 windows 中用 gdb 单步调试汇编目前还没搞定,在 linux 上很轻松,不过也不影响自己学习研究,毕竟可以用强大的 windbg 和 ollydbg 来实现单步调试,对吧!
以上是关于玩好.NET高级调试,你也要会写点汇编的主要内容,如果未能解决你的问题,请参考以下文章