为什么“海湾合作委员会”忽略汇编代码的 -fno-pic

发布于 2025-01-18 04:50:48 字数 8889 浏览 2 评论 0原文

我正在编写一个操作系统,我想切换到长模式。 问题是我的交叉编译器(X86_64-FEL-GCC)即使我传递了-fno-pic选项,也会生成独立的代码。

boot.s

/* boot.S - bootstrap the kernel */
/* https://www.kernel.org/doc/Documentation/x86/boot.txt */
    

#include <boot/param.h>
#include <asm/control_registers.h>
    
    /* 32-bit startup code. */
    .code32
    .text
    .global _start
    .type _start, @function
_start:
    /* Clear DF flag */
    cld
    
    /* Setup stack */
    movl    $stack_top, %esp

    /* Check Multiboot2 */
    call    check_multiboot2
    testl   %eax, %eax
    jnz wrong_multiboot2

    /* Check CPUID */
    call    check_cpuid
    testl   %eax, %eax
    jnz no_cpuid

    /* Check if CPU can run in long mode */
    call    check_longmode
    testl   %eax, %eax
    jnz no_longmode
    
    /* TODO: Check the KEEP_SEGMENTS flag. */   

    /* Update the Global Descriptor Table with 64-bit segments */
    lgdt    gdt64

    /* Enable PAE */
    movl    %cr4, %eax
    orl $(1 << X86_CR4_PAE_BIT), %eax
    movl    %eax, %cr4

    /* TODO: Build the structure for paging. */
    
    /* TODO: Transition to long mode. */

    movl    $0x2f4b2f4f, 0xb8000
    
    cli
1:  hlt
    jmp 1b
wrong_multiboot2:
    movl    $'0, %eax
    jmp error
no_cpuid:
    movl    $'1, %eax
    jmp error
no_longmode:
    movl    $'2, %eax   
error:
    movl    $0x4f524f45, (0xb8000)
    movl    $0x4f3a4f52, (0xb8004)
    movl    $0x4f204f20, (0xb8008)
    movb    %al, (0xb800a)
1:  hlt
    jmp 1b

    
#include "check.S"

    
    .section .rodata
    /* GDT */
gdt64:
    .word   gdt_end - gdt - 1   /* limit */
    .quad   gdt         /* base */
gdt:
    .quad   0           /* Null Descriptor */
    .quad   0x00af9a000000ffff  /* Kernel Mode Code Segment */
    .quad   0x00cf92000000ffff  /* Kernel Mode Data Segment */
    .quad   0x00affa000000ffff  /* User Mode Code Segment */
    .quad   0x00cff2000000ffff  /* User Mode Data Segment */
                    /* TODO: Task State Segment */
gdt_end:    

    
    .bss
    /* Stack */
    .balign 4
stack_bottom:
    .fill   STACK_SIZE, 1, 0
stack_top:

check.s

/* check.S : check for multiboot2, cpuid, long mode */

#include <boot/multiboot2.h>
    
/* Check multiboot2 */
check_multiboot2:   
    cmpl    $MULTIBOOT2_BOOTLOADER_MAGIC, %eax
    jne .Lcheck_wrong_multiboot2
    xorl    %eax, %eax
    ret
.Lcheck_wrong_multiboot2:
    movl    $1, %eax
    ret

/* Check if CPUID is supported by attempting to flip the ID bit (bit 21) in
   the FLAGS register. If we can flip it, CPUID is available. */
check_cpuid:
    pushf
    push    $0
    popf
    
    /* Copy FLAGS in to EAX via stack */
    pushfl
    popl    %eax

    /* Copy to EBX as well for comparing later on */
    movl    %eax, %ebx

    /* Flip the ID bit */
    xorl    $(1 << 21), %eax

    /* Copy EAX to FLAGS via the stack */
    pushl   %eax
    popfl

    /* Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) */
    pushfl
    popl    %eax

    /* Restore FLAGS from the old version stored in ECX (i.e. flipping the ID bit
       back if it was ever flipped). */
    /* push ecx */

    /* Compare EAX and EBX. If they are equal then that means the bit wasn't
    flipped, and CPUID isn't supported. */
    cmpl    %eax, %ebx
    jz  .Lcheck_no_cpuid
    popf
    xorl    %eax, %eax
    ret
.Lcheck_no_cpuid:
    popf
    movl    $1, %eax
    ret

