Assembly 如何在GDB中反汇编16位x86引导扇区代码;x/i$pc“;?它被视为32位
例如,对于BIOS将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
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