在 VS 代码中调试 NASM

Tou*_*dou 4 c++ debugging assembly nasm visual-studio-code

我有一个调用一些 NASM 代码的简单 C++ 程序:

主.cpp:

#include <iostream>

extern "C" int foo();

int main() {
  std::cout << "The result is: " << foo() << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

foo.asm:

bits 64
global foo

section .text
foo:
    mov rax, 123
    inc rax
    ret
Run Code Online (Sandbox Code Playgroud)

我可以用 CMake 编译所有东西

cmake_minimum_required (VERSION 3.15)

project (assembly-x64 LANGUAGES CXX ASM_NASM)
  
# old school CMAKE to handle NASM formats
if(WIN32)
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F cv8")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT win64)
elseif(APPLE)
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F dwarf")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT macho64)
else()
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F dwarf")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
endif()

add_executable(assembly-x64)

target_compile_features(assembly-x64 PUBLIC cxx_std_17)

target_sources(assembly-x64 PRIVATE main.cpp foo.asm)
Run Code Online (Sandbox Code Playgroud)

我得到了正确的结果。但是,我希望能够像调试 C++ 代码一样调试汇编代码。我可以在foo函数上创建一个断点(虽然不使用 GUI),但它在暂停时不会显示相应的源位置。有没有办法解决这个问题?我希望能够查看寄存器等。不确定在 VS 代码中是否可行。

Waq*_*med 6

简短回答:不可以。在 linux 上,从 vs-code 启动 gdb 以调试 asm 代码会导致快速崩溃。它甚至不允许您在汇编代码上放置断点。

如果您想了解替代方案,请阅读更长的答案。


我假设您没有使用 Linux,因为我无法使用您提供的 cmake 在 Linux 上构建项目。我必须添加以下内容:

...
else()
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F dwarf")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
    # had to add this to build on linux
    set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> \
    <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
endif()
...
Run Code Online (Sandbox Code Playgroud)

好的,现在项目已构建并运行。然而,坏消息是我无法使用 VS-Code 设置“调试”环境。VS-Code 一开始就没有很好的汇编支持,所以我在这里并不感到惊讶。我尝试launch.json多次配置,但每次启动 GDB 时,VS-Code 都会崩溃。这可能会或可能不会发生在 Windows 或 Mac 上,所以我无法回答这些平台,但我认为它不会在那里工作。

我个人只是gdb直接从终端使用,因为一旦你弄清楚它就更强大且更容易使用。我将为您提供两个工作流程,您可以使用它们来代替 Vs 代码。

使用终端

  • 构建你的可执行文件
  • 接下来使用 gdb 启动它,如下所示:
gdb ./assembly-64 --tui
Run Code Online (Sandbox Code Playgroud)

这将打开gdb并将您带到 tui 屏幕。

  • 让我们假设我们想在foo, 为这种类型放置一个断点:
b foo
Run Code Online (Sandbox Code Playgroud)
  • 现在我们的断点都设置好了。我们准备开始我们的调试会话。类型:
run
Run Code Online (Sandbox Code Playgroud)
  • 它将在foo.

但是等一下,没有寄存器,我们应该如何看到它们?这是我最喜欢的关于 gdb 的部分。类型:

layout regs
Run Code Online (Sandbox Code Playgroud)

您将在顶部看到一个漂亮的窗口,向您显示所有寄存器。它甚至会在寄存器更改时突出显示它们,以便您轻松监控更改。

  • 除此之外,用于n下一步,用于si进入。这就是基础知识。如果您想查看某个内存位置或寄存器的值。类型:
print $rax
Run Code Online (Sandbox Code Playgroud)

这还有很多,但这会给你一个快速的开始。

图形用户界面

当我发现它QtCreator可以很好地调试 asm + cpp 文件时,我感到很惊喜。只需加载您的 cmake 项目并放置断点。您可以从 启用寄存器窗格Menu->Window->Views->Registers。截屏:

在此处输入图片说明

还有其他 guis(用于 gdb),nemiver,ddd 等。