Assembly 如何在GDB中反汇编16位x86引导扇区代码;x/i$pc“;?它被视为32位

Assembly 如何在GDB中反汇编16位x86引导扇区代码;x/i$pc“;?它被视为32位,assembly,x86,gdb,qemu,disassembly,Assembly,X86,Gdb,Qemu,Disassembly,例如,对于BIOS将a打印到屏幕main.asm的引导扇区: org 0x7c00 bits 16 cli mov ax, 0x0E61 int 0x10 hlt times 510 - ($-$$) db 0 dw 0xaa55 然后: 我得到: 0x7c00: cli 0x7c01: mov $0x10cd0e61,%eax 0x7c06: hlt 因此,似乎mov ax,0x0E61被解释为32位mov%eax并将下一条指令int 0x10

例如,对于BIOS将
a
打印到屏幕
main.asm
的引导扇区:

org 0x7c00
bits 16
cli
mov ax, 0x0E61
int 0x10
hlt
times 510 - ($-$$) db 0
dw 0xaa55
然后:

我得到:

0x7c00:      cli    
0x7c01:      mov    $0x10cd0e61,%eax
0x7c06:      hlt 
因此,似乎
mov ax,0x0E61
被解释为32位
mov%eax
并将下一条指令
int 0x10
作为数据吃掉

我怎样才能告诉GDB这是16位代码

另见:

  • 2007年,一位GDB开发人员回答说“使用
    objdump
    ”,正如在上所解释的,也许它是同时实现的
  • 超集:
  • 类似,但OP在那里出错了,所以可能是其他原因
它与以下部件一起工作:

set architecture i8086
如前所述


set architecture
记录在:中,我们可以获得目标列表,其中包括:

set architecture

(无参数)或GDB提示符上的制表符完成。

正如Jester在评论中正确指出的那样,在使用
GDB
时,您只需使用
set architecture i8086
,以便它知道采用16位8086指令格式。您可以了解gdb目标

我加上这个作为回答,因为在评论中很难解释。如果您单独组装和链接东西,您可以生成调试信息,然后可以由
gdb
使用这些信息来提供源代码级调试,即使是针对16位代码进行远程调试。为此,我们稍微修改了部件文件:

;org 0x7c00    - remove as it may be rejected when assembling
;                with elf format. We can specify it on command
;                line or via a linker script.
bits 16

; Use a label for our main entry point so we can break on it
; by name in the debugger
main:
    cli
    mov ax, 0x0E61
    int 0x10
    hlt
    times 510 - ($-$$) db 0
    dw 0xaa55
我添加了一些注释,以确定所做的细微更改。现在,我们可以使用这些命令来组装文件,使其包含dwarf格式的调试输出。我们将其链接到最终的elf图像。此elf映像可通过
gdb
用于符号调试。然后,我们可以使用
objcopy

nasm -f elf32 -g3 -F dwarf main.asm -o main.o
ld -Ttext=0x7c00 -melf_i386 main.o -o main.elf
objcopy -O binary main.elf main.img

qemu-system-i386 -hda main.img -S -s &
gdb main.elf \
        -ex 'target remote localhost:1234' \
        -ex 'set architecture i8086' \
        -ex 'layout src' \
        -ex 'layout regs' \
        -ex 'break main' \
        -ex 'continue'
我做了一些小改动。启动
gdb
时,我使用
main.elf
文件(带有符号信息)

我还为汇编代码和寄存器添加了一些更有用的代码,这些代码和寄存器可以使命令行上的调试更容易。我还打开了
main
(不是地址)。由于调试信息,程序集文件中的源代码也应该出现。如果希望查看原始部件,可以使用
layout asm
而不是
layout src

这个通用概念可以在其他平台上NASM和LD支持的其他格式上使用<代码>elf32和
elf_i386
以及调试类型必须针对特定环境进行修改。我的示例针对理解Linux Elf32二进制文件的系统


用GDB/QEMU调试16位实模式引导加载程序 不幸的是,默认情况下,
gdb
不进行分段:偏移计算,并将使用EIP中的值作为断点。必须将断点指定为32位地址(EIP)