/* Check if CPU can support long mode (64 bits) */
check_longmode:
    pushf
    push    $0
    popf
    
    /* test if extended processor info in available */
    /* implicit argument for cpuid */
    movl    $0x80000000, %eax
    /* get highest supported argument */
    cpuid
    /* it needs to be at least 0x80000001 */
    cmpl    $0x80000001, %eax     
    jb  .Lcheck_no_longmode

    /* use extended info to test if long mode is available */
    /* argument for extended processor info */
    movl    $0x80000001, %eax     
    cpuid
    /* test if the LM-bit is set in the D-register */
    testl $(1 << 29), %edx
    /* If it's not set, there is no long mode */
    jz  .Lcheck_no_longmode
    popf
    xorl    %eax, %eax  
    ret
.Lcheck_no_longmode:
    popf
    movl    $1, %eax
    ret

i用x86_64 -elf -gcc -wall -wall -wextra -wextra -nostdlib -lgcc -lgcc -mno -red -red -Zone -ffreesting -Std = GNU99 -fno -pic -c src/boot/boot.s -o build/boot.o -i include

这是boot.o的objdump,

0000000000000000 <_start>:
   0:   fc                      cld    
   1:   bc 00 00 00 00          mov    $0x0,%esp
   6:   e8 6d 00 00 00          call   78 <check_multiboot2>
   b:   85 c0                   test   %eax,%eax
   d:   75 30                   jne    3f <wrong_multiboot2>
   f:   e8 74 00 00 00          call   88 <check_cpuid>
  14:   85 c0                   test   %eax,%eax
  16:   75 2e                   jne    46 <no_cpuid>
  18:   e8 8b 00 00 00          call   a8 <check_longmode>
  1d:   85 c0                   test   %eax,%eax
  1f:   75 2c                   jne    4d <no_longmode>
  21:   0f 01 15 00 00 00 00    lgdt   0x0(%rip)        # 28 <_start+0x28>
  28:   0f 20 e0                mov    %cr4,%rax
  2b:   83 c8 20                or     $0x20,%eax
  2e:   0f 22 e0                mov    %rax,%cr4
  31:   c7 05 00 80 0b 00 4f    movl   $0x2f4b2f4f,0xb8000(%rip)        # b803b <stack_top+0xb403b>
  38:   2f 4b 2f 
  3b:   fa                      cli    
  3c:   f4                      hlt    
  3d:   eb fd                   jmp    3c <_start+0x3c>

000000000000003f <wrong_multiboot2>:
  3f:   b8 30 00 00 00          mov    $0x30,%eax
  44:   eb 0c                   jmp    52 <error>

0000000000000046 <no_cpuid>:
  46:   b8 31 00 00 00          mov    $0x31,%eax
  4b:   eb 05                   jmp    52 <error>

000000000000004d <no_longmode>:
  4d:   b8 32 00 00 00          mov    $0x32,%eax

0000000000000052 <error>:
  52:   c7 05 00 80 0b 00 45    movl   $0x4f524f45,0xb8000(%rip)        # b805c <stack_top+0xb405c>
  59:   4f 52 4f 
  5c:   c7 05 04 80 0b 00 52    movl   $0x4f3a4f52,0xb8004(%rip)        # b806a <stack_top+0xb406a>
  63:   4f 3a 4f 
  66:   c7 05 08 80 0b 00 20    movl   $0x4f204f20,0xb8008(%rip)        # b8078 <stack_top+0xb4078>
  6d:   4f 20 4f 
  70:   a2 0a 80 0b 00 f4 eb    movabs %al,0x3dfdebf4000b800a
  77:   fd  

0000000000000078 <check_multiboot2>:
  78:   3d 89 62 d7 36          cmp    $0x36d76289,%eax
  7d:   75 03                   jne    82 <check_multiboot2+0xa>
  7f:   31 c0                   xor    %eax,%eax
  81:   c3                      ret    
  82:   b8 01 00 00 00          mov    $0x1,%eax
  87:   c3                      ret    

