请添加图片描述
2、错误调试方向
请添加图片描述

3、使用 虚拟网络编辑器(仅适用于较新版本)
打开 VMware Workstation → 编辑 → 虚拟网络编辑器
选择 VMnet8(NAT 模式)
点击 NAT 设置 → 高级
如果有 “端口转发”按钮,点击添加:
主机端口:50000
协议:TCP
虚拟机 IP:192.168.100.128(你的虚拟机 IP)
虚拟机端口:50000
⚠️ 如果没有这个按钮,说明你的版本不支持图形化配置。
请添加图片描述
请添加图片描述

4、ping
请添加图片描述
5、telnet安装
请添加图片描述
6、虚拟机内联调
请添加图片描述
7winDbg

确保你在虚拟机里运行了:

ntsd -server tcp:port=50000 -noio "C:\path\to\test.exe"

虚拟机 防火墙阻止了 50000 端口
在虚拟机中临时关闭防火墙测试:

netsh advfirewall set allprofiles state off

Microsoft Windows [版本 10.0.19045.3803]
(c) Microsoft Corporation。保留所有权利。

C:\Windows\system32>ipconfig

Windows IP 配置


以太网适配器 以太网(内核调试器):

   连接特定的 DNS 后缀 . . . . . . . : localdomain
   本地链接 IPv6 地址. . . . . . . . : fe80::18c7:552f:b098:436c%7
   IPv4 地址 . . . . . . . . . . . . : 192.168.88.136
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 192.168.88.2

以太网适配器 蓝牙网络连接:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . :

C:\Windows\system32>ntsd -server tcp:port=50000,server=0.0.0.0 -noio test.exe
'ntsd' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

C:\Windows\system32>cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>ntsd -server tcp:port=50000,server=0.0.0.0 -noio test.exe

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>netsh advfirewall set allprofiles state off
确定。


C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>

切换到 test.exe 所在目录再运行
cmd
编辑
cd /d C:\Users\lenovo\Desktop\64asm\64asm
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe" -server tcp:port=50000,server=0.0.0.0 -noio test.exe

最终完整命令(复制粘贴即可)
在虚拟机中以管理员身份打开 CMD,执行:

cmd
编辑
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe" -server tcp:port=50000,server=0.0.0.0 -noio "C:\Users\lenovo\Desktop\64asm\64asm\test.exe"

Microsoft (R) Windows Debugger Version 10.0.22621.5193 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Microsoft (R) Windows Debugger Version 10.0.22621.5193 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: test.exe
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\atlmfc.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\ObjectiveC.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\concurrency.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\cpp_rest.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\stl.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Data.Json.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Devices.Geolocation.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Devices.Sensors.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\Windows.Media.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\windows.natvis'
NatVis script successfully loaded from 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers\winrt.natvis'

************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
Symbol search path is: srv*
Executable search path is: 
ModLoad: 00007ff6`c86f0000 00007ff6`c873a000   image00007ff6`c86f0000
ModLoad: 00007ff9`2aad0000 00007ff9`2acc8000   ntdll.dll
ModLoad: 00007ff9`28c60000 00007ff9`28d1d000   C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ff9`28460000 00007ff9`28756000   C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ff9`25a20000 00007ff9`25ab0000   C:\Windows\SYSTEM32\apphelp.dll
(d10.2134): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ff9`2aba0730 cc              int     3
DESKTOP-5C1UUIK\lenovo (tcp [::ffff:192.168.88.1]:62092) connected at Thu Jan  1 10:25:27 2026

二、代码实现

1. C++ 主程序(test.cpp)
cpp
编辑
#include <iostream>
using namespace std;

// 声明外部汇编函数(C 调用约定)
extern "C" unsigned long long __cdecl Chapter6_Demo();

