NASM 与 GDB 简易调试指南

本文目标:在 Linux 平台中,利用 nasm 与 gdb 快速构建一个编译与调试工具链,以下仅做简单演示。
主要还是因为学习“计算机组成原理”中 intel 指令相关内容的时候,太生涩难懂了。就是想简单实操一下,深刻理解,因此才出了这篇文章。

我们以一下程序为例举例说明。

section .data
    hello db "hello, world", 10 ; 定义要输出的字符串,10 是换行符的 ASCII 码
    hello_len equ $ - hello ; 计算字符串长度

section .text
    global _start ; 必须声明 _start 为全局符号,这是链接器识别的入口点


; 调用系统调用 exit
exit:
    mov rax, 1 ; 系统调用号,这里是 exit
    int 0x80 ; 触发系统调用

; 一个简易的加法函数
; 传参寄存器 edi, esi
add:
    push rbp
    mov rbp, rsp
    ; 函数无变量
    mov [rbp - 4], edi
    mov [rbp - 8], esi
    mov edx, [rbp - 4]
    mov eax, [rbp - 8]
    add eax, edx
    pop rbp
    ret

; 入口函数   
_start:
    ; 调用系统调用 write 功能, 向终端输出文本
    mov eax, 4 ; 系统调用号,这里是 write
    mov ebx, 1 ; 文件描述符 1,代表标准输出
    mov ecx, hello ; 字符串的地址
    mov edx, hello_len ; 字符串长度
    int 0x80 ; 触发系统调用

    mov edi, 10
    mov esi, 20
    call add
    mov rbx, rax
    jmp exit

如何使用 NASM 编译生成可执行文件

在 Linux 平台上,我们可以直接使用 nasm 生成 elf 可执行文件,目前 nasm 提供了两种生成方法。

  1. 生成可重定向目标代码,然后再链接代码。

    nasm -f elf64 test.asm -o test.o
    ld -o test test.o
    
  2. 直接生成可执行文件。

    nasm -f aout test.asm -o test
    

如何使用 GDB 调试生成的代码

由于我们生成的代码并不可能包含调试信息,以至于我们在调试的时候困难重重。我们只能使用 disassemble 指令来查看调试内容。

gdb ./test	# 执行指令
# 以下是交互式界面需要执行的命令
break _start	# 在 _start 处添加短点信息
run	# 执行程序
layout asm	# TUI显示汇编信息
layout regs	# TUI显示寄存器信息

以下是一些常用命令:

  • info registers:查看所有寄存器信息
  • stepi:单次执行一条指令
  • continue:继续执行指令
  • break *0x401016:在指定内存位置添加端点
  • x /10x $sp - 16:查看 esp - 16 所在内存的连续 10 个 dword 大小的内存空间数据。

调试的时候需要注意位数(64 位占 8 字节),以及intel处理器为小端方式

posted @ 2024-08-27 22:38  乾坤盘  阅读(13)  评论(0编辑  收藏  举报