0000000000000088 <check_cpuid>:
  88:   9c                      pushf  
  89:   6a 00                   push   $0x0
  8b:   9d                      popf   
  8c:   9c                      pushf  
  8d:   58                      pop    %rax
  8e:   89 c3                   mov    %eax,%ebx
  90:   35 00 00 20 00          xor    $0x200000,%eax
  95:   50                      push   %rax
  96:   9d                      popf   
  97:   9c                      pushf  
  98:   58                      pop    %rax
  99:   39 c3                   cmp    %eax,%ebx
  9b:   74 04                   je     a1 <check_cpuid+0x19>
  9d:   9d                      popf   
  9e:   31 c0                   xor    %eax,%eax
  a0:   c3                      ret    
  a1:   9d                      popf   
  a2:   b8 01 00 00 00          mov    $0x1,%eax
  a7:   c3                      ret    

00000000000000a8 <check_longmode>:
  a8:   9c                      pushf  
  a9:   6a 00                   push   $0x0
  ab:   9d                      popf   
  ac:   b8 00 00 00 80          mov    $0x80000000,%eax
  b1:   0f a2                   cpuid  
  b3:   3d 01 00 00 80          cmp    $0x80000001,%eax
  b8:   72 13                   jb     cd <check_longmode+0x25>
  ba:   b8 01 00 00 80          mov    $0x80000001,%eax
  bf:   0f a2                   cpuid  
  c1:   f7 c2 00 00 00 20       test   $0x20000000,%edx
  c7:   74 04                   je     cd <check_longmode+0x25>
  c9:   9d                      popf   
  ca:   31 c0                   xor    %eax,%eax
  cc:   c3                      ret    
  cd:   9d                      popf   
  ce:   b8 01 00 00 00          mov    $0x1,%eax
  d3:   c3                      ret    

我们可以看到> movl $ 0x2f4b2f4f,0xb8000被编译为movl $ 0x2f4b2f4f,0xb8000(%RIP),因此我无法正确写入0xB8000

我也要接受任何其他建议。

I'm writing an OS and I want to switch to long mode.
The problem is that my cross compiler (x86_64-elf-gcc) is generating position independent code even if I pass the -fno-pic option.

boot.S

/* boot.S - bootstrap the kernel */
/* https://www.kernel.org/doc/Documentation/x86/boot.txt */
    

#include <boot/param.h>
#include <asm/control_registers.h>
    
    /* 32-bit startup code. */
    .code32
    .text
    .global _start
    .type _start, @function
_start:
    /* Clear DF flag */
    cld
    
    /* Setup stack */
    movl    $stack_top, %esp

    /* Check Multiboot2 */
    call    check_multiboot2
    testl   %eax, %eax
    jnz wrong_multiboot2

    /* Check CPUID */
    call    check_cpuid
    testl   %eax, %eax
    jnz no_cpuid

    /* Check if CPU can run in long mode */
    call    check_longmode
    testl   %eax, %eax
    jnz no_longmode
    
    /* TODO: Check the KEEP_SEGMENTS flag. */   

    /* Update the Global Descriptor Table with 64-bit segments */
    lgdt    gdt64

    /* Enable PAE */
    movl    %cr4, %eax
    orl $(1 << X86_CR4_PAE_BIT), %eax
    movl    %eax, %cr4

    /* TODO: Build the structure for paging. */
    
    /* TODO: Transition to long mode. */

    movl    $0x2f4b2f4f, 0xb8000
    
    cli
1:  hlt
    jmp 1b
wrong_multiboot2:
    movl    

check.S

/* check.S : check for multiboot2, cpuid, long mode */

#include <boot/multiboot2.h>
    
/* Check multiboot2 */
check_multiboot2:   
    cmpl    $MULTIBOOT2_BOOTLOADER_MAGIC, %eax
    jne .Lcheck_wrong_multiboot2
    xorl    %eax, %eax
    ret
.Lcheck_wrong_multiboot2:
    movl    $1, %eax
    ret

/* Check if CPUID is supported by attempting to flip the ID bit (bit 21) in
   the FLAGS register. If we can flip it, CPUID is available. */
check_cpuid:
    pushf
    push    $0
    popf
    
    /* Copy FLAGS in to EAX via stack */
    pushfl
    popl    %eax

    /* Copy to EBX as well for comparing later on */
    movl    %eax, %ebx

    /* Flip the ID bit */
    xorl    $(1 << 21), %eax

    /* Copy EAX to FLAGS via the stack */
    pushl   %eax
    popfl

    /* Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) */
    pushfl
    popl    %eax

    /* Restore FLAGS from the old version stored in ECX (i.e. flipping the ID bit
       back if it was ever flipped). */
    /* push ecx */

    /* Compare EAX and EBX. If they are equal then that means the bit wasn't
    flipped, and CPUID isn't supported. */
    cmpl    %eax, %ebx
    jz  .Lcheck_no_cpuid
    popf
    xorl    %eax, %eax
    ret