当涉及到逐步通过实模式代码时,它可能会很麻烦,因为
gdb
不处理实模式分段。如果您进入一个中断处理程序,您将发现
gdb
将显示与EIP相关的汇编代码。实际上,
gdb
将向您显示错误内存位置的反汇编,因为它没有考虑CS。谢天谢地,有人创造了一个新的方法来帮助我们。将脚本下载到您的开发目录中,然后使用以下内容运行QEMU:

qemu-system-i386 -hda main.img -S -s &
gdb -ix gdbinit_real_mode.txt main.elf \
        -ex 'target remote localhost:1234' \
        -ex 'break main' \
        -ex 'continue'
脚本负责将体系结构设置为i8086,然后将自身挂接到
gdb
。它提供了许多可以使单步执行16位代码更容易的方法

break_int:在软件中断向量上添加断点 好的旧MS DOS和BIOS公开了它们的API)

break_int_if_ah:在软件中断上添加一个条件断点。AH必须等于给定的参数。这用于过滤中断的服务调用。例如,您有时只想在调用中断10h的函数AH=0h时中断(更改屏幕模式)

stepo:这是一个kabalistic宏,用于“跳过”函数和中断调用。它是如何工作的?提取当前指令的操作码,如果是函数或中断调用,则计算“下一个”指令地址,在该地址上添加临时断点,并调用“继续”函数

step_until_ret:用于单步执行,直到遇到“ret”指令

step_until_iret:用于单步执行,直到遇到“iret”指令

step_until_int:用于单步执行,直到遇到“int”指令

该脚本还打印出地址和寄存器,并在中计算分段。每个指令执行后的输出如下所示:

---------------------------[ STACK ]---
D2EA F000 0000 0000 6F62 0000 0000 0000
7784 0000 7C00 0000 0080 0000 0000 0000
---------------------------[ DS:SI ]---
00000000: 53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0  S...S.......S...
00000010: 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0  S...S...S...S...
00000020: A5 FE 00 F0 87 E9 00 F0 76 D6 00 F0 76 D6 00 F0  ........v...v...
00000030: 76 D6 00 F0 76 D6 00 F0 57 EF 00 F0 76 D6 00 F0  v...v...W...v...
---------------------------[ ES:DI ]---
00000000: 53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0  S...S.......S...
00000010: 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0  S...S...S...S...
00000020: A5 FE 00 F0 87 E9 00 F0 76 D6 00 F0 76 D6 00 F0  ........v...v...
00000030: 76 D6 00 F0 76 D6 00 F0 57 EF 00 F0 76 D6 00 F0  v...v...W...v...
----------------------------[ CPU ]----
AX: AA55 BX: 0000 CX: 0000 DX: 0080
SI: 0000 DI: 0000 SP: 6F2C BP: 0000
CS: 0000 DS: 0000 ES: 0000 SS: 0000

IP: 7C00 EIP:00007C00
CS:IP: 0000:7C00 (0x07C00)
SS:SP: 0000:6F2C (0x06F2C)
SS:BP: 0000:0000 (0x00000)
OF <0>  DF <0>  IF <1>  TF <0>  SF <0>  ZF <0>  AF <0>  PF <0>  CF <0>
ID <0>  VIP <0> VIF <0> AC <0>  VM <0>  RF <0>  NT <0>  IOPL <0>
---------------------------[ CODE ]----
=> 0x7c00 <main>:       cli
   0x7c01:      mov    ax,0xe61
   0x7c04:      int    0x10
   0x7c06:      hlt
   0x7c07:      add    BYTE PTR [bx+si],al
   0x7c09:      add    BYTE PTR [bx+si],al
   0x7c0b:      add    BYTE PTR [bx+si],al
   0x7c0d:      add    BYTE PTR [bx+si],al
   0x7c0f:      add    BYTE PTR [bx+si],al
   0x7c11:      add    BYTE PTR [bx+si],al