int main() {
    unsigned long long result = Chapter6_Demo();
    cout << "第六章指令演示运行成功,结果汇总:0x" << hex << result << endl;
    system("pause"); // 防止程序立即退出,便于调试
    return 0;
}
  1. x64 汇编模块(Chapter6_Demo.asm)
    使用 .data 定义全局变量(QWORD 类型)
    使用 .code 实现数据传送(MOV/MOVZX/MOVSX)与算术运算(ADD/SUB/INC/DEC/NEG)
    函数以 PROC … ENDP 包裹
    必须在文件末尾添加 END 指令
    返回值通过 RAX 寄存器传递
    ✅ 示例结尾:
;Chapter6_Demo 
asm
option casemap:none

; 数据段:定义全局变量(64位类型)
.data
    ; 无符号64位整数
    uNum1 QWORD 1000000000000000h  ; 64位无符号数
    uNum2 QWORD 0000000000000002h  ; 64位无符号数
    uResult QWORD 0                ; 无符号运算结果存储
    
    ; 有符号64位整数
    sNum1 QWORD -100h              ; 64位有符号数
    sNum2 QWORD 200h               ; 64位有符号数
    sResult QWORD 0                ; 有符号运算结果存储

; 代码段:核心逻辑实现
.code
; 函数名:Chapter6_Demo
; 功能:演示本章数据传送与算术运算指令
; 参数:无
; 返回值:RAX(返回运算结果汇总)
Chapter6_Demo PROC
    ; ========== 一、数据传送指令演示 ==========
    ; 1. MOV指令:寄存器<->寄存器、寄存器<->内存
    MOV RAX, uNum1          ; 内存->64位寄存器:uNum1 -> RAX
    MOV RBX, uNum2          ; 内存->64位寄存器:uNum2 -> RBX
    MOV RCX, RAX            ; 寄存器->寄存器:RAX -> RCX
    
    ; 2. MOVZX指令:零扩展传送(无符号数,8位->64位)
    MOV DL, 0FFh            ; 8位无符号数(255)存入DL(RDX的8位低位)
    MOVZX RDX, DL           ; 零扩展:DL -> RDX(RDX高位补0,结果为00000000000000FFh)
    
    ; 3. MOVSX指令:符号扩展传送(有符号数,8位->64位)
    MOV AL, 0FFh            ; 8位有符号数(-1)存入AL(RAX的8位低位)
    MOVSX RAX, AL           ; 符号扩展:AL -> RAX(RAX高位补1,结果为FFFFFFFFFFFFFFFFh)

    ; ========== 二、算术运算指令演示 ==========
    ; 1. ADD指令:无符号数加法
    MOV RAX, uNum1
    ADD RAX, uNum2          ; RAX = uNum1 + uNum2(1000000000000000h + 2h = 1000000000000002h)
    MOV uResult, RAX        ; 结果存入uResult

    ; 2. SUB指令:无符号数减法
    MOV RAX, uResult
    SUB RAX, uNum2          ; RAX = uResult - uNum2(还原为uNum1的值)
    MOV uResult, RAX        ; 存储还原后的值

    ; 3. INC/DEC指令:自增/自减
    INC uResult             ; uResult自增1(1000000000000001h)
    DEC uResult             ; uResult自减1(还原为1000000000000000h)

    ; 4. ADD/SUB指令:有符号数运算
    MOV RAX, sNum1
    ADD RAX, sNum2          ; RAX = sNum1 + sNum2(-100h + 200h = 100h)
    MOV sResult, RAX        ; 结果存入sResult
    
    MOV RAX, sResult
    SUB RAX, sNum2          ; RAX = sResult - sNum2(还原为sNum1的值)
    MOV sResult, RAX        ; 存储还原后的值

    ; 5. NEG指令:求补运算(正负转换)
    NEG sResult             ; sResult = 0 - sResult(-100h 转换为 100h)
    NEG sResult             ; 再次求补,还原为-100h

    ; ========== 三、结果返回 ==========
    MOV RAX, uResult        ; RAX存储无符号结果
    MOV RBX, sResult        ; RBX存储有符号结果
    OR RAX, RBX             ; 汇总结果(仅作演示,可根据需求调整返回逻辑)
    RET                     ; 函数返回,RAX为返回值
Chapter6_Demo ENDP
END

三、编译与链接(命令行)
在虚拟机中执行:

cmd
编辑
:: 1. 汇编 .asm 文件
ml64 /c Chapter6_Demo.asm

:: 2. 编译 C++ 并链接 .obj
cl /EHsc test.cpp Chapter6_Demo.obj
✅ 生成 test.exe,可独立运行。

四、远程调试配置(关键步骤)
步骤 1:启动调试服务(在虚拟机中)
cmd
编辑
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe" ^
  -server tcp:port=50000,server=0.0.0.0 ^
  -noio ^
  "C:\Users\<用户名>\Desktop\64asm\64asm\test.exe"
⚠️ 注意:

必须使用 绝对路径(避免“找不到文件”)
server=0.0.0.0 表示监听所有网络接口(否则仅限 localhost)
用户名需准确(如 wanni,非 lenovo)
步骤 2:关闭防火墙(临时)
cmd
编辑
netsh advfirewall set allprofiles state off
步骤 3:验证端口监听(虚拟机内)
cmd
编辑
netstat -ano | findstr :50000
✅ 应显示:TCP 0.0.0.0:50000 ... LISTENING

步骤 4:宿主机连接 WinDbg
打开 WinDbg(x64 版本)
菜单:File → Connect to Remote Stub
输入:
text
编辑
tcp:server=192.168.88.136,port=50000
成功标志:出现 connected at ... 日志,并中断在初始断点
五、常见问题与解决方案
问题	原因	解决方案
A2088: END directive required	.asm 文件缺少 END	在文件末尾添加 END
LNK1561: 必须定义入口点	单独链接 .obj 无 main	用 cl 同时编译 .cpp 和 .obj
telnet 连接失败	端口未监听或防火墙阻止	检查 ntsd 路径、加 server=0.0.0.0、关防火墙
'ntsd' 不是命令	PATH 未包含调试器路径	使用完整路径调用 ntsd.exe
系统找不到指定路径	用户名或文件路径错误	核对实际路径(如 C:\Users\wanni\...)
调试器连不上	NAT 模式限制	改用 桥接模式(最简单可靠)
六、调试技巧
使用 r rax 查看汇编函数返回值
使用 g 继续执行,q 退出调试
利用 system("pause") 让程序暂停,便于观察寄存器状态
本地调试更简单:直接在虚拟机内用 WinDbg 打开 test.exe
七、总结
通过本次实践,成功实现了:
✅ C++ 与 x64 汇编的混合编程

✅ 手动汇编与链接流程

✅ 跨机器远程调试(WinDbg + ntsd)

✅ 网络、防火墙、路径等系统级问题排查

核心经验:

路径必须准确(尤其含空格和中文用户目录)
server=0.0.0.0 是远程调试的关键参数
桥接模式 > NAT 模式(简化网络配置)
调试前务必确认程序不会立即退出
📝 适用场景:操作系统开发、逆向工程、性能优化、底层安全研究等。

八、开始调式

0:000> bp test!main
0:000> g
Breakpoint 0 hit
test!main:
00007ff6`ddcc0620 4883ec38        sub     rsp,38h
✅ 连接远程调试

✅ 加载符号(test!main 可见)

✅ 在 main 函数入口下断点

✅ 程序中断在 main 的第一条指令!

现在你正处于 main 函数的 prologue(函数序言),这是 x64 调用约定的标准开头。

🔍 当前状态解析
asm
编辑
test!main:
00007ff6`ddcc0620 4883ec38        sub     rsp,38h
sub rsp, 38h:为局部变量和调用保存空间(0x38 = 56 字节)
这是 MSVC 编译器生成的标准函数入口

你的 C++ 代码:
int main() {
    unsigned long long result = Chapter6_Demo();  // ← 即将调用这里
    cout << "结果:" << hex << result << endl;
    system("pause");
    return 0;
}
✅ 接下来操作建议(逐步调试)
步骤 1:单步执行到 Chapter6_Demo 调用
使用 p(Step Over)多次,直到看到 call 指令:

dbg
编辑
0:000> p
...
0:000> p
test!main+0xa:
00007ff6`ddcc062a e8b1090000      call    test!Chapter6_Demo (00007ff6`ddcc1000)
💡 p 会逐条执行汇编指令,但不会进入子函数(适合快速到达 call)