.Lcheck_no_cpuid:
    popf
    movl    $1, %eax
    ret

/* Check if CPU can support long mode (64 bits) */
check_longmode:
    pushf
    push    $0
    popf
    
    /* test if extended processor info in available */
    /* implicit argument for cpuid */
    movl    $0x80000000, %eax
    /* get highest supported argument */
    cpuid
    /* it needs to be at least 0x80000001 */
    cmpl    $0x80000001, %eax     
    jb  .Lcheck_no_longmode

    /* use extended info to test if long mode is available */
    /* argument for extended processor info */
    movl    $0x80000001, %eax     
    cpuid
    /* test if the LM-bit is set in the D-register */
    testl $(1 << 29), %edx
    /* If it's not set, there is no long mode */
    jz  .Lcheck_no_longmode
    popf
    xorl    %eax, %eax  
    ret
.Lcheck_no_longmode:
    popf
    movl    $1, %eax
    ret

I compile with x86_64-elf-gcc -Wall -Wextra -nostdlib -lgcc -mno-red-zone -ffreestanding -std=gnu99 -fno-pic -c src/boot/boot.S -o build/boot.o -I include

Here is the objdump of boot.o

0000000000000000 <_start>:
   0:   fc                      cld    
   1:   bc 00 00 00 00          mov    $0x0,%esp
   6:   e8 6d 00 00 00          call   78 <check_multiboot2>
   b:   85 c0                   test   %eax,%eax
   d:   75 30                   jne    3f <wrong_multiboot2>
   f:   e8 74 00 00 00          call   88 <check_cpuid>
  14:   85 c0                   test   %eax,%eax
  16:   75 2e                   jne    46 <no_cpuid>
  18:   e8 8b 00 00 00          call   a8 <check_longmode>
  1d:   85 c0                   test   %eax,%eax
  1f:   75 2c                   jne    4d <no_longmode>
  21:   0f 01 15 00 00 00 00    lgdt   0x0(%rip)        # 28 <_start+0x28>
  28:   0f 20 e0                mov    %cr4,%rax
  2b:   83 c8 20                or     $0x20,%eax
  2e:   0f 22 e0                mov    %rax,%cr4
  31:   c7 05 00 80 0b 00 4f    movl   $0x2f4b2f4f,0xb8000(%rip)        # b803b <stack_top+0xb403b>
  38:   2f 4b 2f 
  3b:   fa                      cli    
  3c:   f4                      hlt    
  3d:   eb fd                   jmp    3c <_start+0x3c>

000000000000003f <wrong_multiboot2>:
  3f:   b8 30 00 00 00          mov    $0x30,%eax
  44:   eb 0c                   jmp    52 <error>

0000000000000046 <no_cpuid>:
  46:   b8 31 00 00 00          mov    $0x31,%eax
  4b:   eb 05                   jmp    52 <error>

000000000000004d <no_longmode>:
  4d:   b8 32 00 00 00          mov    $0x32,%eax

0000000000000052 <error>:
  52:   c7 05 00 80 0b 00 45    movl   $0x4f524f45,0xb8000(%rip)        # b805c <stack_top+0xb405c>
  59:   4f 52 4f 
  5c:   c7 05 04 80 0b 00 52    movl   $0x4f3a4f52,0xb8004(%rip)        # b806a <stack_top+0xb406a>
  63:   4f 3a 4f 
  66:   c7 05 08 80 0b 00 20    movl   $0x4f204f20,0xb8008(%rip)        # b8078 <stack_top+0xb4078>
  6d:   4f 20 4f 
  70:   a2 0a 80 0b 00 f4 eb    movabs %al,0x3dfdebf4000b800a
  77:   fd  

0000000000000078 <check_multiboot2>:
  78:   3d 89 62 d7 36          cmp    $0x36d76289,%eax
  7d:   75 03                   jne    82 <check_multiboot2+0xa>
  7f:   31 c0                   xor    %eax,%eax
  81:   c3                      ret    
  82:   b8 01 00 00 00          mov    $0x1,%eax
  87:   c3                      ret    