-----------------------------------[STACK]---
D2EA F000 0000 6F62 0000 0000
7784 0000 7C00 0000 0080 0000 0000
---------------------------[DS:SI]---
00000000:53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0 S…S…S。。。
00000010:53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 S…S…S…S。。。
00000020:A5 FE 00 F0 87 E9 00 F0 76 D6 00 F0 76 D6 00 F0…v…v。。。
00000030:76 D6 00 F0 76 D6 00 F0 57 EF 00 F0 76 D6 00 F0 v…v…W…v。。。
---------------------------[ES:DI]---
00000000:53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0 S…S…S。。。
00000010:53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 S…S…S…S。。。
00000020:A5 FE 00 F0 87 E9 00 F0 76 D6 00 F0 76 D6 00 F0…v…v。。。
00000030:76 D6 00 F0 76 D6 00 F0 57 EF 00 F0 76 D6 00 F0 v…v…W…v。。。
----------------------------[中央处理器]----
AX:AA55 BX:0000 CX:0000 DX:0080
SI:0000 DI:0000 SP:6F2C BP:0000
CS:0000 DS:0000 ES:0000 SS:0000
IP:7C00 EIP:00007C00
CS:IP:0000:7C00(0x07C00)
SS:SP:0000:6F2C(0x06F2C)
SS:BP:0000:0000(0x00000)
如果TF SF ZF AF PF CF
ID VIP VIF AC VM RF NT IOPL
---------------------------[守则]----
=>0x7c00:cli
---------------------------[ STACK ]---
D2EA F000 0000 0000 6F62 0000 0000 0000
7784 0000 7C00 0000 0080 0000 0000 0000
---------------------------[ DS:SI ]---
00000000: 53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0  S...S.......S...
00000010: 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0  S...S...S...S...
00000020: A5 FE 00 F0 87 E9 00 F0 76 D6 00 F0 76 D6 00 F0  ........v...v...
00000030: 76 D6 00 F0 76 D6 00 F0 57 EF 00 F0 76 D6 00 F0  v...v...W...v...
---------------------------[ ES:DI ]---
00000000: 53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0  S...S.......S...
00000010: 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0 53 FF 00 F0  S...S...S...S...
00000020: A5 FE 00 F0 87 E9 00 F0 76 D6 00 F0 76 D6 00 F0  ........v...v...
00000030: 76 D6 00 F0 76 D6 00 F0 57 EF 00 F0 76 D6 00 F0  v...v...W...v...
----------------------------[ CPU ]----
AX: AA55 BX: 0000 CX: 0000 DX: 0080
SI: 0000 DI: 0000 SP: 6F2C BP: 0000
CS: 0000 DS: 0000 ES: 0000 SS: 0000

IP: 7C00 EIP:00007C00
CS:IP: 0000:7C00 (0x07C00)
SS:SP: 0000:6F2C (0x06F2C)
SS:BP: 0000:0000 (0x00000)
OF <0>  DF <0>  IF <1>  TF <0>  SF <0>  ZF <0>  AF <0>  PF <0>  CF <0>
ID <0>  VIP <0> VIF <0> AC <0>  VM <0>  RF <0>  NT <0>  IOPL <0>
---------------------------[ CODE ]----
=> 0x7c00 <main>:       cli
   0x7c01:      mov    ax,0xe61
   0x7c04:      int    0x10
   0x7c06:      hlt
   0x7c07:      add    BYTE PTR [bx+si],al
   0x7c09:      add    BYTE PTR [bx+si],al
   0x7c0b:      add    BYTE PTR [bx+si],al
   0x7c0d:      add    BYTE PTR [bx+si],al
   0x7c0f:      add    BYTE PTR [bx+si],al
   0x7c11:      add    BYTE PTR [bx+si],al
set architecture <arch>
set tdesc filename <file>
(gdb) target remote localhost:26000
[...]
Breakpoint 1, 0x00007c00 in ?? ()
(gdb) x /5i 0x7c24
   0x7c24:      cli    
   0x7c25:      cld    
   0x7c26:      mov    eax,0xc08e0050
   0x7c2b:      xor    ebx,ebx
   0x7c2d:      mov    al,0x2
(gdb) set tdesc filename target.xml 
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB.  Attempting to continue with the default i8086 settings.

