RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 609162
Accepted
AccumPlus
AccumPlus
Asked:2020-12-29 17:47:14 +0000 UTC2020-12-29 17:47:14 +0000 UTC 2020-12-29 17:47:14 +0000 UTC

C引导扇区编程

  • 772

我了解引导扇区编程。我是按照这篇文章做的。一切顺利,直到对输出“Hello, World!”进行编程为止。在C中。这是文章中给出的代码(实际上,我只是复制它):

__asm__(".code16\n");
__asm__("jmpl $0x0000, $main\n");

void printString(const char* pStr) {
     while(*pStr) {
          __asm__ __volatile__ (
               "int $0x10" : : "a"(0x0e00 | *pStr), "b"(0x0007)
          );
          ++pStr;
     }
}

void main() {
     printString("Hello, World");
}

我又按照那篇文章编译、链接等:

gcc -c -g -Os -m32 -ffreestanding -Wall -Werror test.c -o test.o
ld -melf_i386 -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o
objcopy -O binary test.elf test.bin
dd if=/dev/zero of=floppy.img bs=512 count=2880
dd if=test.bin of=floppy.img

为了以防万一,我给出test.ld的内容:

ENTRY(main);
SECTIONS
{
    . = 0x7C00;
    .text : AT(0x7C00)
    {
        *(.text);
    }
    .sig : AT(0x7DFE)
    {
        SHORT(0xaa55);
    }
}

我运行 bochs,但我没有打印“Hello, World”,而是只得到一个“S”字符。

将函数移至 main:

__asm__(".code16\n");
__asm__("jmpl $0x0000, $main\n");
void main()
{
    char s[] = "Hello, World";
    char *str = s;
    while (*str)
    {
        __asm__ __volatile__ (
               "int $0x10" : : "a"(0x0e00 | *str), "b"(0x0007)
          );
        ++str;
    }
}

之后,他原则上不再展示任何东西。-Os 优化标志的异常有所帮助。结论是正确的。经过一些试验,我意识到这种优化“杀死”了循环。

然而,相同的代码,但移至一个函数,仍然输出“S”字符。

我寻求帮助解决这个问题。并且,如果可能的话,解释为什么优化标志“杀死”循环。谢谢!

更新。

来自 test.bin 的十六进制:

66 EA 3A 7C 00 00 00 00 66 55 66 89 E5 EB 19 67 66 8B 45 08 67 66 0F B6 00 66 0F BE C0 80 CC 0E CD 10 67 66 83 45 08 01 67 66 8B 45 08 67 66 0F B6 00 84 C0 75 D9 90 66 5D C3 66 55 66 89 E5 66 68 4F 7C 00 00 E8 C0 FF 66 83 C4 04 90 C9 C3 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 00 14 00 00 00 00 00 00 00 01 7A 52 00 01 7C 08 01 1B 0C 04 04 88 01 00 00 1C 00 00 00 1C 00 00 00 8C FF FF FF 32 00 00 00 00 42 0E 08 85 02 43 0D 05 6C C5 0C 04 04 00 00 1C 00 00 00 3C 00 00 00 9E FF FF FF 15 00 00 00 00 42 0E 08 85 02 43 0D 05 4F C5 0C 04 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA

该文件是从以下来源获得的:

__asm__(".code16\n");
__asm__("jmpl $0x0000, $main\n");

void printString(const char* str)
{
    while (*str)
    {
        __asm__ __volatile__ (
               "int $0x10" : : "a"(0x0e00 | *str));
        ++str;
    }
}

void main()
{
    printString("Hello, World");
}

更新。

test.elf文件反汇编结果:

% objdump -d test.elf

test.elf:     file format elf32-i386

Disassembly of section .text:

00007c00 <printString-0x8>:
    7c00:   66 ea 3a 7c 00 00       ljmpw  $0x0,$0x7c3a
    ...