0000000000000088 <check_cpuid>:
  88:   9c                      pushf  
  89:   6a 00                   push   $0x0
  8b:   9d                      popf   
  8c:   9c                      pushf  
  8d:   58                      pop    %rax
  8e:   89 c3                   mov    %eax,%ebx
  90:   35 00 00 20 00          xor    $0x200000,%eax
  95:   50                      push   %rax
  96:   9d                      popf   
  97:   9c                      pushf  
  98:   58                      pop    %rax
  99:   39 c3                   cmp    %eax,%ebx
  9b:   74 04                   je     a1 <check_cpuid+0x19>
  9d:   9d                      popf   
  9e:   31 c0                   xor    %eax,%eax
  a0:   c3                      ret    
  a1:   9d                      popf   
  a2:   b8 01 00 00 00          mov    $0x1,%eax
  a7:   c3                      ret    

00000000000000a8 <check_longmode>:
  a8:   9c                      pushf  
  a9:   6a 00                   push   $0x0
  ab:   9d                      popf   
  ac:   b8 00 00 00 80          mov    $0x80000000,%eax
  b1:   0f a2                   cpuid  
  b3:   3d 01 00 00 80          cmp    $0x80000001,%eax
  b8:   72 13                   jb     cd <check_longmode+0x25>
  ba:   b8 01 00 00 80          mov    $0x80000001,%eax
  bf:   0f a2                   cpuid  
  c1:   f7 c2 00 00 00 20       test   $0x20000000,%edx
  c7:   74 04                   je     cd <check_longmode+0x25>
  c9:   9d                      popf   
  ca:   31 c0                   xor    %eax,%eax
  cc:   c3                      ret    
  cd:   9d                      popf   
  ce:   b8 01 00 00 00          mov    $0x1,%eax
  d3:   c3                      ret    

We can see that movl $0x2f4b2f4f, 0xb8000 is compiled into movl $0x2f4b2f4f,0xb8000(%rip) so I can't properly write into the VGA text buffer starting at 0xb8000.

I'm also taking any other advice.

0, %eax jmp error no_cpuid: movl

check.S


I compile with x86_64-elf-gcc -Wall -Wextra -nostdlib -lgcc -mno-red-zone -ffreestanding -std=gnu99 -fno-pic -c src/boot/boot.S -o build/boot.o -I include

Here is the objdump of boot.o


We can see that movl $0x2f4b2f4f, 0xb8000 is compiled into movl $0x2f4b2f4f,0xb8000(%rip) so I can't properly write into the VGA text buffer starting at 0xb8000.

I'm also taking any other advice.

1, %eax jmp error no_longmode: movl

check.S


I compile with x86_64-elf-gcc -Wall -Wextra -nostdlib -lgcc -mno-red-zone -ffreestanding -std=gnu99 -fno-pic -c src/boot/boot.S -o build/boot.o -I include

Here is the objdump of boot.o


We can see that movl $0x2f4b2f4f, 0xb8000 is compiled into movl $0x2f4b2f4f,0xb8000(%rip) so I can't properly write into the VGA text buffer starting at 0xb8000.

I'm also taking any other advice.

2, %eax error: movl $0x4f524f45, (0xb8000) movl $0x4f3a4f52, (0xb8004) movl $0x4f204f20, (0xb8008) movb %al, (0xb800a) 1: hlt jmp 1b #include "check.S" .section .rodata /* GDT */ gdt64: .word gdt_end - gdt - 1 /* limit */ .quad gdt /* base */ gdt: .quad 0 /* Null Descriptor */ .quad 0x00af9a000000ffff /* Kernel Mode Code Segment */ .quad 0x00cf92000000ffff /* Kernel Mode Data Segment */ .quad 0x00affa000000ffff /* User Mode Code Segment */ .quad 0x00cff2000000ffff /* User Mode Data Segment */ /* TODO: Task State Segment */ gdt_end: .bss /* Stack */ .balign 4 stack_bottom: .fill STACK_SIZE, 1, 0 stack_top:

check.S

I compile with x86_64-elf-gcc -Wall -Wextra -nostdlib -lgcc -mno-red-zone -ffreestanding -std=gnu99 -fno-pic -c src/boot/boot.S -o build/boot.o -I include

Here is the objdump of boot.o

We can see that movl $0x2f4b2f4f, 0xb8000 is compiled into movl $0x2f4b2f4f,0xb8000(%rip) so I can't properly write into the VGA text buffer starting at 0xb8000.

I'm also taking any other advice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文