步骤 2:进入 Chapter6_Demo 函数
当停在 call test!Chapter6_Demo 时,输入:

dbg
编辑
0:000> t
t = Trace into(单步进入)
程序将跳转到你的汇编函数内部!
步骤 3:逐条调试汇编指令
在 Chapter6_Demo 中,你可以:

使用 t 逐条执行
观察寄存器变化(如 RAX, RCX, RDX)
查看内存(如全局变量)
例如:

dbg
编辑
0:000> t
Chapter6_Demo+0x5:
00007ff6`ddcc1005 48c7c0ff000000  mov rax, 0FFh

0:000> r rax
rax=00000000000000ff
步骤 4:函数返回后查看结果
当 Chapter6_Demo 执行完 ret 后,会回到 main,此时:

dbg
编辑
0:000> r rax
就能看到最终返回值!

然后继续 p,会执行到 cout,输出结果。

在这里插入图片描述

0:000> p
test!main+0x4:
00007ff6`ddcc0624 e8c04dffff      call    test!ILT+17380(Chapter6_Demo) (00007ff6`ddcb53e9)
这行 call 指令正是 C++ 调用你的汇编函数 Chapter6_Demo 的地方!

🔍 为什么显示 test!ILT+17380(...)?
这是 MSVC 编译器的增量链接表(Incremental Linking Thunk, ILT) 机制:

为了加快链接速度,MSVC 会生成一个跳转表(ILT)
test!ILT+17380(Chapter6_Demo) 是一个跳板函数(thunk)
它内部只有一条指令:jmp Chapter6_Demo
✅ 这是完全正常的,不影响调试。

✅ 正确操作:进入真正的 Chapter6_Demo
你现在有两个选择:

✅ 推荐方式:用 t 进入,自动穿透 ILT
输入:

dbg
编辑
0:000> t
WinDbg 会:

先跳到 00007ff6ddcb53e9`(ILT 跳板)
执行 jmp Chapter6_Demo
最终停在你真正的汇编函数第一条指令
💡 WinDbg 默认会“穿透”这种单指令跳转,直接带你到目标函数。

⚠️ 如果你想手动验证(可选)
你可以先 p 一次,看看 ILT 内容:

dbg
编辑
0:000> p
test!ILT+17380(Chapter6_Demo):
00007ff6`ddcb53e9 e912bc0000      jmp     test!Chapter6_Demo (00007ff6`ddcc1000)
然后再 t 进入 jmp,就会到达真正的 Chapter6_Demo。

但通常直接 t 一次就够了!

默认情况下,cl.exe 编译不带调试信息(除非加 /Zi)。
✅ 解决方案:重新编译时生成调试符号
在虚拟机中重新编译:

ml64 /c Chapter6_Demo.asm
cl /EHsc /Zi test.cpp Chapter6_Demo.obj

/Zi:生成 .pdb 调试信息文件
之后 x test!main 就能正确显示地址
💡 如果不想生成 PDB,也可以直接通过入口点反汇编

💡 小技巧:直接跳到 Chapter6_Demo(避免 ILT)
如果你希望完全避开 ILT,可以在链接时加 /INCREMENTAL:NO:

cl /EHsc /Zi /INCREMENTAL:NO test.cpp Chapter6_Demo.obj
这样 call 指令会直接指向 Chapter6_Demo,但对功能无影响,仅用于调试清晰度。

你现在只需输入一个 t,就能进入自己的汇编世界了!🚀