(gdb) x /5i 0x7c24
   0x7c24:      cli    
   0x7c25:      cld    
   0x7c26:      mov    ax,0x50
   0x7c29:      mov    es,ax
   0x7c2b:      xor    bx,bx
$ echo '<?xml version="1.0"?><!DOCTYPE target SYSTEM "gdb-target.dtd"><target><architecture>i8086</architecture><xi:include href="i386-32bit.xml"/></target>' > target.xml
$ wget https://raw.githubusercontent.com/qemu/qemu/master/gdb-xml/i386-32bit.xml
set tdesc filename target.xml
# Real mode
set architecture i8086
set tdesc filename target.xml
bits 16

; Use a label for our main entry point so we can break on it
; by name in the debugger
main:
    cli
    mov ax, 0x0E61
    int 0x10
    hlt
    times 510 - ($-$$) db 0
    dw 0xaa55
nasm -f elf32 -g3 -F dwarf main.asm -o main.o
ld -Ttext=0x7c00 -melf_i386 main.o -o main.elf
objcopy -O binary main.elf main.img
qemu-system-i386 -hda main.img -S -s &
gdb --nx -ix gdb.txt main.elf \
        -ex 'target remote localhost:1234'
real-mode-gdb$ b main  
Breakpoint 1 at 0x7c00: file main.asm, line 6.  
real-mode-gdb$ c   
Continuing.  
---------------------------[ STACK ]---  
D002 F000 0000 0000 6F5E 0000 8016 0000   
8057 0000 0000 0000 0000 0000 8016 0000   
---------------------------[ DS:SI ]---  
00000000: 53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0  S...S.......S...  
00000010: 53 FF 00 F0 54 FF 00 F0 53 FF 00 F0 53 FF 00 F0  S...T...S...S...  
00000020: A5 FE 00 F0 87 E9 00 F0 42 D4 00 F0 42 D4 00 F0  ........B...B...  
00000030: 42 D4 00 F0 42 D4 00 F0 57 EF 00 F0 42 D4 00 F0  B...B...W...B...  
---------------------------[ ES:DI ]---  
00000000: 53 FF 00 F0 53 FF 00 F0 C3 E2 00 F0 53 FF 00 F0  S...S.......S...  
00000010: 53 FF 00 F0 54 FF 00 F0 53 FF 00 F0 53 FF 00 F0  S...T...S...S...  
00000020: A5 FE 00 F0 87 E9 00 F0 42 D4 00 F0 42 D4 00 F0  ........B...B...  
00000030: 42 D4 00 F0 42 D4 00 F0 57 EF 00 F0 42 D4 00 F0  B...B...W...B...  
----------------------------[ CPU ]----  
AX: AA55 BX: 0000 CX: 0000 DX: 0080  
SI: 0000 DI: 0000 SP: 6F00 BP: 0000  
CS: 0000 DS: 0000 ES: 0000 SS: 0000  
  
IP: 7C00 EIP:00007C00  
CS:IP: 0000:7C00 (0x07C00)  
SS:SP: 0000:6F00 (0x06F00)  
SS:BP: 0000:0000 (0x00000)  
OF <0>  DF <0>  IF <1>  TF <0>  SF <0>  ZF <0>  AF <0>  PF <0>  CF <0>  
ID <0>  VIP <0> VIF <0> AC <0>  VM <0>  RF <0>  NT <0>  IOPL <0>  
---------------------------[ CODE ]----  
=> 0x7c00 <main>:       cli  
   0x7c01:      mov    ax,0xe61  
   0x7c04:      int    0x10  
   0x7c06:      hlt  
   0x7c07:      add    BYTE PTR [bx+si],al  
   0x7c09:      add    BYTE PTR [bx+si],al  
   0x7c0b:      add    BYTE PTR [bx+si],al  
   0x7c0d:      add    BYTE PTR [bx+si],al  
   0x7c0f:      add    BYTE PTR [bx+si],al  
   0x7c11:      add    BYTE PTR [bx+si],al  
  
Breakpoint 1, main () at main.asm:6  
6           cli