【问题标题】:Debugging a compiled C program with GDB to learn Assembly programming用 GDB 调试编译的 C 程序学习汇编编程
【发布时间】:2017-07-01 17:30:47
【问题描述】:

我对 gdb 很陌生。我写了一个非常简单的hello world程序

#include <stdio.h>

int main() {
  printf("Hello world\n");
  return 0;
}

我用-g编译它添加调试符号

gcc -g -o hello hello.c

由于我不熟悉 gdb,我不确定下一步该做什么。我希望能够使用 gdb 来检查汇编代码。这就是我在 IRC 上被告知的内容。

【问题讨论】:

  • 如果您只想要 ASM 并且不想打扰 gdb,您可以考虑使用 -S 标志编译以获得可以使用文本编辑器打开的程序集输出。但是,如果您这样做了,您将无法在不进一步编译的情况下执行或逐步执行执行。那只会给你作为文本的汇编代码。

标签: c gcc assembly gdb


【解决方案1】:

首先,启动程序,正好停在main函数的开头。

(gdb) start

切换到装配布局以在单独的窗口中以交互方式查看装配说明。

(gdb) layout asm

使用stepinexti 命令单步执行程序。当您走过程序中的汇编指令时,您会看到汇编窗口中的当前指令指针移动。

【讨论】:

  • 我喜欢layout asm / layout reg 将终端分成三个窗口:寄存器、反汇编和命令。 GDB 突出显示自上次停止后发生更改的寄存器,因此单步执行时非常棒。我在the x86 tag wiki 的底部放了一个关于这个的部分,里面有很多有用的东西。
【解决方案2】:

printf 几乎是你想用来学习汇编的最后一个函数,库调用会稍后出现,但你不需要使用库/系统调用。使用调试器也会使用系统调用将您带入老鼠巢。试试这样的方法,特别是如果你想从这个练习中学习汇编语言。

unsigned int fun ( unsigned int a, unsigned int b )
{
    return(a^b^3);
}

gcc -O2 -c so.c -o so.o
objdump -D so.o

Disassembly of section .text:

0000000000000000 <fun>:
   0:   89 f0                   mov    %esi,%eax
   2:   83 f0 03                xor    $0x3,%eax
   5:   31 f8                   xor    %edi,%eax
   7:   c3                      retq   

我强烈建议您避免将 x86 作为您的第一个指令集。尝试更清洁的东西...

arm-none-eabi-gcc -O2 -c so.c -o so.o
arm-none-eabi-gcc -O2 -c -mthumb  so.c -o so.o
arm-none-eabi-objdump -D so.o

00000000 <fun>:
   0:   2303        movs    r3, #3
   2:   4059        eors    r1, r3
   4:   4048        eors    r0, r1
   6:   4770        bx  lr

msp430-gcc -O2 -c so.c -o so.o
msp430-objdump -D so.o

00000000 <fun>:
   0:   3f e0 03 00     xor #3, r15 ;#0x0003
   4:   0f ee           xor r14,    r15 
   6:   30 41           ret

非常认真地认为这是第一个指令集,msp430 接近它,但这个最有意义,不幸的是 gnu 汇编器语法与书籍不匹配,而且不幸的是当时用八进制思考的世界,我们认为是十六进制现在...

pdp11-aout-gcc -O2 -c so.c -o so.o
pdp11-aout-objdump -D so.o


00000000 <_fun>:
   0:   1166            mov r5, -(sp)
   2:   1185            mov sp, r5
   4:   15c0 0003       mov $3, r0
   8:   1d41 0006       mov 6(r5), r1
   c:   7840            xor r1, r0
   e:   1d41 0004       mov 4(r5), r1
  12:   7840            xor r1, r0
  14:   1585            mov (sp)+, r5
  16:   0087            rts pc

适合所有人的模拟器或硬件,最好在模拟器中学习而不是在真实硬件上学习...