0:000> p
test!main+0x4:
00007ff6`ddcc0624 e8c04dffff      call    test!ILT+17380(Chapter6_Demo) (00007ff6`ddcb53e9)
0:000> p
test!main+0x9:
00007ff6`ddcc0629 4889442420      mov     qword ptr [rsp+20h],rax ss:000000b0`d6dbfdb0=0000000000000000
0:000> t
test!main+0xe:
00007ff6`ddcc062e 488d158b2c1100  lea     rdx,[test!__xt_z+0x110 (00007ff6`dddd32c0)]
🔍 关键指令解析
1. 函数调用已完成
asm
编辑
00007ff6`ddcc0624 e8c04dffff      call    test!ILT+17380(Chapter6_Demo)
这是调用你的汇编函数。
2. 保存返回值到栈
asm
编辑
00007ff6`ddcc0629 4889442420      mov     qword ptr [rsp+20h], rax
✅ RAX 中的返回值已被存入局部变量 result
[rsp+20h] 就是 C++ 中 unsigned long long result 的内存位置
💡 这说明:Chapter6_Demo 已经执行完毕,且结果已传回!

3. 准备 cout 字符串参数
asm
编辑
00007ff6`ddcc062e 488d158b2c1100  lea     rdx, [test!__xt_z+0x110 (...)]
这是在加载 "第六章指令演示运行成功,结果汇总:0x" 字符串地址
下一步将调用 operator<<
✅ 如何查看 Chapter6_Demo 的返回值?
虽然你已经离开了汇编函数,但 RAX 的值仍然保留(直到被覆盖)!

立即输入:

dbg
编辑
0:000> r rax
你会看到类似:

text
编辑
rax=00000000ffffff00
这就是你的汇编函数计算出的最终结果!

🎁 附加:想重新调试汇编内部?
如果想再次进入 Chapter6_Demo 逐条调试:

退出当前调试会话(q)
重新启动 ntsd:
cmd
编辑
ntsd -server tcp:port=50000,server=0.0.0.0 -noio test.exe
在 WinDbg 中连接后,下断点:
dbg
编辑
bp test!Chapter6_Demo
g
当中断在汇编函数时,用 t 逐条执行
恭喜你圆满完成 x64 汇编与 C++ 混合编程调试实验!👏

0:000> r rax
rax=ffffffffffffff00
太棒了!🎉

你刚刚通过 WinDbg 成功读取到了 Chapter6_Demo 汇编函数的返回值:

text
编辑
rax=ffffffffffffff00
🔍 结果解析
这个值是 十六进制,表示一个 64 位有符号整数:

十六进制:0xffffffffffffff00
十进制(有符号):-256
十进制(无符号):18,446,744,073,709,551,360
但在你的 C++ 代码中,变量类型是:

cpp
编辑
unsigned long long result = Chapter6_Demo();
所以程序会按 无符号 解释,但输出时用 hex,因此会打印:

text
编辑
第六章指令演示运行成功,结果汇总:0xffffffffffffff00
✅ 这与你从 RAX 中看到的值完全一致!

💡 这个结果说明什么?
0xffffffffffffff00 通常是由以下汇编操作产生的:

常见场景 1:符号扩展 + 负数
asm
编辑
mov al, 0x00      ; AL = 0x00
neg al            ; AL = -0x00 → 实际为 0x00?不对
更可能是:

常见场景 2:对负数进行符号扩展
asm
编辑
mov eax, 0xffffff00   ; EAX = -256 (32)
; 当返回 64 位时,CPU 自动符号扩展到 RAX:
; RAX = 0xffffffffffffff00
或者你在汇编中写了类似:

asm
编辑
mov rax, -256
或

asm
编辑
mov rax, 0FFh    ; 255
neg rax          ; → -255? 不对
但 0xffffffffffffff00 = -256 是非常典型的“32 位负数被符号扩展到 64 位”的结果。

在这里插入图片描述

0:000> r rax
rax=ffffffffffffff00
0:000> g
ModLoad: 00007ffd`6ab60000 00007ffd`6abfc000   C:\Windows\System32\sechost.dll
ModLoad: 00007ffd`6ad80000 00007ffd`6aea6000   C:\Windows\System32\RPCRT4.dll
Qwen3-Max
11:59:50
你执行了 g(Go)命令后,程序继续运行,并开始加载系统 DLL(如 sechost.dll, RPCRT4.dll),这是 cout 或 system("pause") 触发的正常行为。

但你可能注意到:控制台窗口没有立即显示输出,或者 WinDbg 似乎“卡住”了。

✅ 这是完全正常的!原因如下:
你的程序代码是:

cpp
编辑
cout << "第六章指令演示运行成功,结果汇总:0x" << hex << result << endl;
system("pause"); // ← 程序在这里等待用户按键!
当你在 WinDbg 中输入 g 后:

程序执行 cout,输出文本到控制台(虚拟机窗口)
然后调用 system("pause")
程序暂停,等待你按任意键
WinDbg 也会暂停(因为被调试进程在等待 I/O)
🔍 所以 WinDbg 显示 ModLoad 后不再动,并不是卡死,而是 程序正在等你按键盘!

✅ 正确操作步骤
1️⃣ 切换到虚拟机窗口
点击 VMware 的虚拟机窗口(确保它获得焦点)
你会看到类似输出

在这里插入图片描述

2️⃣ 按任意键(如空格或回车)
这会让 system("pause") 返回
程序继续执行 return 0; 并退出
3️⃣ WinDbg 会自动捕获进程退出事件
你会看到类似:

log
编辑
ntdll!NtTerminateProcess+0x14:
00007ffd`6d5bfa94 c3              ret
或

