【问题标题】:GDB shows error message when trying to print a variable in an Assembly program尝试在汇编程序中打印变量时 GDB 显示错误消息
【发布时间】:2019-02-14 11:01:20
【问题描述】:

在从书中学习汇编语言时,有一个清单显示了一些基本操作:

segment .data
a   dq  176
b   dq  4097

segment .text
global _start

_start:
    mov rax, [a]    ; Move a into rax.
    add rax, [b]    ; add b o rax.
    xor rax, rax
    ret

在使用"$yasm -f elf64 -g dwarf2 -l listing.lst listing.asm" 命令组装并与"$ld -o listing listing.o" 链接后,我在gdb 中运行了程序。每当我尝试打印变量的值时,gdb 都会显示以下错误消息:

(gdb) p a
'a' has unknown type; cast it to its declared type

其他变量“b”也是如此。但是为 int 强制转换 'a' 或 'b' 有效:

(gdb) p (int)a
$11 = 176
(gdb) p (int)b
$12 = 4097

但这不应该在没有强制转换的情况下工作吗?为什么我需要投?我在源文件中犯了什么错误?

【问题讨论】:

  • dq 在您的目标平台上很可能不是int(我从头到尾都不确定int 在哪个目标平台上是64b)。因此,您可能只打印了铸造值的 32 位部分。 (而且我也不确定 gdb 识别什么类型,p (int64_t)a 是否有效,或者您必须使用基本 C 类型,如 p (long long)a?甚至一些 asm 也被识别为 p (qword)a?)
  • 感谢您注意到 Ped7g。 sizeof() 在我的 PC 中为 int 返回 4。所以应该是dd。但是将 dq 更改为 dd 并不能解决问题。
  • mov rax,[a] 确实读取了 8 个字节,因此如果您只想使用 dd 来定义数据,那么它应该是 mov eax,[a](或者 movsx rax,dword [a] 如果您想要符号扩展32 位内存值转换为 64 位 rax)。我也看不出dqdd 将如何解决任何问题,它只是改变了标签a 之后定义的内存量。在调试信息中提供标签a 某种类型信息超出了我通常在汇编中所做的工作(你让我有点认识到 8 位时代如何迫使我如此多地跟踪头脑中的所有内容,而我没有甚至考虑调试器知道“类型”)。
  • 我的意思是,对我来说,你的问题甚至不是“问题”,我总是自己在调试器中为特定符号选择正确的大小。既然您问了这个问题,是的,如果汇编器能提供有关调试器符号的更多信息,那就太好了。然后,通常当一个人需要汇编程序(很少)时,他也经常需要非常规的内存工作,因此为标签a 定义某种“类型”实际上可能会影响您(如果您通过以下方式访问该内存)不同的指令,例如,如果你对一些代码进行矢量化,一次访问多个元素)。
  • so “但是这不应该在没有强制转换的情况下工作吗?” - 不,不是靠它自己。当特定标签还附加了有关存储在那里的预期数据“类型”的信息时,调试器将执行此操作,这是高级语言通常提供的,因为在 C 中,int32_t a = 1; 之类的东西确实定义了 32 位整数,但在汇编中类似于a: dd 1 确实定义了指向发出机器码的下一个第一个字节的标签(行的a: 部分),然后它定义了四个字节1, 0, 0, 0(行的dd 1 部分),它们就像断开连接的实体,你甚至可以使用两条线。

标签: assembly gdb yasm


【解决方案1】:

当一个符号没有描述大小/类型的调试信息时,旧的 GDB 过去默认假定符号是 int

这通常会导致比当前行为更多混乱,因此对其进行了更改。例如The value displayed in Kdbg is wrong -- NASM

【讨论】:

  • 所以必须指定变量类型毕竟不是一件坏事。它绝对不是错误,是吗? PS:我使用的是 GDB 版本 8.1.0.20180409
  • @AnikSamiurRahman:没错,这是预期的行为。 NASM 没有语法来创建必要的调试信息这一事实可能被认为是缺少的功能。与 MASM 不同,标签和同一行上的 dq 之间没有神奇的关联。不要忘记在 dq 之前的标签名称之后的:,以避免指令助记符产生歧义。例如bound: dq 1 是合法的,但 bound dq 1 不会汇编,因为 bound 是一条指令。在 NASM 语法中使用 a dq 1 而不是 a: dq 1 的优势为零。
【解决方案2】:

但这不应该在没有强制转换的情况下工作吗?

没有。 GDB 告诉你它不知道ab 是什么type

我在源文件中犯了什么错误?

你没有犯任何错误,但你也没有提供任何 GDB 可以使用的调试信息。

您可能希望yasm -g dwarf2 ... 这样做,但它只创建描述源的最小调试信息,没有别的:

$ readelf -wi listing.o

Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0x37 (32-bit)
   Version:       2
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_stmt_list   : 0x0
    <10>   DW_AT_low_pc      : 0x0
    <18>   DW_AT_high_pc     : 0x14
    <20>   DW_AT_name        : listing.asm
    <28>   DW_AT_comp_dir    : /tmp/
    <2e>   DW_AT_producer    : yasm 1.3.0
    <39>   DW_AT_language    : 32769    (MIPS assembler)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 2017-05-19
    • 1970-01-01
    • 2023-01-08
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    相关资源
    最近更新 更多