00007c08 <printString>:
    7c08:   66 55                   push   %bp
    7c0a:   66 89 e5                mov    %sp,%bp
    7c0d:   eb 19                   jmp    7c28 <printString+0x20>
    7c0f:   67 66 8b 45 08          mov    0x8(%di),%ax
    7c14:   67 66 0f b6 00          movzbw (%bx,%si),%ax
    7c19:   66 0f be c0             movsbw %al,%ax
    7c1d:   80 cc 0e                or     $0xe,%ah
    7c20:   cd 10                   int    $0x10
    7c22:   67 66 83 45 08 01       addw   $0x1,0x8(%di)
    7c28:   67 66 8b 45 08          mov    0x8(%di),%ax
    7c2d:   67 66 0f b6 00          movzbw (%bx,%si),%ax
    7c32:   84 c0                   test   %al,%al
    7c34:   75 d9                   jne    7c0f <printString+0x7>
    7c36:   90                      nop
    7c37:   66 5d                   pop    %bp
    7c39:   c3                      ret    

00007c3a <main>:
    7c3a:   66 55                   push   %bp
    7c3c:   66 89 e5                mov    %sp,%bp
    7c3f:   66 68 4f 7c             pushw  $0x7c4f
    7c43:   00 00                   add    %al,(%eax)
    7c45:   e8 c0 ff 66 83          call   83677c0a <main+0x8366ffd0>
    7c4a:   c4 04 90                les    (%eax,%edx,4),%eax
    7c4d:   c9                      leave  
    7c4e:   c3                      ret

更新。

这是处理器看到程序时对 hiew 的反汇编:

7c00: 66EA3A7C00000000              jmpf        00000:07C3A
7c08: 6655                         3push        ebp
7c0A: 6689E5                        mov         ebp,esp
7c0D: EB19                          jmps        000000028 --↓1
7c0F: 67668B4508                   2mov         eax,[ebp][8]
7c14: 67660FB600                    movzx       eax,b,[eax]
7c19: 660FBEC0                      movsx       eax,al
7c1D: 80CC0E                        or          ah,00E
7c20: CD10                          int         010
7c22: 676683450801                  add         d,[ebp][8],1
7c28: 67668B4508                   1mov         eax,[ebp][8]
7c2D: 67660FB600                    movzx       eax,b,[eax]
7c32: 84C0                          test        al,al
7c34: 75D9                          jnz         00000000F --↑2
7c36: 90                           nop
7c37: 665D                          pop         ebp
7c39: C3                            retn ;
7c3A: 6655                          push        ebp
7c3C: 6689E5                        mov         ebp,esp
7c3F: 66684F7C0000                  push        000007C4F ;'  |O'
7c45: E8C0FF                        call        000000008 --↑3
7c48: 6683C404                      add         esp,4
7c4C: 90                            nop
7c4C: 90                            nop
7c4D: C9                            leave
7c4E: C3                            retn ;
7c4F: 48 65 6C 6C 6F-2C 20 57 6F-72 6C 64  Hellow, World

随机地,我注意到指针确实需要移动。对于引导区,需要将代码放在磁盘的第一个扇区,偏移量为0x7C00字节。我在 test.ld 文件中指定它。我试图展示我所拥有的一切。在一堆不同的符号中,潜伏着想要的“你好,世界”。同时,更改代码需要更改偏移量,但我几乎可以肯定它总是大于 0x7C00。仍然需要了解如何正确跟踪此偏移量......

c
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    nick_n_a
    2020-03-28T22:20:38Z2020-03-28T22:20:38Z

    在编写引导扇区的情况下,请使用反汇编程序检查您得到了什么。对于 Linux 我不知道如何,对于 Windows hiew.exe 是一个很好的反汇编程序。不要忘记在开始时 - 处理器处于 16 位指令模式和 16 位寻址模式 - 这很重要 1) 在构建二进制文件时 2) 了解发生了什么 3) 在反汇编时。

    对该案例的分析表明,代码被编译器或链接器“错误地”编译。代码 66 - 切换到 32 位指令模式,代码 67 - 切换到 32 位寻址

    7c22: 676683450801                  add         d,[ebp][8],1
    7c28: 67668B4508                   1mov         eax,[ebp][8]
    7c2D: 67660FB600                    movzx       eax,b,[eax]
    

    这些过渡应该紧张。您可以使用它们 (66),但要明智。最好完全避免 32 位寻址 (67),直到切换到保护模式,但主加载程序不会。作为结论 - 如果代码不起作用,虽然它被检查,并且图片没有加起来,那么问题出在构建选项上。

    具体来说,在这种情况下,它有助于将指令code16(它在新版本的 gcc 中消失)更改为 code16gcc. 指定code16或 code16gcc取决于 GCC 的版本。

    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5