log
编辑
Process exited with status 0
💡 如果你想在退出前再次中断
可以在 main 返回前下断点:

dbg
编辑
0:000> bp test!main+0xXX  ; XX 是 return 0 的地址
但更简单的方式是:就在 system("pause") 处中断。

不过由于 system() 是外部函数,建议直接在虚拟机窗口按任意键即可。

在这里插入图片描述
🎯 完整流程闭环确认
C++ 调用汇编函数 → ✔️
汇编计算并返回 0xffffffffffffff00 → ✔️ (r rax)
C++ 成功接收并打印该值 → ✔️(虚拟机窗口可见)
程序暂停等待确认 → ✔️ (system(“pause”))
用户按键后程序正常退出 → ✔️(即将发生)
✅ 恭喜你!整个 x64 汇编 + C++ + 远程调试实验已圆满完成!

正确退出 WinDbg 与虚拟机中的调试会话,确保下次能直接运行 test.exe(不被占用、可重新编译),请按以下步骤操作:

✅ 正确退出流程(两步走)
第一步:在 WinDbg 中安全退出调试会话
在 WinDbg 命令窗口输入:

dbg
编辑
q
q = quit,会终止被调试进程(test.exe)并关闭调试连接
此时虚拟机中的 ntsd.exe 也会自动退出
💡 如果程序停在 system("pause"),先切换到虚拟机窗口按任意键让程序继续,再在 WinDbg 中输入 q。

第二步:在 虚拟机中确认无残留进程
按 Ctrl + Shift + Esc 打开 任务管理器
结束以下可能残留的进程(如有):
test.exe
ntsd.exe
conhost.exe(有时会残留)
⚠️ 关键:只要 ntsd.exe 或 test.exe 还在运行,test.exe 文件就会被锁定,导致下次编译失败(LNK1104)。

✅ 验证是否可直接运行 test.exe
完成上述退出后,在虚拟机命令行中:

cmd
编辑
cd C:\Users\wanni\Desktop\Asm64\Asm64
test.exe
✅ 应正常运行并输出结果,无需调试器介入。

🔁 下次调试时如何快速启动?
只需重复以下命令(无需重启虚拟机):

1. 编译(如需修改代码)
cmd
编辑
ml64 /c Chapter6_Demo.asm
cl /EHsc /Zi test.cpp Chapter6_Demo.obj
2. 直接运行(非调试)
cmd
编辑
test.exe
3. 如需再次调试,启动 ntsd:
cmd
编辑
"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe" -server tcp:port=50000,server=0.0.0.0 -noio test.exe
然后从宿主机 WinDbg 重新连接即可。

🛠 推荐:创建一键清理脚本(可选)
新建 cleanup.bat:

bat
编辑
@echo off
taskkill /f /im test.exe >nul 2>&1
taskkill /f /im ntsd.exe >nul 2>&1
echo 已清理调试进程,可安全编译或运行 test.exe。
每次调试前/后运行此脚本,避免文件锁定。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