【问题标题】:%sp register doesn't point to stack%sp 寄存器不指向堆栈
【发布时间】:2014-03-12 13:37:01
【问题描述】:

我正在编写一个非常基本的内核。我试图编写一个函数,参数通过堆栈传递。内核使用 nasm 编译(如 this question 中所述)并使用 QEMU 运行。我正在使用 gdb 进行调试。

在遇到问题很长一段时间后,我写了这个来测试一些基本的堆栈操作:

BITS 16

global start
start:
    mov ax, 0x7C00
    add ax, 288
    mov ss, ax
    mov sp, 4096
    mov ax, 0x7C00
    mov ds, ax

test:
    push 42
    push 43
    push "T"
    pop ax
    pop ax
    push 44
    pop ax
    pop ax
    jmp $

一步一步地查看sp 包含的内容并查看指向地址的内容表明sp 被正确地递减/递增,但它指向的地址始终包含0x0000。

我认为这可能与mov sp, 4096 行有关。所以我把它注释掉了。这也不起作用。唯一的区别是sp 指向的值现在是其他一些值,而不是我推到那里的值。

我需要做些什么来初始化堆栈或类似的东西吗?

【问题讨论】:

  • 您确定您在寻找正确的细分市场吗?
  • 没有。我如何选择要查看的细分市场。我必须看哪个?
  • 您已将ss 设置为0x7d20 (288=0x120)。您应该查看该段,或者,如果您的调试器使用物理地址,则应用通常的实模式计算 16*ss+sp

标签: assembly gdb stack qemu osdev


【解决方案1】:

说明

  • 你想在 GDB 中查看16*$ss + $esp。 (就像 Jester 在他的评论中建议的那样)
  • x86 Segmentation 对此进行了解释。请注意,这同样适用于数据存储器访问和DS 寄存器。
  • 您将SS 设置为0x7C00 + 288 并将SP 设置为4096。因此物理堆栈指针地址为((0x7c00+0x0120)<<4) + 0x1000 给出0x7e200
  • 在代码中以十六进制写入所有内存地址和偏移量可能有助于算术。

编写 GDB 脚本以检查堆栈

boot.asm

位 16 全局启动 开始: 移动斧头,0x7C00 添加斧头,0x0120 mov ss, ax 移动 sp, 0x1000 移动斧头,0x7C00 mov ds, ax 测试: 推42 推43 按“T” 流行斧 流行斧 推44 流行斧 流行斧 hlt

检查-stack.gdb

set confirm 0
set pagination 0
set architecture i8086
target remote localhost:1234

file boot

set disassemble-next-line 1

define hook-stop
    printf "Stack Pointer: 0x%04x, AX: 0x%04x\n", ($ss*16 + $esp), $ax
    # after stack setup, the linear stack pointer address is 0x7e200
    set variable $sp_linear = 0x7e200
    x/8xb ($sp_linear - 8)
end

break test
continue

set variable $i = 0
while $i < 8
    stepi
    set variable $i = $i + 1
end

monitor quit
disconnect
quit

x86-boot.ld

进入(开始); 部分 { . = 0x7C00; .text : AT(0x7C00) { _text = .; *(。文本); _text_end = .; } 。数据 : { _data = .; *(.bss); *(.bss*); *(。数据); *(.rodata*); *(常见的) _data_end = .; } .sig : AT(0x7DFE) { 短(0xaa55); } /丢弃/ : { *(。笔记*); *(.iplt*); *(。我有*); *(.rel*); *(。评论); /* 在此处添加由您的 gcc 版本和标志喷出的任何不需要的部分 */ } }

构建:

nasm -g -f elf -F 矮人 boot.asm -o boot.o cc -nostdlib -m32 -T x86-boot.ld -Os -Wall -g3 -I。 -Wl,--build-id=none boot.o -o boot objcopy -O 二进制启动 boot.good.bin

示例会话

$ qemu-system-x86_64 -s -S boot.good.bin & $ gdb -q -x 检查堆栈.gdb 目标架构假设为 i8086 0x0000fff0 在 ?? () 0x7c10 处的断点 1:文件 boot.asm,第 13 行。 堆栈指针:0x7e200,AX:0x7c00 0x7e1f8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 断点 1,test() at boot.asm:13 13推42 => 0x00007c10 : 6a 2a 推送 $0x2a 堆栈指针:0x7e1fe,AX:0x7c00 0x7e1f8: 0x00 0x00 0x00 0x00 0x00 0x00 0x2a 0x00 14推43 => 0x00007c12 : 6a 2b 推送 $0x2b 堆栈指针:0x7e1fc,AX:0x7c00 0x7e1f8:0x00 0x00 0x00 0x00 0x2b 0x00 0x2a 0x00 15 按“T” => 0x00007c14 : 6a 54 推送 $0x54 堆栈指针:0x7e1fa,AX:0x7c00 0x7e1f8: 0x00 0x00 0x54 0x00 0x2b 0x00 0x2a 0x00 16 流行斧 => 0x00007c16 : 58 流行 %ax 堆栈指针:0x7e1fc,AX:0x0054 0x7e1f8: 0x00 0x00 0x54 0x00 0x2b 0x00 0x2a 0x00 17 流行斧 => 0x00007c17 : 58 流行 %ax 堆栈指针:0x7e1fe,AX:0x002b 0x7e1f8: 0x00 0x00 0x54 0x00 0x2b 0x00 0x2a 0x00 18推44 => 0x00007c18 : 6a 2c 推送 $0x2c 堆栈指针:0x7e1fc,AX:0x002b 0x7e1f8: 0x00 0x00 0x54 0x00 0x2c 0x00 0x2a 0x00 19 流行斧 => 0x00007c1a : 58 流行 %ax 堆栈指针:0x7e1fe,AX:0x002c 0x7e1f8: 0x00 0x00 0x54 0x00 0x2c 0x00 0x2a 0x00 20 流行斧 => 0x00007c1b : 58 流行 %ax 堆栈指针:0x7e200,AX:0x002a 0x7e1f8: 0x00 0x00 0x54 0x00 0x2c 0x00 0x2a 0x00 21 小时 => 0x00007c1c:f4 hlt

【讨论】:

    猜你喜欢
    • 2021-06-10
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    • 2012-04-27
    • 1970-01-01
    • 2016-03-15
    • 2020-03-09
    相关资源
    最近更新 更多