【问题标题】:Debugging NASM in VS code在 VS 代码中调试 NASM
【发布时间】:2020-11-21 02:55:39
【问题描述】:

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

main.cpp:

#include <iostream>

extern "C" int foo();

int main() {
  std::cout << "The result is: " << foo() << std::endl;
  return 0;
}

foo.asm:

bits 64
global foo

section .text
foo:
    mov rax, 123
    inc rax
    ret

我可以用 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)

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

【问题讨论】:

    标签: c++ debugging assembly visual-studio-code nasm


    【解决方案1】:

    简短回答:否。在 linux 上,从 vs-code 启动 gdb 以调试 asm 代码会导致快速崩溃。它甚至不允许你在 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()
    ...
    

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

    我个人只是直接从终端使用gdb,因为一旦你弄清楚它就更强大且易于使用。我会给你两个工作流程,你可以用它们来代替 Vs-code。

    使用终端

    • 构建您的可执行文件
    • 接下来使用 gdb 启动它,如下所示:
    gdb ./assembly-64 --tui
    

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

    • 假设我们想在foo 处设置一个断点,对于这种类型:
    b foo
    
    • 现在我们的断点都设置好了。我们已准备好开始调试会话。类型:
    run
    
    • 它将在foo 中断。

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

    layout regs
    

    您将在顶部看到一个漂亮的外观窗口,显示所有寄存器。它甚至会在寄存器发生变化时突出显示它们,使您可以轻松监控变化。

    • 除此之外,使用n 进入下一步,使用si 进入。这就是基本的内容。如果您想查看某个内存位置或寄存器的值。类型:
    print $rax
    

    还有很多其他内容,但这会让您快速入门。

    图形界面

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

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

    【讨论】:

    • 感谢您的详细回答。那么我会给 QtCreator 一个机会。如果由于某种原因它不起作用,我将牺牲可移植性,并按照您的建议使用 gdb 在我的 Linux 机器上完成所有工作。
    • cs.uaf.edu/2017/fall/cs301/reference/nasm_vs 如果你有 Visual Studio,这可能对你有用。
    • 感谢您的提示,但我想设置一个可以在我的 Linux 和 Windows 机器上运行的环境。到目前为止,QtCreator 似乎做得很好。请注意,不知何故,我的代码是用 VS Code 编译的,而不是用 QtCreator 编译的。我还必须添加您提到的行以使其正确构建。
    • 为了完整起见,Visual Studio 也可以使用 MI 引擎在 Linux 中进行远程调试。出于某种原因,gdb 中的 asm 调试实际上在那里工作,您可以在代码中设置断点,可视化寄存器内容等。
    • 我知道那是很久以前的事了,但你能上传所有项目供某个网站下载吗?当我放一个断点时,我遇到了 qt creator 的问题,它只是错过了整个 asm 文件,只调试了 cpp 文件。
    猜你喜欢
    • 2014-01-03
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 2016-03-18
    • 2018-11-19
    相关资源
    最近更新 更多