我通过编写反汇编程序学到的大多数指令集,arm 和 thumb 都属于这一类,因为它们的指令长度是固定的(如果你避免使用 thumb2 扩展)。或者只是写一个模拟器,msp430和pdp11就属于这一类。后者要么是一个下午的项目,要么是一个长周末的项目。你会比一般人更了解每个指令集,甚至有些人已经使用它编程了一段时间。

如果您坚持使用 x86(我强烈建议您不要这样做),请使用 8086/8088 模拟器(如 pcemu)并坚持使用原始指令集,使用 nasm 或 a86 或任何需要的东西来执行此操作。即使在当时,它也不是很好的指令集,但当时比现在更有意义。 bitsavers 很好地扫描了原始英特尔文档的搜索功能版本,是最好的起点。

arm 文档在 arm(正在寻找 armv5 的架构参考手册,我想他们现在称之为)。 msp430 看看wikipedia 指令集有没有pdp11 google 一下,用C 机器码反汇编找出语法。

如果你真的想玩得开心,从 opencores 获取 amber core 是 arm2/3,几乎所有指令都与 armv4 及更高版本相同,可以使用 gnu 工具。使用 verilator 构建和模拟并从内部查看正在工作的处理器。理解就像让 100 名程序员给他们一个编程任务并获得 1 到 100 种不同的解决方案一样,拿一个指令集并给 100 名工程师执行它的任务,你会得到 1 到 100 种不同的解决方案。 Arm 本身已经为相同的指令集重新设计了他们的内核数次,更不用说为数不多的合法克隆了。

推荐顺序 pdp11、msp430、thumb、arm,然后是 mips,如果您仍然觉得需要拆卸一些 x86。 PIC12/14 简单且具有教育意义(你应该花半小时到一个小时来制作一个模拟器),6502、z80、8051、6800 和其他一些在历史上也像 x86 一样具有教育意义,可以查看文档,但是不需要编写程序。如果您从一个好的开始,那么从第二个指令集开始,每个第 N 个指令集都会容易得多。它们的相似之处多于不同之处,但是您确实可以看到不同的东西,例如如何在 mips 中没有标志的情况下做事等……我遗漏了其他几个仍然在硅片中可用或由于各种原因而有趣的指令集。

另一种方法是安装 clang/llvm 并快速或更长时间地查看 llc 可以生成的每个指令集(编译为位码/字节码,然后使用 llc 对任何指令集进行后端处理)。就像上面一样,使用相同的代码并至少使用该编译器查看不同的指令集是什么样的,它的设置非常有教育意义,有助于从心理上了解如何将编程任务分解为这些原子步骤。

【讨论】:

  • 这太棒了!谢谢大家的提醒。谢谢你非常详细的解释。我从你的帖子中学到了很多。
  • IMO,32 位(或 64 位)用户空间 x86 代码比 8086 更容易学习。没有分段,对于哪些寄存器可以在寻址方式。您无需交叉编译器即可轻松查看编译器的工作方式。不过我是先学m68k的,只是偶尔随便看了一下i386 asm才真正进入,所以不能说先学x86的经验。不过,我真的很喜欢学习桌面实际使用的 asm 的想法。
  • ARM 可能是第一个学习 asm 的明智选择,至少如果您设法避免被 ARM 与 thumb 与 thumb2 混淆... MIPS 也很好。主要的皱纹是分支延迟槽和the register-naming convention has $a0 being the same register as $r4,很容易忘记实际上只有 31 个平面寄存器和一个零寄存器。此外,通常的 ABI 还为内核保留了几个寄存器,以便在中断处理程序中异步破坏!无论如何,除了 MIPS 是干净的。
  • @devwannabe:如果 / 当你学习 x86 时,我建议你学习 Intel 语法。 GNU 工具默认使用 AT&T 语法,但 gcc -masm=intel 使用类似于 MASM 的语法。 objdump -drwC -Mintel 也是如此。对于 GDB,请将 set disassembly-flavor intel 放入您的 ~/.gdbinit
  • mac osx 使用什么架构?是 x86 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多